Replaced the P-Buffer implementation of RenderImage with a generic "in-memory context" one

This commit is contained in:
Laurent Gomila 2011-04-04 08:20:03 +02:00
parent 3acacc8049
commit 92f70b32e9
23 changed files with 386 additions and 1103 deletions

View File

@ -177,20 +177,6 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
const Image& GetImage() const; const Image& GetImage() const;
////////////////////////////////////////////////////////////
/// \brief Check whether the system supports render images or not
///
/// It is very important to always call this function before
/// trying to use the RenderImage class, as the feature may not
/// be supported on all platforms (especially very old ones).
/// If this function returns false, then you won't be able
/// to use the class at all.
///
/// \return True if the RenderImage class can be used
///
////////////////////////////////////////////////////////////
static bool IsAvailable();
private : private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -30,6 +30,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Config.hpp> #include <SFML/Config.hpp>
#include <SFML/Window/GlResource.hpp> #include <SFML/Window/GlResource.hpp>
#include <SFML/Window/ContextSettings.hpp>
#include <SFML/System/NonCopyable.hpp> #include <SFML/System/NonCopyable.hpp>
@ -69,8 +70,25 @@ public :
/// ///
/// \param active True to activate, false to deactivate /// \param active True to activate, false to deactivate
/// ///
/// \return True on success, false on failure
///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void SetActive(bool active); bool SetActive(bool active);
public :
////////////////////////////////////////////////////////////
/// \brief Construct a in-memory context
///
/// This constructor is for internal use, you don't need
/// to bother with it.
///
/// \param settings Creation parameters
/// \param width Back buffer width
/// \param height Back buffer height
///
////////////////////////////////////////////////////////////
Context(const ContextSettings& settings, unsigned int width, unsigned int height);
private : private :

View File

@ -45,7 +45,7 @@ struct ContextSettings
/// \param minor Minor number of the context version /// \param minor Minor number of the context version
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
explicit ContextSettings(unsigned int depth = 24, unsigned int stencil = 8, unsigned int antialiasing = 0, unsigned int major = 2, unsigned int minor = 0) : explicit ContextSettings(unsigned int depth = 0, unsigned int stencil = 0, unsigned int antialiasing = 0, unsigned int major = 2, unsigned int minor = 0) :
DepthBits (depth), DepthBits (depth),
StencilBits (stencil), StencilBits (stencil),
AntialiasingLevel(antialiasing), AntialiasingLevel(antialiasing),

View File

@ -31,7 +31,8 @@ set(SRC
${SRCROOT}/RenderImageImpl.hpp ${SRCROOT}/RenderImageImpl.hpp
${SRCROOT}/RenderImageImplFBO.cpp ${SRCROOT}/RenderImageImplFBO.cpp
${SRCROOT}/RenderImageImplFBO.hpp ${SRCROOT}/RenderImageImplFBO.hpp
${SRCROOT}/RenderImageImplPBuffer.hpp ${SRCROOT}/RenderImageImplDefault.cpp
${SRCROOT}/RenderImageImplDefault.hpp
${SRCROOT}/RenderTarget.cpp ${SRCROOT}/RenderTarget.cpp
${INCROOT}/RenderTarget.hpp ${INCROOT}/RenderTarget.hpp
${SRCROOT}/RenderWindow.cpp ${SRCROOT}/RenderWindow.cpp
@ -50,27 +51,6 @@ set(SRC
${SRCROOT}/stb_image/stb_image_write.h ${SRCROOT}/stb_image/stb_image_write.h
) )
# add platform specific sources
if(WINDOWS)
set(SRC
${SRC}
${SRCROOT}/Win32/RenderImageImplPBuffer.cpp
${SRCROOT}/Win32/RenderImageImplPBuffer.hpp
)
elseif(LINUX)
set(SRC
${SRC}
${SRCROOT}/Linux/RenderImageImplPBuffer.cpp
${SRCROOT}/Linux/RenderImageImplPBuffer.hpp
)
elseif(MACOSX)
set(SRC
${SRC}
${SRCROOT}/OSX/RenderImageImplPBuffer.cpp
${SRCROOT}/OSX/RenderImageImplPBuffer.hpp
)
endif()
# let CMake know about our additional graphics libraries paths (on Windows and OSX) # let CMake know about our additional graphics libraries paths (on Windows and OSX)
if (WINDOWS OR MACOSX) if (WINDOWS OR MACOSX)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${CMAKE_SOURCE_DIR}/extlibs/headers/freetype") set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${CMAKE_SOURCE_DIR}/extlibs/headers/freetype")

View File

