diff --git a/src/wgl_context.c b/src/wgl_context.c index 27cf1b47..03732dd3 100644 --- a/src/wgl_context.c +++ b/src/wgl_context.c @@ -288,8 +288,6 @@ static int extensionSupportedWGL(const char* extension) { const char* extensions; - _GLFWwindow* window = _glfwPlatformGetCurrentContext(); - if (_glfw.wgl.GetExtensionsStringEXT) { extensions = _glfw.wgl.GetExtensionsStringEXT(); @@ -302,7 +300,7 @@ static int extensionSupportedWGL(const char* extension) if (_glfw.wgl.GetExtensionsStringARB) { - extensions = _glfw.wgl.GetExtensionsStringARB(window->context.wgl.dc); + extensions = _glfw.wgl.GetExtensionsStringARB(wglGetCurrentDC()); if (extensions) { if (_glfwStringInExtensionString(extension, extensions)) @@ -335,8 +333,61 @@ static void destroyContextWGL(_GLFWwindow* window) // Initialize WGL-specific extensions // -static void loadExtensions(void) +static void loadWGLExtensions(void) { + int pf; + PIXELFORMATDESCRIPTOR pfd; + HDC dc; + HGLRC rc; + + _glfw.wgl.extensionsLoaded = GLFW_TRUE; + + ZeroMemory(&pfd, sizeof(pfd)); + pfd.nSize = sizeof(pfd); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = 24; + + dc = GetDC(_glfw.win32.helperWindowHandle); + + pf = ChoosePixelFormat(dc, &pfd); + if (!pf) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "WGL: Failed to choose pixel format for WGL extension loading"); + return; + } + + if (!DescribePixelFormat(dc, pf, sizeof(pfd), &pfd)) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "WGL: Failed to describe pixel format for WGL extension loading"); + return; + } + + if (!SetPixelFormat(dc, pf, &pfd)) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "WGL: Failed to set pixel format for WGL extension loading"); + return; + } + + rc = wglCreateContext(dc); + if (!rc) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "WGL: Failed to create context for WGL extension loading"); + return; + } + + if (!wglMakeCurrent(dc, rc)) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "WGL: Failed to make context current for WGL extension loading"); + return; + } + // Functions for WGL_EXT_extension_string // NOTE: These are needed by extensionSupported _glfw.wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC) @@ -379,7 +430,8 @@ static void loadExtensions(void) _glfw.wgl.ARB_context_flush_control = extensionSupportedWGL("WGL_ARB_context_flush_control"); - _glfw.wgl.extensionsLoaded = GLFW_TRUE; + wglMakeCurrent(dc, NULL); + wglDeleteContext(rc); } @@ -404,6 +456,8 @@ GLFWbool _glfwInitWGL(void) GetProcAddress(_glfw.wgl.instance, "wglDeleteContext"); _glfw.wgl.GetProcAddress = (WGLGETPROCADDRESS_T) GetProcAddress(_glfw.wgl.instance, "wglGetProcAddress"); + _glfw.wgl.GetCurrentDC = (WGLGETCURRENTDC_T) + GetProcAddress(_glfw.wgl.instance, "wglGetCurrentDC"); _glfw.wgl.MakeCurrent = (WGLMAKECURRENT_T) GetProcAddress(_glfw.wgl.instance, "wglMakeCurrent"); _glfw.wgl.ShareLists = (WGLSHARELISTS_T) @@ -438,8 +492,8 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, PIXELFORMATDESCRIPTOR pfd; HGLRC share = NULL; - if (ctxconfig->client == GLFW_NO_API) - return GLFW_TRUE; + if (!_glfw.wgl.extensionsLoaded) + loadWGLExtensions(); if (ctxconfig->share) share = ctxconfig->share->context.wgl.handle; @@ -470,6 +524,40 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, return GLFW_FALSE; } + if (ctxconfig->client == GLFW_OPENGL_API) + { + if (ctxconfig->forward) + { + if (!_glfw.wgl.ARB_create_context) + { + _glfwInputError(GLFW_VERSION_UNAVAILABLE, + "WGL: A forward compatible OpenGL context requested but WGL_ARB_create_context is unavailable"); + return GLFW_FALSE; + } + } + + if (ctxconfig->profile) + { + if (!_glfw.wgl.ARB_create_context_profile) + { + _glfwInputError(GLFW_VERSION_UNAVAILABLE, + "WGL: OpenGL profile requested but WGL_ARB_create_context_profile is unavailable"); + return GLFW_FALSE; + } + } + } + else + { + if (!_glfw.wgl.ARB_create_context || + !_glfw.wgl.ARB_create_context_profile || + !_glfw.wgl.EXT_create_context_es2_profile) + { + _glfwInputError(GLFW_API_UNAVAILABLE, + "WGL: OpenGL ES requested but WGL_ARB_create_context_es2_profile is unavailable"); + return GLFW_FALSE; + } + } + if (_glfw.wgl.ARB_create_context) { int index = 0, mask = 0, flags = 0; @@ -588,102 +676,6 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, #undef setWGLattrib -// Analyzes the specified context for possible recreation -// -int _glfwAnalyzeContextWGL(_GLFWwindow* window, - const _GLFWctxconfig* ctxconfig, - const _GLFWfbconfig* fbconfig) -{ - GLFWbool required = GLFW_FALSE; - - if (_glfw.wgl.extensionsLoaded) - return _GLFW_RECREATION_NOT_NEEDED; - - makeContextCurrentWGL(window); - loadExtensions(); - - if (ctxconfig->client == GLFW_OPENGL_API) - { - if (ctxconfig->forward) - { - if (!_glfw.wgl.ARB_create_context) - { - _glfwInputError(GLFW_VERSION_UNAVAILABLE, - "WGL: A forward compatible OpenGL context requested but WGL_ARB_create_context is unavailable"); - return _GLFW_RECREATION_IMPOSSIBLE; - } - - required = GLFW_TRUE; - } - - if (ctxconfig->profile) - { - if (!_glfw.wgl.ARB_create_context_profile) - { - _glfwInputError(GLFW_VERSION_UNAVAILABLE, - "WGL: OpenGL profile requested but WGL_ARB_create_context_profile is unavailable"); - return _GLFW_RECREATION_IMPOSSIBLE; - } - - required = GLFW_TRUE; - } - - if (ctxconfig->release) - { - if (_glfw.wgl.ARB_context_flush_control) - required = GLFW_TRUE; - } - } - else - { - if (!_glfw.wgl.ARB_create_context || - !_glfw.wgl.ARB_create_context_profile || - !_glfw.wgl.EXT_create_context_es2_profile) - { - _glfwInputError(GLFW_API_UNAVAILABLE, - "WGL: OpenGL ES requested but WGL_ARB_create_context_es2_profile is unavailable"); - return _GLFW_RECREATION_IMPOSSIBLE; - } - - required = GLFW_TRUE; - } - - if (ctxconfig->major != 1 || ctxconfig->minor != 0) - { - if (_glfw.wgl.ARB_create_context) - required = GLFW_TRUE; - } - - if (ctxconfig->debug) - { - if (_glfw.wgl.ARB_create_context) - required = GLFW_TRUE; - } - - if (fbconfig->samples > 0) - { - // MSAA is not a hard constraint, so do nothing if it's not supported - if (_glfw.wgl.ARB_multisample && _glfw.wgl.ARB_pixel_format) - required = GLFW_TRUE; - } - - if (fbconfig->sRGB) - { - // sRGB is not a hard constraint, so do nothing if it's not supported - if ((_glfw.wgl.ARB_framebuffer_sRGB || - _glfw.wgl.EXT_framebuffer_sRGB) && - _glfw.wgl.ARB_pixel_format) - { - required = GLFW_TRUE; - } - } - - if (required) - return _GLFW_RECREATION_REQUIRED; - - return _GLFW_RECREATION_NOT_NEEDED; -} - ////////////////////////////////////////////////////////////////////////// ////// GLFW native API ////// diff --git a/src/wgl_context.h b/src/wgl_context.h index 9207e2f0..e3a22025 100644 --- a/src/wgl_context.h +++ b/src/wgl_context.h @@ -82,6 +82,7 @@ typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC,HGLRC,const int*) typedef HGLRC (WINAPI * WGLCREATECONTEXT_T)(HDC); typedef BOOL (WINAPI * WGLDELETECONTEXT_T)(HGLRC); typedef PROC (WINAPI * WGLGETPROCADDRESS_T)(LPCSTR); +typedef HDC (WINAPI * WGLGETCURRENTDC_T)(void); typedef BOOL (WINAPI * WGLMAKECURRENT_T)(HDC,HGLRC); typedef BOOL (WINAPI * WGLSHARELISTS_T)(HGLRC,HGLRC); @@ -89,6 +90,7 @@ typedef BOOL (WINAPI * WGLSHARELISTS_T)(HGLRC,HGLRC); #define wglCreateContext _glfw.wgl.CreateContext #define wglDeleteContext _glfw.wgl.DeleteContext #define wglGetProcAddress _glfw.wgl.GetProcAddress +#define wglGetCurrentDC _glfw.wgl.GetCurrentDC #define wglMakeCurrent _glfw.wgl.MakeCurrent #define wglShareLists _glfw.wgl.ShareLists @@ -118,6 +120,7 @@ typedef struct _GLFWlibraryWGL WGLCREATECONTEXT_T CreateContext; WGLDELETECONTEXT_T DeleteContext; WGLGETPROCADDRESS_T GetProcAddress; + WGLGETCURRENTDC_T GetCurrentDC; WGLMAKECURRENT_T MakeCurrent; WGLSHARELISTS_T ShareLists; @@ -147,8 +150,5 @@ void _glfwTerminateWGL(void); GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig); -int _glfwAnalyzeContextWGL(_GLFWwindow* window, - const _GLFWctxconfig* ctxconfig, - const _GLFWfbconfig* fbconfig); #endif // _glfw3_wgl_context_h_ diff --git a/src/win32_window.c b/src/win32_window.c index 32f8b68c..f46a44a6 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -928,21 +928,6 @@ static int createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig) return GLFW_TRUE; } -// Destroys the GLFW window and rendering context -// -static void destroyWindow(_GLFWwindow* window) -{ - if (_glfw.win32.disabledCursorWindow == window) - _glfw.win32.disabledCursorWindow = NULL; - - if (window->win32.handle) - { - RemovePropW(window->win32.handle, L"GLFW"); - DestroyWindow(window->win32.handle); - window->win32.handle = NULL; - } -} - ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// @@ -1001,8 +986,6 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig) { - int status; - if (!createWindow(window, wndconfig)) return GLFW_FALSE; @@ -1012,46 +995,6 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, { if (!_glfwCreateContextWGL(window, ctxconfig, fbconfig)) return GLFW_FALSE; - - status = _glfwAnalyzeContextWGL(window, ctxconfig, fbconfig); - - if (status == _GLFW_RECREATION_IMPOSSIBLE) - return GLFW_FALSE; - - if (status == _GLFW_RECREATION_REQUIRED) - { - // Some window hints require us to re-create the context using WGL - // extensions retrieved through the current context, as we cannot - // check for WGL extensions or retrieve WGL entry points before we - // have a current context (actually until we have implicitly loaded - // the vendor ICD) - - // Yes, this is strange, and yes, this is the proper way on WGL - - // As Windows only allows you to set the pixel format once for - // a window, we need to destroy the current window and create a new - // one to be able to use the new pixel format - - // Technically, it may be possible to keep the old window around if - // we're just creating an OpenGL 3.0+ context with the same pixel - // format, but it's not worth the added code complexity - - // First we clear the current context (the one we just created) - // This is usually done by glfwDestroyWindow, but as we're not doing - // full GLFW window destruction, it's duplicated here - window->context.makeCurrent(NULL); - - // Next destroy the Win32 window and WGL context (without resetting - // or destroying the GLFW window object) - window->context.destroy(window); - destroyWindow(window); - - // ...and then create them again, this time with better APIs - if (!createWindow(window, wndconfig)) - return GLFW_FALSE; - if (!_glfwCreateContextWGL(window, ctxconfig, fbconfig)) - return GLFW_FALSE; - } } else { @@ -1081,7 +1024,15 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) if (window->context.client != GLFW_NO_API) window->context.destroy(window); - destroyWindow(window); + if (_glfw.win32.disabledCursorWindow == window) + _glfw.win32.disabledCursorWindow = NULL; + + if (window->win32.handle) + { + RemovePropW(window->win32.handle, L"GLFW"); + DestroyWindow(window->win32.handle); + window->win32.handle = NULL; + } if (window->win32.bigIcon) DestroyIcon(window->win32.bigIcon);