00001 00002 // 00003 // SFML - Simple and Fast Multimedia Library 00004 // Copyright (C) 2007-2008 Laurent Gomila (laurent.gom@gmail.com) 00005 // 00006 // This software is provided 'as-is', without any express or implied warranty. 00007 // In no event will the authors be held liable for any damages arising from the use of this software. 00008 // 00009 // Permission is granted to anyone to use this software for any purpose, 00010 // including commercial applications, and to alter it and redistribute it freely, 00011 // subject to the following restrictions: 00012 // 00013 // 1. The origin of this software must not be misrepresented; 00014 // you must not claim that you wrote the original software. 00015 // If you use this software in a product, an acknowledgment 00016 // in the product documentation would be appreciated but is not required. 00017 // 00018 // 2. Altered source versions must be plainly marked as such, 00019 // and must not be misrepresented as being the original software. 00020 // 00021 // 3. This notice may not be removed or altered from any source distribution. 00022 // 00024 00026 // Headers 00028 #include <SFML/Graphics/Win32/RenderImageImplPBuffer.hpp> 00029 #include <SFML/Graphics/Image.hpp> 00030 #include <SFML/Graphics/GraphicsContext.hpp> 00031 #include <iostream> 00032 00033 00034 namespace sf 00035 { 00036 namespace priv 00037 { 00041 RenderImageImplPBuffer::RenderImageImplPBuffer(Image& TargetImage) : 00042 RenderImageImpl(TargetImage), 00043 myPBuffer (NULL), 00044 myDeviceContext(NULL), 00045 myContext (NULL), 00046 myUpdating (false) 00047 { 00048 00049 } 00050 00051 00055 RenderImageImplPBuffer::~RenderImageImplPBuffer() 00056 { 00057 if (myPBuffer && myDeviceContext && myContext) 00058 { 00059 wglDeleteContext(myContext); 00060 wglReleasePbufferDCARB(myPBuffer, myDeviceContext); 00061 wglDestroyPbufferARB(myPBuffer); 00062 } 00063 } 00064 00065 00069 bool RenderImageImplPBuffer::IsSupported() 00070 { 00071 // Make sure we have a valid context 00072 priv::GraphicsContext Ctx; 00073 00074 return wglewIsSupported("WGL_ARB_pbuffer") && 00075 wglewIsSupported("WGL_ARB_pixel_format"); 00076 } 00077 00078 00082 bool RenderImageImplPBuffer::Create(bool DepthBuffer) 00083 { 00084 // Extract the image dimensions 00085 int Width = static_cast<int>(myImage.GetWidth()); 00086 int Height = static_cast<int>(myImage.GetHeight()); 00087 00088 // Make sure we have a valid context 00089 priv::GraphicsContext Ctx; 00090 00091 // Get the current HDC 00092 HDC CurrentDeviceContext = wglGetCurrentDC(); 00093 00094 // Define the minimum PBuffer attributes 00095 int Attributes[] = 00096 { 00097 WGL_SUPPORT_OPENGL_ARB, GL_TRUE, 00098 WGL_DRAW_TO_PBUFFER_ARB, GL_TRUE, 00099 WGL_RED_BITS_ARB, 8, 00100 WGL_GREEN_BITS_ARB, 8, 00101 WGL_BLUE_BITS_ARB, 8, 00102 WGL_ALPHA_BITS_ARB, 8, 00103 WGL_DEPTH_BITS_ARB, (DepthBuffer ? 24 : 0), 00104 WGL_DOUBLE_BUFFER_ARB, GL_FALSE, 00105 0 00106 }; 00107 00108 // Select the best pixel format for our attributes 00109 unsigned int NbFormats = 0; 00110 int PixelFormat = -1; 00111 wglChoosePixelFormatARB(CurrentDeviceContext, Attributes, NULL, 1, &PixelFormat, &NbFormats); 00112 00113 // Make sure one pixel format has been found 00114 if (NbFormats == 0) 00115 { 00116 std::cerr << "Impossible to create render image (failed to find a suitable pixel format for PBuffer)" << std::endl; 00117 return false; 00118 } 00119 00120 // Create the PBuffer and its OpenGL context 00121 myPBuffer = wglCreatePbufferARB(CurrentDeviceContext, PixelFormat, Width, Height, NULL); 00122 myDeviceContext = wglGetPbufferDCARB(myPBuffer); 00123 myContext = wglCreateContext(myDeviceContext); 00124 00125 // Check the actual size of the PBuffer 00126 int ActualWidth, ActualHeight; 00127 wglQueryPbufferARB(myPBuffer, WGL_PBUFFER_WIDTH_ARB, &ActualWidth); 00128 wglQueryPbufferARB(myPBuffer, WGL_PBUFFER_HEIGHT_ARB, &ActualHeight); 00129 if ((ActualWidth != Width) || (ActualHeight != Height)) 00130 { 00131 std::cerr << "Impossible to create render image (failed to match the requested size). " 00132 << "Size: " << ActualWidth << "x" << ActualHeight << " - " 00133 << "Requested: " << Width << "x" << Height 00134 << std::endl; 00135 return false; 00136 } 00137 00138 // Check errors 00139 if (!myPBuffer || !myDeviceContext || !myContext) 00140 { 00141 std::cerr << "Impossible to create render image (failed to create PBuffer)" << std::endl; 00142 return false; 00143 } 00144 00145 // Share the PBuffer context with other SFML contexts 00146 HGLRC CurrentContext = wglGetCurrentContext(); 00147 if (CurrentContext) 00148 wglShareLists(CurrentContext, myContext); 00149 00150 myUpdating = false; 00151 00152 return true; 00153 } 00154 00155 00159 bool RenderImageImplPBuffer::Activate(bool Active) 00160 { 00161 if (Active) 00162 { 00163 if (myDeviceContext && myContext && (wglGetCurrentContext() != myContext)) 00164 { 00165 // Save the previous bind 00166 myPrevDeviceContext = wglGetCurrentDC(); 00167 myPrevContext = wglGetCurrentContext(); 00168 00169 // Bind the PBuffer 00170 if (!wglMakeCurrent(myDeviceContext, myContext)) 00171 { 00172 std::cout << "Failed to activate render image" << std::endl; 00173 return false; 00174 } 00175 } 00176 } 00177 else 00178 { 00179 if (wglGetCurrentContext() == myContext) 00180 { 00181 // Unbind the PBuffer 00182 if (!wglMakeCurrent(NULL, NULL)) 00183 { 00184 std::cout << "Failed to deactivate render image" << std::endl; 00185 return false; 00186 } 00187 00188 // Restore the previous bind 00189 if (myPrevDeviceContext && myPrevContext) 00190 wglMakeCurrent(myPrevDeviceContext, myPrevContext); 00191 } 00192 00193 // We have to schedule an external update for the target image 00194 if (!myUpdating) 00195 myImage.ScheduleTextureUpdate(this); 00196 } 00197 00198 return true; 00199 } 00200 00201 00205 bool RenderImageImplPBuffer::UpdateImage(Image& ImageToUpdate) 00206 { 00207 myUpdating = true; 00208 00209 // Bind the P-Buffer 00210 if (Activate(true)) 00211 { 00212 // Copy its content to the image's texture 00213 GLCheck(glBindTexture(GL_TEXTURE_2D, ImageToUpdate.myTexture)); 00214 GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, ImageToUpdate.GetWidth(), ImageToUpdate.GetHeight())); 00215 00216 // Unbind the P-Buffer 00217 Activate(false); 00218 } 00219 00220 myUpdating = false; 00221 00222 return true; 00223 } 00224 00225 } // namespace priv 00226 00227 } // namespace sf
:: Copyright © 2007-2008 Laurent Gomila, all rights reserved :: Documentation generated by doxygen 1.5.2 ::