@ -1,207 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Linux/RenderImageImplPBuffer.hpp>
#include <SFML/Graphics/GLCheck.hpp>
#include <SFML/Window/Context.hpp>
#include <SFML/System/Err.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
RenderImageImplPBuffer::RenderImageImplPBuffer() :
myPBuffer(0),
myContext(NULL),
myWidth (0),
myHeight (0)
{
myDisplay = XOpenDisplay(NULL);
}
////////////////////////////////////////////////////////////
RenderImageImplPBuffer::~RenderImageImplPBuffer()
{
EnsureGlContext();
if (myContext)
glXDestroyContext(myDisplay, myContext);
if (myPBuffer)
glXDestroyGLXPbufferSGIX(myDisplay, myPBuffer);
XCloseDisplay(myDisplay);
}
////////////////////////////////////////////////////////////
bool RenderImageImplPBuffer::IsSupported()
{
EnsureGlContext();
// Make sure that GLEW is initialized
EnsureGlewInit();
return GLXEW_SGIX_pbuffer && GLXEW_SGIX_fbconfig;
}
////////////////////////////////////////////////////////////
bool RenderImageImplPBuffer::Create(unsigned int width, unsigned int height, unsigned int, bool depthBuffer)
{
// Store the dimensions
myWidth = width;
myHeight = height;
// Define the PBuffer attributes
int visualAttributes[] =
{
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
GLX_ALPHA_SIZE, 8,
GLX_DEPTH_SIZE, (depthBuffer ? 24 : 0),
0
};
int PBufferAttributes[] =
{
GLX_PBUFFER_WIDTH, width,
GLX_PBUFFER_HEIGHT, height,
0
};
// Get the available FB configurations
int nbConfigs = 0;
GLXFBConfig* configs = glXChooseFBConfigSGIX(myDisplay, DefaultScreen(myDisplay), visualAttributes, &nbConfigs);
if (!configs || !nbConfigs)
{
Err() << "Impossible to create render image (failed to find a suitable pixel format for PBuffer)" << std::endl;
return false;
}
// Create the P-Buffer
myPBuffer = glXCreateGLXPbufferSGIX(myDisplay, configs[0], width, height, PBufferAttributes);
if (!myPBuffer)
{
Err() << "Impossible to create render image (failed to create the OpenGL PBuffer)" << std::endl;
XFree(configs);
return false;
}
// Check the actual size of the P-Buffer
unsigned int actualWidth, actualHeight;
glXQueryGLXPbufferSGIX(myDisplay, myPBuffer, GLX_WIDTH_SGIX, &actualWidth);
glXQueryGLXPbufferSGIX(myDisplay, myPBuffer, GLX_HEIGHT_SGIX, &actualHeight);
if ((actualWidth != width) || (actualHeight != height))
{
Err() << "Impossible to create render image (failed to match the requested size). "
<< "Size: " << actualWidth << "x" << actualHeight << " - "
<< "Requested: " << width << "x" << height
<< std::endl;
XFree(configs);
return false;
}
// We'll have to share the P-Buffer context with the current context
GLXDrawable currentDrawable = glXGetCurrentDrawable();
GLXContext currentContext = glXGetCurrentContext();
if (currentContext)
glXMakeCurrent(myDisplay, 0, NULL);
// Create the context
XVisualInfo* visual = glXGetVisualFromFBConfig(myDisplay, configs[0]);
myContext = glXCreateContext(myDisplay, visual, currentContext, true);
if (!myContext)
{
Err() << "Impossible to create render image (failed to create the OpenGL context)" << std::endl;
XFree(configs);
XFree(visual);
return false;
}
// Restore the previous active context
if (currentContext)
glXMakeCurrent(myDisplay, currentDrawable, currentContext);
// Cleanup resources
XFree(configs);
XFree(visual);
return true;
}
////////////////////////////////////////////////////////////
bool RenderImageImplPBuffer::Activate(bool active)
{
if (active)
{
if (myPBuffer && myContext)
{
if (glXGetCurrentContext() != myContext)
return glXMakeCurrent(myDisplay, myPBuffer, myContext) != 0;
else
return true;
}
else
{
return false;
}
}
else
{
// To deactivate the P-Buffer's context, we actually activate
// another one so that we make sure that there is always an
// active context for subsequent graphics operations
// @odo fixme
//return Context::SetReferenceActive();
return true;
}
}
////////////////////////////////////////////////////////////
void RenderImageImplPBuffer::UpdateTexture(unsigned int textureId)
{
GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
// Copy the rendered pixels to the image
GLCheck(glBindTexture(GL_TEXTURE_2D, textureId));
GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, myWidth, myHeight));
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
}
} // namespace priv
} // namespace sf

View File

