mirror of
https://github.com/SFML/SFML.git
synced 2024-11-25 04:41:05 +08:00
Removed internal OpenGL contexts, reduced the number of temporary contexts that get created during runtime.
This commit is contained in:
parent
95828a85a2
commit
39208efb55
@ -29,10 +29,14 @@
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Window/Export.hpp>
|
||||
#include <SFML/System/NonCopyable.hpp>
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
|
||||
class Context;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Base class for classes that require an OpenGL context
|
||||
///
|
||||
@ -54,10 +58,27 @@ protected:
|
||||
~GlResource();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Make sure that a valid OpenGL context exists in the current thread
|
||||
/// \brief RAII helper class to temporarily lock an available context for use
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void ensureGlContext();
|
||||
class SFML_WINDOW_API TransientContextLock : NonCopyable
|
||||
{
|
||||
public:
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Default constructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
TransientContextLock();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Destructor
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
~TransientContextLock();
|
||||
|
||||
private:
|
||||
Context* m_context; ///< Temporary context, in case we needed to create one
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace sf
|
||||
|
@ -645,10 +645,6 @@ Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold, f
|
||||
// Delete the FT glyph
|
||||
FT_Done_Glyph(glyphDesc);
|
||||
|
||||
// Force an OpenGL flush, so that the font's texture will appear updated
|
||||
// in all contexts immediately (solves problems in multi-threaded apps)
|
||||
glCheck(glFlush());
|
||||
|
||||
// Done :)
|
||||
return glyph;
|
||||
}
|
||||
|
@ -29,6 +29,14 @@
|
||||
#include <SFML/Window/Context.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
|
||||
#if !defined(GL_MAJOR_VERSION)
|
||||
#define GL_MAJOR_VERSION 0x821B
|
||||
#endif
|
||||
|
||||
#if !defined(GL_MINOR_VERSION)
|
||||
#define GL_MINOR_VERSION 0x821C
|
||||
#endif
|
||||
|
||||
|
||||
namespace sf
|
||||
{
|
||||
@ -41,22 +49,41 @@ void ensureExtensionsInit()
|
||||
static bool initialized = false;
|
||||
if (!initialized)
|
||||
{
|
||||
const Context* context = Context::getActiveContext();
|
||||
|
||||
if (!context)
|
||||
return;
|
||||
initialized = true;
|
||||
|
||||
sfogl_LoadFunctions();
|
||||
|
||||
ContextSettings settings = context->getSettings();
|
||||
// Retrieve the context version number
|
||||
int majorVersion = 0;
|
||||
int minorVersion = 0;
|
||||
|
||||
if ((settings.majorVersion < 1) || ((settings.majorVersion == 1) && (settings.minorVersion < 1)))
|
||||
// Try the new way first
|
||||
glGetIntegerv(GL_MAJOR_VERSION, &majorVersion);
|
||||
glGetIntegerv(GL_MINOR_VERSION, &minorVersion);
|
||||
|
||||
if (glGetError() == GL_INVALID_ENUM)
|
||||
{
|
||||
// Try the old way
|
||||
const GLubyte* version = glGetString(GL_VERSION);
|
||||
if (version)
|
||||
{
|
||||
// The beginning of the returned string is "major.minor" (this is standard)
|
||||
majorVersion = version[0] - '0';
|
||||
minorVersion = version[2] - '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
// Can't get the version number, assume 1.1
|
||||
majorVersion = 1;
|
||||
minorVersion = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((majorVersion < 1) || ((majorVersion == 1) && (minorVersion < 1)))
|
||||
{
|
||||
err() << "sfml-graphics requires support for OpenGL 1.1 or greater" << std::endl;
|
||||
err() << "Ensure that hardware acceleration is enabled if available" << std::endl;
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ m_depthBuffer(0)
|
||||
////////////////////////////////////////////////////////////
|
||||
RenderTextureImplFBO::~RenderTextureImplFBO()
|
||||
{
|
||||
ensureGlContext();
|
||||
m_context->setActive(true);
|
||||
|
||||
// Destroy the depth buffer
|
||||
if (m_depthBuffer)
|
||||
@ -72,7 +72,7 @@ RenderTextureImplFBO::~RenderTextureImplFBO()
|
||||
////////////////////////////////////////////////////////////
|
||||
bool RenderTextureImplFBO::isAvailable()
|
||||
{
|
||||
ensureGlContext();
|
||||
TransientContextLock lock;
|
||||
|
||||
// Make sure that extensions are initialized
|
||||
priv::ensureExtensionsInit();
|
||||
|
@ -56,7 +56,8 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
sf::Mutex mutex;
|
||||
sf::Mutex maxTextureUnitsMutex;
|
||||
sf::Mutex isAvailableMutex;
|
||||
|
||||
GLint checkMaxTextureUnits()
|
||||
{
|
||||
@ -70,7 +71,7 @@ namespace
|
||||
GLint getMaxTextureUnits()
|
||||
{
|
||||
// TODO: Remove this lock when it becomes unnecessary in C++11
|
||||
sf::Lock lock(mutex);
|
||||
sf::Lock lock(maxTextureUnitsMutex);
|
||||
|
||||
static GLint maxUnits = checkMaxTextureUnits();
|
||||
|
||||
@ -116,53 +117,6 @@ namespace
|
||||
return success;
|
||||
}
|
||||
|
||||
bool checkShadersAvailable()
|
||||
{
|
||||
// Create a temporary context in case the user checks
|
||||
// before a GlResource is created, thus initializing
|
||||
// the shared context
|
||||
if (!sf::Context::getActiveContext())
|
||||
{
|
||||
sf::Context context;
|
||||
|
||||
// Make sure that extensions are initialized
|
||||
sf::priv::ensureExtensionsInit();
|
||||
|
||||
bool available = GLEXT_multitexture &&
|
||||
GLEXT_shading_language_100 &&
|
||||
GLEXT_shader_objects &&
|
||||
GLEXT_vertex_shader &&
|
||||
GLEXT_fragment_shader;
|
||||
|
||||
return available;
|
||||
}
|
||||
|
||||
// Make sure that extensions are initialized
|
||||
sf::priv::ensureExtensionsInit();
|
||||
|
||||
bool available = GLEXT_multitexture &&
|
||||
GLEXT_shading_language_100 &&
|
||||
GLEXT_shader_objects &&
|
||||
GLEXT_vertex_shader &&
|
||||
GLEXT_fragment_shader;
|
||||
|
||||
return available;
|
||||
}
|
||||
bool checkGeometryShadersAvailable()
|
||||
{
|
||||
// Create a temporary context in case the user checks
|
||||
// before a GlResource is created, thus initializing
|
||||
// the shared context
|
||||
sf::Context context;
|
||||
|
||||
// Make sure that extensions are initialized
|
||||
sf::priv::ensureExtensionsInit();
|
||||
|
||||
bool available = checkShadersAvailable() && GLEXT_geometry_shader4;
|
||||
|
||||
return available;
|
||||
}
|
||||
|
||||
// Transforms an array of 2D vectors into a contiguous array of scalars
|
||||
template <typename T>
|
||||
std::vector<T> flatten(const sf::Vector2<T>* vectorArray, std::size_t length)
|
||||
@ -236,8 +190,6 @@ struct Shader::UniformBinder : private NonCopyable
|
||||
{
|
||||
if (currentProgram)
|
||||
{
|
||||
ensureGlContext();
|
||||
|
||||
// Enable program object
|
||||
glCheck(savedProgram = GLEXT_glGetHandle(GLEXT_GL_PROGRAM_OBJECT));
|
||||
if (currentProgram != savedProgram)
|
||||
@ -259,9 +211,10 @@ struct Shader::UniformBinder : private NonCopyable
|
||||
glCheck(GLEXT_glUseProgramObject(savedProgram));
|
||||
}
|
||||
|
||||
GLEXT_GLhandle savedProgram; ///< Handle to the previously active program object
|
||||
GLEXT_GLhandle currentProgram; ///< Handle to the program object of the modified sf::Shader instance
|
||||
GLint location; ///< Uniform location, used by the surrounding sf::Shader code
|
||||
TransientContextLock lock; ///< Lock to keep context active while uniform is bound
|
||||
GLEXT_GLhandle savedProgram; ///< Handle to the previously active program object
|
||||
GLEXT_GLhandle currentProgram; ///< Handle to the program object of the modified sf::Shader instance
|
||||
GLint location; ///< Uniform location, used by the surrounding sf::Shader code
|
||||
};
|
||||
|
||||
|
||||
@ -278,7 +231,7 @@ m_uniforms ()
|
||||
////////////////////////////////////////////////////////////
|
||||
Shader::~Shader()
|
||||
{
|
||||
ensureGlContext();
|
||||
TransientContextLock lock;
|
||||
|
||||
// Destroy effect program
|
||||
if (m_shaderProgram)
|
||||
@ -592,7 +545,7 @@ void Shader::setUniform(const std::string& name, const Texture& texture)
|
||||
{
|
||||
if (m_shaderProgram)
|
||||
{
|
||||
ensureGlContext();
|
||||
TransientContextLock lock;
|
||||
|
||||
// Find the location of the variable in the shader
|
||||
int location = getUniformLocation(name);
|
||||
@ -627,7 +580,7 @@ void Shader::setUniform(const std::string& name, CurrentTextureType)
|
||||
{
|
||||
if (m_shaderProgram)
|
||||
{
|
||||
ensureGlContext();
|
||||
TransientContextLock lock;
|
||||
|
||||
// Find the location of the variable in the shader
|
||||
m_currentTexture = getUniformLocation(name);
|
||||
@ -787,7 +740,7 @@ unsigned int Shader::getNativeHandle() const
|
||||
////////////////////////////////////////////////////////////
|
||||
void Shader::bind(const Shader* shader)
|
||||
{
|
||||
ensureGlContext();
|
||||
TransientContextLock lock;
|
||||
|
||||
// Make sure that we can use shaders
|
||||
if (!isAvailable())
|
||||
@ -820,10 +773,26 @@ void Shader::bind(const Shader* shader)
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Shader::isAvailable()
|
||||
{
|
||||
// TODO: Remove this lock when it becomes unnecessary in C++11
|
||||
Lock lock(mutex);
|
||||
Lock lock(isAvailableMutex);
|
||||
|
||||
static bool available = checkShadersAvailable();
|
||||
static bool checked = false;
|
||||
static bool available = false;
|
||||
|
||||
if (!checked)
|
||||
{
|
||||
checked = true;
|
||||
|
||||
TransientContextLock contextLock;
|
||||
|
||||
// Make sure that extensions are initialized
|
||||
sf::priv::ensureExtensionsInit();
|
||||
|
||||
available = GLEXT_multitexture &&
|
||||
GLEXT_shading_language_100 &&
|
||||
GLEXT_shader_objects &&
|
||||
GLEXT_vertex_shader &&
|
||||
GLEXT_fragment_shader;
|
||||
}
|
||||
|
||||
return available;
|
||||
}
|
||||
@ -832,10 +801,22 @@ bool Shader::isAvailable()
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Shader::isGeometryAvailable()
|
||||
{
|
||||
// TODO: Remove this lock when it becomes unnecessary in C++11
|
||||
Lock lock(mutex);
|
||||
Lock lock(isAvailableMutex);
|
||||
|
||||
static bool available = checkGeometryShadersAvailable();
|
||||
static bool checked = false;
|
||||
static bool available = false;
|
||||
|
||||
if (!checked)
|
||||
{
|
||||
checked = true;
|
||||
|
||||
TransientContextLock contextLock;
|
||||
|
||||
// Make sure that extensions are initialized
|
||||
sf::priv::ensureExtensionsInit();
|
||||
|
||||
available = isAvailable() && GLEXT_geometry_shader4;
|
||||
}
|
||||
|
||||
return available;
|
||||
}
|
||||
@ -844,7 +825,7 @@ bool Shader::isGeometryAvailable()
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Shader::compile(const char* vertexShaderCode, const char* geometryShaderCode, const char* fragmentShaderCode)
|
||||
{
|
||||
ensureGlContext();
|
||||
TransientContextLock lock;
|
||||
|
||||
// First make sure that we can use shaders
|
||||
if (!isAvailable())
|
||||
|
@ -40,39 +40,19 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
sf::Mutex mutex;
|
||||
sf::Mutex idMutex;
|
||||
sf::Mutex maximumSizeMutex;
|
||||
|
||||
// Thread-safe unique identifier generator,
|
||||
// is used for states cache (see RenderTarget)
|
||||
sf::Uint64 getUniqueId()
|
||||
{
|
||||
sf::Lock lock(mutex);
|
||||
sf::Lock lock(idMutex);
|
||||
|
||||
static sf::Uint64 id = 1; // start at 1, zero is "no texture"
|
||||
|
||||
return id++;
|
||||
}
|
||||
|
||||
unsigned int checkMaximumTextureSize()
|
||||
{
|
||||
// Create a temporary context in case the user queries
|
||||
// the size before a GlResource is created, thus
|
||||
// initializing the shared context
|
||||
if (!sf::Context::getActiveContext())
|
||||
{
|
||||
sf::Context context;
|
||||
|
||||
GLint size;
|
||||
glCheck(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size));
|
||||
|
||||
return static_cast<unsigned int>(size);
|
||||
}
|
||||
|
||||
GLint size;
|
||||
glCheck(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size));
|
||||
|
||||
return static_cast<unsigned int>(size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -118,7 +98,7 @@ Texture::~Texture()
|
||||
// Destroy the OpenGL texture
|
||||
if (m_texture)
|
||||
{
|
||||
ensureGlContext();
|
||||
TransientContextLock lock;
|
||||
|
||||
GLuint texture = static_cast<GLuint>(m_texture);
|
||||
glCheck(glDeleteTextures(1, &texture));
|
||||
@ -157,7 +137,7 @@ bool Texture::create(unsigned int width, unsigned int height)
|
||||
m_pixelsFlipped = false;
|
||||
m_fboAttachment = false;
|
||||
|
||||
ensureGlContext();
|
||||
TransientContextLock lock;
|
||||
|
||||
// Create the OpenGL texture if it doesn't exist yet
|
||||
if (!m_texture)
|
||||
@ -265,10 +245,6 @@ bool Texture::loadFromImage(const Image& image, const IntRect& area)
|
||||
{
|
||||
update(image);
|
||||
|
||||
// Force an OpenGL flush, so that the texture will appear updated
|
||||
// in all contexts immediately (solves problems in multi-threaded apps)
|
||||
glCheck(glFlush());
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@ -290,6 +266,8 @@ bool Texture::loadFromImage(const Image& image, const IntRect& area)
|
||||
// Create the texture and upload the pixels
|
||||
if (create(rectangle.width, rectangle.height))
|
||||
{
|
||||
TransientContextLock lock;
|
||||
|
||||
// Make sure that the current texture binding will be preserved
|
||||
priv::TextureSaver save;
|
||||
|
||||
@ -333,7 +311,7 @@ Image Texture::copyToImage() const
|
||||
if (!m_texture)
|
||||
return Image();
|
||||
|
||||
ensureGlContext();
|
||||
TransientContextLock lock;
|
||||
|
||||
// Make sure that the current texture binding will be preserved
|
||||
priv::TextureSaver save;
|
||||
@ -424,7 +402,7 @@ void Texture::update(const Uint8* pixels, unsigned int width, unsigned int heigh
|
||||
|
||||
if (pixels && m_texture)
|
||||
{
|
||||
ensureGlContext();
|
||||
TransientContextLock lock;
|
||||
|
||||
// Make sure that the current texture binding will be preserved
|
||||
priv::TextureSaver save;
|
||||
@ -436,6 +414,10 @@ void Texture::update(const Uint8* pixels, unsigned int width, unsigned int heigh
|
||||
m_hasMipmap = false;
|
||||
m_pixelsFlipped = false;
|
||||
m_cacheId = getUniqueId();
|
||||
|
||||
// Force an OpenGL flush, so that the texture data will appear updated
|
||||
// in all contexts immediately (solves problems in multi-threaded apps)
|
||||
glCheck(glFlush());
|
||||
}
|
||||
}
|
||||
|
||||
@ -470,6 +452,8 @@ void Texture::update(const Window& window, unsigned int x, unsigned int y)
|
||||
|
||||
if (m_texture && window.setActive(true))
|
||||
{
|
||||
TransientContextLock lock;
|
||||
|
||||
// Make sure that the current texture binding will be preserved
|
||||
priv::TextureSaver save;
|
||||
|
||||
@ -480,6 +464,10 @@ void Texture::update(const Window& window, unsigned int x, unsigned int y)
|
||||
m_hasMipmap = false;
|
||||
m_pixelsFlipped = true;
|
||||
m_cacheId = getUniqueId();
|
||||
|
||||
// Force an OpenGL flush, so that the texture will appear updated
|
||||
// in all contexts immediately (solves problems in multi-threaded apps)
|
||||
glCheck(glFlush());
|
||||
}
|
||||
}
|
||||
|
||||
@ -493,7 +481,7 @@ void Texture::setSmooth(bool smooth)
|
||||
|
||||
if (m_texture)
|
||||
{
|
||||
ensureGlContext();
|
||||
TransientContextLock lock;
|
||||
|
||||
// Make sure that the current texture binding will be preserved
|
||||
priv::TextureSaver save;
|
||||
@ -544,7 +532,7 @@ void Texture::setRepeated(bool repeated)
|
||||
|
||||
if (m_texture)
|
||||
{
|
||||
ensureGlContext();
|
||||
TransientContextLock lock;
|
||||
|
||||
// Make sure that the current texture binding will be preserved
|
||||
priv::TextureSaver save;
|
||||
@ -586,7 +574,7 @@ bool Texture::generateMipmap()
|
||||
if (!m_texture)
|
||||
return false;
|
||||
|
||||
ensureGlContext();
|
||||
TransientContextLock lock;
|
||||
|
||||
// Make sure that extensions are initialized
|
||||
priv::ensureExtensionsInit();
|
||||
@ -613,7 +601,7 @@ void Texture::invalidateMipmap()
|
||||
if (!m_hasMipmap)
|
||||
return;
|
||||
|
||||
ensureGlContext();
|
||||
TransientContextLock lock;
|
||||
|
||||
// Make sure that the current texture binding will be preserved
|
||||
priv::TextureSaver save;
|
||||
@ -628,7 +616,7 @@ void Texture::invalidateMipmap()
|
||||
////////////////////////////////////////////////////////////
|
||||
void Texture::bind(const Texture* texture, CoordinateType coordinateType)
|
||||
{
|
||||
ensureGlContext();
|
||||
TransientContextLock lock;
|
||||
|
||||
if (texture && texture->m_texture)
|
||||
{
|
||||
@ -684,12 +672,21 @@ void Texture::bind(const Texture* texture, CoordinateType coordinateType)
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int Texture::getMaximumSize()
|
||||
{
|
||||
// TODO: Remove this lock when it becomes unnecessary in C++11
|
||||
Lock lock(mutex);
|
||||
Lock lock(maximumSizeMutex);
|
||||
|
||||
static unsigned int size = checkMaximumTextureSize();
|
||||
static bool checked = false;
|
||||
static GLint size = 0;
|
||||
|
||||
return size;
|
||||
if (!checked)
|
||||
{
|
||||
checked = true;
|
||||
|
||||
TransientContextLock lock;
|
||||
|
||||
glCheck(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size));
|
||||
}
|
||||
|
||||
return static_cast<unsigned int>(size);
|
||||
}
|
||||
|
||||
|
||||
@ -722,7 +719,7 @@ unsigned int Texture::getNativeHandle() const
|
||||
////////////////////////////////////////////////////////////
|
||||
unsigned int Texture::getValidSize(unsigned int size)
|
||||
{
|
||||
ensureGlContext();
|
||||
TransientContextLock lock;
|
||||
|
||||
// Make sure that extensions are initialized
|
||||
priv::ensureExtensionsInit();
|
||||
|
@ -28,24 +28,6 @@
|
||||
#include <SFML/Window/Context.hpp>
|
||||
#include <SFML/Window/GlContext.hpp>
|
||||
#include <SFML/System/ThreadLocalPtr.hpp>
|
||||
#include <SFML/OpenGL.hpp>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#if defined(SFML_SYSTEM_WINDOWS)
|
||||
|
||||
typedef const GLubyte* (APIENTRY *glGetStringiFuncType)(GLenum, GLuint);
|
||||
|
||||
#else
|
||||
|
||||
typedef const GLubyte* (*glGetStringiFuncType)(GLenum, GLuint);
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(GL_NUM_EXTENSIONS)
|
||||
#define GL_NUM_EXTENSIONS 0x821D
|
||||
#endif
|
||||
|
||||
|
||||
namespace
|
||||
@ -99,70 +81,16 @@ const Context* Context::getActiveContext()
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
GlFunctionPointer Context::getFunction(const char* name)
|
||||
bool Context::isExtensionAvailable(const char* name)
|
||||
{
|
||||
return priv::GlContext::getFunction(name);
|
||||
return priv::GlContext::isExtensionAvailable(name);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool Context::isExtensionAvailable(const char* name)
|
||||
GlFunctionPointer Context::getFunction(const char* name)
|
||||
{
|
||||
static std::vector<std::string> extensions;
|
||||
static bool loaded = false;
|
||||
|
||||
if (!loaded)
|
||||
{
|
||||
const Context* context = getActiveContext();
|
||||
|
||||
if (!context)
|
||||
return false;
|
||||
|
||||
const char* extensionString = NULL;
|
||||
|
||||
if(context->getSettings().majorVersion < 3)
|
||||
{
|
||||
// Try to load the < 3.0 way
|
||||
extensionString = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
|
||||
|
||||
do
|
||||
{
|
||||
const char* extension = extensionString;
|
||||
|
||||
while(*extensionString && (*extensionString != ' '))
|
||||
extensionString++;
|
||||
|
||||
extensions.push_back(std::string(extension, extensionString));
|
||||
}
|
||||
while (*extensionString++);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to load the >= 3.0 way
|
||||
glGetStringiFuncType glGetStringiFunc = NULL;
|
||||
glGetStringiFunc = reinterpret_cast<glGetStringiFuncType>(getFunction("glGetStringi"));
|
||||
|
||||
if (glGetStringiFunc)
|
||||
{
|
||||
int numExtensions = 0;
|
||||
glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
|
||||
|
||||
if (numExtensions)
|
||||
{
|
||||
for (unsigned int i = 0; i < static_cast<unsigned int>(numExtensions); ++i)
|
||||
{
|
||||
extensionString = reinterpret_cast<const char*>(glGetStringiFunc(GL_EXTENSIONS, i));
|
||||
|
||||
extensions.push_back(extensionString);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
return std::find(extensions.begin(), extensions.end(), name) != extensions.end();
|
||||
return priv::GlContext::getFunction(name);
|
||||
}
|
||||
|
||||
|
||||
|
@ -173,9 +173,12 @@ EglContext::~EglContext()
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool EglContext::makeCurrent()
|
||||
bool EglContext::makeCurrent(bool current)
|
||||
{
|
||||
return m_surface != EGL_NO_SURFACE && eglCheck(eglMakeCurrent(m_display, m_surface, m_surface, m_context));
|
||||
if (current)
|
||||
return m_surface != EGL_NO_SURFACE && eglCheck(eglMakeCurrent(m_display, m_surface, m_surface, m_context));
|
||||
|
||||
return m_surface != EGL_NO_SURFACE && eglCheck(eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
|
||||
}
|
||||
|
||||
|
||||
@ -209,6 +212,9 @@ void EglContext::createContext(EglContext* shared)
|
||||
else
|
||||
toShared = EGL_NO_CONTEXT;
|
||||
|
||||
if (toShared != EGL_NO_CONTEXT)
|
||||
eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
|
||||
// Create EGL context
|
||||
m_context = eglCheck(eglCreateContext(m_display, m_config, toShared, contextVersion));
|
||||
}
|
||||
|
@ -83,10 +83,12 @@ public:
|
||||
/// \brief Activate the context as the current target
|
||||
/// for rendering
|
||||
///
|
||||
/// \param current Whether to make the context current or no longer current
|
||||
///
|
||||
/// \return True on success, false if any error happened
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual bool makeCurrent();
|
||||
virtual bool makeCurrent(bool current);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Display what has been rendered to the context so far
|
||||
|
@ -31,9 +31,13 @@
|
||||
#include <SFML/System/Lock.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <SFML/OpenGL.hpp>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
#if !defined(SFML_OPENGL_ES)
|
||||
|
||||
@ -126,6 +130,8 @@ namespace
|
||||
// AMD drivers have issues with internal synchronization
|
||||
// We need to make sure that no operating system context
|
||||
// or pixel format operations are performed simultaneously
|
||||
// This mutex is also used to protect the shared context
|
||||
// from being locked on multiple threads
|
||||
sf::Mutex mutex;
|
||||
|
||||
// This per-thread variable holds the current context for each thread
|
||||
@ -134,35 +140,12 @@ namespace
|
||||
// The hidden, inactive context that will be shared with all other contexts
|
||||
ContextType* sharedContext = NULL;
|
||||
|
||||
// Internal contexts
|
||||
sf::ThreadLocalPtr<sf::Context> internalContext(NULL);
|
||||
std::set<sf::Context*> internalContexts;
|
||||
sf::Mutex internalContextsMutex;
|
||||
// This per-thread variable is set to point to the shared context
|
||||
// if we had to acquire it when a TransientContextLock was required
|
||||
sf::ThreadLocalPtr<sf::priv::GlContext> currentSharedContext(NULL);
|
||||
|
||||
// Check if the internal context of the current thread is valid
|
||||
bool hasInternalContext()
|
||||
{
|
||||
// The internal context can be null...
|
||||
if (!internalContext)
|
||||
return false;
|
||||
|
||||
// ... or non-null but deleted from the list of internal contexts
|
||||
sf::Lock lock(internalContextsMutex);
|
||||
return internalContexts.find(internalContext) != internalContexts.end();
|
||||
}
|
||||
|
||||
// Retrieve the internal context for the current thread
|
||||
sf::Context* getInternalContext()
|
||||
{
|
||||
if (!hasInternalContext())
|
||||
{
|
||||
internalContext = new sf::Context;
|
||||
sf::Lock lock(internalContextsMutex);
|
||||
internalContexts.insert(internalContext);
|
||||
}
|
||||
|
||||
return internalContext;
|
||||
}
|
||||
// Supported OpenGL extensions
|
||||
std::vector<std::string> extensions;
|
||||
}
|
||||
|
||||
|
||||
@ -182,9 +165,53 @@ void GlContext::globalInit()
|
||||
sharedContext = new ContextType(NULL);
|
||||
sharedContext->initialize(ContextSettings());
|
||||
|
||||
// This call makes sure that:
|
||||
// - the shared context is inactive (it must never be)
|
||||
// - another valid context is activated in the current thread
|
||||
// Load our extensions vector
|
||||
extensions.clear();
|
||||
|
||||
// Check whether a >= 3.0 context is available
|
||||
int majorVersion = 0;
|
||||
glGetIntegerv(GL_MAJOR_VERSION, &majorVersion);
|
||||
|
||||
if (glGetError() == GL_INVALID_ENUM)
|
||||
{
|
||||
// Try to load the < 3.0 way
|
||||
const char* extensionString = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
|
||||
|
||||
do
|
||||
{
|
||||
const char* extension = extensionString;
|
||||
|
||||
while(*extensionString && (*extensionString != ' '))
|
||||
extensionString++;
|
||||
|
||||
extensions.push_back(std::string(extension, extensionString));
|
||||
}
|
||||
while (*extensionString++);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to load the >= 3.0 way
|
||||
glGetStringiFuncType glGetStringiFunc = NULL;
|
||||
glGetStringiFunc = reinterpret_cast<glGetStringiFuncType>(getFunction("glGetStringi"));
|
||||
|
||||
if (glGetStringiFunc)
|
||||
{
|
||||
int numExtensions = 0;
|
||||
glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
|
||||
|
||||
if (numExtensions)
|
||||
{
|
||||
for (unsigned int i = 0; i < static_cast<unsigned int>(numExtensions); ++i)
|
||||
{
|
||||
const char* extensionString = reinterpret_cast<const char*>(glGetStringiFunc(GL_EXTENSIONS, i));
|
||||
|
||||
extensions.push_back(extensionString);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Deactivate the shared context so that others can activate it when necessary
|
||||
sharedContext->setActive(false);
|
||||
}
|
||||
|
||||
@ -200,31 +227,59 @@ void GlContext::globalCleanup()
|
||||
// Destroy the shared context
|
||||
delete sharedContext;
|
||||
sharedContext = NULL;
|
||||
|
||||
// Destroy the internal contexts
|
||||
Lock internalContextsLock(internalContextsMutex);
|
||||
for (std::set<Context*>::iterator it = internalContexts.begin(); it != internalContexts.end(); ++it)
|
||||
delete *it;
|
||||
internalContexts.clear();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void GlContext::ensureContext()
|
||||
void GlContext::acquireTransientContext()
|
||||
{
|
||||
// If there's no active context on the current thread, activate an internal one
|
||||
if (!currentContext)
|
||||
getInternalContext()->setActive(true);
|
||||
// If a capable context is already active on this thread
|
||||
// there is no need to use the shared context for the operation
|
||||
if (currentContext)
|
||||
{
|
||||
currentSharedContext = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
mutex.lock();
|
||||
currentSharedContext = sharedContext;
|
||||
sharedContext->setActive(true);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void GlContext::releaseTransientContext()
|
||||
{
|
||||
if (!currentSharedContext)
|
||||
return;
|
||||
|
||||
sharedContext->setActive(false);
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
GlContext* GlContext::create()
|
||||
{
|
||||
// Make sure that there's an active context (context creation may need extensions, and thus a valid context)
|
||||
assert(sharedContext != NULL);
|
||||
|
||||
Lock lock(mutex);
|
||||
|
||||
// Create the context
|
||||
GlContext* context = new ContextType(sharedContext);
|
||||
GlContext* context = NULL;
|
||||
|
||||
// We don't use acquireTransientContext here since we have
|
||||
// to ensure we have exclusive access to the shared context
|
||||
// in order to make sure it is not active during context creation
|
||||
{
|
||||
sharedContext->setActive(true);
|
||||
|
||||
// Create the context
|
||||
context = new ContextType(sharedContext);
|
||||
|
||||
sharedContext->setActive(false);
|
||||
}
|
||||
|
||||
context->initialize(ContextSettings());
|
||||
|
||||
return context;
|
||||
@ -235,12 +290,24 @@ GlContext* GlContext::create()
|
||||
GlContext* GlContext::create(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)
|
||||
ensureContext();
|
||||
assert(sharedContext != NULL);
|
||||
|
||||
Lock lock(mutex);
|
||||
|
||||
// Create the context
|
||||
GlContext* context = new ContextType(sharedContext, settings, owner, bitsPerPixel);
|
||||
GlContext* context = NULL;
|
||||
|
||||
// We don't use acquireTransientContext here since we have
|
||||
// to ensure we have exclusive access to the shared context
|
||||
// in order to make sure it is not active during context creation
|
||||
{
|
||||
sharedContext->setActive(true);
|
||||
|
||||
// Create the context
|
||||
context = new ContextType(sharedContext, settings, owner, bitsPerPixel);
|
||||
|
||||
sharedContext->setActive(false);
|
||||
}
|
||||
|
||||
context->initialize(settings);
|
||||
context->checkSettings(settings);
|
||||
|
||||
@ -252,12 +319,24 @@ GlContext* GlContext::create(const ContextSettings& settings, const WindowImpl*
|
||||
GlContext* GlContext::create(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();
|
||||
assert(sharedContext != NULL);
|
||||
|
||||
Lock lock(mutex);
|
||||
|
||||
// Create the context
|
||||
GlContext* context = new ContextType(sharedContext, settings, width, height);
|
||||
GlContext* context = NULL;
|
||||
|
||||
// We don't use acquireTransientContext here since we have
|
||||
// to ensure we have exclusive access to the shared context
|
||||
// in order to make sure it is not active during context creation
|
||||
{
|
||||
sharedContext->setActive(true);
|
||||
|
||||
// Create the context
|
||||
context = new ContextType(sharedContext, settings, width, height);
|
||||
|
||||
sharedContext->setActive(false);
|
||||
}
|
||||
|
||||
context->initialize(settings);
|
||||
context->checkSettings(settings);
|
||||
|
||||
@ -265,6 +344,13 @@ GlContext* GlContext::create(const ContextSettings& settings, unsigned int width
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool GlContext::isExtensionAvailable(const char* name)
|
||||
{
|
||||
return std::find(extensions.begin(), extensions.end(), name) != extensions.end();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
GlFunctionPointer GlContext::getFunction(const char* name)
|
||||
{
|
||||
@ -287,7 +373,10 @@ GlContext::~GlContext()
|
||||
{
|
||||
// Deactivate the context before killing it, unless we're inside Cleanup()
|
||||
if (sharedContext)
|
||||
setActive(false);
|
||||
{
|
||||
if (this == currentContext)
|
||||
currentContext = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -308,7 +397,7 @@ bool GlContext::setActive(bool active)
|
||||
Lock lock(mutex);
|
||||
|
||||
// Activate the context
|
||||
if (makeCurrent())
|
||||
if (makeCurrent(true))
|
||||
{
|
||||
// Set it as the new current context for this thread
|
||||
currentContext = this;
|
||||
@ -329,9 +418,18 @@ bool GlContext::setActive(bool active)
|
||||
{
|
||||
if (this == currentContext)
|
||||
{
|
||||
// To deactivate the context, we actually activate another one so that we make
|
||||
// sure that there is always an active context for subsequent graphics operations
|
||||
return getInternalContext()->setActive(true);
|
||||
Lock lock(mutex);
|
||||
|
||||
// Deactivate the context
|
||||
if (makeCurrent(false))
|
||||
{
|
||||
currentContext = NULL;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -73,10 +73,16 @@ public:
|
||||
static void globalCleanup();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Ensures that an OpenGL context is active in the current thread
|
||||
/// \brief Acquires a context for short-term use on the current thread
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void ensureContext();
|
||||
static void acquireTransientContext();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Releases a context after short-term use on the current thread
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static void releaseTransientContext();
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Create a new context, not associated to a window
|
||||
@ -120,6 +126,16 @@ public:
|
||||
static GlContext* create(const ContextSettings& settings, unsigned int width, unsigned int height);
|
||||
|
||||
public:
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Check whether a given OpenGL extension is available
|
||||
///
|
||||
/// \param name Name of the extension to check for
|
||||
///
|
||||
/// \return True if available, false if unavailable
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
static bool isExtensionAvailable(const char* name);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Get the address of an OpenGL function
|
||||
///
|
||||
@ -197,10 +213,12 @@ protected:
|
||||
/// \brief Activate the context as the current target
|
||||
/// for rendering
|
||||
///
|
||||
/// \param current Whether to make the context current or no longer current
|
||||
///
|
||||
/// \return True on success, false if any error happened
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual bool makeCurrent() = 0;
|
||||
virtual bool makeCurrent(bool current) = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Evaluate a pixel format configuration
|
||||
|
@ -27,6 +27,7 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Window/GlResource.hpp>
|
||||
#include <SFML/Window/GlContext.hpp>
|
||||
#include <SFML/Window/Context.hpp>
|
||||
#include <SFML/System/Mutex.hpp>
|
||||
#include <SFML/System/Lock.hpp>
|
||||
|
||||
@ -44,20 +45,15 @@ namespace sf
|
||||
////////////////////////////////////////////////////////////
|
||||
GlResource::GlResource()
|
||||
{
|
||||
{
|
||||
// Protect from concurrent access
|
||||
Lock lock(mutex);
|
||||
// Protect from concurrent access
|
||||
Lock lock(mutex);
|
||||
|
||||
// If this is the very first resource, trigger the global context initialization
|
||||
if (count == 0)
|
||||
priv::GlContext::globalInit();
|
||||
// If this is the very first resource, trigger the global context initialization
|
||||
if (count == 0)
|
||||
priv::GlContext::globalInit();
|
||||
|
||||
// Increment the resources counter
|
||||
count++;
|
||||
}
|
||||
|
||||
// Now make sure that there is an active OpenGL context in the current thread
|
||||
priv::GlContext::ensureContext();
|
||||
// Increment the resources counter
|
||||
count++;
|
||||
}
|
||||
|
||||
|
||||
@ -77,9 +73,31 @@ GlResource::~GlResource()
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
void GlResource::ensureGlContext()
|
||||
GlResource::TransientContextLock::TransientContextLock() :
|
||||
m_context(0)
|
||||
{
|
||||
priv::GlContext::ensureContext();
|
||||
Lock lock(mutex);
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
m_context = new Context;
|
||||
return;
|
||||
}
|
||||
|
||||
priv::GlContext::acquireTransientContext();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
GlResource::TransientContextLock::~TransientContextLock()
|
||||
{
|
||||
if (m_context)
|
||||
{
|
||||
delete m_context;
|
||||
return;
|
||||
}
|
||||
|
||||
priv::GlContext::releaseTransientContext();
|
||||
}
|
||||
|
||||
} // namespace sf
|
||||
|
@ -137,10 +137,12 @@ protected:
|
||||
/// \brief Activate the context as the current target
|
||||
/// for rendering
|
||||
///
|
||||
/// \param current Whether to make the context current or no longer current
|
||||
///
|
||||
/// \return True on success, false if any error happened
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual bool makeCurrent();
|
||||
virtual bool makeCurrent(bool current);
|
||||
|
||||
private:
|
||||
////////////////////////////////////////////////////////////
|
||||
|
@ -104,6 +104,10 @@ m_window(0)
|
||||
SFContext::~SFContext()
|
||||
{
|
||||
[m_context clearDrawable];
|
||||
|
||||
if (m_context == [NSOpenGLContext currentContext])
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
|
||||
[m_context release];
|
||||
|
||||
[m_view release]; // Might be nil but we don't care.
|
||||
@ -124,10 +128,18 @@ GlFunctionPointer SFContext::getFunction(const char* name)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool SFContext::makeCurrent()
|
||||
bool SFContext::makeCurrent(bool current)
|
||||
{
|
||||
[m_context makeCurrentContext];
|
||||
return m_context == [NSOpenGLContext currentContext]; // Should be true.
|
||||
if (current)
|
||||
{
|
||||
[m_context makeCurrentContext];
|
||||
return m_context == [NSOpenGLContext currentContext]; // Should be true.
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
return m_context != [NSOpenGLContext currentContext]; // Should be true.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -257,6 +269,17 @@ void SFContext::createContext(SFContext* shared,
|
||||
// Use the shared context if one is given.
|
||||
NSOpenGLContext* sharedContext = shared != NULL ? shared->m_context : nil;
|
||||
|
||||
if (sharedContext != nil)
|
||||
{
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
|
||||
if (sharedContext == [NSOpenGLContext currentContext])
|
||||
{
|
||||
sf::err() << "Failed to deactivate shared context before sharing" << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the context.
|
||||
m_context = [[NSOpenGLContext alloc] initWithFormat:pixFmt
|
||||
shareContext:sharedContext];
|
||||
|
@ -26,6 +26,8 @@
|
||||
// Headers
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/System/Err.hpp>
|
||||
#include <SFML/System/Mutex.hpp>
|
||||
#include <SFML/System/Lock.hpp>
|
||||
#include <SFML/Window/Unix/Display.hpp>
|
||||
#include <X11/keysym.h>
|
||||
#include <cassert>
|
||||
@ -38,6 +40,7 @@ namespace
|
||||
// The shared display and its reference counter
|
||||
Display* sharedDisplay = NULL;
|
||||
unsigned int referenceCount = 0;
|
||||
sf::Mutex mutex;
|
||||
|
||||
typedef std::map<std::string, Atom> AtomMap;
|
||||
AtomMap atoms;
|
||||
@ -50,6 +53,8 @@ namespace priv
|
||||
////////////////////////////////////////////////////////////
|
||||
Display* OpenDisplay()
|
||||
{
|
||||
Lock lock(mutex);
|
||||
|
||||
if (referenceCount == 0)
|
||||
{
|
||||
sharedDisplay = XOpenDisplay(NULL);
|
||||
@ -71,6 +76,8 @@ Display* OpenDisplay()
|
||||
////////////////////////////////////////////////////////////
|
||||
void CloseDisplay(Display* display)
|
||||
{
|
||||
Lock lock(mutex);
|
||||
|
||||
assert(display == sharedDisplay);
|
||||
|
||||
referenceCount--;
|
||||
|
@ -211,7 +211,7 @@ GlFunctionPointer GlxContext::getFunction(const char* name)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool GlxContext::makeCurrent()
|
||||
bool GlxContext::makeCurrent(bool current)
|
||||
{
|
||||
if (!m_context)
|
||||
return false;
|
||||
@ -222,13 +222,20 @@ bool GlxContext::makeCurrent()
|
||||
|
||||
bool result = false;
|
||||
|
||||
if (m_pbuffer)
|
||||
if (current)
|
||||
{
|
||||
result = glXMakeContextCurrent(m_display, m_pbuffer, m_pbuffer, m_context);
|
||||
if (m_pbuffer)
|
||||
{
|
||||
result = glXMakeContextCurrent(m_display, m_pbuffer, m_pbuffer, m_context);
|
||||
}
|
||||
else if (m_window)
|
||||
{
|
||||
result = glXMakeCurrent(m_display, m_window, m_context);
|
||||
}
|
||||
}
|
||||
else if (m_window)
|
||||
else
|
||||
{
|
||||
result = glXMakeCurrent(m_display, m_window, m_context);
|
||||
result = glXMakeCurrent(m_display, None, NULL);
|
||||
}
|
||||
|
||||
#if defined(GLX_DEBUGGING)
|
||||
@ -686,6 +693,15 @@ void GlxContext::createContext(GlxContext* shared)
|
||||
// On an error, glXCreateContextAttribsARB will return 0 anyway
|
||||
GlxErrorHandler handler(m_display);
|
||||
|
||||
if (toShare)
|
||||
{
|
||||
if (!glXMakeCurrent(m_display, None, NULL))
|
||||
{
|
||||
err() << "Failed to deactivate shared context before sharing" << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the context
|
||||
m_context = glXCreateContextAttribsARB(m_display, *config, toShare, true, &attributes[0]);
|
||||
|
||||
@ -732,6 +748,15 @@ void GlxContext::createContext(GlxContext* shared)
|
||||
GlxErrorHandler handler(m_display);
|
||||
#endif
|
||||
|
||||
if (toShare)
|
||||
{
|
||||
if (!glXMakeCurrent(m_display, None, NULL))
|
||||
{
|
||||
err() << "Failed to deactivate shared context before sharing" << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the context, using the target window's visual
|
||||
m_context = glXCreateContext(m_display, visualInfo, toShare, true);
|
||||
|
||||
|
@ -94,10 +94,12 @@ public:
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Activate the context as the current target for rendering
|
||||
///
|
||||
/// \param current Whether to make the context current or no longer current
|
||||
///
|
||||
/// \return True on success, false if any error happened
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual bool makeCurrent();
|
||||
virtual bool makeCurrent(bool current);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Display what has been rendered to the context so far
|
||||
|
@ -200,9 +200,9 @@ GlFunctionPointer WglContext::getFunction(const char* name)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool WglContext::makeCurrent()
|
||||
bool WglContext::makeCurrent(bool current)
|
||||
{
|
||||
return m_deviceContext && m_context && wglMakeCurrent(m_deviceContext, m_context);
|
||||
return m_deviceContext && m_context && wglMakeCurrent(current ? m_deviceContext : NULL, current ? m_context : NULL);
|
||||
}
|
||||
|
||||
|
||||
@ -599,6 +599,18 @@ void WglContext::createContext(WglContext* shared)
|
||||
attributes.push_back(0);
|
||||
attributes.push_back(0);
|
||||
|
||||
if (sharedContext)
|
||||
{
|
||||
static Mutex mutex;
|
||||
Lock lock(mutex);
|
||||
|
||||
if (!wglMakeCurrent(NULL, NULL))
|
||||
{
|
||||
err() << "Failed to deactivate shared context before sharing: " << getErrorString(GetLastError()).toAnsiString() << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the context
|
||||
m_context = wglCreateContextAttribsARB(m_deviceContext, sharedContext, &attributes[0]);
|
||||
}
|
||||
@ -657,6 +669,12 @@ void WglContext::createContext(WglContext* shared)
|
||||
static Mutex mutex;
|
||||
Lock lock(mutex);
|
||||
|
||||
if (!wglMakeCurrent(NULL, NULL))
|
||||
{
|
||||
err() << "Failed to deactivate shared context before sharing: " << getErrorString(GetLastError()).toAnsiString() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!wglShareLists(sharedContext, m_context))
|
||||
err() << "Failed to share the OpenGL context: " << getErrorString(GetLastError()).toAnsiString() << std::endl;
|
||||
}
|
||||
|
@ -93,10 +93,12 @@ public:
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Activate the context as the current target for rendering
|
||||
///
|
||||
/// \param current Whether to make the context current or no longer current
|
||||
///
|
||||
/// \return True on success, false if any error happened
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual bool makeCurrent();
|
||||
virtual bool makeCurrent(bool current);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
/// \brief Display what has been rendered to the context so far
|
||||
|
@ -126,10 +126,12 @@ protected:
|
||||
/// \brief Activate the context as the current target
|
||||
/// for rendering
|
||||
///
|
||||
/// \param current Whether to make the context current or no longer current
|
||||
///
|
||||
/// \return True on success, false if any error happened
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
||||
virtual bool makeCurrent();
|
||||
virtual bool makeCurrent(bool current);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -107,6 +107,9 @@ EaglContext::~EaglContext()
|
||||
|
||||
// Restore the previous context
|
||||
[EAGLContext setCurrentContext:previousContext];
|
||||
|
||||
if (m_context == [EAGLContext currentContext])
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,9 +170,12 @@ void EaglContext::recreateRenderBuffers(SFView* glView)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
bool EaglContext::makeCurrent()
|
||||
bool EaglContext::makeCurrent(bool current)
|
||||
{
|
||||
return [EAGLContext setCurrentContext:m_context];
|
||||
if (current)
|
||||
return [EAGLContext setCurrentContext:m_context];
|
||||
|
||||
return [EAGLContext setCurrentContext:nil];
|
||||
}
|
||||
|
||||
|
||||
@ -215,12 +221,18 @@ void EaglContext::createContext(EaglContext* shared,
|
||||
|
||||
// Create the context
|
||||
if (shared)
|
||||
{
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
|
||||
m_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1 sharegroup:[shared->m_context sharegroup]];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
|
||||
}
|
||||
|
||||
// Activate it
|
||||
makeCurrent();
|
||||
makeCurrent(true);
|
||||
|
||||
// Create the framebuffer (this is the only allowed drawable on iOS)
|
||||
glGenFramebuffersOES(1, &m_framebuffer);
|
||||
@ -230,6 +242,9 @@ void EaglContext::createContext(EaglContext* shared,
|
||||
|
||||
// Attach the context to the GL view for future updates
|
||||
window->getGlView().context = this;
|
||||
|
||||
// Deactivate it
|
||||
makeCurrent(false);
|
||||
}
|
||||
|
||||
} // namespace priv
|
||||
|
Loading…
Reference in New Issue
Block a user