Add run-time context creation API selection Fixes #145.
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dab94ef..5042aba 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt
@@ -7,23 +7,29 @@ if (_GLFW_COCOA) set(glfw_HEADERS ${common_HEADERS} cocoa_platform.h cocoa_joystick.h - posix_tls.h) + posix_tls.h nsgl_context.h) set(glfw_SOURCES ${common_SOURCES} cocoa_init.m cocoa_joystick.m - cocoa_monitor.m cocoa_window.m cocoa_time.c posix_tls.c) + cocoa_monitor.m cocoa_window.m cocoa_time.c posix_tls.c + nsgl_context.m) elseif (_GLFW_WIN32) - set(glfw_HEADERS ${common_HEADERS} win32_platform.h win32_joystick.h) + set(glfw_HEADERS ${common_HEADERS} win32_platform.h win32_joystick.h + wgl_context.h egl_context.h) set(glfw_SOURCES ${common_SOURCES} win32_init.c win32_joystick.c - win32_monitor.c win32_time.c win32_tls.c win32_window.c) + win32_monitor.c win32_time.c win32_tls.c win32_window.c + wgl_context.c egl_context.c) elseif (_GLFW_X11) set(glfw_HEADERS ${common_HEADERS} x11_platform.h xkb_unicode.h - linux_joystick.h posix_time.h posix_tls.h) + linux_joystick.h posix_time.h posix_tls.h glx_context.h + egl_context.h) set(glfw_SOURCES ${common_SOURCES} x11_init.c x11_monitor.c x11_window.c - xkb_unicode.c linux_joystick.c posix_time.c posix_tls.c) + xkb_unicode.c linux_joystick.c posix_time.c posix_tls.c + glx_context.c egl_context.c) elseif (_GLFW_WAYLAND) set(glfw_HEADERS ${common_HEADERS} wl_platform.h linux_joystick.h - posix_time.h posix_tls.h xkb_unicode.h) + posix_time.h posix_tls.h xkb_unicode.h egl_context.h) set(glfw_SOURCES ${common_SOURCES} wl_init.c wl_monitor.c wl_window.c - linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c) + linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c + egl_context.c) ecm_add_wayland_client_protocol(glfw_SOURCES PROTOCOL @@ -35,23 +41,10 @@ BASENAME pointer-constraints-unstable-v1) elseif (_GLFW_MIR) set(glfw_HEADERS ${common_HEADERS} mir_platform.h linux_joystick.h - posix_time.h posix_tls.h xkb_unicode.h) + posix_time.h posix_tls.h xkb_unicode.h egl_context.h) set(glfw_SOURCES ${common_SOURCES} mir_init.c mir_monitor.c mir_window.c - linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c) -endif() - -if (_GLFW_EGL) - list(APPEND glfw_HEADERS ${common_HEADERS} egl_context.h) - list(APPEND glfw_SOURCES ${common_SOURCES} egl_context.c) -elseif (_GLFW_NSGL) - list(APPEND glfw_HEADERS ${common_HEADERS} nsgl_context.h) - list(APPEND glfw_SOURCES ${common_SOURCES} nsgl_context.m) -elseif (_GLFW_WGL) - list(APPEND glfw_HEADERS ${common_HEADERS} wgl_context.h) - list(APPEND glfw_SOURCES ${common_SOURCES} wgl_context.c) -elseif (_GLFW_X11) - list(APPEND glfw_HEADERS ${common_HEADERS} glx_context.h) - list(APPEND glfw_SOURCES ${common_SOURCES} glx_context.c) + linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c + egl_context.c) endif() if (APPLE)
diff --git a/src/cocoa_init.m b/src/cocoa_init.m index 16b8c9f..9b6434d 100644 --- a/src/cocoa_init.m +++ b/src/cocoa_init.m
@@ -280,10 +280,7 @@ const char* _glfwPlatformGetVersionString(void) { - return _GLFW_VERSION_NUMBER " Cocoa" -#if defined(_GLFW_NSGL) - " NSGL" -#endif + return _GLFW_VERSION_NUMBER " Cocoa NSGL" #if defined(_GLFW_USE_CHDIR) " chdir" #endif
diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h index eeeb472..95eae62 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h
@@ -41,12 +41,7 @@ #include "posix_tls.h" #include "cocoa_joystick.h" - -#if defined(_GLFW_NSGL) - #include "nsgl_context.h" -#else - #error "The Cocoa backend depends on NSGL platform support" -#endif +#include "nsgl_context.h" #define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL) #define _glfw_dlclose(handle) dlclose(handle) @@ -58,6 +53,9 @@ #define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorNS ns #define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorNS ns +#define _GLFW_EGL_CONTEXT_STATE +#define _GLFW_EGL_LIBRARY_CONTEXT_STATE + // Cocoa-specific per-window data //
diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 6f51439..f5e9928 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m
@@ -209,7 +209,7 @@ - (void)windowDidResize:(NSNotification *)notification { - if (window->context.api != GLFW_NO_API) + if (window->context.client != GLFW_NO_API) [window->context.nsgl.object update]; if (_glfw.cursorWindow == window && @@ -227,7 +227,7 @@ - (void)windowDidMove:(NSNotification *)notification { - if (window->context.api != GLFW_NO_API) + if (window->context.client != GLFW_NO_API) [window->context.nsgl.object update]; if (_glfw.cursorWindow == window && @@ -1002,10 +1002,18 @@ if (!createWindow(window, wndconfig)) return GLFW_FALSE; - if (ctxconfig->api != GLFW_NO_API) + if (ctxconfig->client != GLFW_NO_API) { - if (!_glfwCreateContextNSGL(window, ctxconfig, fbconfig)) + if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API) + { + if (!_glfwCreateContextNSGL(window, ctxconfig, fbconfig)) + return GLFW_FALSE; + } + else + { + _glfwInputError(GLFW_API_UNAVAILABLE, "Cocoa: EGL not available"); return GLFW_FALSE; + } } if (window->monitor) @@ -1026,8 +1034,8 @@ if (window->monitor) releaseMonitor(window); - if (window->context.api != GLFW_NO_API) - _glfwDestroyContextNSGL(window); + if (window->context.client != GLFW_NO_API) + window->context.destroyContext(window); [window->ns.object setDelegate:nil]; [window->ns.delegate release];
diff --git a/src/context.c b/src/context.c index eb8a561..5f4a08c 100644 --- a/src/context.c +++ b/src/context.c
@@ -90,17 +90,26 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig) { - if (ctxconfig->api != GLFW_NO_API && - ctxconfig->api != GLFW_OPENGL_API && - ctxconfig->api != GLFW_OPENGL_ES_API) + if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API && + ctxconfig->source != GLFW_EGL_CONTEXT_API) { _glfwInputError(GLFW_INVALID_ENUM, - "Invalid client API %i", - ctxconfig->api); + "Invalid context creation API %i", + ctxconfig->source); return GLFW_FALSE; } - if (ctxconfig->api == GLFW_OPENGL_API) + if (ctxconfig->client != GLFW_NO_API && + ctxconfig->client != GLFW_OPENGL_API && + ctxconfig->client != GLFW_OPENGL_ES_API) + { + _glfwInputError(GLFW_INVALID_ENUM, + "Invalid client API %i", + ctxconfig->client); + return GLFW_FALSE; + } + + if (ctxconfig->client == GLFW_OPENGL_API) { if ((ctxconfig->major < 1 || ctxconfig->minor < 0) || (ctxconfig->major == 1 && ctxconfig->minor > 5) || @@ -150,7 +159,7 @@ return GLFW_FALSE; } } - else if (ctxconfig->api == GLFW_OPENGL_ES_API) + else if (ctxconfig->client == GLFW_OPENGL_ES_API) { if (ctxconfig->major < 1 || ctxconfig->minor < 0 || (ctxconfig->major == 1 && ctxconfig->minor > 1) || @@ -366,8 +375,13 @@ glfwGetProcAddress("glGetIntegerv"); window->context.GetString = (PFNGLGETSTRINGPROC) glfwGetProcAddress("glGetString"); + if (!window->context.GetIntegerv || !window->context.GetString) + { + _glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken"); + return GLFW_FALSE; + } - if (!parseVersionString(&window->context.api, + if (!parseVersionString(&window->context.client, &window->context.major, &window->context.minor, &window->context.revision)) @@ -375,6 +389,8 @@ return GLFW_FALSE; } + window->context.source = ctxconfig->source; + if (window->context.major < ctxconfig->major || (window->context.major == ctxconfig->major && window->context.minor < ctxconfig->minor)) @@ -409,7 +425,7 @@ } } - if (window->context.api == GLFW_OPENGL_API) + if (window->context.client == GLFW_OPENGL_API) { // Read back context flags (OpenGL 3.0 and above) if (window->context.major >= 3) @@ -507,7 +523,7 @@ { PFNGLCLEARPROC glClear = (PFNGLCLEARPROC) glfwGetProcAddress("glClear"); glClear(GL_COLOR_BUFFER_BIT); - _glfwPlatformSwapBuffers(window); + window->context.swapBuffers(window); } return GLFW_TRUE; @@ -547,16 +563,24 @@ GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle; + _GLFWwindow* previous = _glfwPlatformGetCurrentContext(); _GLFW_REQUIRE_INIT(); - if (window && window->context.api == GLFW_NO_API) + if (window && window->context.client == GLFW_NO_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return; } - _glfwPlatformMakeContextCurrent(window); + if (previous) + { + if (!window || window->context.source != previous->context.source) + previous->context.makeContextCurrent(NULL); + } + + if (window) + window->context.makeContextCurrent(window); } GLFWAPI GLFWwindow* glfwGetCurrentContext(void) @@ -572,26 +596,29 @@ _GLFW_REQUIRE_INIT(); - if (window->context.api == GLFW_NO_API) + if (window->context.client == GLFW_NO_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return; } - _glfwPlatformSwapBuffers(window); + window->context.swapBuffers(window); } GLFWAPI void glfwSwapInterval(int interval) { + _GLFWwindow* window; + _GLFW_REQUIRE_INIT(); - if (!_glfwPlatformGetCurrentContext()) + window = _glfwPlatformGetCurrentContext(); + if (!window) { _glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL); return; } - _glfwPlatformSwapInterval(interval); + window->context.swapInterval(interval); } GLFWAPI int glfwExtensionSupported(const char* extension) @@ -657,21 +684,23 @@ } // Check if extension is in the platform-specific string - return _glfwPlatformExtensionSupported(extension); + return window->context.extensionSupported(extension); } GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname) { + _GLFWwindow* window; assert(procname != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - if (!_glfwPlatformGetCurrentContext()) + window = _glfwPlatformGetCurrentContext(); + if (!window) { _glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL); return NULL; } - return _glfwPlatformGetProcAddress(procname); + return window->context.getProcAddress(procname); }
diff --git a/src/egl_context.c b/src/egl_context.c index 26df456..0620302 100644 --- a/src/egl_context.c +++ b/src/egl_context.c
@@ -125,7 +125,7 @@ continue; #endif // _GLFW_X11 - if (ctxconfig->api == GLFW_OPENGL_ES_API) + if (ctxconfig->client == GLFW_OPENGL_ES_API) { if (ctxconfig->major == 1) { @@ -138,7 +138,7 @@ continue; } } - else if (ctxconfig->api == GLFW_OPENGL_API) + else if (ctxconfig->client == GLFW_OPENGL_API) { if (!(getConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT)) continue; @@ -169,6 +169,110 @@ return closest != NULL; } +static void makeContextCurrent(_GLFWwindow* window) +{ + if (window) + { + if (!eglMakeCurrent(_glfw.egl.display, + window->context.egl.surface, + window->context.egl.surface, + window->context.egl.handle)) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "EGL: Failed to make context current: %s", + getErrorString(eglGetError())); + return; + } + } + else + { + if (!eglMakeCurrent(_glfw.egl.display, + EGL_NO_SURFACE, + EGL_NO_SURFACE, + EGL_NO_CONTEXT)) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "EGL: Failed to clear current context: %s", + getErrorString(eglGetError())); + return; + } + } + + _glfwPlatformSetCurrentContext(window); +} + +static void swapBuffers(_GLFWwindow* window) +{ + if (window != _glfwPlatformGetCurrentContext()) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "EGL: The context must be current on the calling thread when swapping buffers"); + return; + } + + eglSwapBuffers(_glfw.egl.display, window->context.egl.surface); +} + +static void swapInterval(int interval) +{ + eglSwapInterval(_glfw.egl.display, interval); +} + +static int extensionSupported(const char* extension) +{ + const char* extensions = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS); + if (extensions) + { + if (_glfwStringInExtensionString(extension, extensions)) + return GLFW_TRUE; + } + + return GLFW_FALSE; +} + +static GLFWglproc getProcAddress(const char* procname) +{ + _GLFWwindow* window = _glfwPlatformGetCurrentContext(); + + if (window->context.egl.client) + { + GLFWglproc proc = (GLFWglproc) _glfw_dlsym(window->context.egl.client, + procname); + if (proc) + return proc; + } + + return eglGetProcAddress(procname); +} + +static void destroyContext(_GLFWwindow* window) +{ +#if defined(_GLFW_X11) + // NOTE: Do not unload libGL.so.1 while the X11 display is still open, + // as it will make XCloseDisplay segfault + if (window->context.client != GLFW_OPENGL_API) +#endif // _GLFW_X11 + { + if (window->context.egl.client) + { + _glfw_dlclose(window->context.egl.client); + window->context.egl.client = NULL; + } + } + + if (window->context.egl.surface) + { + eglDestroySurface(_glfw.egl.display, window->context.egl.surface); + window->context.egl.surface = EGL_NO_SURFACE; + } + + if (window->context.egl.handle) + { + eglDestroyContext(_glfw.egl.display, window->context.egl.handle); + window->context.egl.handle = EGL_NO_CONTEXT; + } +} + ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// @@ -200,10 +304,7 @@ } if (!_glfw.egl.handle) - { - _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to load EGL"); return GLFW_FALSE; - } _glfw.egl.GetConfigAttrib = (PFNEGLGETCONFIGATTRIBPROC) _glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib"); @@ -244,6 +345,8 @@ _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to get EGL display: %s", getErrorString(eglGetError())); + + _glfwTerminateEGL(); return GLFW_FALSE; } @@ -252,15 +355,17 @@ _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to initialize EGL: %s", getErrorString(eglGetError())); + + _glfwTerminateEGL(); return GLFW_FALSE; } _glfw.egl.KHR_create_context = - _glfwPlatformExtensionSupported("EGL_KHR_create_context"); + extensionSupported("EGL_KHR_create_context"); _glfw.egl.KHR_create_context_no_error = - _glfwPlatformExtensionSupported("EGL_KHR_create_context_no_error"); + extensionSupported("EGL_KHR_create_context_no_error"); _glfw.egl.KHR_gl_colorspace = - _glfwPlatformExtensionSupported("EGL_KHR_gl_colorspace"); + extensionSupported("EGL_KHR_gl_colorspace"); return GLFW_TRUE; } @@ -299,6 +404,12 @@ EGLConfig config; EGLContext share = NULL; + if (!_glfw.egl.display) + { + _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: API not available"); + return GLFW_FALSE; + } + if (ctxconfig->share) share = ctxconfig->share->context.egl.handle; @@ -309,7 +420,7 @@ return GLFW_FALSE; } - if (ctxconfig->api == GLFW_OPENGL_ES_API) + if (ctxconfig->client == GLFW_OPENGL_ES_API) { if (!eglBindAPI(EGL_OPENGL_ES_API)) { @@ -334,7 +445,7 @@ { int index = 0, mask = 0, flags = 0; - if (ctxconfig->api == GLFW_OPENGL_API) + if (ctxconfig->client == GLFW_OPENGL_API) { if (ctxconfig->forward) flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; @@ -388,7 +499,7 @@ { int index = 0; - if (ctxconfig->api == GLFW_OPENGL_ES_API) + if (ctxconfig->client == GLFW_OPENGL_ES_API) setEGLattrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major); setEGLattrib(EGL_NONE, EGL_NONE); @@ -477,7 +588,7 @@ NULL }; - if (ctxconfig->api == GLFW_OPENGL_ES_API) + if (ctxconfig->client == GLFW_OPENGL_ES_API) { if (ctxconfig->major == 1) sonames = es1sonames; @@ -502,41 +613,18 @@ } } + window->context.makeContextCurrent = makeContextCurrent; + window->context.swapBuffers = swapBuffers; + window->context.swapInterval = swapInterval; + window->context.extensionSupported = extensionSupported; + window->context.getProcAddress = getProcAddress; + window->context.destroyContext = destroyContext; + return GLFW_TRUE; } #undef setEGLattrib -// Destroy the OpenGL context -// -void _glfwDestroyContextEGL(_GLFWwindow* window) -{ -#if defined(_GLFW_X11) - // NOTE: Do not unload libGL.so.1 while the X11 display is still open, - // as it will make XCloseDisplay segfault - if (window->context.api != GLFW_OPENGL_API) -#endif // _GLFW_X11 - { - if (window->context.egl.client) - { - _glfw_dlclose(window->context.egl.client); - window->context.egl.client = NULL; - } - } - - if (window->context.egl.surface) - { - eglDestroySurface(_glfw.egl.display, window->context.egl.surface); - window->context.egl.surface = EGL_NO_SURFACE; - } - - if (window->context.egl.handle) - { - eglDestroyContext(_glfw.egl.display, window->context.egl.handle); - window->context.egl.handle = EGL_NO_CONTEXT; - } -} - // Returns the Visual and depth of the chosen EGLConfig // #if defined(_GLFW_X11) @@ -581,87 +669,6 @@ ////////////////////////////////////////////////////////////////////////// -////// GLFW platform API ////// -////////////////////////////////////////////////////////////////////////// - -void _glfwPlatformMakeContextCurrent(_GLFWwindow* window) -{ - if (window) - { - if (!eglMakeCurrent(_glfw.egl.display, - window->context.egl.surface, - window->context.egl.surface, - window->context.egl.handle)) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "EGL: Failed to make context current: %s", - getErrorString(eglGetError())); - return; - } - } - else - { - if (!eglMakeCurrent(_glfw.egl.display, - EGL_NO_SURFACE, - EGL_NO_SURFACE, - EGL_NO_CONTEXT)) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "EGL: Failed to clear current context: %s", - getErrorString(eglGetError())); - return; - } - } - - _glfwPlatformSetCurrentContext(window); -} - -void _glfwPlatformSwapBuffers(_GLFWwindow* window) -{ - if (window != _glfwPlatformGetCurrentContext()) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "EGL: The context must be current on the calling thread when swapping buffers"); - return; - } - - eglSwapBuffers(_glfw.egl.display, window->context.egl.surface); -} - -void _glfwPlatformSwapInterval(int interval) -{ - eglSwapInterval(_glfw.egl.display, interval); -} - -int _glfwPlatformExtensionSupported(const char* extension) -{ - const char* extensions = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS); - if (extensions) - { - if (_glfwStringInExtensionString(extension, extensions)) - return GLFW_TRUE; - } - - return GLFW_FALSE; -} - -GLFWglproc _glfwPlatformGetProcAddress(const char* procname) -{ - _GLFWwindow* window = _glfwPlatformGetCurrentContext(); - - if (window->context.egl.client) - { - GLFWglproc proc = (GLFWglproc) _glfw_dlsym(window->context.egl.client, - procname); - if (proc) - return proc; - } - - return eglGetProcAddress(procname); -} - - -////////////////////////////////////////////////////////////////////////// ////// GLFW native API ////// ////////////////////////////////////////////////////////////////////////// @@ -676,7 +683,7 @@ _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT); - if (window->context.api == GLFW_NO_API) + if (window->context.client == GLFW_NO_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return EGL_NO_CONTEXT; @@ -690,7 +697,7 @@ _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE); - if (window->context.api == GLFW_NO_API) + if (window->context.client == GLFW_NO_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return EGL_NO_SURFACE;
diff --git a/src/egl_context.h b/src/egl_context.h index 0b0b4dc..aed8a25 100644 --- a/src/egl_context.h +++ b/src/egl_context.h
@@ -149,8 +149,8 @@ #define eglQueryString _glfw.egl.QueryString #define eglGetProcAddress _glfw.egl.GetProcAddress -#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextEGL egl -#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryEGL egl +#define _GLFW_EGL_CONTEXT_STATE _GLFWcontextEGL egl +#define _GLFW_EGL_LIBRARY_CONTEXT_STATE _GLFWlibraryEGL egl // EGL-specific per-context data @@ -204,7 +204,6 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig); -void _glfwDestroyContextEGL(_GLFWwindow* window); #if defined(_GLFW_X11) GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig,
diff --git a/src/glfw_config.h.in b/src/glfw_config.h.in index ab57dd5..aed7f7a 100644 --- a/src/glfw_config.h.in +++ b/src/glfw_config.h.in
@@ -45,15 +45,6 @@ // Define this to 1 if building GLFW for Mir #cmakedefine _GLFW_MIR -// Define this to 1 if building GLFW for EGL -#cmakedefine _GLFW_EGL -// Define this to 1 if building GLFW for GLX -#cmakedefine _GLFW_GLX -// Define this to 1 if building GLFW for WGL -#cmakedefine _GLFW_WGL -// Define this to 1 if building GLFW for NSGL -#cmakedefine _GLFW_NSGL - // Define this to 1 if building as a shared library / dynamic library / DLL #cmakedefine _GLFW_BUILD_DLL
diff --git a/src/glx_context.c b/src/glx_context.c index 0a5b833..1760582 100644 --- a/src/glx_context.c +++ b/src/glx_context.c
@@ -142,6 +142,96 @@ True); } +static void makeContextCurrent(_GLFWwindow* window) +{ + if (window) + { + if (!glXMakeCurrent(_glfw.x11.display, + window->context.glx.window, + window->context.glx.handle)) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "GLX: Failed to make context current"); + return; + } + } + else + { + if (!glXMakeCurrent(_glfw.x11.display, None, NULL)) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "GLX: Failed to clear current context"); + return; + } + } + + _glfwPlatformSetCurrentContext(window); +} + +static void swapBuffers(_GLFWwindow* window) +{ + glXSwapBuffers(_glfw.x11.display, window->context.glx.window); +} + +static void swapInterval(int interval) +{ + _GLFWwindow* window = _glfwPlatformGetCurrentContext(); + + if (_glfw.glx.EXT_swap_control) + { + _glfw.glx.SwapIntervalEXT(_glfw.x11.display, + window->context.glx.window, + interval); + } + else if (_glfw.glx.MESA_swap_control) + _glfw.glx.SwapIntervalMESA(interval); + else if (_glfw.glx.SGI_swap_control) + { + if (interval > 0) + _glfw.glx.SwapIntervalSGI(interval); + } +} + +static int extensionSupported(const char* extension) +{ + const char* extensions = + glXQueryExtensionsString(_glfw.x11.display, _glfw.x11.screen); + if (extensions) + { + if (_glfwStringInExtensionString(extension, extensions)) + return GLFW_TRUE; + } + + return GLFW_FALSE; +} + +static GLFWglproc getProcAddress(const char* procname) +{ + if (_glfw.glx.GetProcAddress) + return _glfw.glx.GetProcAddress((const GLubyte*) procname); + else if (_glfw.glx.GetProcAddressARB) + return _glfw.glx.GetProcAddressARB((const GLubyte*) procname); + else + return dlsym(_glfw.glx.handle, procname); +} + +// Destroy the OpenGL context +// +static void destroyContext(_GLFWwindow* window) +{ + if (window->context.glx.window) + { + glXDestroyWindow(_glfw.x11.display, window->context.glx.window); + window->context.glx.window = None; + } + + if (window->context.glx.handle) + { + glXDestroyContext(_glfw.x11.display, window->context.glx.handle); + window->context.glx.handle = NULL; + } +} + ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// @@ -229,61 +319,61 @@ return GLFW_FALSE; } - if (_glfwPlatformExtensionSupported("GLX_EXT_swap_control")) + if (extensionSupported("GLX_EXT_swap_control")) { _glfw.glx.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) - _glfwPlatformGetProcAddress("glXSwapIntervalEXT"); + getProcAddress("glXSwapIntervalEXT"); if (_glfw.glx.SwapIntervalEXT) _glfw.glx.EXT_swap_control = GLFW_TRUE; } - if (_glfwPlatformExtensionSupported("GLX_SGI_swap_control")) + if (extensionSupported("GLX_SGI_swap_control")) { _glfw.glx.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) - _glfwPlatformGetProcAddress("glXSwapIntervalSGI"); + getProcAddress("glXSwapIntervalSGI"); if (_glfw.glx.SwapIntervalSGI) _glfw.glx.SGI_swap_control = GLFW_TRUE; } - if (_glfwPlatformExtensionSupported("GLX_MESA_swap_control")) + if (extensionSupported("GLX_MESA_swap_control")) { _glfw.glx.SwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC) - _glfwPlatformGetProcAddress("glXSwapIntervalMESA"); + getProcAddress("glXSwapIntervalMESA"); if (_glfw.glx.SwapIntervalMESA) _glfw.glx.MESA_swap_control = GLFW_TRUE; } - if (_glfwPlatformExtensionSupported("GLX_ARB_multisample")) + if (extensionSupported("GLX_ARB_multisample")) _glfw.glx.ARB_multisample = GLFW_TRUE; - if (_glfwPlatformExtensionSupported("GLX_ARB_framebuffer_sRGB")) + if (extensionSupported("GLX_ARB_framebuffer_sRGB")) _glfw.glx.ARB_framebuffer_sRGB = GLFW_TRUE; - if (_glfwPlatformExtensionSupported("GLX_EXT_framebuffer_sRGB")) + if (extensionSupported("GLX_EXT_framebuffer_sRGB")) _glfw.glx.EXT_framebuffer_sRGB = GLFW_TRUE; - if (_glfwPlatformExtensionSupported("GLX_ARB_create_context")) + if (extensionSupported("GLX_ARB_create_context")) { _glfw.glx.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) - _glfwPlatformGetProcAddress("glXCreateContextAttribsARB"); + getProcAddress("glXCreateContextAttribsARB"); if (_glfw.glx.CreateContextAttribsARB) _glfw.glx.ARB_create_context = GLFW_TRUE; } - if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_robustness")) + if (extensionSupported("GLX_ARB_create_context_robustness")) _glfw.glx.ARB_create_context_robustness = GLFW_TRUE; - if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_profile")) + if (extensionSupported("GLX_ARB_create_context_profile")) _glfw.glx.ARB_create_context_profile = GLFW_TRUE; - if (_glfwPlatformExtensionSupported("GLX_EXT_create_context_es2_profile")) + if (extensionSupported("GLX_EXT_create_context_es2_profile")) _glfw.glx.EXT_create_context_es2_profile = GLFW_TRUE; - if (_glfwPlatformExtensionSupported("GLX_ARB_context_flush_control")) + if (extensionSupported("GLX_ARB_context_flush_control")) _glfw.glx.ARB_context_flush_control = GLFW_TRUE; return GLFW_TRUE; @@ -330,7 +420,7 @@ return GLFW_FALSE; } - if (ctxconfig->api == GLFW_OPENGL_ES_API) + if (ctxconfig->client == GLFW_OPENGL_ES_API) { if (!_glfw.glx.ARB_create_context || !_glfw.glx.ARB_create_context_profile || @@ -369,7 +459,7 @@ { int index = 0, mask = 0, flags = 0; - if (ctxconfig->api == GLFW_OPENGL_API) + if (ctxconfig->client == GLFW_OPENGL_API) { if (ctxconfig->forward) flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; @@ -454,7 +544,7 @@ if (!window->context.glx.handle) { if (_glfw.x11.errorCode == _glfw.glx.errorBase + GLXBadProfileARB && - ctxconfig->api == GLFW_OPENGL_API && + ctxconfig->client == GLFW_OPENGL_API && ctxconfig->profile == GLFW_OPENGL_ANY_PROFILE && ctxconfig->forward == GLFW_FALSE) { @@ -482,28 +572,18 @@ return GLFW_FALSE; } + window->context.makeContextCurrent = makeContextCurrent; + window->context.swapBuffers = swapBuffers; + window->context.swapInterval = swapInterval; + window->context.extensionSupported = extensionSupported; + window->context.getProcAddress = getProcAddress; + window->context.destroyContext = destroyContext; + return GLFW_TRUE; } #undef setGLXattrib -// Destroy the OpenGL context -// -void _glfwDestroyContextGLX(_GLFWwindow* window) -{ - if (window->context.glx.window) - { - glXDestroyWindow(_glfw.x11.display, window->context.glx.window); - window->context.glx.window = None; - } - - if (window->context.glx.handle) - { - glXDestroyContext(_glfw.x11.display, window->context.glx.handle); - window->context.glx.handle = NULL; - } -} - // Returns the Visual and depth of the chosen GLXFBConfig // GLFWbool _glfwChooseVisualGLX(const _GLFWctxconfig* ctxconfig, @@ -537,84 +617,6 @@ ////////////////////////////////////////////////////////////////////////// -////// GLFW platform API ////// -////////////////////////////////////////////////////////////////////////// - -void _glfwPlatformMakeContextCurrent(_GLFWwindow* window) -{ - if (window) - { - if (!glXMakeCurrent(_glfw.x11.display, - window->context.glx.window, - window->context.glx.handle)) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "GLX: Failed to make context current"); - return; - } - } - else - { - if (!glXMakeCurrent(_glfw.x11.display, None, NULL)) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "GLX: Failed to clear current context"); - return; - } - } - - _glfwPlatformSetCurrentContext(window); -} - -void _glfwPlatformSwapBuffers(_GLFWwindow* window) -{ - glXSwapBuffers(_glfw.x11.display, window->context.glx.window); -} - -void _glfwPlatformSwapInterval(int interval) -{ - _GLFWwindow* window = _glfwPlatformGetCurrentContext(); - - if (_glfw.glx.EXT_swap_control) - { - _glfw.glx.SwapIntervalEXT(_glfw.x11.display, - window->context.glx.window, - interval); - } - else if (_glfw.glx.MESA_swap_control) - _glfw.glx.SwapIntervalMESA(interval); - else if (_glfw.glx.SGI_swap_control) - { - if (interval > 0) - _glfw.glx.SwapIntervalSGI(interval); - } -} - -int _glfwPlatformExtensionSupported(const char* extension) -{ - const char* extensions = - glXQueryExtensionsString(_glfw.x11.display, _glfw.x11.screen); - if (extensions) - { - if (_glfwStringInExtensionString(extension, extensions)) - return GLFW_TRUE; - } - - return GLFW_FALSE; -} - -GLFWglproc _glfwPlatformGetProcAddress(const char* procname) -{ - if (_glfw.glx.GetProcAddress) - return _glfw.glx.GetProcAddress((const GLubyte*) procname); - else if (_glfw.glx.GetProcAddressARB) - return _glfw.glx.GetProcAddressARB((const GLubyte*) procname); - else - return dlsym(_glfw.glx.handle, procname); -} - - -////////////////////////////////////////////////////////////////////////// ////// GLFW native API ////// ////////////////////////////////////////////////////////////////////////// @@ -623,7 +625,7 @@ _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - if (window->context.api == GLFW_NO_API) + if (window->context.client == GLFW_NO_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return NULL; @@ -637,7 +639,7 @@ _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(None); - if (window->context.api == GLFW_NO_API) + if (window->context.client == GLFW_NO_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return None;
diff --git a/src/internal.h b/src/internal.h index e830477..6c084f8 100644 --- a/src/internal.h +++ b/src/internal.h
@@ -58,6 +58,13 @@ typedef struct _GLFWmonitor _GLFWmonitor; typedef struct _GLFWcursor _GLFWcursor; +typedef void (* _GLFWmakecontextcurrentfun)(_GLFWwindow*); +typedef void (* _GLFWswapbuffersfun)(_GLFWwindow*); +typedef void (* _GLFWswapintervalfun)(int); +typedef int (* _GLFWextensionsupportedfun)(const char*); +typedef GLFWglproc (* _GLFWgetprocaddressfun)(const char*); +typedef void (* _GLFWdestroycontextfun)(_GLFWwindow*); + #define GL_VERSION 0x1f02 #define GL_NONE 0 #define GL_COLOR_BUFFER_BIT 0x00004000 @@ -258,7 +265,8 @@ */ struct _GLFWctxconfig { - int api; + int client; + int source; int major; int minor; GLFWbool forward; @@ -304,7 +312,8 @@ */ struct _GLFWcontext { - int api; + int client; + int source; int major, minor, revision; GLFWbool forward, debug, noerror; int profile; @@ -315,8 +324,17 @@ PFNGLGETINTEGERVPROC GetIntegerv; PFNGLGETSTRINGPROC GetString; + _GLFWmakecontextcurrentfun makeContextCurrent; + _GLFWswapbuffersfun swapBuffers; + _GLFWswapintervalfun swapInterval; + _GLFWextensionsupportedfun extensionSupported; + _GLFWgetprocaddressfun getProcAddress; + _GLFWdestroycontextfun destroyContext; + // This is defined in the context API's context.h _GLFW_PLATFORM_CONTEXT_STATE; + // This is defined in egl_context.h + _GLFW_EGL_CONTEXT_STATE; }; @@ -461,6 +479,8 @@ _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE; // This is defined in the platform's tls.h _GLFW_PLATFORM_LIBRARY_TLS_STATE; + // This is defined in egl_context.h + _GLFW_EGL_LIBRARY_CONTEXT_STATE; }; @@ -742,11 +762,6 @@ */ void _glfwPlatformPostEmptyEvent(void); -/*! @copydoc glfwMakeContextCurrent - * @ingroup platform - */ -void _glfwPlatformMakeContextCurrent(_GLFWwindow* window); - /*! @ingroup platform */ void _glfwPlatformSetCurrentContext(_GLFWwindow* context); @@ -756,26 +771,6 @@ */ _GLFWwindow* _glfwPlatformGetCurrentContext(void); -/*! @copydoc glfwSwapBuffers - * @ingroup platform - */ -void _glfwPlatformSwapBuffers(_GLFWwindow* window); - -/*! @copydoc glfwSwapInterval - * @ingroup platform - */ -void _glfwPlatformSwapInterval(int interval); - -/*! @copydoc glfwExtensionSupported - * @ingroup platform - */ -int _glfwPlatformExtensionSupported(const char* extension); - -/*! @copydoc glfwGetProcAddress - * @ingroup platform - */ -GLFWglproc _glfwPlatformGetProcAddress(const char* procname); - /*! @copydoc glfwCreateCursor * @ingroup platform */
diff --git a/src/mir_platform.h b/src/mir_platform.h index 5d328c2..66c6776 100644 --- a/src/mir_platform.h +++ b/src/mir_platform.h
@@ -51,12 +51,7 @@ #include "posix_time.h" #include "linux_joystick.h" #include "xkb_unicode.h" - -#if defined(_GLFW_EGL) - #include "egl_context.h" -#else - #error "The Mir backend depends on EGL platform support" -#endif +#include "egl_context.h" #define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL) #define _glfw_dlclose(handle) dlclose(handle) @@ -70,6 +65,9 @@ #define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryMir mir #define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorMir mir +#define _GLFW_PLATFORM_CONTEXT_STATE +#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE + // Mir-specific Event Queue //
diff --git a/src/mir_window.c b/src/mir_window.c index 8ab4a4f..26ee526 100644 --- a/src/mir_window.c +++ b/src/mir_window.c
@@ -378,7 +378,7 @@ window->mir.window = mir_buffer_stream_get_egl_native_window( mir_surface_get_buffer_stream(window->mir.surface)); - if (ctxconfig->api != GLFW_NO_API) + if (ctxconfig->client != GLFW_NO_API) { if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig)) return GLFW_FALSE; @@ -395,7 +395,8 @@ window->mir.surface = NULL; } - _glfwDestroyContextEGL(window); + if (window->context.client != GLFW_NO_API) + window->context.destroyContext(window); } void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
diff --git a/src/nsgl_context.m b/src/nsgl_context.m index 714d527..1b515cb 100644 --- a/src/nsgl_context.m +++ b/src/nsgl_context.m
@@ -27,6 +27,63 @@ #include "internal.h" +static void makeContextCurrent(_GLFWwindow* window) +{ + if (window) + [window->context.nsgl.object makeCurrentContext]; + else + [NSOpenGLContext clearCurrentContext]; + + _glfwPlatformSetCurrentContext(window); +} + +static void swapBuffers(_GLFWwindow* window) +{ + // ARP appears to be unnecessary, but this is future-proof + [window->context.nsgl.object flushBuffer]; +} + +static void swapInterval(int interval) +{ + _GLFWwindow* window = _glfwPlatformGetCurrentContext(); + + GLint sync = interval; + [window->context.nsgl.object setValues:&sync + forParameter:NSOpenGLCPSwapInterval]; +} + +static int extensionSupported(const char* extension) +{ + // There are no NSGL extensions + return GLFW_FALSE; +} + +static GLFWglproc getProcAddress(const char* procname) +{ + CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault, + procname, + kCFStringEncodingASCII); + + GLFWglproc symbol = CFBundleGetFunctionPointerForName(_glfw.nsgl.framework, + symbolName); + + CFRelease(symbolName); + + return symbol; +} + +// Destroy the OpenGL context +// +static void destroyContext(_GLFWwindow* window) +{ + [window->context.nsgl.pixelFormat release]; + window->context.nsgl.pixelFormat = nil; + + [window->context.nsgl.object release]; + window->context.nsgl.object = nil; +} + + ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// @@ -61,7 +118,7 @@ { unsigned int attributeCount = 0; - if (ctxconfig->api == GLFW_OPENGL_ES_API) + if (ctxconfig->client == GLFW_OPENGL_ES_API) { _glfwInputError(GLFW_API_UNAVAILABLE, "NSGL: OpenGL ES is not available on OS X"); @@ -216,70 +273,17 @@ } [window->context.nsgl.object setView:window->ns.view]; + + window->context.makeContextCurrent = makeContextCurrent; + window->context.swapBuffers = swapBuffers; + window->context.swapInterval = swapInterval; + window->context.extensionSupported = extensionSupported; + window->context.getProcAddress = getProcAddress; + window->context.destroyContext = destroyContext; + return GLFW_TRUE; } -// Destroy the OpenGL context -// -void _glfwDestroyContextNSGL(_GLFWwindow* window) -{ - [window->context.nsgl.pixelFormat release]; - window->context.nsgl.pixelFormat = nil; - - [window->context.nsgl.object release]; - window->context.nsgl.object = nil; -} - - -////////////////////////////////////////////////////////////////////////// -////// GLFW platform API ////// -////////////////////////////////////////////////////////////////////////// - -void _glfwPlatformMakeContextCurrent(_GLFWwindow* window) -{ - if (window) - [window->context.nsgl.object makeCurrentContext]; - else - [NSOpenGLContext clearCurrentContext]; - - _glfwPlatformSetCurrentContext(window); -} - -void _glfwPlatformSwapBuffers(_GLFWwindow* window) -{ - // ARP appears to be unnecessary, but this is future-proof - [window->context.nsgl.object flushBuffer]; -} - -void _glfwPlatformSwapInterval(int interval) -{ - _GLFWwindow* window = _glfwPlatformGetCurrentContext(); - - GLint sync = interval; - [window->context.nsgl.object setValues:&sync - forParameter:NSOpenGLCPSwapInterval]; -} - -int _glfwPlatformExtensionSupported(const char* extension) -{ - // There are no NSGL extensions - return GLFW_FALSE; -} - -GLFWglproc _glfwPlatformGetProcAddress(const char* procname) -{ - CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault, - procname, - kCFStringEncodingASCII); - - GLFWglproc symbol = CFBundleGetFunctionPointerForName(_glfw.nsgl.framework, - symbolName); - - CFRelease(symbolName); - - return symbol; -} - ////////////////////////////////////////////////////////////////////////// ////// GLFW native API ////// @@ -290,7 +294,7 @@ _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(nil); - if (window->context.api == GLFW_NO_API) + if (window->context.client == GLFW_NO_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return NULL;
diff --git a/src/wgl_context.c b/src/wgl_context.c index 608587c..55399cb 100644 --- a/src/wgl_context.c +++ b/src/wgl_context.c
@@ -32,55 +32,6 @@ #include <assert.h> -// Initialize WGL-specific extensions -// -static void loadExtensions(void) -{ - // Functions for WGL_EXT_extension_string - // NOTE: These are needed by _glfwPlatformExtensionSupported - _glfw.wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC) - wglGetProcAddress("wglGetExtensionsStringEXT"); - _glfw.wgl.GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) - wglGetProcAddress("wglGetExtensionsStringARB"); - - // Functions for WGL_ARB_create_context - _glfw.wgl.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) - wglGetProcAddress("wglCreateContextAttribsARB"); - - // Functions for WGL_EXT_swap_control - _glfw.wgl.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) - wglGetProcAddress("wglSwapIntervalEXT"); - - // Functions for WGL_ARB_pixel_format - _glfw.wgl.GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC) - wglGetProcAddress("wglGetPixelFormatAttribivARB"); - - // This needs to include every extension used below except for - // WGL_ARB_extensions_string and WGL_EXT_extensions_string - _glfw.wgl.ARB_multisample = - _glfwPlatformExtensionSupported("WGL_ARB_multisample"); - _glfw.wgl.ARB_framebuffer_sRGB = - _glfwPlatformExtensionSupported("WGL_ARB_framebuffer_sRGB"); - _glfw.wgl.EXT_framebuffer_sRGB = - _glfwPlatformExtensionSupported("WGL_EXT_framebuffer_sRGB"); - _glfw.wgl.ARB_create_context = - _glfwPlatformExtensionSupported("WGL_ARB_create_context"); - _glfw.wgl.ARB_create_context_profile = - _glfwPlatformExtensionSupported("WGL_ARB_create_context_profile"); - _glfw.wgl.EXT_create_context_es2_profile = - _glfwPlatformExtensionSupported("WGL_EXT_create_context_es2_profile"); - _glfw.wgl.ARB_create_context_robustness = - _glfwPlatformExtensionSupported("WGL_ARB_create_context_robustness"); - _glfw.wgl.EXT_swap_control = - _glfwPlatformExtensionSupported("WGL_EXT_swap_control"); - _glfw.wgl.ARB_pixel_format = - _glfwPlatformExtensionSupported("WGL_ARB_pixel_format"); - _glfw.wgl.ARB_context_flush_control = - _glfwPlatformExtensionSupported("WGL_ARB_context_flush_control"); - - _glfw.wgl.extensionsLoaded = GLFW_TRUE; -} - // Returns the specified attribute of the specified pixel format // static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib) @@ -280,6 +231,157 @@ return enabled; } +static void makeContextCurrent(_GLFWwindow* window) +{ + if (window) + { + if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle)) + _glfwPlatformSetCurrentContext(window); + else + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "WGL: Failed to make context current"); + _glfwPlatformSetCurrentContext(NULL); + } + } + else + { + if (!wglMakeCurrent(NULL, NULL)) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "WGL: Failed to clear current context"); + } + + _glfwPlatformSetCurrentContext(NULL); + } +} + +static void swapBuffers(_GLFWwindow* window) +{ + // HACK: Use DwmFlush when desktop composition is enabled + if (isCompositionEnabled() && !window->monitor) + { + int count = abs(window->context.wgl.interval); + while (count--) + _glfw_DwmFlush(); + } + + SwapBuffers(window->context.wgl.dc); +} + +static void swapInterval(int interval) +{ + _GLFWwindow* window = _glfwPlatformGetCurrentContext(); + + window->context.wgl.interval = interval; + + // HACK: Disable WGL swap interval when desktop composition is enabled to + // avoid interfering with DWM vsync + if (isCompositionEnabled() && !window->monitor) + interval = 0; + + if (_glfw.wgl.EXT_swap_control) + _glfw.wgl.SwapIntervalEXT(interval); +} + +static int extensionSupported(const char* extension) +{ + const char* extensions; + + _GLFWwindow* window = _glfwPlatformGetCurrentContext(); + + if (_glfw.wgl.GetExtensionsStringEXT) + { + extensions = _glfw.wgl.GetExtensionsStringEXT(); + if (extensions) + { + if (_glfwStringInExtensionString(extension, extensions)) + return GLFW_TRUE; + } + } + + if (_glfw.wgl.GetExtensionsStringARB) + { + extensions = _glfw.wgl.GetExtensionsStringARB(window->context.wgl.dc); + if (extensions) + { + if (_glfwStringInExtensionString(extension, extensions)) + return GLFW_TRUE; + } + } + + return GLFW_FALSE; +} + +static GLFWglproc getProcAddress(const char* procname) +{ + const GLFWglproc proc = (GLFWglproc) wglGetProcAddress(procname); + if (proc) + return proc; + + return (GLFWglproc) GetProcAddress(_glfw.wgl.instance, procname); +} + +// Destroy the OpenGL context +// +static void destroyContext(_GLFWwindow* window) +{ + if (window->context.wgl.handle) + { + wglDeleteContext(window->context.wgl.handle); + window->context.wgl.handle = NULL; + } +} + +// Initialize WGL-specific extensions +// +static void loadExtensions(void) +{ + // Functions for WGL_EXT_extension_string + // NOTE: These are needed by extensionSupported + _glfw.wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC) + wglGetProcAddress("wglGetExtensionsStringEXT"); + _glfw.wgl.GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) + wglGetProcAddress("wglGetExtensionsStringARB"); + + // Functions for WGL_ARB_create_context + _glfw.wgl.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) + wglGetProcAddress("wglCreateContextAttribsARB"); + + // Functions for WGL_EXT_swap_control + _glfw.wgl.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) + wglGetProcAddress("wglSwapIntervalEXT"); + + // Functions for WGL_ARB_pixel_format + _glfw.wgl.GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC) + wglGetProcAddress("wglGetPixelFormatAttribivARB"); + + // This needs to include every extension used below except for + // WGL_ARB_extensions_string and WGL_EXT_extensions_string + _glfw.wgl.ARB_multisample = + extensionSupported("WGL_ARB_multisample"); + _glfw.wgl.ARB_framebuffer_sRGB = + extensionSupported("WGL_ARB_framebuffer_sRGB"); + _glfw.wgl.EXT_framebuffer_sRGB = + extensionSupported("WGL_EXT_framebuffer_sRGB"); + _glfw.wgl.ARB_create_context = + extensionSupported("WGL_ARB_create_context"); + _glfw.wgl.ARB_create_context_profile = + extensionSupported("WGL_ARB_create_context_profile"); + _glfw.wgl.EXT_create_context_es2_profile = + extensionSupported("WGL_EXT_create_context_es2_profile"); + _glfw.wgl.ARB_create_context_robustness = + extensionSupported("WGL_ARB_create_context_robustness"); + _glfw.wgl.EXT_swap_control = + extensionSupported("WGL_EXT_swap_control"); + _glfw.wgl.ARB_pixel_format = + extensionSupported("WGL_ARB_pixel_format"); + _glfw.wgl.ARB_context_flush_control = + extensionSupported("WGL_ARB_context_flush_control"); + + _glfw.wgl.extensionsLoaded = GLFW_TRUE; +} + ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// @@ -336,7 +438,7 @@ PIXELFORMATDESCRIPTOR pfd; HGLRC share = NULL; - if (ctxconfig->api == GLFW_NO_API) + if (ctxconfig->client == GLFW_NO_API) return GLFW_TRUE; if (ctxconfig->share) @@ -372,7 +474,7 @@ { int index = 0, mask = 0, flags = 0; - if (ctxconfig->api == GLFW_OPENGL_API) + if (ctxconfig->client == GLFW_OPENGL_API) { if (ctxconfig->forward) flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; @@ -474,22 +576,18 @@ } } + window->context.makeContextCurrent = makeContextCurrent; + window->context.swapBuffers = swapBuffers; + window->context.swapInterval = swapInterval; + window->context.extensionSupported = extensionSupported; + window->context.getProcAddress = getProcAddress; + window->context.destroyContext = destroyContext; + return GLFW_TRUE; } #undef setWGLattrib -// Destroy the OpenGL context -// -void _glfwDestroyContextWGL(_GLFWwindow* window) -{ - if (window->context.wgl.handle) - { - wglDeleteContext(window->context.wgl.handle); - window->context.wgl.handle = NULL; - } -} - // Analyzes the specified context for possible recreation // int _glfwAnalyzeContextWGL(_GLFWwindow* window, @@ -501,10 +599,10 @@ if (_glfw.wgl.extensionsLoaded) return _GLFW_RECREATION_NOT_NEEDED; - _glfwPlatformMakeContextCurrent(window); + makeContextCurrent(window); loadExtensions(); - if (ctxconfig->api == GLFW_OPENGL_API) + if (ctxconfig->client == GLFW_OPENGL_API) { if (ctxconfig->forward) { @@ -588,102 +686,6 @@ ////////////////////////////////////////////////////////////////////////// -////// GLFW platform API ////// -////////////////////////////////////////////////////////////////////////// - -void _glfwPlatformMakeContextCurrent(_GLFWwindow* window) -{ - if (window) - { - if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle)) - _glfwPlatformSetCurrentContext(window); - else - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "WGL: Failed to make context current"); - _glfwPlatformSetCurrentContext(NULL); - } - } - else - { - if (!wglMakeCurrent(NULL, NULL)) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "WGL: Failed to clear current context"); - } - - _glfwPlatformSetCurrentContext(NULL); - } -} - -void _glfwPlatformSwapBuffers(_GLFWwindow* window) -{ - // HACK: Use DwmFlush when desktop composition is enabled - if (isCompositionEnabled() && !window->monitor) - { - int count = abs(window->context.wgl.interval); - while (count--) - _glfw_DwmFlush(); - } - - SwapBuffers(window->context.wgl.dc); -} - -void _glfwPlatformSwapInterval(int interval) -{ - _GLFWwindow* window = _glfwPlatformGetCurrentContext(); - - window->context.wgl.interval = interval; - - // HACK: Disable WGL swap interval when desktop composition is enabled to - // avoid interfering with DWM vsync - if (isCompositionEnabled() && !window->monitor) - interval = 0; - - if (_glfw.wgl.EXT_swap_control) - _glfw.wgl.SwapIntervalEXT(interval); -} - -int _glfwPlatformExtensionSupported(const char* extension) -{ - const char* extensions; - - _GLFWwindow* window = _glfwPlatformGetCurrentContext(); - - if (_glfw.wgl.GetExtensionsStringEXT) - { - extensions = _glfw.wgl.GetExtensionsStringEXT(); - if (extensions) - { - if (_glfwStringInExtensionString(extension, extensions)) - return GLFW_TRUE; - } - } - - if (_glfw.wgl.GetExtensionsStringARB) - { - extensions = _glfw.wgl.GetExtensionsStringARB(window->context.wgl.dc); - if (extensions) - { - if (_glfwStringInExtensionString(extension, extensions)) - return GLFW_TRUE; - } - } - - return GLFW_FALSE; -} - -GLFWglproc _glfwPlatformGetProcAddress(const char* procname) -{ - const GLFWglproc proc = (GLFWglproc) wglGetProcAddress(procname); - if (proc) - return proc; - - return (GLFWglproc) GetProcAddress(_glfw.wgl.instance, procname); -} - - -////////////////////////////////////////////////////////////////////////// ////// GLFW native API ////// ////////////////////////////////////////////////////////////////////////// @@ -692,7 +694,7 @@ _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - if (window->context.api == GLFW_NO_API) + if (window->context.client == GLFW_NO_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return NULL;
diff --git a/src/wgl_context.h b/src/wgl_context.h index cca55e0..f1e653c 100644 --- a/src/wgl_context.h +++ b/src/wgl_context.h
@@ -148,7 +148,6 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig); -void _glfwDestroyContextWGL(_GLFWwindow* window); int _glfwAnalyzeContextWGL(_GLFWwindow* window, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig);
diff --git a/src/win32_init.c b/src/win32_init.c index 521f045..0bfe34c 100644 --- a/src/win32_init.c +++ b/src/win32_init.c
@@ -421,14 +421,10 @@ _glfwPlatformPollEvents(); -#if defined(_GLFW_WGL) if (!_glfwInitWGL()) return GLFW_FALSE; -#elif defined(_GLFW_EGL) - if (!_glfwInitEGL()) - return GLFW_FALSE; -#endif + _glfwInitEGL(); _glfwInitTimerWin32(); _glfwInitJoysticksWin32(); @@ -449,11 +445,8 @@ free(_glfw.win32.clipboardString); -#if defined(_GLFW_WGL) _glfwTerminateWGL(); -#elif defined(_GLFW_EGL) _glfwTerminateEGL(); -#endif _glfwTerminateJoysticksWin32(); _glfwTerminateThreadLocalStorageWin32(); @@ -463,12 +456,7 @@ const char* _glfwPlatformGetVersionString(void) { - return _GLFW_VERSION_NUMBER " Win32" -#if defined(_GLFW_WGL) - " WGL" -#elif defined(_GLFW_EGL) - " EGL" -#endif + return _GLFW_VERSION_NUMBER " Win32 WGL EGL" #if defined(__MINGW32__) " MinGW" #elif defined(_MSC_VER)
diff --git a/src/win32_platform.h b/src/win32_platform.h index d44ca3b..f3570bc 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h
@@ -205,16 +205,8 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice,uint32_t); #include "win32_joystick.h" - -#if defined(_GLFW_WGL) - #include "wgl_context.h" -#elif defined(_GLFW_EGL) - #define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->win32.handle) - #define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY - #include "egl_context.h" -#else - #error "No supported context creation API selected" -#endif +#include "wgl_context.h" +#include "egl_context.h" #define _GLFW_WNDCLASSNAME L"GLFW30" @@ -222,6 +214,9 @@ #define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle) #define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name) +#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->win32.handle) +#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY + #define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32 #define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32 #define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeWin32 win32_time
diff --git a/src/win32_window.c b/src/win32_window.c index 944bff6..b5c03ea 100644 --- a/src/win32_window.c +++ b/src/win32_window.c
@@ -940,55 +940,58 @@ if (!createWindow(window, wndconfig)) return GLFW_FALSE; - if (ctxconfig->api != GLFW_NO_API) + if (ctxconfig->client != GLFW_NO_API) { -#if defined(_GLFW_WGL) - 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) + if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API) { - // 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 - _glfwPlatformMakeContextCurrent(NULL); - - // Next destroy the Win32 window and WGL context (without resetting - // or destroying the GLFW window object) - _glfwDestroyContextWGL(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; + + 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.makeContextCurrent(NULL); + + // Next destroy the Win32 window and WGL context (without resetting + // or destroying the GLFW window object) + window->context.destroyContext(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; + } } -#elif defined(_GLFW_EGL) - if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig)) - return GLFW_FALSE; -#endif + else + { + if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig)) + return GLFW_FALSE; + } } if (window->monitor) @@ -1007,14 +1010,8 @@ if (window->monitor) releaseMonitor(window); - if (window->context.api != GLFW_NO_API) - { -#if defined(_GLFW_WGL) - _glfwDestroyContextWGL(window); -#elif defined(_GLFW_EGL) - _glfwDestroyContextEGL(window); -#endif - } + if (window->context.client != GLFW_NO_API) + window->context.destroyContext(window); destroyWindow(window);
diff --git a/src/window.c b/src/window.c index fee08b2..89b0189 100644 --- a/src/window.c +++ b/src/window.c
@@ -155,7 +155,7 @@ if (ctxconfig.share) { - if (ctxconfig.share->context.api == GLFW_NO_API) + if (ctxconfig.share->context.client == GLFW_NO_API) { _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return NULL; @@ -192,29 +192,31 @@ // Save the currently current context so it can be restored later previous = _glfwPlatformGetCurrentContext(); + if (ctxconfig.client != GLFW_NO_API) + glfwMakeContextCurrent(NULL); // Open the actual window and create its context if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig)) { + glfwMakeContextCurrent((GLFWwindow*) previous); glfwDestroyWindow((GLFWwindow*) window); - _glfwPlatformMakeContextCurrent(previous); return NULL; } - if (ctxconfig.api != GLFW_NO_API) + if (ctxconfig.client != GLFW_NO_API) { - _glfwPlatformMakeContextCurrent(window); + window->context.makeContextCurrent(window); // Retrieve the actual (as opposed to requested) context attributes if (!_glfwRefreshContextAttribs(&ctxconfig)) { + glfwMakeContextCurrent((GLFWwindow*) previous); glfwDestroyWindow((GLFWwindow*) window); - _glfwPlatformMakeContextCurrent(previous); return NULL; } // Restore the previously current context (or NULL) - _glfwPlatformMakeContextCurrent(previous); + glfwMakeContextCurrent((GLFWwindow*) previous); } if (window->monitor) @@ -247,9 +249,10 @@ memset(&_glfw.hints, 0, sizeof(_glfw.hints)); // The default is OpenGL with minimum version 1.0 - _glfw.hints.context.api = GLFW_OPENGL_API; - _glfw.hints.context.major = 1; - _glfw.hints.context.minor = 0; + _glfw.hints.context.client = GLFW_OPENGL_API; + _glfw.hints.context.source = GLFW_NATIVE_CONTEXT_API; + _glfw.hints.context.major = 1; + _glfw.hints.context.minor = 0; // The default is a focused, visible, resizable window with decorations _glfw.hints.window.resizable = GLFW_TRUE; @@ -345,7 +348,10 @@ _glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE; break; case GLFW_CLIENT_API: - _glfw.hints.context.api = value; + _glfw.hints.context.client = value; + break; + case GLFW_CONTEXT_CREATION_API: + _glfw.hints.context.source = value; break; case GLFW_CONTEXT_VERSION_MAJOR: _glfw.hints.context.major = value; @@ -396,7 +402,7 @@ // The window's context must not be current on another thread when the // window is destroyed if (window == _glfwPlatformGetCurrentContext()) - _glfwPlatformMakeContextCurrent(NULL); + glfwMakeContextCurrent(NULL); // Clear the focused window pointer if this is the focused window if (_glfw.cursorWindow == window) @@ -683,7 +689,9 @@ case GLFW_FLOATING: return window->floating; case GLFW_CLIENT_API: - return window->context.api; + return window->context.client; + case GLFW_CONTEXT_CREATION_API: + return window->context.source; case GLFW_CONTEXT_VERSION_MAJOR: return window->context.major; case GLFW_CONTEXT_VERSION_MINOR:
diff --git a/src/wl_platform.h b/src/wl_platform.h index d75c025..221108e 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h
@@ -49,12 +49,7 @@ #include "posix_time.h" #include "linux_joystick.h" #include "xkb_unicode.h" - -#if defined(_GLFW_EGL) - #include "egl_context.h" -#else - #error "The Wayland backend depends on EGL platform support" -#endif +#include "egl_context.h" #include "wayland-relative-pointer-unstable-v1-client-protocol.h" #include "wayland-pointer-constraints-unstable-v1-client-protocol.h" @@ -71,6 +66,9 @@ #define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWayland wl #define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWayland wl +#define _GLFW_PLATFORM_CONTEXT_STATE +#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE + // Wayland-specific video mode data //
diff --git a/src/wl_window.c b/src/wl_window.c index 194c0ec..5ff9990 100644 --- a/src/wl_window.c +++ b/src/wl_window.c
@@ -373,7 +373,7 @@ if (!createSurface(window, wndconfig)) return GLFW_FALSE; - if (ctxconfig->api != GLFW_NO_API) + if (ctxconfig->client != GLFW_NO_API) { if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig)) return GLFW_FALSE; @@ -417,7 +417,8 @@ _glfwInputWindowFocus(window, GLFW_FALSE); } - _glfwDestroyContextEGL(window); + if (window->context.client != GLFW_NO_API) + window->context.destroyContext(window); if (window->wl.native) wl_egl_window_destroy(window->wl.native);
diff --git a/src/x11_init.c b/src/x11_init.c index b81afcc..112e454 100644 --- a/src/x11_init.c +++ b/src/x11_init.c
@@ -766,17 +766,13 @@ if (!_glfwInitThreadLocalStoragePOSIX()) return GLFW_FALSE; -#if defined(_GLFW_GLX) if (!_glfwInitGLX()) return GLFW_FALSE; -#elif defined(_GLFW_EGL) - if (!_glfwInitEGL()) - return GLFW_FALSE; -#endif if (!_glfwInitJoysticksLinux()) return GLFW_FALSE; + _glfwInitEGL(); _glfwInitTimerPOSIX(); return GLFW_TRUE; @@ -804,9 +800,7 @@ _glfw.x11.im = NULL; } -#if defined(_GLFW_EGL) _glfwTerminateEGL(); -#endif if (_glfw.x11.display) { @@ -816,9 +810,7 @@ // NOTE: This needs to be done after XCloseDisplay, as libGL registers // cleanup callbacks that get called by it -#if defined(_GLFW_GLX) _glfwTerminateGLX(); -#endif _glfwTerminateJoysticksLinux(); _glfwTerminateThreadLocalStoragePOSIX(); @@ -826,12 +818,7 @@ const char* _glfwPlatformGetVersionString(void) { - return _GLFW_VERSION_NUMBER " X11" -#if defined(_GLFW_GLX) - " GLX" -#elif defined(_GLFW_EGL) - " EGL" -#endif + return _GLFW_VERSION_NUMBER " X11 GLX EGL" #if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK) " clock_gettime" #else
diff --git a/src/x11_platform.h b/src/x11_platform.h index a12374a..9c76d18 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h
@@ -87,21 +87,16 @@ #include "posix_time.h" #include "linux_joystick.h" #include "xkb_unicode.h" - -#if defined(_GLFW_GLX) - #include "glx_context.h" -#elif defined(_GLFW_EGL) - #define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->x11.handle) - #define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.x11.display) - #include "egl_context.h" -#else - #error "No supported context creation API selected" -#endif +#include "glx_context.h" +#include "egl_context.h" #define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL) #define _glfw_dlclose(handle) dlclose(handle) #define _glfw_dlsym(handle, name) dlsym(handle, name) +#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->x11.handle) +#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.x11.display) + #define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowX11 x11 #define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11 #define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorX11 x11
diff --git a/src/x11_window.c b/src/x11_window.c index 7cf26ce..19b9d24 100644 --- a/src/x11_window.c +++ b/src/x11_window.c
@@ -1478,34 +1478,40 @@ Visual* visual; int depth; - if (ctxconfig->api == GLFW_NO_API) + if (ctxconfig->client == GLFW_NO_API) { visual = DefaultVisual(_glfw.x11.display, _glfw.x11.screen); depth = DefaultDepth(_glfw.x11.display, _glfw.x11.screen); } else { -#if defined(_GLFW_GLX) - if (!_glfwChooseVisualGLX(ctxconfig, fbconfig, &visual, &depth)) - return GLFW_FALSE; -#elif defined(_GLFW_EGL) - if (!_glfwChooseVisualEGL(ctxconfig, fbconfig, &visual, &depth)) - return GLFW_FALSE; -#endif + if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API) + { + if (!_glfwChooseVisualGLX(ctxconfig, fbconfig, &visual, &depth)) + return GLFW_FALSE; + } + else + { + if (!_glfwChooseVisualEGL(ctxconfig, fbconfig, &visual, &depth)) + return GLFW_FALSE; + } } if (!createWindow(window, wndconfig, visual, depth)) return GLFW_FALSE; - if (ctxconfig->api != GLFW_NO_API) + if (ctxconfig->client != GLFW_NO_API) { -#if defined(_GLFW_GLX) - if (!_glfwCreateContextGLX(window, ctxconfig, fbconfig)) - return GLFW_FALSE; -#elif defined(_GLFW_EGL) - if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig)) - return GLFW_FALSE; -#endif + if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API) + { + if (!_glfwCreateContextGLX(window, ctxconfig, fbconfig)) + return GLFW_FALSE; + } + else + { + if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig)) + return GLFW_FALSE; + } } if (window->monitor) @@ -1530,14 +1536,8 @@ window->x11.ic = NULL; } - if (window->context.api != GLFW_NO_API) - { -#if defined(_GLFW_GLX) - _glfwDestroyContextGLX(window); -#elif defined(_GLFW_EGL) - _glfwDestroyContextEGL(window); -#endif - } + if (window->context.client != GLFW_NO_API) + window->context.destroyContext(window); if (window->x11.handle) {