mirror of
https://github.com/SFML/SFML.git
synced 2024-11-25 04:41:05 +08:00
Allow re-creation of the shared context as a core context if the user indicates they want a core profile context. Sharing of compatibility and core profile contexts is not possible on macOS which is why we need to have a way to re-create the shared context as a core context if required in this case.
This commit is contained in:
parent
3f4bc3683b
commit
ac98be760b
@ -212,6 +212,55 @@ namespace
|
|||||||
// Supported OpenGL extensions
|
// Supported OpenGL extensions
|
||||||
std::vector<std::string> extensions;
|
std::vector<std::string> extensions;
|
||||||
|
|
||||||
|
// Load our extensions vector with the supported extensions
|
||||||
|
void loadExtensions()
|
||||||
|
{
|
||||||
|
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>(sf::priv::GlContext::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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Helper to parse OpenGL version strings
|
// Helper to parse OpenGL version strings
|
||||||
bool parseVersionString(const char* version, const char* prefix, unsigned int &major, unsigned int &minor)
|
bool parseVersionString(const char* version, const char* prefix, unsigned int &major, unsigned int &minor)
|
||||||
{
|
{
|
||||||
@ -260,50 +309,7 @@ void GlContext::initResource()
|
|||||||
sharedContext->initialize(ContextSettings());
|
sharedContext->initialize(ContextSettings());
|
||||||
|
|
||||||
// Load our extensions vector
|
// Load our extensions vector
|
||||||
extensions.clear();
|
loadExtensions();
|
||||||
|
|
||||||
// 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
|
// Deactivate the shared context so that others can activate it when necessary
|
||||||
sharedContext->setActive(false);
|
sharedContext->setActive(false);
|
||||||
@ -417,6 +423,25 @@ GlContext* GlContext::create(const ContextSettings& settings, const WindowImpl*
|
|||||||
|
|
||||||
Lock lock(mutex);
|
Lock lock(mutex);
|
||||||
|
|
||||||
|
// If resourceCount is 1 we know that we are inside sf::Context or sf::Window
|
||||||
|
// Only in this situation we allow the user to indirectly re-create the shared context as a core context
|
||||||
|
|
||||||
|
// Check if we need to convert our shared context into a core context
|
||||||
|
if ((resourceCount == 1) &&
|
||||||
|
(settings.attributeFlags & ContextSettings::Core) &&
|
||||||
|
!(sharedContext->m_settings.attributeFlags & ContextSettings::Core))
|
||||||
|
{
|
||||||
|
// Re-create our shared context as a core context
|
||||||
|
ContextSettings sharedSettings(0, 0, 0, settings.majorVersion, settings.minorVersion, settings.attributeFlags);
|
||||||
|
|
||||||
|
delete sharedContext;
|
||||||
|
sharedContext = new ContextType(NULL, sharedSettings, 1, 1);
|
||||||
|
sharedContext->initialize(sharedSettings);
|
||||||
|
|
||||||
|
// Reload our extensions vector
|
||||||
|
loadExtensions();
|
||||||
|
}
|
||||||
|
|
||||||
GlContext* context = NULL;
|
GlContext* context = NULL;
|
||||||
|
|
||||||
// We don't use acquireTransientContext here since we have
|
// We don't use acquireTransientContext here since we have
|
||||||
@ -446,6 +471,25 @@ GlContext* GlContext::create(const ContextSettings& settings, unsigned int width
|
|||||||
|
|
||||||
Lock lock(mutex);
|
Lock lock(mutex);
|
||||||
|
|
||||||
|
// If resourceCount is 1 we know that we are inside sf::Context or sf::Window
|
||||||
|
// Only in this situation we allow the user to indirectly re-create the shared context as a core context
|
||||||
|
|
||||||
|
// Check if we need to convert our shared context into a core context
|
||||||
|
if ((resourceCount == 1) &&
|
||||||
|
(settings.attributeFlags & ContextSettings::Core) &&
|
||||||
|
!(sharedContext->m_settings.attributeFlags & ContextSettings::Core))
|
||||||
|
{
|
||||||
|
// Re-create our shared context as a core context
|
||||||
|
ContextSettings sharedSettings(0, 0, 0, settings.majorVersion, settings.minorVersion, settings.attributeFlags);
|
||||||
|
|
||||||
|
delete sharedContext;
|
||||||
|
sharedContext = new ContextType(NULL, sharedSettings, 1, 1);
|
||||||
|
sharedContext->initialize(sharedSettings);
|
||||||
|
|
||||||
|
// Reload our extensions vector
|
||||||
|
loadExtensions();
|
||||||
|
}
|
||||||
|
|
||||||
GlContext* context = NULL;
|
GlContext* context = NULL;
|
||||||
|
|
||||||
// We don't use acquireTransientContext here since we have
|
// We don't use acquireTransientContext here since we have
|
||||||
|
@ -84,19 +84,15 @@ m_deviceContext(NULL),
|
|||||||
m_context (NULL),
|
m_context (NULL),
|
||||||
m_ownsWindow (false)
|
m_ownsWindow (false)
|
||||||
{
|
{
|
||||||
|
// TODO: Delegate to the other constructor in C++11
|
||||||
|
|
||||||
// Save the creation settings
|
// Save the creation settings
|
||||||
m_settings = ContextSettings();
|
m_settings = ContextSettings();
|
||||||
|
|
||||||
// Make sure that extensions are initialized if this is not the shared context
|
|
||||||
// The shared context is the context used to initialize the extensions
|
|
||||||
if (shared && shared->m_deviceContext)
|
|
||||||
ensureExtensionsInit(shared->m_deviceContext);
|
|
||||||
|
|
||||||
// Create the rendering surface (window or pbuffer if supported)
|
// Create the rendering surface (window or pbuffer if supported)
|
||||||
createSurface(shared, 1, 1, VideoMode::getDesktopMode().bitsPerPixel);
|
createSurface(shared, 1, 1, VideoMode::getDesktopMode().bitsPerPixel);
|
||||||
|
|
||||||
// Create the context
|
// Create the context
|
||||||
if (m_deviceContext)
|
|
||||||
createContext(shared);
|
createContext(shared);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,16 +108,10 @@ m_ownsWindow (false)
|
|||||||
// Save the creation settings
|
// Save the creation settings
|
||||||
m_settings = settings;
|
m_settings = settings;
|
||||||
|
|
||||||
// Make sure that extensions are initialized if this is not the shared context
|
|
||||||
// The shared context is the context used to initialize the extensions
|
|
||||||
if (shared && shared->m_deviceContext)
|
|
||||||
ensureExtensionsInit(shared->m_deviceContext);
|
|
||||||
|
|
||||||
// Create the rendering surface from the owner window
|
// Create the rendering surface from the owner window
|
||||||
createSurface(owner->getSystemHandle(), bitsPerPixel);
|
createSurface(owner->getSystemHandle(), bitsPerPixel);
|
||||||
|
|
||||||
// Create the context
|
// Create the context
|
||||||
if (m_deviceContext)
|
|
||||||
createContext(shared);
|
createContext(shared);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,16 +127,10 @@ m_ownsWindow (false)
|
|||||||
// Save the creation settings
|
// Save the creation settings
|
||||||
m_settings = settings;
|
m_settings = settings;
|
||||||
|
|
||||||
// Make sure that extensions are initialized if this is not the shared context
|
|
||||||
// The shared context is the context used to initialize the extensions
|
|
||||||
if (shared && shared->m_deviceContext)
|
|
||||||
ensureExtensionsInit(shared->m_deviceContext);
|
|
||||||
|
|
||||||
// Create the rendering surface (window or pbuffer if supported)
|
// Create the rendering surface (window or pbuffer if supported)
|
||||||
createSurface(shared, width, height, VideoMode::getDesktopMode().bitsPerPixel);
|
createSurface(shared, width, height, VideoMode::getDesktopMode().bitsPerPixel);
|
||||||
|
|
||||||
// Create the context
|
// Create the context
|
||||||
if (m_deviceContext)
|
|
||||||
createContext(shared);
|
createContext(shared);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,6 +578,10 @@ void WglContext::createSurface(HWND window, unsigned int bitsPerPixel)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void WglContext::createContext(WglContext* shared)
|
void WglContext::createContext(WglContext* shared)
|
||||||
{
|
{
|
||||||
|
// We can't create an OpenGL context if we don't have a DC
|
||||||
|
if (!m_deviceContext)
|
||||||
|
return;
|
||||||
|
|
||||||
// Get a working copy of the context settings
|
// Get a working copy of the context settings
|
||||||
ContextSettings settings = m_settings;
|
ContextSettings settings = m_settings;
|
||||||
|
|
||||||
@ -730,6 +718,15 @@ void WglContext::createContext(WglContext* shared)
|
|||||||
err() << "Failed to share the OpenGL context: " << getErrorString(GetLastError()).toAnsiString() << std::endl;
|
err() << "Failed to share the OpenGL context: " << getErrorString(GetLastError()).toAnsiString() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we are the shared context, initialize extensions now
|
||||||
|
// This enables us to re-create the shared context using extensions if we need to
|
||||||
|
if (!shared && m_context)
|
||||||
|
{
|
||||||
|
makeCurrent(true);
|
||||||
|
ensureExtensionsInit(m_deviceContext);
|
||||||
|
makeCurrent(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
Loading…
Reference in New Issue
Block a user