00001 00002 // 00003 // SFML - Simple and Fast Multimedia Library 00004 // Copyright (C) 2007-2009 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/GLCheck.hpp> 00030 #include <SFML/Window/Context.hpp> 00031 #include <SFML/System/Err.hpp> 00032 00033 00034 namespace sf 00035 { 00036 namespace priv 00037 { 00041 RenderImageImplPBuffer::RenderImageImplPBuffer() : 00042 myPBuffer (NULL), 00043 myDeviceContext(NULL), 00044 myContext (NULL), 00045 myWidth (0), 00046 myHeight (0) 00047 { 00048 00049 } 00050 00051 00055 RenderImageImplPBuffer::~RenderImageImplPBuffer() 00056 { 00057 if (myContext) 00058 { 00059 wglDeleteContext(myContext); 00060 } 00061 00062 if (myPBuffer && myDeviceContext) 00063 { 00064 wglReleasePbufferDCARB(myPBuffer, myDeviceContext); 00065 wglDestroyPbufferARB(myPBuffer); 00066 } 00067 00068 // This is to make sure that another valid context is made 00069 // active after we destroy the P-Buffer's one 00070 Context::SetReferenceActive(); 00071 } 00072 00073 00077 bool RenderImageImplPBuffer::IsSupported() 00078 { 00079 // Make sure that GLEW is initialized 00080 priv::EnsureGlewInit(); 00081 00082 return WGLEW_ARB_pbuffer && WGLEW_ARB_pixel_format; 00083 } 00084 00085 00089 bool RenderImageImplPBuffer::Create(unsigned int width, unsigned int height, unsigned int, bool depthBuffer) 00090 { 00091 // Store the dimensions 00092 myWidth = width; 00093 myHeight = height; 00094 00095 // Get the current HDC 00096 HDC currentDC = wglGetCurrentDC(); 00097 00098 // Define the minimum PBuffer attributes 00099 int attributes[] = 00100 { 00101 WGL_SUPPORT_OPENGL_ARB, GL_TRUE, 00102 WGL_DRAW_TO_PBUFFER_ARB, GL_TRUE, 00103 WGL_RED_BITS_ARB, 8, 00104 WGL_GREEN_BITS_ARB, 8, 00105 WGL_BLUE_BITS_ARB, 8, 00106 WGL_ALPHA_BITS_ARB, 8, 00107 WGL_DEPTH_BITS_ARB, (depthBuffer ? 24 : 0), 00108 WGL_DOUBLE_BUFFER_ARB, GL_FALSE, 00109 0 00110 }; 00111 00112 // Select the best pixel format for our attributes 00113 unsigned int nbFormats = 0; 00114 int pixelFormat = -1; 00115 wglChoosePixelFormatARB(currentDC, attributes, NULL, 1, &pixelFormat, &nbFormats); 00116 00117 // Make sure that one pixel format has been found 00118 if (nbFormats == 0) 00119 { 00120 Err() << "Impossible to create render image (failed to find a suitable pixel format for PBuffer)" << std::endl; 00121 return false; 00122 } 00123 00124 // Create the P-Buffer and its OpenGL context 00125 myPBuffer = wglCreatePbufferARB(currentDC, pixelFormat, width, height, NULL); 00126 myDeviceContext = wglGetPbufferDCARB(myPBuffer); 00127 myContext = wglCreateContext(myDeviceContext); 00128 00129 // Check errors 00130 if (!myPBuffer || !myDeviceContext || !myContext) 00131 { 00132 Err() << "Impossible to create render image (failed to create PBuffer)" << std::endl; 00133 return false; 00134 } 00135 00136 // Check the actual size of the P-Buffer 00137 int actualWidth, actualHeight; 00138 wglQueryPbufferARB(myPBuffer, WGL_PBUFFER_WIDTH_ARB, &actualWidth); 00139 wglQueryPbufferARB(myPBuffer, WGL_PBUFFER_HEIGHT_ARB, &actualHeight); 00140 if ((actualWidth != static_cast<int>(width)) || (actualHeight != static_cast<int>(height))) 00141 { 00142 Err() << "Impossible to create render image (failed to match the requested size). " 00143 << "Size: " << actualWidth << "x" << actualHeight << " - " 00144 << "Requested: " << width << "x" << height 00145 << std::endl; 00146 return false; 00147 } 00148 00149 // Share the P-Buffer context with the current context 00150 HGLRC currentContext = wglGetCurrentContext(); 00151 if (currentContext) 00152 { 00153 wglMakeCurrent(NULL, NULL); 00154 wglShareLists(currentContext, myContext); 00155 wglMakeCurrent(currentDC, currentContext); 00156 } 00157 00158 return true; 00159 } 00160 00161 00165 bool RenderImageImplPBuffer::Activate(bool active) 00166 { 00167 if (active) 00168 { 00169 if (myDeviceContext && myContext) 00170 { 00171 if (wglGetCurrentContext() != myContext) 00172 return wglMakeCurrent(myDeviceContext, myContext) != 0; 00173 else 00174 return true; 00175 } 00176 else 00177 { 00178 return false; 00179 } 00180 } 00181 else 00182 { 00183 // To deactivate the P-Buffer's context, we actually activate 00184 // another one so that we make sure that there is always an 00185 // active context for subsequent graphics operations 00186 return Context::SetReferenceActive(); 00187 } 00188 } 00189 00190 00194 void RenderImageImplPBuffer::UpdateTexture(unsigned int textureId) 00195 { 00196 if (Activate(true)) 00197 { 00198 GLint previous; 00199 GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous)); 00200 00201 // Copy the rendered pixels to the image 00202 GLCheck(glBindTexture(GL_TEXTURE_2D, textureId)); 00203 GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, myWidth, myHeight)); 00204 00205 GLCheck(glBindTexture(GL_TEXTURE_2D, previous)); 00206 } 00207 } 00208 00209 } // namespace priv 00210 00211 } // namespace sf
:: Copyright © 2007-2008 Laurent Gomila, all rights reserved :: Documentation generated by doxygen 1.5.2 ::