Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow re-creation of the shared context as a core context #1443

Merged
merged 1 commit into from
Oct 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
132 changes: 88 additions & 44 deletions src/SFML/Window/GlContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,55 @@ namespace
// Supported OpenGL 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
bool parseVersionString(const char* version, const char* prefix, unsigned int &major, unsigned int &minor)
{
Expand Down Expand Up @@ -260,50 +309,7 @@ void GlContext::initResource()
sharedContext->initialize(ContextSettings());

// 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);
}
}
}
}
loadExtensions();

// Deactivate the shared context so that others can activate it when necessary
sharedContext->setActive(false);
Expand Down Expand Up @@ -417,6 +423,25 @@ GlContext* GlContext::create(const ContextSettings& settings, const WindowImpl*

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;

// We don't use acquireTransientContext here since we have
Expand Down Expand Up @@ -446,6 +471,25 @@ GlContext* GlContext::create(const ContextSettings& settings, unsigned int width

Lock lock(mutex);

// If resourceCount is 1 we know that we are inside sf::Context or sf::Window
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DRY code: re-factor this code and the identical one from above into a function. Maybe a template function to accommodate for the width/height vs owner/bpp difference? If the logic is the same (except how context is constructed), I think it makes sense.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I initially tried to do this, but GlContext::initialize() is private.

// 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;

// We don't use acquireTransientContext here since we have
Expand Down
39 changes: 18 additions & 21 deletions src/SFML/Window/Win32/WglContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,20 +84,16 @@ m_deviceContext(NULL),
m_context (NULL),
m_ownsWindow (false)
{
// TODO: Delegate to the other constructor in C++11

// Save the creation settings
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)
createSurface(shared, 1, 1, VideoMode::getDesktopMode().bitsPerPixel);

// Create the context
if (m_deviceContext)
createContext(shared);
createContext(shared);
}


Expand All @@ -112,17 +108,11 @@ m_ownsWindow (false)
// Save the creation 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
createSurface(owner->getSystemHandle(), bitsPerPixel);

// Create the context
if (m_deviceContext)
createContext(shared);
createContext(shared);
}


Expand All @@ -137,17 +127,11 @@ m_ownsWindow (false)
// Save the creation 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)
createSurface(shared, width, height, VideoMode::getDesktopMode().bitsPerPixel);

// Create the context
if (m_deviceContext)
createContext(shared);
createContext(shared);
}


Expand Down Expand Up @@ -594,6 +578,10 @@ void WglContext::createSurface(HWND window, unsigned int bitsPerPixel)
////////////////////////////////////////////////////////////
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
ContextSettings settings = m_settings;

Expand Down Expand Up @@ -730,6 +718,15 @@ void WglContext::createContext(WglContext* shared)
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
Expand Down