git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/branches/sfml2@1809 4e206d99-4929-0410-ac5d-dfc041789085
This commit is contained in:
laurentgom 2011-03-21 07:08:26 +00:00
parent 6cf2303484
commit a94ed51702
25 changed files with 496 additions and 229 deletions

View File

@ -130,16 +130,16 @@ int main()
ShaderSelector globalShader(shaders, "nothing"); ShaderSelector globalShader(shaders, "nothing");
// Do specific initializations // Do specific initializations
shaders["nothing"].SetTexture("texture", sf::Shader::CurrentTexture); shaders["nothing"].SetCurrentTexture("texture");
shaders["blur"].SetTexture("texture", sf::Shader::CurrentTexture); shaders["blur"].SetCurrentTexture("texture");
shaders["blur"].SetParameter("offset", 0.f); shaders["blur"].SetParameter("offset", 0.f);
shaders["colorize"].SetTexture("texture", sf::Shader::CurrentTexture); shaders["colorize"].SetCurrentTexture("texture");
shaders["colorize"].SetParameter("color", 1.f, 1.f, 1.f); shaders["colorize"].SetParameter("color", 1.f, 1.f, 1.f);
shaders["edge"].SetTexture("texture", sf::Shader::CurrentTexture); shaders["edge"].SetCurrentTexture("texture");
shaders["fisheye"].SetTexture("texture", sf::Shader::CurrentTexture); shaders["fisheye"].SetCurrentTexture("texture");
shaders["wave"].SetTexture("texture", sf::Shader::CurrentTexture); shaders["wave"].SetCurrentTexture("texture");
shaders["wave"].SetTexture("wave", waveImage); shaders["wave"].SetTexture("wave", waveImage);
shaders["pixelate"].SetTexture("texture", sf::Shader::CurrentTexture); shaders["pixelate"].SetCurrentTexture("texture");
// Define a string for displaying the description of the current shader // Define a string for displaying the description of the current shader
sf::Text shaderStr; sf::Text shaderStr;

View File

