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