@ -1,202 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2011 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent.gom@gmail.com),
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/OSX/RenderImageImplPBuffer.hpp>
#include <SFML/Graphics/GLCheck.hpp>
#include <SFML/Window/Context.hpp>
#include <SFML/System/Err.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
RenderImageImplPBuffer::RenderImageImplPBuffer() :
myPBuffer(NULL),
myContext(NULL),
myWidth (0),
myHeight (0)
{
/* Nothing else */
}
////////////////////////////////////////////////////////////
RenderImageImplPBuffer::~RenderImageImplPBuffer()
{
if (myPBuffer && aglDestroyPBuffer(myPBuffer) == GL_FALSE) {
sf::Err()
<< "An error occurs while destroying the PBuffer in "
<< __PRETTY_FUNCTION__
<< ". The error code is "
<< aglGetError()
<< std::endl;
}
if (myContext && aglDestroyContext(myContext) == GL_FALSE) {
sf::Err()
<< "An error occurs while destroying the context in "
<< __PRETTY_FUNCTION__
<< ". The error code is "
<< aglGetError()
<< std::endl;
}
}
////////////////////////////////////////////////////////////
bool RenderImageImplPBuffer::IsSupported()
{
EnsureGlContext();
const GLubyte* strExt = glGetString(GL_EXTENSIONS);
GLboolean isSupported = gluCheckExtension((const GLubyte*)"GL_APPLE_pixel_buffer", strExt);
return isSupported;
}
////////////////////////////////////////////////////////////
bool RenderImageImplPBuffer::Create(unsigned int width, unsigned int height, unsigned int, bool depthBuffer)
{
// Store the dimensions
myWidth = width;
myHeight = height;
// Create the pixel format.
GLint attribs[] = {
AGL_RGBA,
AGL_RED_SIZE, 8,
AGL_GREEN_SIZE, 8,
AGL_BLUE_SIZE, 8,
AGL_ALPHA_SIZE, 8,
AGL_DEPTH_SIZE, (depthBuffer ? 24 : 0),
0
};
AGLPixelFormat pf = aglChoosePixelFormat(NULL, 0, attribs);
if (!pf) {
sf::Err()
<< "Couldn't create the pixel format for the PBuffer."
<< std::endl;
return false;
}
// Create the context.
myContext = aglCreateContext(pf, NULL);
if (!myContext) {
sf::Err()
<< "Couldn't create the context for the PBuffer. (Error : "
<< aglGetError()
<< ")"
<< std::endl;
return false;
}
// Create the PBuffer.
GLboolean status = aglCreatePBuffer(myWidth, myHeight, GL_TEXTURE_RECTANGLE_EXT, GL_RGBA, 0, &myPBuffer);
if (status == GL_FALSE) {
sf::Err()
<< "Couldn't create the PBuffer. (Error : "
<< aglGetError()
<< ")"
<< std::endl;
return false;
}
// Set up the PBuffer with the context.
GLint screen = aglGetVirtualScreen(myContext);
if (screen == -1) {
sf::Err()
<< "Couldn't get the virtual screen of the context used with the PBuffer. (Error : "
<< aglGetError()
<< ")"
<< std::endl;
return false;
}
status = aglSetPBuffer(myContext, myPBuffer, 0, 0, screen);
if (status == GL_FALSE) {
sf::Err()
<< "Couldn't set up the PBuffer with the context. (Error : "
<< aglGetError()
<< ")"
<< std::endl;
return false;
}
return true;
}
////////////////////////////////////////////////////////////
bool RenderImageImplPBuffer::Activate(bool active)
{
if (active)
{
if (!myContext || !myPBuffer) // Not created yet.
return false;
if (aglGetCurrentContext() == myContext)
return true;
else
return aglSetCurrentContext(myContext);
}
else
{
// To deactivate the P-Buffer's context, we actually activate
// another one so that we make sure that there is always an
// active context for subsequent graphics operations
// @todo fixme
// return Context::SetReferenceActive();
return true;
}
}
////////////////////////////////////////////////////////////
void RenderImageImplPBuffer::UpdateTexture(unsigned int textureId)
{
GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
// Copy the rendered pixels to the image
GLCheck(glBindTexture(GL_TEXTURE_2D, textureId));
GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, myWidth, myHeight));
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
}
} // namespace priv
} // namespace sf

View File

@ -1,116 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2011 Marco Antognini (antognini.marco@gmail.com),
// Laurent Gomila (laurent.gom@gmail.com),
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_RENDERIMAGEIMPLPBUFFER_HPP
#define SFML_RENDERIMAGEIMPLPBUFFER_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderImageImpl.hpp>
#include <SFML/Window/GlResource.hpp>
#include <GL/glew.h>
#include <AGL/agl.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Specialization of RenderImageImpl using AGL P-Buffers
///
////////////////////////////////////////////////////////////
class RenderImageImplPBuffer : public RenderImageImpl, GlResource
{
public :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
RenderImageImplPBuffer();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~RenderImageImplPBuffer();
////////////////////////////////////////////////////////////
/// \brief Check whether the system supports P-Buffer or not
///
/// \return True if P-Buffer render images are supported
///
////////////////////////////////////////////////////////////
static bool IsSupported();
private :
////////////////////////////////////////////////////////////
/// \brief Create the render image implementation
///
/// \param width Width of the image to render to
/// \param height Height of the image to render to
/// \param textureId OpenGL texture identifier of the target image
/// \param depthBuffer Is a depth buffer requested?
///
/// \return True if creation has been successful
///
////////////////////////////////////////////////////////////
virtual bool Create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer);
////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the render image for rendering
///
/// \param active True to activate, false to deactivate
///
/// \return True on success, false on failure
///
////////////////////////////////////////////////////////////
virtual bool Activate(bool active);
////////////////////////////////////////////////////////////
/// \brief Update the pixels of the target texture
///
/// \param textureId OpenGL identifier of the target texture
///
////////////////////////////////////////////////////////////
virtual void UpdateTexture(unsigned textureId);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
AGLPbuffer myPBuffer; ///< P-Buffer
AGLContext myContext; ///< Associated OpenGL context
unsigned int myWidth; ///< Width of the P-Buffer
unsigned int myHeight; ///< Height of the P-Buffer
};
} // namespace priv
} // namespace sf
#endif // SFML_RENDERIMAGEIMPLPBUFFER_HPP

View File