@ -29,6 +29,7 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/System/Resource.hpp> #include <SFML/System/Resource.hpp>
#include <SFML/Window/GlResource.hpp>
#include <SFML/Graphics/Color.hpp> #include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/Rect.hpp> #include <SFML/Graphics/Rect.hpp>
#include <string> #include <string>
@ -45,7 +46,7 @@ class RenderWindow;
/// \brief Class for loading, manipulating and saving images /// \brief Class for loading, manipulating and saving images
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
class SFML_API Image : public Resource<Image> class SFML_API Image : public Resource<Image>, GlResource
{ {
public : public :

View File

@ -30,6 +30,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Config.hpp> #include <SFML/Config.hpp>
#include <SFML/System/NonCopyable.hpp> #include <SFML/System/NonCopyable.hpp>
#include <SFML/Window/GlResource.hpp>
#include <SFML/Graphics/Color.hpp> #include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/Drawable.hpp> #include <SFML/Graphics/Drawable.hpp>
#include <SFML/Graphics/Matrix3.hpp> #include <SFML/Graphics/Matrix3.hpp>
@ -44,7 +45,7 @@ class Shader;
/// \brief Handles the low-level rendering (states and geometry) /// \brief Handles the low-level rendering (states and geometry)
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
class SFML_API Renderer : NonCopyable class SFML_API Renderer : GlResource, NonCopyable
{ {
public : public :

View File

@ -30,6 +30,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Config.hpp> #include <SFML/Config.hpp>
#include <SFML/Graphics/Image.hpp> #include <SFML/Graphics/Image.hpp>
#include <SFML/Window/GlResource.hpp>
#include <SFML/System/Vector2.hpp> #include <SFML/System/Vector2.hpp>
#include <SFML/System/Vector3.hpp> #include <SFML/System/Vector3.hpp>
#include <map> #include <map>
@ -44,7 +45,7 @@ class Renderer;
/// \brief Pixel/fragment shader class /// \brief Pixel/fragment shader class
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
class SFML_API Shader class SFML_API Shader : GlResource
{ {
public : public :
@ -120,7 +121,7 @@ public :
/// \param name Name of the parameter in the shader /// \param name Name of the parameter in the shader
/// \param x Value to assign /// \param x Value to assign
/// ///
/// \see SetTexture /// \see SetTexture, SetCurrentTexture
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void SetParameter(const std::string& name, float x); void SetParameter(const std::string& name, float x);
@ -141,7 +142,7 @@ public :
/// \param x First component of the value to assign /// \param x First component of the value to assign
/// \param y Second component of the value to assign /// \param y Second component of the value to assign
/// ///
/// \see SetTexture /// \see SetTexture, SetCurrentTexture
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void SetParameter(const std::string& name, float x, float y); void SetParameter(const std::string& name, float x, float y);
@ -163,7 +164,7 @@ public :
/// \param y Second component of the value to assign /// \param y Second component of the value to assign
/// \param z Third component of the value to assign /// \param z Third component of the value to assign
/// ///
/// \see SetTexture /// \see SetTexture, SetCurrentTexture
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void SetParameter(const std::string& name, float x, float y, float z); void SetParameter(const std::string& name, float x, float y, float z);
@ -186,7 +187,7 @@ public :
/// \param z Third component of the value to assign /// \param z Third component of the value to assign
/// \param w Fourth component of the value to assign /// \param w Fourth component of the value to assign
/// ///
/// \see SetTexture /// \see SetTexture, SetCurrentTexture
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void SetParameter(const std::string& name, float x, float y, float z, float w); void SetParameter(const std::string& name, float x, float y, float z, float w);
@ -206,7 +207,7 @@ public :
/// \param name Name of the parameter in the shader /// \param name Name of the parameter in the shader
/// \param vector Vector to assign /// \param vector Vector to assign
/// ///
/// \see SetTexture /// \see SetTexture, SetCurrentTexture
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void SetParameter(const std::string& name, const Vector2f& vector); void SetParameter(const std::string& name, const Vector2f& vector);
@ -226,7 +227,7 @@ public :
/// \param name Name of the parameter in the shader /// \param name Name of the parameter in the shader
/// \param vector Vector to assign /// \param vector Vector to assign
/// ///
/// \see SetTexture /// \see SetTexture, SetCurrentTexture
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void SetParameter(const std::string& name, const Vector3f& vector); void SetParameter(const std::string& name, const Vector3f& vector);
@ -235,19 +236,18 @@ public :
/// \brief Change a texture parameter of the shader /// \brief Change a texture parameter of the shader
/// ///
/// \a name is the name of the texture to change in the shader. /// \a name is the name of the texture to change in the shader.
/// To tell the shader to use the current texture of the object being /// This function maps an external image to the texture variable;
/// drawn, pass Shader::CurrentTexture. /// to use the current texture of the object being drawn, use
/// SetCurrentTexture instead.
/// Example: /// Example:
/// \code /// \code
/// // These are the variables in the pixel shader /// // These are the variables in the pixel shader
/// uniform sampler2D current; /// uniform sampler2D texture;
/// uniform sampler2D other;
/// \endcode /// \endcode
/// \code /// \code
/// sf::Image image; /// sf::Image image;
/// ... /// ...
/// shader.SetParameter("current", sf::Shader::CurrentTexture); /// shader.SetTexture("texture", image);
/// shader.SetParameter("other", image);
/// \endcode /// \endcode
/// It is important to note that \a texture must remain alive as long /// It is important to note that \a texture must remain alive as long
/// as the shader uses it, no copy is made internally. /// as the shader uses it, no copy is made internally.
@ -255,11 +255,32 @@ public :
/// \param name Name of the texture in the shader /// \param name Name of the texture in the shader
/// \param texture Image to assign /// \param texture Image to assign
/// ///
/// \see SetParameter /// \see SetParameter, SetCurrentTexture
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void SetTexture(const std::string& name, const Image& texture); void SetTexture(const std::string& name, const Image& texture);
////////////////////////////////////////////////////////////
/// \brief Set the current object texture in the shader
///
/// This function maps a shader texture variable to the
/// image of the object being drawn.
/// Example:
/// \code
/// // This is the variable in the pixel shader
/// uniform sampler2D current;
/// \endcode
/// \code
/// shader.SetCurrentTexture("current");
/// \endcode
///
/// \param name Name of the texture in the shader
///
/// \see SetParameter, SetTexture
///
////////////////////////////////////////////////////////////
void SetCurrentTexture(const std::string& name);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Bind the shader for rendering (activate it) /// \brief Bind the shader for rendering (activate it)
/// ///
@ -312,11 +333,6 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
static bool IsAvailable(); static bool IsAvailable();
////////////////////////////////////////////////////////////
// Static member data
////////////////////////////////////////////////////////////
static const Image CurrentTexture; ///< Special image representing the texture used by the object being drawn
private : private :
friend class Renderer; friend class Renderer;
@ -394,12 +410,12 @@ private :
/// \code /// \code
/// shader.SetParameter("offset", 2.f); /// shader.SetParameter("offset", 2.f);
/// shader.SetParameter("color", 0.5f, 0.8f, 0.3f); /// shader.SetParameter("color", 0.5f, 0.8f, 0.3f);
/// shader.SetTexture("image", image); // image is a sf::Image /// shader.SetTexture("overlay", image); // image is a sf::Image
/// shader.SetTexture("current", sf::Shader::CurrentTexture); /// shader.SetCurrentTexture("texture");
/// \endcode /// \endcode
/// ///
/// Shader::CurrentTexture is a special value that represents /// Shader::SetCurrentTexture maps the given texture variable
/// the texture that the object being drawn is using. /// to the current texture of the object being drawn.
/// ///
/// To apply a shader to a drawable, you must pass it as an /// To apply a shader to a drawable, you must pass it as an
/// additional parameter to the Draw function: /// additional parameter to the Draw function:

View File

@ -29,6 +29,7 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Config.hpp> #include <SFML/Config.hpp>
#include <SFML/Window/GlResource.hpp>
#include <SFML/System/NonCopyable.hpp> #include <SFML/System/NonCopyable.hpp>
@ -43,7 +44,7 @@ namespace priv
/// \brief Class holding a valid drawing context /// \brief Class holding a valid drawing context
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
class SFML_API Context : NonCopyable class SFML_API Context : GlResource, NonCopyable
{ {
public : public :
@ -71,18 +72,6 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void SetActive(bool active); void SetActive(bool active);
////////////////////////////////////////////////////////////
/// \brief Make the current thread's reference context active
///
/// This function is meant to be called internally; it is used
/// to deactivate the current context by activating another one
/// (so that we still have an active context on the current thread).
///
/// \return True if operation was successful, false otherwise
///
////////////////////////////////////////////////////////////
static bool SetReferenceActive();
private : private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -0,0 +1,72 @@
////////////////////////////////////////////////////////////
//
// 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_GLRESOURCE_HPP
#define SFML_GLRESOURCE_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Base class for classes that require an OpenGL context
///
////////////////////////////////////////////////////////////
class SFML_API GlResource
{
protected :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
GlResource();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~GlResource();
static void EnsureGlContext();
};
} // namespace sf
#endif // SFML_GLRESOURCE_HPP
////////////////////////////////////////////////////////////
/// \class sf::GlResource
/// \ingroup window
///
/// This class is for internal use only, it must be the base
/// of every class that requires a valid OpenGL context in
/// order to work.
///
////////////////////////////////////////////////////////////

View File

@ -33,6 +33,7 @@
#include <SFML/Window/VideoMode.hpp> #include <SFML/Window/VideoMode.hpp>
#include <SFML/Window/WindowHandle.hpp> #include <SFML/Window/WindowHandle.hpp>
#include <SFML/Window/WindowStyle.hpp> #include <SFML/Window/WindowStyle.hpp>
#include <SFML/Window/GlResource.hpp>
#include <SFML/System/Clock.hpp> #include <SFML/System/Clock.hpp>
#include <SFML/System/NonCopyable.hpp> #include <SFML/System/NonCopyable.hpp>
#include <string> #include <string>
@ -52,7 +53,7 @@ class Event;
/// \brief Window that serves as a target for OpenGL rendering /// \brief Window that serves as a target for OpenGL rendering
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
class SFML_API Window : NonCopyable class SFML_API Window : GlResource, NonCopyable
{ {
public : public :

View File

@ -84,6 +84,8 @@ Image::~Image()
// Destroy the OpenGL texture // Destroy the OpenGL texture
if (myTexture) if (myTexture)
{ {
EnsureGlContext();
GLuint Texture = static_cast<GLuint>(myTexture); GLuint Texture = static_cast<GLuint>(myTexture);
GLCheck(glDeleteTextures(1, &Texture)); GLCheck(glDeleteTextures(1, &Texture));
} }
@ -410,6 +412,8 @@ void Image::UpdatePixels(const Uint8* pixels)
{ {
if (pixels && myTexture) if (pixels && myTexture)
{ {
EnsureGlContext();
GLint previous; GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous)); GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
@ -468,6 +472,8 @@ void Image::SetSmooth(bool smooth)
if (myTexture) if (myTexture)
{ {
EnsureGlContext();
GLint previous; GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous)); GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
@ -535,6 +541,8 @@ FloatRect Image::GetTexCoords(const IntRect& rect) const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
unsigned int Image::GetMaximumSize() unsigned int Image::GetMaximumSize()
{ {
EnsureGlContext();
GLint size; GLint size;
GLCheck(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size)); GLCheck(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size));
@ -565,6 +573,8 @@ Image& Image::operator =(const Image& right)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
unsigned int Image::GetValidSize(unsigned int size) unsigned int Image::GetValidSize(unsigned int size)
{ {
EnsureGlContext();
// Make sure that GLEW is initialized // Make sure that GLEW is initialized
priv::EnsureGlewInit(); priv::EnsureGlewInit();
@ -613,6 +623,8 @@ bool Image::CreateTexture(unsigned int width, unsigned int height)
myTextureWidth = textureWidth; myTextureWidth = textureWidth;
myTextureHeight = textureHeight; myTextureHeight = textureHeight;
EnsureGlContext();
// Create the OpenGL texture if it doesn't exist yet // Create the OpenGL texture if it doesn't exist yet
if (!myTexture) if (!myTexture)
{ {
@ -645,6 +657,8 @@ void Image::EnsureTextureUpdate() const
{ {
if (myTexture && !myPixels.empty()) if (myTexture && !myPixels.empty())
{ {
EnsureGlContext();
GLint previous; GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous)); GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
@ -666,6 +680,8 @@ void Image::EnsureArrayUpdate() const
{ {
if (!myArrayUpdated) if (!myArrayUpdated)
{ {
EnsureGlContext();
// Save the previous texture // Save the previous texture
GLint previous; GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous)); GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));

View File

@ -49,6 +49,8 @@ myHeight (0)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
RenderImageImplPBuffer::~RenderImageImplPBuffer() RenderImageImplPBuffer::~RenderImageImplPBuffer()
{ {
EnsureGlContext();
if (myContext) if (myContext)
glXDestroyContext(myDisplay, myContext); glXDestroyContext(myDisplay, myContext);
@ -56,20 +58,18 @@ RenderImageImplPBuffer::~RenderImageImplPBuffer()
glXDestroyGLXPbufferSGIX(myDisplay, myPBuffer); glXDestroyGLXPbufferSGIX(myDisplay, myPBuffer);
XCloseDisplay(myDisplay); XCloseDisplay(myDisplay);
// This is to make sure that another valid context is made
// active after we destroy the P-Buffer's one
Context::SetReferenceActive();
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool RenderImageImplPBuffer::IsSupported() bool RenderImageImplPBuffer::IsSupported()
{ {
EnsureGlContext();
// Make sure that GLEW is initialized // Make sure that GLEW is initialized
EnsureGlewInit(); EnsureGlewInit();
return glxewIsSupported("GLX_SGIX_pbuffer"); return GLXEW_SGIX_pbuffer && GLXEW_SGIX_fbconfig;
} }
@ -182,7 +182,9 @@ bool RenderImageImplPBuffer::Activate(bool active)
// To deactivate the P-Buffer's context, we actually activate // To deactivate the P-Buffer's context, we actually activate
// another one so that we make sure that there is always an // another one so that we make sure that there is always an
// active context for subsequent graphics operations // active context for subsequent graphics operations
return Context::SetReferenceActive(); // @odo fixme
//return Context::SetReferenceActive();
return true;
} }
} }
@ -190,8 +192,6 @@ bool RenderImageImplPBuffer::Activate(bool active)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void RenderImageImplPBuffer::UpdateTexture(unsigned int textureId) void RenderImageImplPBuffer::UpdateTexture(unsigned int textureId)
{ {
if (Activate(true))
{
GLint previous; GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous)); GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
@ -200,7 +200,6 @@ void RenderImageImplPBuffer::UpdateTexture(unsigned int textureId)
GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, myWidth, myHeight)); GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, myWidth, myHeight));
GLCheck(glBindTexture(GL_TEXTURE_2D, previous)); GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
}
} }
} // namespace priv } // namespace priv

View File

@ -29,6 +29,7 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderImageImpl.hpp> #include <SFML/Graphics/RenderImageImpl.hpp>
#include <SFML/Window/GlResource.hpp>
#include <GL/glew.h> #include <GL/glew.h>
#include <GL/glxew.h> #include <GL/glxew.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
@ -42,7 +43,7 @@ namespace priv
/// \brief Specialization of RenderImageImpl using GLX P-Buffers /// \brief Specialization of RenderImageImpl using GLX P-Buffers
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
class RenderImageImplPBuffer : public RenderImageImpl class RenderImageImplPBuffer : public RenderImageImpl, GlResource
{ {
public : public :

View File

@ -66,16 +66,14 @@ RenderImageImplPBuffer::~RenderImageImplPBuffer()
<< aglGetError() << aglGetError()
<< std::endl; << std::endl;
} }
// This is to make sure that another valid context is made
// active after we destroy the P-Buffer's one
Context::SetReferenceActive();
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool RenderImageImplPBuffer::IsSupported() bool RenderImageImplPBuffer::IsSupported()
{ {
EnsureGlContext();
const GLubyte* strExt = glGetString(GL_EXTENSIONS); const GLubyte* strExt = glGetString(GL_EXTENSIONS);
GLboolean isSupported = gluCheckExtension((const GLubyte*)"GL_APPLE_pixel_buffer", strExt); GLboolean isSupported = gluCheckExtension((const GLubyte*)"GL_APPLE_pixel_buffer", strExt);
@ -164,21 +162,24 @@ bool RenderImageImplPBuffer::Create(unsigned int width, unsigned int height, uns
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool RenderImageImplPBuffer::Activate(bool active) bool RenderImageImplPBuffer::Activate(bool active)
{ {
if (active) { if (active)
if (!myContext || !myPBuffer) { // Not created yet. {
if (!myContext || !myPBuffer) // Not created yet.
return false; return false;
}
if (aglGetCurrentContext() == myContext) { if (aglGetCurrentContext() == myContext)
return true; return true;
} else { else
return aglSetCurrentContext(myContext); return aglSetCurrentContext(myContext);
} }
} else { else
{
// To deactivate the P-Buffer's context, we actually activate // To deactivate the P-Buffer's context, we actually activate
// another one so that we make sure that there is always an // another one so that we make sure that there is always an
// active context for subsequent graphics operations // active context for subsequent graphics operations
return Context::SetReferenceActive(); // @todo fixme
// return Context::SetReferenceActive();
return true;
} }
} }
@ -186,8 +187,6 @@ bool RenderImageImplPBuffer::Activate(bool active)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void RenderImageImplPBuffer::UpdateTexture(unsigned int textureId) void RenderImageImplPBuffer::UpdateTexture(unsigned int textureId)
{ {
if (Activate(true))
{
GLint previous; GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous)); GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
@ -196,7 +195,6 @@ void RenderImageImplPBuffer::UpdateTexture(unsigned int textureId)
GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, myWidth, myHeight)); GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, myWidth, myHeight));
GLCheck(glBindTexture(GL_TEXTURE_2D, previous)); GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
}
} }
} // namespace priv } // namespace priv

View File

@ -30,6 +30,7 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderImageImpl.hpp> #include <SFML/Graphics/RenderImageImpl.hpp>
#include <SFML/Window/GlResource.hpp>
#include <GL/glew.h> #include <GL/glew.h>
#include <AGL/agl.h> #include <AGL/agl.h>
@ -41,7 +42,7 @@ namespace priv
/// \brief Specialization of RenderImageImpl using AGL P-Buffers /// \brief Specialization of RenderImageImpl using AGL P-Buffers
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
class RenderImageImplPBuffer : public RenderImageImpl class RenderImageImplPBuffer : public RenderImageImpl, GlResource
{ {
public : public :

View File

@ -44,6 +44,7 @@ myRenderImage(NULL)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
RenderImage::~RenderImage() RenderImage::~RenderImage()
{ {
SetActive(false);
delete myRenderImage; delete myRenderImage;
} }
@ -117,7 +118,7 @@ bool RenderImage::SetActive(bool active)
void RenderImage::Display() void RenderImage::Display()
{ {
// Update the target image // Update the target image
if (myRenderImage) if (SetActive(true))
{ {
myRenderImage->UpdateTexture(myImage.myTexture); myRenderImage->UpdateTexture(myImage.myTexture);

View File

@ -47,6 +47,8 @@ myDepthBuffer(0)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
RenderImageImplFBO::~RenderImageImplFBO() RenderImageImplFBO::~RenderImageImplFBO()
{ {
EnsureGlContext();
// Destroy the depth buffer // Destroy the depth buffer
if (myDepthBuffer) if (myDepthBuffer)
{ {
@ -66,6 +68,8 @@ RenderImageImplFBO::~RenderImageImplFBO()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool RenderImageImplFBO::IsSupported() bool RenderImageImplFBO::IsSupported()
{ {
EnsureGlContext();
// Make sure that GLEW is initialized // Make sure that GLEW is initialized
priv::EnsureGlewInit(); priv::EnsureGlewInit();
@ -76,6 +80,9 @@ 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
myContext.SetActive(true);
// Create the framebuffer object // Create the framebuffer object
GLuint frameBuffer = 0; GLuint frameBuffer = 0;
GLCheck(glGenFramebuffersEXT(1, &frameBuffer)); GLCheck(glGenFramebuffersEXT(1, &frameBuffer));

View File

@ -30,6 +30,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderImageImpl.hpp> #include <SFML/Graphics/RenderImageImpl.hpp>
#include <SFML/Window/Context.hpp> #include <SFML/Window/Context.hpp>
#include <SFML/Window/GlResource.hpp>
namespace sf namespace sf
@ -41,7 +42,7 @@ namespace priv
/// Frame Buffer Object OpenGL extension /// Frame Buffer Object OpenGL extension
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
class RenderImageImplFBO : public RenderImageImpl class RenderImageImplFBO : public RenderImageImpl, GlResource
{ {
public : public :

View File

@ -35,12 +35,6 @@
namespace sf namespace sf
{ {
////////////////////////////////////////////////////////////
// Static member data
////////////////////////////////////////////////////////////
const Image Shader::CurrentTexture;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Shader::Shader() : Shader::Shader() :
myShaderProgram (0), myShaderProgram (0),
@ -66,6 +60,8 @@ myFragmentShader(copy.myFragmentShader)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Shader::~Shader() Shader::~Shader()
{ {
EnsureGlContext();
// Destroy effect program // Destroy effect program
if (myShaderProgram) if (myShaderProgram)
GLCheck(glDeleteObjectARB(myShaderProgram)); GLCheck(glDeleteObjectARB(myShaderProgram));
@ -109,6 +105,8 @@ void Shader::SetParameter(const std::string& name, float x)
{ {
if (myShaderProgram) if (myShaderProgram)
{ {
EnsureGlContext();
// Enable program // Enable program
GLhandleARB program = glGetHandleARB(GL_PROGRAM_OBJECT_ARB); GLhandleARB program = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);
GLCheck(glUseProgramObjectARB(myShaderProgram)); GLCheck(glUseProgramObjectARB(myShaderProgram));
@ -131,6 +129,8 @@ void Shader::SetParameter(const std::string& name, float x, float y)
{ {
if (myShaderProgram) if (myShaderProgram)
{ {
EnsureGlContext();
// Enable program // Enable program
GLhandleARB program = glGetHandleARB(GL_PROGRAM_OBJECT_ARB); GLhandleARB program = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);
GLCheck(glUseProgramObjectARB(myShaderProgram)); GLCheck(glUseProgramObjectARB(myShaderProgram));
@ -153,6 +153,8 @@ void Shader::SetParameter(const std::string& name, float x, float y, float z)
{ {
if (myShaderProgram) if (myShaderProgram)
{ {
EnsureGlContext();
// Enable program // Enable program
GLhandleARB program = glGetHandleARB(GL_PROGRAM_OBJECT_ARB); GLhandleARB program = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);
GLCheck(glUseProgramObjectARB(myShaderProgram)); GLCheck(glUseProgramObjectARB(myShaderProgram));
@ -175,6 +177,8 @@ void Shader::SetParameter(const std::string& name, float x, float y, float z, fl
{ {
if (myShaderProgram) if (myShaderProgram)
{ {
EnsureGlContext();
// Enable program // Enable program
GLhandleARB program = glGetHandleARB(GL_PROGRAM_OBJECT_ARB); GLhandleARB program = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);
GLCheck(glUseProgramObjectARB(myShaderProgram)); GLCheck(glUseProgramObjectARB(myShaderProgram));
@ -211,7 +215,21 @@ void Shader::SetTexture(const std::string& name, const Image& texture)
{ {
if (myShaderProgram) if (myShaderProgram)
{ {
// Check if there is a texture unit available EnsureGlContext();
// Find the location of the variable in the shader
int location = glGetUniformLocationARB(myShaderProgram, name.c_str());
if (location == -1)
{
Err() << "Texture \"" << name << "\" not found in shader" << std::endl;
return;
}
// Store the location -> texture mapping
TextureTable::iterator it = myTextures.find(location);
if (it == myTextures.end())
{
// New entry, make sure there are enough texture units
GLint maxUnits; GLint maxUnits;
GLCheck(glGetIntegerv(GL_MAX_TEXTURE_COORDS_ARB, &maxUnits)); GLCheck(glGetIntegerv(GL_MAX_TEXTURE_COORDS_ARB, &maxUnits));
if (myTextures.size() + 1 >= static_cast<std::size_t>(maxUnits)) if (myTextures.size() + 1 >= static_cast<std::size_t>(maxUnits))
@ -220,19 +238,28 @@ void Shader::SetTexture(const std::string& name, const Image& texture)
return; return;
} }
// Make sure the given name is a valid variable in the effect
int location = glGetUniformLocationARB(myShaderProgram, name.c_str());
if (location == -1)
{
Err() << "Texture \"" << name << "\" not found in shader" << std::endl;
return;
}
// Store the texture for later use
if (&texture != &CurrentTexture)
myTextures[location] = &texture; myTextures[location] = &texture;
}
else else
myCurrentTexture = location; {
// Location already used, just replace the texture
it->second = &texture;
}
}
}
////////////////////////////////////////////////////////////
void Shader::SetCurrentTexture(const std::string& name)
{
if (myShaderProgram)
{
EnsureGlContext();
// Find the location of the variable in the shader
int myCurrentTexture = glGetUniformLocationARB(myShaderProgram, name.c_str());
if (myCurrentTexture == -1)
Err() << "Texture \"" << name << "\" not found in shader" << std::endl;
} }
} }
@ -242,6 +269,8 @@ void Shader::Bind() const
{ {
if (myShaderProgram) if (myShaderProgram)
{ {
EnsureGlContext();
// Enable the program // Enable the program
GLCheck(glUseProgramObjectARB(myShaderProgram)); GLCheck(glUseProgramObjectARB(myShaderProgram));
@ -258,6 +287,8 @@ void Shader::Bind() const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Shader::Unbind() const void Shader::Unbind() const
{ {
EnsureGlContext();
GLCheck(glUseProgramObjectARB(0)); GLCheck(glUseProgramObjectARB(0));
} }
@ -279,6 +310,8 @@ Shader& Shader::operator =(const Shader& right)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool Shader::IsAvailable() bool Shader::IsAvailable()
{ {
EnsureGlContext();
// Make sure that GLEW is initialized // Make sure that GLEW is initialized
priv::EnsureGlewInit(); priv::EnsureGlewInit();
@ -292,6 +325,8 @@ bool Shader::IsAvailable()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool Shader::CompileProgram() bool Shader::CompileProgram()
{ {
EnsureGlContext();
// First make sure that we can use shaders // First make sure that we can use shaders
if (!IsAvailable()) if (!IsAvailable())
{ {
@ -300,9 +335,6 @@ bool Shader::CompileProgram()
return false; return false;
} }
// Make sure that GLEW is initialized (extra safety -- it is already done in IsAvailable())
priv::EnsureGlewInit();
// Destroy the shader if it was already created // Destroy the shader if it was already created
if (myShaderProgram) if (myShaderProgram)
GLCheck(glDeleteObjectARB(myShaderProgram)); GLCheck(glDeleteObjectARB(myShaderProgram));
@ -398,7 +430,7 @@ void Shader::BindTextures() const
GLCheck(glUniform1iARB(it->first, index)); GLCheck(glUniform1iARB(it->first, index));
GLCheck(glActiveTextureARB(GL_TEXTURE0_ARB + index)); GLCheck(glActiveTextureARB(GL_TEXTURE0_ARB + index));
it->second->Bind(); it->second->Bind();
it++; ++it;
} }
// Make sure that the texture unit which is left active is the number 0 // Make sure that the texture unit which is left active is the number 0

View File

@ -50,6 +50,8 @@ myHeight (0)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
RenderImageImplPBuffer::~RenderImageImplPBuffer() RenderImageImplPBuffer::~RenderImageImplPBuffer()
{ {
EnsureGlContext();
if (myContext) if (myContext)
wglDeleteContext(myContext); wglDeleteContext(myContext);
@ -58,16 +60,14 @@ RenderImageImplPBuffer::~RenderImageImplPBuffer()
wglReleasePbufferDCARB(myPBuffer, myDeviceContext); wglReleasePbufferDCARB(myPBuffer, myDeviceContext);
wglDestroyPbufferARB(myPBuffer); wglDestroyPbufferARB(myPBuffer);
} }
// This is to make sure that another valid context is made
// active after we destroy the P-Buffer's one
Context::SetReferenceActive();
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool RenderImageImplPBuffer::IsSupported() bool RenderImageImplPBuffer::IsSupported()
{ {
EnsureGlContext();
// Make sure that GLEW is initialized // Make sure that GLEW is initialized
priv::EnsureGlewInit(); priv::EnsureGlewInit();
@ -171,7 +171,9 @@ bool RenderImageImplPBuffer::Activate(bool active)
// To deactivate the P-Buffer's context, we actually activate // To deactivate the P-Buffer's context, we actually activate
// another one so that we make sure that there is always an // another one so that we make sure that there is always an
// active context for subsequent graphics operations // active context for subsequent graphics operations
return Context::SetReferenceActive(); // @todo fix
//return Context::SetReferenceActive();
return true;
} }
} }
@ -179,8 +181,6 @@ bool RenderImageImplPBuffer::Activate(bool active)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void RenderImageImplPBuffer::UpdateTexture(unsigned int textureId) void RenderImageImplPBuffer::UpdateTexture(unsigned int textureId)
{ {
if (Activate(true))
{
GLint previous; GLint previous;
GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous)); GLCheck(glGetIntegerv(GL_TEXTURE_BINDING_2D, &previous));
@ -189,7 +189,6 @@ void RenderImageImplPBuffer::UpdateTexture(unsigned int textureId)
GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, myWidth, myHeight)); GLCheck(glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, myWidth, myHeight));
GLCheck(glBindTexture(GL_TEXTURE_2D, previous)); GLCheck(glBindTexture(GL_TEXTURE_2D, previous));
}
} }
} // namespace priv } // namespace priv

View File

@ -29,6 +29,7 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderImageImpl.hpp> #include <SFML/Graphics/RenderImageImpl.hpp>
#include <SFML/Window/GlResource.hpp>
#include <GL/glew.h> #include <GL/glew.h>
#include <GL/wglew.h> #include <GL/wglew.h>
@ -41,7 +42,7 @@ namespace priv
/// \brief Specialization of RenderImageImpl using WGL P-Buffers /// \brief Specialization of RenderImageImpl using WGL P-Buffers
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
class RenderImageImplPBuffer : public RenderImageImpl class RenderImageImplPBuffer : public RenderImageImpl, GlResource
{ {
public : public :

View File

@ -8,6 +8,8 @@ set(SRC
${INCROOT}/Context.hpp ${INCROOT}/Context.hpp
${SRCROOT}/GlContext.cpp ${SRCROOT}/GlContext.cpp
${SRCROOT}/GlContext.hpp ${SRCROOT}/GlContext.hpp
${SRCROOT}/GlResource.cpp
${INCROOT}/GlResource.hpp
${INCROOT}/ContextSettings.hpp ${INCROOT}/ContextSettings.hpp
${INCROOT}/Event.hpp ${INCROOT}/Event.hpp
${SRCROOT}/Input.cpp ${SRCROOT}/Input.cpp

View File

@ -54,11 +54,4 @@ void Context::SetActive(bool active)
} }
////////////////////////////////////////////////////////////
bool Context::SetReferenceActive()
{
return priv::GlContext::SetReferenceActive();
}
} // namespace sf } // namespace sf

View File

@ -27,9 +27,13 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Window/GlContext.hpp> #include <SFML/Window/GlContext.hpp>
#include <SFML/System/ThreadLocalPtr.hpp> #include <SFML/System/ThreadLocalPtr.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/OpenGL.hpp> #include <SFML/OpenGL.hpp>
#include <SFML/Window/glext/glext.h> #include <SFML/Window/glext/glext.h>
#include <vector>
#include <cstdlib> #include <cstdlib>
#include <cassert>
#if defined(SFML_SYSTEM_WINDOWS) #if defined(SFML_SYSTEM_WINDOWS)
@ -55,16 +59,29 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
namespace namespace
{ {
// This thread-local variable will hold the "global" context for each thread // This per-thread variable holds the current context for each thread
sf::ThreadLocalPtr<sf::priv::GlContext> threadContext(NULL); sf::ThreadLocalPtr<sf::priv::GlContext> currentContext = NULL;
// Now we create two global contexts. // The hidden, inactive context that will be shared with all other contexts
// The first one is the reference context: it will be shared with every other ContextType* sharedContext = NULL;
// context, and it can't be activated if we want the sharing operation to always succeed.
// That's why we need the second context: this one will be activated and used // Internal contexts
// in the main thread whenever there's no other context (window) active. sf::ThreadLocalPtr<sf::priv::GlContext> internalContext = NULL;
ContextType referenceContext(NULL); std::vector<sf::priv::GlContext*> internalContexts;
ContextType defaultContext(&referenceContext); sf::Mutex internalContextsMutex;
// Retrieve the internal context for the current thread
sf::priv::GlContext* GetInternalContext()
{
if (!internalContext)
{
internalContext = sf::priv::GlContext::New();
sf::Lock lock(internalContextsMutex);
internalContexts.push_back(internalContext);
}
return internalContext;
}
} }
@ -72,17 +89,58 @@ namespace sf
{ {
namespace priv namespace priv
{ {
////////////////////////////////////////////////////////////
void GlContext::Initialize()
{
// Create the shared context
sharedContext = new ContextType(NULL);
// This call makes sure that:
// - the shared context is inactive (it must never be)
// - another valid context is activated in the current thread
sharedContext->SetActive(false);
}
////////////////////////////////////////////////////////////
void GlContext::Cleanup()
{
// Destroy the shared context
delete sharedContext;
sharedContext = NULL;
// Destroy the internal contexts
sf::Lock lock(internalContextsMutex);
for (std::vector<GlContext*>::iterator it = internalContexts.begin(); it != internalContexts.end(); ++it)
delete *it;
internalContexts.clear();
}
////////////////////////////////////////////////////////////
void GlContext::EnsureContext()
{
// If there's no active context on the current thread, activate an internal one
if (!currentContext)
GetInternalContext()->SetActive(true);
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
GlContext* GlContext::New() GlContext* GlContext::New()
{ {
return new ContextType(&referenceContext); return new ContextType(sharedContext);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
GlContext* GlContext::New(const WindowImpl* owner, unsigned int bitsPerPixel, const ContextSettings& settings) GlContext* GlContext::New(const WindowImpl* owner, unsigned int bitsPerPixel, const ContextSettings& settings)
{ {
ContextType* context = new ContextType(&referenceContext, owner, bitsPerPixel, settings); // 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, owner, bitsPerPixel, settings);
// Enable antialiasing if needed // Enable antialiasing if needed
if (context->GetSettings().AntialiasingLevel > 0) if (context->GetSettings().AntialiasingLevel > 0)
@ -95,15 +153,8 @@ GlContext* GlContext::New(const WindowImpl* owner, unsigned int bitsPerPixel, co
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
GlContext::~GlContext() GlContext::~GlContext()
{ {
if (threadContext == this) // Deactivate the context before killing it
{ SetActive(false);
threadContext = NULL;
}
else if (threadContext)
{
// Don't call this->SetActive(false), it would lead to a pure virtual function call
threadContext->SetActive(true);
}
} }
@ -118,43 +169,41 @@ const ContextSettings& GlContext::GetSettings() const
bool GlContext::SetActive(bool active) bool GlContext::SetActive(bool active)
{ {
if (active) if (active)
{
if (this != currentContext)
{ {
// Activate the context // Activate the context
if (MakeCurrent()) if (MakeCurrent())
{ {
// If this is the first context to be activated on this thread, make // Set it as the new current context for this thread
// it the reference context for the whole thread. currentContext = this;
// referenceContext must *not* be the threadContext of the main thread return true;
if (!threadContext && (this != &referenceContext)) }
threadContext = this; else
{
return false;
}
}
else
{
// This context is already the active one on this thread, don't do anything
return true; return true;
} }
} }
else else
{ {
// Deactivate the context if (this == currentContext)
if (threadContext && (threadContext != this))
{ {
// To deactivate the context, we actually activate another one // To deactivate the context, we actually activate another one so that we make
// so that we make sure that there is always an active context // sure that there is always an active context for subsequent graphics operations
// for subsequent graphics operations return GetInternalContext()->SetActive(true);
return threadContext->SetActive(true);
} }
}
// If we got there then something failed
return false;
}
////////////////////////////////////////////////////////////
bool GlContext::SetReferenceActive()
{
if (threadContext)
return threadContext->SetActive(true);
else else
return false; {
// This context is not the active one on this thread, don't do anything
return true;
}
}
} }

View File

@ -47,6 +47,36 @@ class GlContext : NonCopyable
{ {
public : public :
////////////////////////////////////////////////////////////
/// \brief Perform the global initialization
///
/// This function is called once, before the very first OpenGL
/// resource is created. It makes sure that everything is ready
/// for contexts to work properly.
/// Note: this function doesn't need to be thread-safe, as it
/// can be called only once.
///
////////////////////////////////////////////////////////////
static void Initialize();
////////////////////////////////////////////////////////////
/// \brief Perform the global cleanup
///
/// This function is called after the very last OpenGL resource
/// is destroyed. It makes sure that everything that was
/// created by Initialize() is properly released.
/// Note: this function doesn't need to be thread-safe, as it
/// can be called only once.
///
////////////////////////////////////////////////////////////
static void Cleanup();
////////////////////////////////////////////////////////////
/// \brief Ensures that an OpenGL context is active in the current thread
///
////////////////////////////////////////////////////////////
static void EnsureContext();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Create a new context, not associated to a window /// \brief Create a new context, not associated to a window
/// ///
@ -129,18 +159,6 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
virtual void EnableVerticalSync(bool enabled) = 0; virtual void EnableVerticalSync(bool enabled) = 0;
////////////////////////////////////////////////////////////
/// \brief Make the current thread's reference context active
///
/// This function is meant to be called internally; it is used
/// to deactivate the current context by activating another one
/// (so that we still have an active context on the current thread).
///
/// \return True if operation was successful, false otherwise
///
////////////////////////////////////////////////////////////
static bool SetReferenceActive();
protected : protected :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -0,0 +1,89 @@
////////////////////////////////////////////////////////////
//
// 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/Window/GlResource.hpp>
#include <SFML/Window/GlContext.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
////////////////////////////////////////////////////////////
// Private data
////////////////////////////////////////////////////////////
namespace
{
// OpenGL resources counter and its mutex
unsigned long count = 0;
bool initialized = false;
sf::Mutex mutex;
}
namespace sf
{
////////////////////////////////////////////////////////////
GlResource::GlResource()
{
{
// Protect from concurrent access
Lock lock(mutex);
// If this is the very first resource, trigger the global context initialization
if (count == 0)
priv::GlContext::Initialize();
// Increment the resources counter
count++;
}
// Now make sure that there is an active OpenGL context in the current thread
priv::GlContext::EnsureContext();
}
////////////////////////////////////////////////////////////
GlResource::~GlResource()
{
// Protect from concurrent access
Lock lock(mutex);
// Decrement the resources counter
count--;
// If there's no more resource alive, we can trigger the global context cleanup
if (count == 0)
priv::GlContext::Cleanup();
}
////////////////////////////////////////////////////////////
void GlResource::EnsureGlContext()
{
priv::GlContext::EnsureContext();
}
} // namespace sf

View File

@ -116,17 +116,7 @@ GlxContext::~GlxContext()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool GlxContext::MakeCurrent() bool GlxContext::MakeCurrent()
{ {
if (myContext) return myContext && glXMakeCurrent(myDisplay, myWindow, myContext);
{
if (glXGetCurrentContext() != myContext)
return glXMakeCurrent(myDisplay, myWindow, myContext) != 0;
else
return true;
}
else
{
return false;
}
} }

View File

@ -107,17 +107,7 @@ WglContext::~WglContext()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool WglContext::MakeCurrent() bool WglContext::MakeCurrent()
{ {
if (myDeviceContext && myContext) return myDeviceContext && myContext && wglMakeCurrent(myDeviceContext, myContext);
{
if (wglGetCurrentContext() != myContext)
return wglMakeCurrent(myDeviceContext, myContext) != 0;
else
return true;
}
else
{
return false;
}
} }