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

RenderImageImplPBuffer.cpp

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