Move context management out of glfwCreateWindow

Related to #25.
This commit is contained in:
Camilla Löwy 2017-12-24 10:07:56 +01:00
parent ac94014ef8
commit 1034b6e0db
5 changed files with 62 additions and 69 deletions

View File

@ -321,10 +321,11 @@ const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
return closest; return closest;
} }
GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig) GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig)
{ {
int i; int i;
_GLFWwindow* window; _GLFWwindow* previous;
const char* version; const char* version;
const char* prefixes[] = const char* prefixes[] =
{ {
@ -334,11 +335,12 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
NULL NULL
}; };
window = _glfwPlatformGetTls(&_glfw.contextSlot);
window->context.source = ctxconfig->source; window->context.source = ctxconfig->source;
window->context.client = GLFW_OPENGL_API; window->context.client = GLFW_OPENGL_API;
previous = _glfwPlatformGetTls(&_glfw.contextSlot);;
glfwMakeContextCurrent((GLFWwindow*) window);
window->context.GetIntegerv = (PFNGLGETINTEGERVPROC) window->context.GetIntegerv = (PFNGLGETINTEGERVPROC)
window->context.getProcAddress("glGetIntegerv"); window->context.getProcAddress("glGetIntegerv");
window->context.GetString = (PFNGLGETSTRINGPROC) window->context.GetString = (PFNGLGETSTRINGPROC)
@ -346,6 +348,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
if (!window->context.GetIntegerv || !window->context.GetString) if (!window->context.GetIntegerv || !window->context.GetString)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken"); _glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");
glfwMakeContextCurrent((GLFWwindow*) previous);
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -363,6 +366,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
"OpenGL ES version string retrieval is broken"); "OpenGL ES version string retrieval is broken");
} }
glfwMakeContextCurrent((GLFWwindow*) previous);
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -394,6 +398,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
"No version found in OpenGL ES version string"); "No version found in OpenGL ES version string");
} }
glfwMakeContextCurrent((GLFWwindow*) previous);
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -423,6 +428,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
window->context.major, window->context.minor); window->context.major, window->context.minor);
} }
glfwMakeContextCurrent((GLFWwindow*) previous);
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -438,6 +444,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Entry point retrieval is broken"); "Entry point retrieval is broken");
glfwMakeContextCurrent((GLFWwindow*) previous);
return GLFW_FALSE; return GLFW_FALSE;
} }
} }
@ -544,6 +551,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
window->context.swapBuffers(window); window->context.swapBuffers(window);
} }
glfwMakeContextCurrent((GLFWwindow*) previous);
return GLFW_TRUE; return GLFW_TRUE;
} }

View File