@ -27,7 +27,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderImage.hpp> #include <SFML/Graphics/RenderImage.hpp>
#include <SFML/Graphics/RenderImageImplFBO.hpp> #include <SFML/Graphics/RenderImageImplFBO.hpp>
#include <SFML/Graphics/RenderImageImplPBuffer.hpp> #include <SFML/Graphics/RenderImageImplDefault.hpp>
#include <SFML/System/Err.hpp> #include <SFML/System/Err.hpp>
@ -44,7 +44,6 @@ myRenderImage(NULL)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
RenderImage::~RenderImage() RenderImage::~RenderImage()
{ {
SetActive(false);
delete myRenderImage; delete myRenderImage;
} }
@ -52,13 +51,6 @@ RenderImage::~RenderImage()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool RenderImage::Create(unsigned int width, unsigned int height, bool depthBuffer) bool RenderImage::Create(unsigned int width, unsigned int height, bool depthBuffer)
{ {
// Make sure that render-images are supported
if (!IsAvailable())
{
Err() << "Impossible to create render image (your system doesn't support this feature)" << std::endl;
return false;
}
// Create the image // Create the image
if (!myImage.Create(width, height)) if (!myImage.Create(width, height))
{ {
@ -71,15 +63,15 @@ bool RenderImage::Create(unsigned int width, unsigned int height, bool depthBuff
// Create the implementation // Create the implementation
delete myRenderImage; delete myRenderImage;
if (priv::RenderImageImplFBO::IsSupported()) if (priv::RenderImageImplFBO::IsAvailable())
{ {
// Use FBO // Use frame-buffer object (FBO)
myRenderImage = new priv::RenderImageImplFBO; myRenderImage = new priv::RenderImageImplFBO;
} }
else if (priv::RenderImageImplPBuffer::IsSupported()) else
{ {
// Use P-Buffer // Use default implementation
myRenderImage = new priv::RenderImageImplPBuffer; myRenderImage = new priv::RenderImageImplDefault;
} }
// Initialize the render image // Initialize the render image
@ -150,14 +142,6 @@ const Image& RenderImage::GetImage() const
} }
////////////////////////////////////////////////////////////
bool RenderImage::IsAvailable()
{
return priv::RenderImageImplFBO::IsSupported() ||
priv::RenderImageImplPBuffer::IsSupported();
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool RenderImage::Activate(bool active) bool RenderImage::Activate(bool active)
{ {

View File

@ -0,0 +1,92 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderImageImplDefault.hpp>
#include <SFML/Graphics/GLCheck.hpp>
#include <SFML/Window/Context.hpp>
#include <SFML/System/Err.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
RenderImageImplDefault::RenderImageImplDefault() :
myWidth (0),
myHeight (0),
myContext(0)
{
}
////////////////////////////////////////////////////////////
RenderImageImplDefault::~RenderImageImplDefault()
{
// Destroy the context
delete myContext;
}
////////////////////////////////////////////////////////////
bool RenderImageImplDefault::Create(unsigned int width, unsigned int height, unsigned int, bool depthBuffer)
{
// Store the dimensions
myWidth = width;
myHeight = height;
// Create the in-memory OpenGL context
myContext = new Context(ContextSettings(depthBuffer ? 32 : 0, 0, 4), width, height);
return true;
}
////////////////////////////////////////////////////////////
bool RenderImageImplDefault::Activate(bool active)
{
return myContext->SetActive(active);
}
////////////////////////////////////////////////////////////
void RenderImageImplDefault::UpdateTexture(unsigned int textureId)
{
GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
// Copy the rendered pixels to the image
GLCheck(glBindTexture(GL_TEXTURE_2D, textureId));
GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, myWidth, myHeight));
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
}
} // namespace priv
} // namespace sf

View File

@ -22,17 +22,15 @@
// //
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#ifndef SFML_RENDERIMAGEIMPLPBUFFER_HPP #ifndef SFML_RENDERIMAGEIMPLDEFAULT_HPP
#define SFML_RENDERIMAGEIMPLPBUFFER_HPP #define SFML_RENDERIMAGEIMPLDEFAULT_HPP
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderImageImpl.hpp> #include <SFML/Graphics/RenderImageImpl.hpp>
#include <SFML/Window/GlResource.hpp> #include <SFML/Window/GlResource.hpp>
#include <GL/glew.h> #include <SFML/Window/Context.hpp>
#include <GL/glxew.h>
#include <X11/Xlib.h>
namespace sf namespace sf
@ -40,10 +38,11 @@ namespace sf
namespace priv namespace priv
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Specialization of RenderImageImpl using GLX P-Buffers /// \brief Default specialization of RenderImageImpl,
/// using a in-memory context
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
class RenderImageImplPBuffer : public RenderImageImpl, GlResource class RenderImageImplDefault : public RenderImageImpl, GlResource
{ {
public : public :
@ -51,21 +50,13 @@ public :
/// \brief Default constructor /// \brief Default constructor
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
RenderImageImplPBuffer(); RenderImageImplDefault();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Destructor /// \brief Destructor
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
~RenderImageImplPBuffer(); ~RenderImageImplDefault();
////////////////////////////////////////////////////////////
/// \brief Check whether the system supports P-Buffer or not
///
/// \return True if P-Buffer render images are supported
///
////////////////////////////////////////////////////////////
static bool IsSupported();
private : private :
@ -103,9 +94,7 @@ private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
::Display* myDisplay; ///< Connection to the X display Context* myContext; ///< P-Buffer based context
GLXPbuffer myPBuffer; ///< P-Buffer
GLXContext myContext; ///< Associated OpenGL context
unsigned int myWidth; ///< Width of the P-Buffer unsigned int myWidth; ///< Width of the P-Buffer
unsigned int myHeight; ///< Height of the P-Buffer unsigned int myHeight; ///< Height of the P-Buffer
}; };
@ -115,4 +104,4 @@ private :
} // namespace sf } // namespace sf
#endif // SFML_RENDERIMAGEIMPLPBUFFER_HPP #endif // SFML_RENDERIMAGEIMPLDEFAULT_HPP

View File

@ -62,11 +62,14 @@ RenderImageImplFBO::~RenderImageImplFBO()
GLuint frameBuffer = static_cast<GLuint>(myFrameBuffer); GLuint frameBuffer = static_cast<GLuint>(myFrameBuffer);
GLCheck(glDeleteFramebuffersEXT(1, &frameBuffer)); GLCheck(glDeleteFramebuffersEXT(1, &frameBuffer));
} }
// Delete the context
delete myContext;
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool RenderImageImplFBO::IsSupported() bool RenderImageImplFBO::IsAvailable()
{ {
EnsureGlContext(); EnsureGlContext();
@ -80,8 +83,8 @@ bool RenderImageImplFBO::IsSupported()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool RenderImageImplFBO::Create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer) bool RenderImageImplFBO::Create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer)
{ {
// Activate the render-image's context //Create the context
myContext.SetActive(true); myContext = new Context;
// Create the framebuffer object // Create the framebuffer object
GLuint frameBuffer = 0; GLuint frameBuffer = 0;
@ -128,9 +131,7 @@ bool RenderImageImplFBO::Create(unsigned int width, unsigned int height, unsigne
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool RenderImageImplFBO::Activate(bool active) bool RenderImageImplFBO::Activate(bool active)
{ {
myContext.SetActive(active); return myContext->SetActive(active);
return true;
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -64,7 +64,7 @@ public :
/// \return True if FBO render images are supported /// \return True if FBO render images are supported
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
static bool IsSupported(); static bool IsAvailable();
private : private :
@ -102,9 +102,9 @@ private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Context* myContext; ///< Needs a separate OpenGL context for not messing up the other ones
unsigned int myFrameBuffer; ///< OpenGL frame buffer object unsigned int myFrameBuffer; ///< OpenGL frame buffer object
unsigned int myDepthBuffer; ///< Optional depth buffer attached to the frame buffer unsigned int myDepthBuffer; ///< Optional depth buffer attached to the frame buffer
Context myContext; ///< Needs a separate OpenGL context for not messing up the other ones
}; };
} // namespace priv } // namespace priv

View File

@ -1,44 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#if defined(SFML_SYSTEM_WINDOWS)
#include <SFML/Graphics/Win32/RenderImageImplPBuffer.hpp>
#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD)
#include <SFML/Graphics/Linux/RenderImageImplPBuffer.hpp>
#elif defined(SFML_SYSTEM_MACOS)
#include <SFML/Graphics/OSX/RenderImageImplPBuffer.hpp>
#endif

View File

@ -1,196 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Win32/RenderImageImplPBuffer.hpp>
#include <SFML/Graphics/GLCheck.hpp>
#include <SFML/Window/Context.hpp>
#include <SFML/System/Err.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
RenderImageImplPBuffer::RenderImageImplPBuffer() :
myPBuffer (NULL),
myDeviceContext(NULL),
myContext (NULL),
myWidth (0),
myHeight (0)
{
}
////////////////////////////////////////////////////////////
RenderImageImplPBuffer::~RenderImageImplPBuffer()
{
EnsureGlContext();
if (myContext)
wglDeleteContext(myContext);
if (myPBuffer && myDeviceContext)
{
wglReleasePbufferDCARB(myPBuffer, myDeviceContext);
wglDestroyPbufferARB(myPBuffer);
}
}
////////////////////////////////////////////////////////////
bool RenderImageImplPBuffer::IsSupported()
{
EnsureGlContext();
// Make sure that GLEW is initialized
priv::EnsureGlewInit();
return WGLEW_ARB_pbuffer && WGLEW_ARB_pixel_format;
}
////////////////////////////////////////////////////////////
bool RenderImageImplPBuffer::Create(unsigned int width, unsigned int height, unsigned int, bool depthBuffer)
{
// Store the dimensions
myWidth = width;
myHeight = height;
// Get the current HDC
HDC currentDC = wglGetCurrentDC();
// Define the minimum PBuffer attributes
int attributes[] =
{
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
WGL_DRAW_TO_PBUFFER_ARB, GL_TRUE,
WGL_RED_BITS_ARB, 8,
WGL_GREEN_BITS_ARB, 8,
WGL_BLUE_BITS_ARB, 8,
WGL_ALPHA_BITS_ARB, 8,
WGL_DEPTH_BITS_ARB, (depthBuffer ? 24 : 0),
WGL_DOUBLE_BUFFER_ARB, GL_FALSE,
0
};
// Select the best pixel format for our attributes
unsigned int nbFormats = 0;
int pixelFormat = -1;
wglChoosePixelFormatARB(currentDC, attributes, NULL, 1, &pixelFormat, &nbFormats);
// Make sure that one pixel format has been found
if (nbFormats == 0)
{
Err() << "Impossible to create render image (failed to find a suitable pixel format for PBuffer)" << std::endl;
return false;
}
// Create the P-Buffer and its OpenGL context
myPBuffer = wglCreatePbufferARB(currentDC, pixelFormat, width, height, NULL);
myDeviceContext = wglGetPbufferDCARB(myPBuffer);
myContext = wglCreateContext(myDeviceContext);
// Check errors
if (!myPBuffer || !myDeviceContext || !myContext)
{
Err() << "Impossible to create render image (failed to create PBuffer)" << std::endl;
return false;
}
// Check the actual size of the P-Buffer
int actualWidth, actualHeight;
wglQueryPbufferARB(myPBuffer, WGL_PBUFFER_WIDTH_ARB, &actualWidth);
wglQueryPbufferARB(myPBuffer, WGL_PBUFFER_HEIGHT_ARB, &actualHeight);
if ((actualWidth != static_cast<int>(width)) || (actualHeight != static_cast<int>(height)))
{
Err() << "Impossible to create render image (failed to match the requested size). "
<< "Size: " << actualWidth << "x" << actualHeight << " - "
<< "Requested: " << width << "x" << height
<< std::endl;
return false;
}
// Share the P-Buffer context with the current context
HGLRC currentContext = wglGetCurrentContext();
if (currentContext)
{
wglMakeCurrent(NULL, NULL);
wglShareLists(currentContext, myContext);
wglMakeCurrent(currentDC, currentContext);
}
return true;
}
////////////////////////////////////////////////////////////
bool RenderImageImplPBuffer::Activate(bool active)
{
if (active)
{
if (myDeviceContext && myContext)
{
if (wglGetCurrentContext() != myContext)
return wglMakeCurrent(myDeviceContext, myContext) != 0;
else
return true;
}
else
{
return false;
}
}
else
{
// To deactivate the P-Buffer's context, we actually activate
// another one so that we make sure that there is always an
// active context for subsequent graphics operations
// @todo fix
//return Context::SetReferenceActive();
return true;
}
}
////////////////////////////////////////////////////////////
void RenderImageImplPBuffer::UpdateTexture(unsigned int textureId)
{
GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
// Copy the rendered pixels to the image
GLCheck(glBindTexture(GL_TEXTURE_2D, textureId));
GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, myWidth, myHeight));
GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
}
} // namespace priv
} // namespace sf

