From afe4aadade132f088a1d88145baed0b384c8d4e0 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Thu, 13 Aug 2015 00:21:33 +0200 Subject: [PATCH] Make all GLX functions dynamically loaded --- README.md | 1 + src/glx_context.c | 72 ++++++++++++++++++++++++++++++++--------------- src/glx_context.h | 48 ++++++++++++++++++++++++++----- src/x11_init.c | 5 +++- 4 files changed, 96 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index de03f8bd..ef428147 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,7 @@ GLFW bundles a number of dependencies in the `deps/` directory. - [WGL] Removed `GLFW_USE_DWM_SWAP_INTERVAL` compile-time option - [WGL] Bugfix: Swap interval was ignored when DWM was enabled - [GLX] Added dependency on `libdl` on systems where it provides `dlopen` + - [GLX] Made all GLX functions dynamically loaded - [GLX] Removed `_GLFW_HAS_GLXGETPROCADDRESS*` and `_GLFW_HAS_DLOPEN` compile-time options diff --git a/src/glx_context.c b/src/glx_context.c index 371355c1..72de582d 100644 --- a/src/glx_context.c +++ b/src/glx_context.c @@ -42,7 +42,7 @@ static int getFBConfigAttrib(GLXFBConfig fbconfig, int attrib) { int value; - glXGetFBConfigAttrib(_glfw.x11.display, fbconfig, attrib, &value); + _glfw_glXGetFBConfigAttrib(_glfw.x11.display, fbconfig, attrib, &value); return value; } @@ -59,12 +59,12 @@ static GLboolean chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* resul // HACK: This is a (hopefully temporary) workaround for Chromium // (VirtualBox GL) not setting the window bit on any GLXFBConfigs - vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR); + vendor = _glfw_glXGetClientString(_glfw.x11.display, GLX_VENDOR); if (strcmp(vendor, "Chromium") == 0) trustWindowBit = GL_FALSE; - nativeConfigs = glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen, - &nativeCount); + nativeConfigs = _glfw_glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen, + &nativeCount); if (!nativeCount) { _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned"); @@ -140,11 +140,11 @@ static GLXContext createLegacyContext(_GLFWwindow* window, GLXFBConfig fbconfig, GLXContext share) { - return glXCreateNewContext(_glfw.x11.display, - fbconfig, - GLX_RGBA_TYPE, - share, - True); + return _glfw_glXCreateNewContext(_glfw.x11.display, + fbconfig, + GLX_RGBA_TYPE, + share, + True); } @@ -172,20 +172,44 @@ int _glfwInitContextAPI(void) return GL_FALSE; } + _glfw.glx.GetFBConfigs = + dlsym(_glfw.glx.handle, "glXGetFBConfigs"); + _glfw.glx.GetFBConfigAttrib = + dlsym(_glfw.glx.handle, "glXGetFBConfigAttrib"); + _glfw.glx.GetClientString = + dlsym(_glfw.glx.handle, "glXGetClientString"); + _glfw.glx.QueryExtension = + dlsym(_glfw.glx.handle, "glXQueryExtension"); + _glfw.glx.QueryVersion = + dlsym(_glfw.glx.handle, "glXQueryVersion"); + _glfw.glx.DestroyContext = + dlsym(_glfw.glx.handle, "glXDestroyContext"); + _glfw.glx.MakeCurrent = + dlsym(_glfw.glx.handle, "glXMakeCurrent"); + _glfw.glx.SwapBuffers = + dlsym(_glfw.glx.handle, "glXSwapBuffers"); + _glfw.glx.QueryExtensionsString = + dlsym(_glfw.glx.handle, "glXQueryExtensionsString"); + _glfw.glx.CreateNewContext = + dlsym(_glfw.glx.handle, "glXCreateNewContext"); + _glfw.glx.GetVisualFromFBConfig = + dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig"); _glfw.glx.GetProcAddress = dlsym(_glfw.glx.handle, "glXGetProcAddress"); _glfw.glx.GetProcAddressARB = dlsym(_glfw.glx.handle, "glXGetProcAddressARB"); - if (!glXQueryExtension(_glfw.x11.display, - &_glfw.glx.errorBase, - &_glfw.glx.eventBase)) + if (!_glfw_glXQueryExtension(_glfw.x11.display, + &_glfw.glx.errorBase, + &_glfw.glx.eventBase)) { _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: GLX extension not found"); return GL_FALSE; } - if (!glXQueryVersion(_glfw.x11.display, &_glfw.glx.major, &_glfw.glx.minor)) + if (!_glfw_glXQueryVersion(_glfw.x11.display, + &_glfw.glx.major, + &_glfw.glx.minor)) { _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: Failed to query GLX version"); @@ -263,6 +287,9 @@ int _glfwInitContextAPI(void) // void _glfwTerminateContextAPI(void) { + // NOTE: This function may not call any X11 functions, as it is called after + // XCloseDisplay (see _glfwPlatformTerminate for details) + if (_glfw.glx.handle) { dlclose(_glfw.glx.handle); @@ -299,7 +326,8 @@ int _glfwCreateContext(_GLFWwindow* window, return GL_FALSE; } - window->glx.visual = glXGetVisualFromFBConfig(_glfw.x11.display, native); + window->glx.visual = _glfw_glXGetVisualFromFBConfig(_glfw.x11.display, + native); if (!window->glx.visual) { _glfwInputError(GLFW_PLATFORM_ERROR, @@ -465,7 +493,7 @@ void _glfwDestroyContext(_GLFWwindow* window) if (window->glx.context) { - glXDestroyContext(_glfw.x11.display, window->glx.context); + _glfw_glXDestroyContext(_glfw.x11.display, window->glx.context); window->glx.context = NULL; } } @@ -479,19 +507,19 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window) { if (window) { - glXMakeCurrent(_glfw.x11.display, - window->x11.handle, - window->glx.context); + _glfw_glXMakeCurrent(_glfw.x11.display, + window->x11.handle, + window->glx.context); } else - glXMakeCurrent(_glfw.x11.display, None, NULL); + _glfw_glXMakeCurrent(_glfw.x11.display, None, NULL); _glfwSetContextTLS(window); } void _glfwPlatformSwapBuffers(_GLFWwindow* window) { - glXSwapBuffers(_glfw.x11.display, window->x11.handle); + _glfw_glXSwapBuffers(_glfw.x11.display, window->x11.handle); } void _glfwPlatformSwapInterval(int interval) @@ -515,8 +543,8 @@ void _glfwPlatformSwapInterval(int interval) int _glfwPlatformExtensionSupported(const char* extension) { - const char* extensions = glXQueryExtensionsString(_glfw.x11.display, - _glfw.x11.screen); + const char* extensions = + _glfw_glXQueryExtensionsString(_glfw.x11.display, _glfw.x11.screen); if (extensions) { if (_glfwStringInExtensionString(extension, extensions)) diff --git a/src/glx_context.h b/src/glx_context.h index c5a4e61e..c774976c 100644 --- a/src/glx_context.h +++ b/src/glx_context.h @@ -37,6 +37,27 @@ #define GLX_GLXEXT_PROTOTYPES #include "../deps/GL/glxext.h" +// libGL.so function pointer typedefs +typedef int (*PFNGLXGETFBCONFIGATTRIBPROC)(Display*,GLXFBConfig,int,int*); +typedef const char* (*PFNGLXGETCLIENTSTRINGPROC)(Display*,int); +typedef Bool (*PFNGLXQUERYEXTENSIONPROC)(Display*,int*,int*); +typedef Bool (*PFNGLXQUERYVERSIONPROC)(Display*,int*,int*); +typedef void (*PFNGLXDESTROYCONTEXTPROC)(Display*,GLXContext); +typedef Bool (*PFNGLXMAKECURRENTPROC)(Display*,GLXDrawable,GLXContext); +typedef void (*PFNGLXSWAPBUFFERSPROC)(Display*,GLXDrawable); +typedef const char* (*PFNGLXQUERYEXTENSIONSSTRINGPROC)(Display*,int); +#define _glfw_glXGetFBConfigs _glfw.glx.GetFBConfigs +#define _glfw_glXGetFBConfigAttrib _glfw.glx.GetFBConfigAttrib +#define _glfw_glXGetClientString _glfw.glx.GetClientString +#define _glfw_glXQueryExtension _glfw.glx.QueryExtension +#define _glfw_glXQueryVersion _glfw.glx.QueryVersion +#define _glfw_glXDestroyContext _glfw.glx.DestroyContext +#define _glfw_glXMakeCurrent _glfw.glx.MakeCurrent +#define _glfw_glXSwapBuffers _glfw.glx.SwapBuffers +#define _glfw_glXQueryExtensionsString _glfw.glx.QueryExtensionsString +#define _glfw_glXCreateNewContext _glfw.glx.CreateNewContext +#define _glfw_glXGetVisualFromFBConfig _glfw.glx.GetVisualFromFBConfig + #define _GLFW_PLATFORM_FBCONFIG GLXFBConfig glx #define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextGLX glx #define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryGLX glx @@ -69,13 +90,26 @@ typedef struct _GLFWlibraryGLX // dlopen handle for libGL.so.1 void* handle; - // GLX extensions - PFNGLXGETPROCADDRESSPROC GetProcAddress; - PFNGLXGETPROCADDRESSPROC GetProcAddressARB; - PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI; - PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT; - PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA; - PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB; + // GLX 1.3 functions + PFNGLXGETFBCONFIGSPROC GetFBConfigs; + PFNGLXGETFBCONFIGATTRIBPROC GetFBConfigAttrib; + PFNGLXGETCLIENTSTRINGPROC GetClientString; + PFNGLXQUERYEXTENSIONPROC QueryExtension; + PFNGLXQUERYVERSIONPROC QueryVersion; + PFNGLXDESTROYCONTEXTPROC DestroyContext; + PFNGLXMAKECURRENTPROC MakeCurrent; + PFNGLXSWAPBUFFERSPROC SwapBuffers; + PFNGLXQUERYEXTENSIONSSTRINGPROC QueryExtensionsString; + PFNGLXCREATENEWCONTEXTPROC CreateNewContext; + PFNGLXGETVISUALFROMFBCONFIGPROC GetVisualFromFBConfig; + + // GLX 1.4 and extension functions + PFNGLXGETPROCADDRESSPROC GetProcAddress; + PFNGLXGETPROCADDRESSPROC GetProcAddressARB; + PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI; + PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT; + PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA; + PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB; GLboolean SGI_swap_control; GLboolean EXT_swap_control; GLboolean MESA_swap_control; diff --git a/src/x11_init.c b/src/x11_init.c index 2fd06358..90101ef4 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -786,13 +786,16 @@ void _glfwPlatformTerminate(void) } _glfwTerminateJoysticks(); - _glfwTerminateContextAPI(); if (_glfw.x11.display) { XCloseDisplay(_glfw.x11.display); _glfw.x11.display = NULL; } + + // NOTE: This needs to be done after XCloseDisplay, as libGL registers + // internal cleanup callbacks in libX11 + _glfwTerminateContextAPI(); } const char* _glfwPlatformGetVersionString(void)