@ -954,7 +954,8 @@ const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
* unusable. * unusable.
* @ingroup utility * @ingroup utility
*/ */
GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig); GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig);
/*! @brief Checks whether the desired context attributes are valid. /*! @brief Checks whether the desired context attributes are valid.
* @param[in] ctxconfig The context attributes to check. * @param[in] ctxconfig The context attributes to check.

View File

@ -329,21 +329,52 @@ static void destroyContextWGL(_GLFWwindow* window)
} }
} }
// Initialize WGL-specific extensions
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
// Initialize WGL
// //
static void loadWGLExtensions(void) GLFWbool _glfwInitWGL(void)
{ {
PIXELFORMATDESCRIPTOR pfd; PIXELFORMATDESCRIPTOR pfd;
HGLRC rc; HGLRC prc, rc;
HDC dc = GetDC(_glfw.win32.helperWindowHandle);; HDC pdc, dc;
_glfw.wgl.extensionsLoaded = GLFW_TRUE; if (_glfw.wgl.instance)
return GLFW_TRUE;
_glfw.wgl.instance = LoadLibraryA("opengl32.dll");
if (!_glfw.wgl.instance)
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to load opengl32.dll");
return GLFW_FALSE;
}
_glfw.wgl.CreateContext = (PFN_wglCreateContext)
GetProcAddress(_glfw.wgl.instance, "wglCreateContext");
_glfw.wgl.DeleteContext = (PFN_wglDeleteContext)
GetProcAddress(_glfw.wgl.instance, "wglDeleteContext");
_glfw.wgl.GetProcAddress = (PFN_wglGetProcAddress)
GetProcAddress(_glfw.wgl.instance, "wglGetProcAddress");
_glfw.wgl.GetCurrentDC = (PFN_wglGetCurrentDC)
GetProcAddress(_glfw.wgl.instance, "wglGetCurrentDC");
_glfw.wgl.GetCurrentContext = (PFN_wglGetCurrentContext)
GetProcAddress(_glfw.wgl.instance, "wglGetCurrentContext");
_glfw.wgl.MakeCurrent = (PFN_wglMakeCurrent)
GetProcAddress(_glfw.wgl.instance, "wglMakeCurrent");
_glfw.wgl.ShareLists = (PFN_wglShareLists)
GetProcAddress(_glfw.wgl.instance, "wglShareLists");
// NOTE: A dummy context has to be created for opengl32.dll to load the // NOTE: A dummy context has to be created for opengl32.dll to load the
// OpenGL ICD, from which we can then query WGL extensions // OpenGL ICD, from which we can then query WGL extensions
// NOTE: This code will accept the Microsoft GDI ICD; accelerated context // NOTE: This code will accept the Microsoft GDI ICD; accelerated context
// creation failure occurs during manual pixel format enumeration // creation failure occurs during manual pixel format enumeration
dc = GetDC(_glfw.win32.helperWindowHandle);;
ZeroMemory(&pfd, sizeof(pfd)); ZeroMemory(&pfd, sizeof(pfd));
pfd.nSize = sizeof(pfd); pfd.nSize = sizeof(pfd);
pfd.nVersion = 1; pfd.nVersion = 1;
@ -355,7 +386,7 @@ static void loadWGLExtensions(void)
{ {
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to set pixel format for dummy context"); "WGL: Failed to set pixel format for dummy context");
return; return GLFW_FALSE;
} }
rc = wglCreateContext(dc); rc = wglCreateContext(dc);
@ -363,15 +394,19 @@ static void loadWGLExtensions(void)
{ {
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to create dummy context"); "WGL: Failed to create dummy context");
return; return GLFW_FALSE;
} }
pdc = wglGetCurrentDC();
prc = wglGetCurrentContext();
if (!wglMakeCurrent(dc, rc)) if (!wglMakeCurrent(dc, rc))
{ {
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to make dummy context current"); "WGL: Failed to make dummy context current");
wglMakeCurrent(pdc, prc);
wglDeleteContext(rc); wglDeleteContext(rc);
return; return GLFW_FALSE;
} }
// NOTE: Functions must be loaded first as they're needed to retrieve the // NOTE: Functions must be loaded first as they're needed to retrieve the
@ -414,43 +449,8 @@ static void loadWGLExtensions(void)
_glfw.wgl.ARB_context_flush_control = _glfw.wgl.ARB_context_flush_control =
extensionSupportedWGL("WGL_ARB_context_flush_control"); extensionSupportedWGL("WGL_ARB_context_flush_control");
wglMakeCurrent(dc, NULL); wglMakeCurrent(pdc, prc);
wglDeleteContext(rc); wglDeleteContext(rc);
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
// Initialize WGL
//
GLFWbool _glfwInitWGL(void)
{
if (_glfw.wgl.instance)
return GLFW_TRUE;
_glfw.wgl.instance = LoadLibraryA("opengl32.dll");
if (!_glfw.wgl.instance)
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to load opengl32.dll");
return GLFW_FALSE;
}
_glfw.wgl.CreateContext = (PFN_wglCreateContext)
GetProcAddress(_glfw.wgl.instance, "wglCreateContext");
_glfw.wgl.DeleteContext = (PFN_wglDeleteContext)
GetProcAddress(_glfw.wgl.instance, "wglDeleteContext");
_glfw.wgl.GetProcAddress = (PFN_wglGetProcAddress)
GetProcAddress(_glfw.wgl.instance, "wglGetProcAddress");
_glfw.wgl.GetCurrentDC = (PFN_wglGetCurrentDC)
GetProcAddress(_glfw.wgl.instance, "wglGetCurrentDC");
_glfw.wgl.MakeCurrent = (PFN_wglMakeCurrent)
GetProcAddress(_glfw.wgl.instance, "wglMakeCurrent");
_glfw.wgl.ShareLists = (PFN_wglShareLists)
GetProcAddress(_glfw.wgl.instance, "wglShareLists");
return GLFW_TRUE; return GLFW_TRUE;
} }
@ -480,9 +480,6 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
PIXELFORMATDESCRIPTOR pfd; PIXELFORMATDESCRIPTOR pfd;
HGLRC share = NULL; HGLRC share = NULL;
if (!_glfw.wgl.extensionsLoaded)
loadWGLExtensions();
if (ctxconfig->share) if (ctxconfig->share)
share = ctxconfig->share->context.wgl.handle; share = ctxconfig->share->context.wgl.handle;

View File

@ -86,6 +86,7 @@ typedef HGLRC (WINAPI * PFN_wglCreateContext)(HDC);
typedef BOOL (WINAPI * PFN_wglDeleteContext)(HGLRC); typedef BOOL (WINAPI * PFN_wglDeleteContext)(HGLRC);
typedef PROC (WINAPI * PFN_wglGetProcAddress)(LPCSTR); typedef PROC (WINAPI * PFN_wglGetProcAddress)(LPCSTR);
typedef HDC (WINAPI * PFN_wglGetCurrentDC)(void); typedef HDC (WINAPI * PFN_wglGetCurrentDC)(void);
typedef HGLRC (WINAPI * PFN_wglGetCurrentContext)(void);
typedef BOOL (WINAPI * PFN_wglMakeCurrent)(HDC,HGLRC); typedef BOOL (WINAPI * PFN_wglMakeCurrent)(HDC,HGLRC);
typedef BOOL (WINAPI * PFN_wglShareLists)(HGLRC,HGLRC); typedef BOOL (WINAPI * PFN_wglShareLists)(HGLRC,HGLRC);
@ -94,6 +95,7 @@ typedef BOOL (WINAPI * PFN_wglShareLists)(HGLRC,HGLRC);
#define wglDeleteContext _glfw.wgl.DeleteContext #define wglDeleteContext _glfw.wgl.DeleteContext
#define wglGetProcAddress _glfw.wgl.GetProcAddress #define wglGetProcAddress _glfw.wgl.GetProcAddress
#define wglGetCurrentDC _glfw.wgl.GetCurrentDC #define wglGetCurrentDC _glfw.wgl.GetCurrentDC
#define wglGetCurrentContext _glfw.wgl.GetCurrentContext
#define wglMakeCurrent _glfw.wgl.MakeCurrent #define wglMakeCurrent _glfw.wgl.MakeCurrent
#define wglShareLists _glfw.wgl.ShareLists #define wglShareLists _glfw.wgl.ShareLists
@ -124,11 +126,10 @@ typedef struct _GLFWlibraryWGL
PFN_wglDeleteContext DeleteContext; PFN_wglDeleteContext DeleteContext;
PFN_wglGetProcAddress GetProcAddress; PFN_wglGetProcAddress GetProcAddress;
PFN_wglGetCurrentDC GetCurrentDC; PFN_wglGetCurrentDC GetCurrentDC;
PFN_wglGetCurrentContext GetCurrentContext;
PFN_wglMakeCurrent MakeCurrent; PFN_wglMakeCurrent MakeCurrent;
PFN_wglShareLists ShareLists; PFN_wglShareLists ShareLists;
GLFWbool extensionsLoaded;
PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT; PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT;
PFNWGLGETPIXELFORMATATTRIBIVARBPROC GetPixelFormatAttribivARB; PFNWGLGETPIXELFORMATATTRIBIVARBPROC GetPixelFormatAttribivARB;
PFNWGLGETEXTENSIONSSTRINGEXTPROC GetExtensionsStringEXT; PFNWGLGETEXTENSIONSSTRINGEXTPROC GetExtensionsStringEXT;

View File

@ -127,7 +127,6 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
_GLFWctxconfig ctxconfig; _GLFWctxconfig ctxconfig;
_GLFWwndconfig wndconfig; _GLFWwndconfig wndconfig;
_GLFWwindow* window; _GLFWwindow* window;
_GLFWwindow* previous;
assert(title != NULL); assert(title != NULL);
assert(width >= 0); assert(width >= 0);
@ -191,33 +190,20 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
window->numer = GLFW_DONT_CARE; window->numer = GLFW_DONT_CARE;
window->denom = GLFW_DONT_CARE; window->denom = GLFW_DONT_CARE;
// Save the currently current context so it can be restored later
previous = _glfwPlatformGetTls(&_glfw.contextSlot);
if (ctxconfig.client != GLFW_NO_API)
glfwMakeContextCurrent(NULL);
// Open the actual window and create its context // Open the actual window and create its context
if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig)) if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig))
{ {
glfwMakeContextCurrent((GLFWwindow*) previous);
glfwDestroyWindow((GLFWwindow*) window); glfwDestroyWindow((GLFWwindow*) window);
return NULL; return NULL;
} }
if (ctxconfig.client != GLFW_NO_API) if (ctxconfig.client != GLFW_NO_API)
{ {
window->context.makeCurrent(window); if (!_glfwRefreshContextAttribs(window, &ctxconfig))
// Retrieve the actual (as opposed to requested) context attributes
if (!_glfwRefreshContextAttribs(&ctxconfig))
{ {
glfwMakeContextCurrent((GLFWwindow*) previous);
glfwDestroyWindow((GLFWwindow*) window); glfwDestroyWindow((GLFWwindow*) window);
return NULL; return NULL;
} }
// Restore the previously current context (or NULL)
glfwMakeContextCurrent((GLFWwindow*) previous);
} }
if (!window->monitor) if (!window->monitor)