View File

@ -1,117 +0,0 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_RENDERIMAGEIMPLPBUFFER_HPP
#define SFML_RENDERIMAGEIMPLPBUFFER_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderImageImpl.hpp>
#include <SFML/Window/GlResource.hpp>
#include <GL/glew.h>
#include <GL/wglew.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Specialization of RenderImageImpl using WGL P-Buffers
///
////////////////////////////////////////////////////////////
class RenderImageImplPBuffer : public RenderImageImpl, GlResource
{
public :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
RenderImageImplPBuffer();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~RenderImageImplPBuffer();
////////////////////////////////////////////////////////////
/// \brief Check whether the system supports P-Buffer or not
///
/// \return True if P-Buffer render images are supported
///
////////////////////////////////////////////////////////////
static bool IsSupported();
private :
////////////////////////////////////////////////////////////
/// \brief Create the render image implementation
///
/// \param width Width of the image to render to
/// \param height Height of the image to render to
/// \param textureId OpenGL texture identifier of the target image
/// \param depthBuffer Is a depth buffer requested?
///
/// \return True if creation has been successful
///
////////////////////////////////////////////////////////////
virtual bool Create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer);
////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the render image for rendering
///
/// \param active True to activate, false to deactivate
///
/// \return True on success, false on failure
///
////////////////////////////////////////////////////////////
virtual bool Activate(bool active);
////////////////////////////////////////////////////////////
/// \brief Update the pixels of the target texture
///
/// \param textureId OpenGL identifier of the target texture
///
////////////////////////////////////////////////////////////
virtual void UpdateTexture(unsigned textureId);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
HPBUFFERARB myPBuffer; ///< P-Buffer
HDC myDeviceContext; ///< Associated device context
HGLRC myContext; ///< Associated OpenGL context
unsigned int myWidth; ///< Width of the P-Buffer
unsigned int myHeight; ///< Height of the P-Buffer
};
} // namespace priv
} // namespace sf
#endif // SFML_RENDERIMAGEIMPLPBUFFER_HPP

