SFML logo
  • Main Page
  • Namespaces
  • Classes
  • Files
  • File List

RenderImageImplPBuffer.cpp

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  ::