View File

@ -42,16 +42,22 @@ Context::Context()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Context::~Context() Context::~Context()
{ {
SetActive(false);
delete myContext; delete myContext;
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Context::SetActive(bool active) bool Context::SetActive(bool active)
{ {
myContext->SetActive(active); return myContext->SetActive(active);
} }
////////////////////////////////////////////////////////////
Context::Context(const ContextSettings& settings, unsigned int width, unsigned int height)
{
myContext = priv::GlContext::New(settings, width, height);
SetActive(true);
}
} // namespace sf } // namespace sf

View File

@ -129,18 +129,38 @@ void GlContext::EnsureContext()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
GlContext* GlContext::New() GlContext* GlContext::New()
{ {
// Make sure that there's an active context (context creation may need extensions, and thus a valid context)
EnsureContext();
return new ContextType(sharedContext); return new ContextType(sharedContext);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
GlContext* GlContext::New(const WindowImpl* owner, unsigned int bitsPerPixel, const ContextSettings& settings) GlContext* GlContext::New(const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel)
{ {
// Make sure that there's an active context (context creation may need extensions, and thus a valid context) // Make sure that there's an active context (context creation may need extensions, and thus a valid context)
EnsureContext(); EnsureContext();
// Create the context // Create the context
GlContext* context = new ContextType(sharedContext, owner, bitsPerPixel, settings); GlContext* context = new ContextType(sharedContext, settings, owner, bitsPerPixel);
// Enable antialiasing if needed
if (context->GetSettings().AntialiasingLevel > 0)
glEnable(GL_MULTISAMPLE_ARB);
return context;
}
////////////////////////////////////////////////////////////
GlContext* GlContext::New(const ContextSettings& settings, unsigned int width, unsigned int height)
{
// Make sure that there's an active context (context creation may need extensions, and thus a valid context)
EnsureContext();
// Create the context
GlContext* context = new ContextType(sharedContext, settings, width, height);
// Enable antialiasing if needed // Enable antialiasing if needed
if (context->GetSettings().AntialiasingLevel > 0) if (context->GetSettings().AntialiasingLevel > 0)

View File

@ -94,14 +94,29 @@ public :
/// This function automatically chooses the specialized class /// This function automatically chooses the specialized class
/// to use according to the OS. /// to use according to the OS.
/// ///
/// \param settings Creation parameters
/// \param owner Pointer to the owner window /// \param owner Pointer to the owner window
/// \param bitsPerPixel Pixel depth (in bits per pixel) /// \param bitsPerPixel Pixel depth (in bits per pixel)
/// \param settings Creation parameters
/// ///
/// \return Pointer to the created context (don't forget to delete it) /// \return Pointer to the created context
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
static GlContext* New(const WindowImpl* owner, unsigned int bitsPerPixel, const ContextSettings& settings); static GlContext* New(const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel);
////////////////////////////////////////////////////////////
/// \brief Create a new context that embeds its own rendering target
///
/// This function automatically chooses the specialized class
/// to use according to the OS.
///
/// \param settings Creation parameters
/// \param width Back buffer width
/// \param height Back buffer height
///
/// \return Pointer to the created context
///
////////////////////////////////////////////////////////////
static GlContext* New(const ContextSettings& settings, unsigned int width, unsigned int height);
public : public :

View File

@ -59,7 +59,7 @@ myOwnsWindow(true)
0, NULL); 0, NULL);
// Create the context // Create the context
CreateContext(shared, VideoMode::GetDesktopMode().BitsPerPixel, ContextSettings(0, 0, 0)); CreateContext(shared, VideoMode::GetDesktopMode().BitsPerPixel, ContextSettings());
// Activate the context // Activate the context
SetActive(true); SetActive(true);
@ -67,7 +67,7 @@ myOwnsWindow(true)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
GlxContext::GlxContext(GlxContext* shared, const WindowImpl* owner, unsigned int bitsPerPixel, const ContextSettings& settings) : GlxContext::GlxContext(GlxContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel) :
myWindow (0), myWindow (0),
myContext (NULL), myContext (NULL),
myOwnsWindow(false) myOwnsWindow(false)
@ -87,6 +87,35 @@ myOwnsWindow(false)
} }
////////////////////////////////////////////////////////////
GlxContext::GlxContext(GlxContext* shared, const ContextSettings& settings, unsigned int width, unsigned int height) :
myWindow (NULL),
myContext (NULL),
myOwnsWindow(true)
{
// Open a connection with the X server
myDisplay = XOpenDisplay(NULL);
// Create the hidden window
int screen = DefaultScreen(myDisplay);
myWindow = XCreateWindow(myDisplay,
RootWindow(myDisplay, screen),
0, 0,
width, height,
0,
DefaultDepth(myDisplay, screen),
InputOutput,
DefaultVisual(myDisplay, screen),
0, NULL);
// Create the context
CreateContext(shared, VideoMode::GetDesktopMode().BitsPerPixel, ContextSettings());
// Activate the context
SetActive(true);
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
GlxContext::~GlxContext() GlxContext::~GlxContext()
{ {
@ -107,9 +136,7 @@ GlxContext::~GlxContext()
// Close the connection with the X server // Close the connection with the X server
if (myOwnsWindow) if (myOwnsWindow)
{
XCloseDisplay(myDisplay); XCloseDisplay(myDisplay);
}
} }

View File

@ -46,7 +46,7 @@ class GlxContext : public GlContext
public : public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Create a new context, not associated to a window /// \brief Create a new default context
/// ///
/// \param shared Context to share the new one with (can be NULL) /// \param shared Context to share the new one with (can be NULL)
/// ///
@ -56,13 +56,24 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Create a new context attached to a window /// \brief Create a new context attached to a window
/// ///
/// \param shared Context to share the new one with (can be NULL) /// \param shared Context to share the new one with
/// \param owner Pointer to the owner window
/// \param bitsPerPixel Pixel depth (in bits per pixel)
/// \param settings Creation parameters /// \param settings Creation parameters
/// \param owner Pointer to the owner window
/// \param bitsPerPixel Pixel depth, in bits per pixel
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
GlxContext(GlxContext* shared, const WindowImpl* owner, unsigned int bitsPerPixel, const ContextSettings& settings); GlxContext(GlxContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel);
////////////////////////////////////////////////////////////
/// \brief Create a new context that embeds its own rendering target
///
/// \param shared Context to share the new one with
/// \param settings Creation parameters
/// \param width Back buffer width, in pixels
/// \param height Back buffer height, in pixels
///
////////////////////////////////////////////////////////////
GlxContext(GlxContext* shared, const ContextSettings& settings, unsigned int width, unsigned int height);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Destructor /// \brief Destructor

View File

@ -27,7 +27,6 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Window/Win32/WglContext.hpp> #include <SFML/Window/Win32/WglContext.hpp>
#include <SFML/Window/WindowImpl.hpp> #include <SFML/Window/WindowImpl.hpp>
#include <SFML/OpenGL.hpp>
#include <SFML/Window/glext/wglext.h> #include <SFML/Window/glext/wglext.h>
#include <SFML/System/Lock.hpp> #include <SFML/System/Lock.hpp>
#include <SFML/System/Mutex.hpp> #include <SFML/System/Mutex.hpp>
@ -56,7 +55,7 @@ myOwnsWindow (true)
// Create the context // Create the context
if (myDeviceContext) if (myDeviceContext)
CreateContext(shared, VideoMode::GetDesktopMode().BitsPerPixel, ContextSettings(0, 0, 0)); CreateContext(shared, VideoMode::GetDesktopMode().BitsPerPixel, ContextSettings());
// Activate the context // Activate the context
SetActive(true); SetActive(true);
@ -64,7 +63,7 @@ myOwnsWindow (true)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WglContext::WglContext(WglContext* shared, const WindowImpl* owner, unsigned int bitsPerPixel, const ContextSettings& settings) : WglContext::WglContext(WglContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel) :
myWindow (NULL), myWindow (NULL),
myDeviceContext(NULL), myDeviceContext(NULL),
myContext (NULL), myContext (NULL),
@ -83,6 +82,32 @@ myOwnsWindow (false)
} }
////////////////////////////////////////////////////////////
WglContext::WglContext(WglContext* shared, const ContextSettings& settings, unsigned int width, unsigned int height) :
myWindow (NULL),
myDeviceContext(NULL),
myContext (NULL),
myOwnsWindow (true)
{
// The target of the context is a hidden window.
// We can't create a memory DC (the resulting context wouldn't be compatible
// with other contexts), and we don't add the extra complexity of P-Buffers;
// we can still support them in the future if this solution is not good enough.
// Create the hidden window
myWindow = CreateWindowA("STATIC", "", WS_POPUP | WS_DISABLED, 0, 0, width, height, NULL, NULL, GetModuleHandle(NULL), NULL);
ShowWindow(myWindow, SW_HIDE);
myDeviceContext = GetDC(myWindow);
// Create the context
if (myDeviceContext)
CreateContext(shared, VideoMode::GetDesktopMode().BitsPerPixel, settings);
// Activate the context
SetActive(true);
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WglContext::~WglContext() WglContext::~WglContext()
{ {
@ -94,8 +119,8 @@ WglContext::~WglContext()
wglDeleteContext(myContext); wglDeleteContext(myContext);
} }
// Release the DC // Destroy the device context
if (myWindow && myDeviceContext) if (myDeviceContext)
ReleaseDC(myWindow, myDeviceContext); ReleaseDC(myWindow, myDeviceContext);
// Destroy the window if we own it // Destroy the window if we own it

View File

@ -29,7 +29,7 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Window/GlContext.hpp> #include <SFML/Window/GlContext.hpp>
#include <windows.h> #include <SFML/OpenGL.hpp>
namespace sf namespace sf
@ -45,7 +45,7 @@ class WglContext : public GlContext
public : public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Create a new context, not associated to a window /// \brief Create a new default context
/// ///
/// \param shared Context to share the new one with (can be NULL) /// \param shared Context to share the new one with (can be NULL)
/// ///
@ -55,13 +55,24 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Create a new context attached to a window /// \brief Create a new context attached to a window
/// ///
/// \param shared Context to share the new one with (can be NULL) /// \param shared Context to share the new one with
/// \param owner Pointer to the owner window
/// \param bitsPerPixel Pixel depth (in bits per pixel)
/// \param settings Creation parameters /// \param settings Creation parameters
/// \param owner Pointer to the owner window
/// \param bitsPerPixel Pixel depth, in bits per pixel
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WglContext(WglContext* shared, const WindowImpl* owner, unsigned int bitsPerPixel, const ContextSettings& settings); WglContext(WglContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel);
////////////////////////////////////////////////////////////
/// \brief Create a new context that embeds its own rendering target
///
/// \param shared Context to share the new one with
/// \param settings Creation parameters
/// \param width Back buffer width, in pixels
/// \param height Back buffer height, in pixels
///
////////////////////////////////////////////////////////////
WglContext(WglContext* shared, const ContextSettings& settings, unsigned int width, unsigned int height);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Destructor /// \brief Destructor
@ -113,9 +124,9 @@ private :
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
HWND myWindow; ///< Window to which the context is attached HWND myWindow; ///< Window to which the context is attached
HDC myDeviceContext; ///< Device context of the window HDC myDeviceContext; ///< Device context associated to the context
HGLRC myContext; ///< OpenGL context HGLRC myContext; ///< OpenGL context
bool myOwnsWindow; ///< Did we create the host window? bool myOwnsWindow; ///< Do we own the target window?
}; };
} // namespace priv } // namespace priv

View File

@ -126,7 +126,7 @@ void Window::Create(VideoMode mode, const std::string& title, unsigned long styl
myWindow = priv::WindowImpl::New(mode, title, style); myWindow = priv::WindowImpl::New(mode, title, style);
// Recreate the context // Recreate the context
myContext = priv::GlContext::New(myWindow, mode.BitsPerPixel, settings); myContext = priv::GlContext::New(settings, myWindow, mode.BitsPerPixel);
// Perform common initializations // Perform common initializations
Initialize(); Initialize();
@ -143,7 +143,7 @@ void Window::Create(WindowHandle handle, const ContextSettings& settings)
myWindow = priv::WindowImpl::New(handle); myWindow = priv::WindowImpl::New(handle);
// Recreate the context // Recreate the context
myContext = priv::GlContext::New(myWindow, VideoMode::GetDesktopMode().BitsPerPixel, settings); myContext = priv::GlContext::New(settings, myWindow, VideoMode::GetDesktopMode().BitsPerPixel);
// Perform common initializations // Perform common initializations
Initialize(); Initialize();