From 231cc9a7780985d3f8685a057fb90eb6a799de1f Mon Sep 17 00:00:00 2001 From: Wolfgang Draxinger Date: Mon, 22 Feb 2016 18:08:15 +0100 Subject: [PATCH 1/4] added support for transparent X11/GLX window --- examples/gears.c | 3 ++ include/GLFW/glfw3.h | 1 + src/glx_context.c | 98 ++++++++++++++++++++++++++++++++++++++++---- src/glx_context.h | 35 ++++++++++++++-- src/internal.h | 2 + src/window.c | 7 ++++ src/x11_window.c | 2 +- 7 files changed, 135 insertions(+), 13 deletions(-) diff --git a/examples/gears.c b/examples/gears.c index 29e63f58b..c5897dcca 100644 --- a/examples/gears.c +++ b/examples/gears.c @@ -172,6 +172,7 @@ static GLfloat angle = 0.f; /* OpenGL draw function & timing */ static void draw(void) { + glClearColor(0., 0., 0., 0.); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); @@ -311,6 +312,8 @@ int main(int argc, char *argv[]) } glfwWindowHint(GLFW_DEPTH_BITS, 16); + glfwWindowHint(GLFW_ALPHA_BITS, 8); + glfwWindowHint(GLFW_TRANSPARENT, GLFW_TRUE); window = glfwCreateWindow( 300, 300, "Gears", NULL, NULL ); if (!window) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 41e5f7d8c..2e6ed0c14 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -627,6 +627,7 @@ extern "C" { #define GLFW_AUTO_ICONIFY 0x00020006 #define GLFW_FLOATING 0x00020007 #define GLFW_MAXIMIZED 0x00020008 +#define GLFW_TRANSPARENT 0x00020009 #define GLFW_RED_BITS 0x00021001 #define GLFW_GREEN_BITS 0x00021002 diff --git a/src/glx_context.c b/src/glx_context.c index 22ec7e10a..b4b8b589f 100644 --- a/src/glx_context.c +++ b/src/glx_context.c @@ -47,7 +47,10 @@ static int getFBConfigAttrib(GLXFBConfig fbconfig, int attrib) // Return a list of available and usable framebuffer configs // -static GLFWbool chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* result) +static GLFWbool chooseFBConfig( + const _GLFWfbconfig* desired, + GLXFBConfig* result, + GLFWbool findTransparent) { GLXFBConfig* nativeConfigs; _GLFWfbconfig* usableConfigs; @@ -56,6 +59,10 @@ static GLFWbool chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* result const char* vendor; GLFWbool trustWindowBit = GLFW_TRUE; + if (findTransparent && !(_glfw.xrender.major || _glfw.xrender.minor)) { + findTransparent = GLFW_FALSE; + } + // 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); @@ -73,6 +80,7 @@ static GLFWbool chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* result usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig)); usableCount = 0; +selectionloop: for (i = 0; i < nativeCount; i++) { const GLXFBConfig n = nativeConfigs[i]; @@ -89,6 +97,22 @@ static GLFWbool chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* result continue; } + if( findTransparent ) { + XVisualInfo *visualinfo; + XRenderPictFormat *pictFormat; + + visualinfo = glXGetVisualFromFBConfig(_glfw.x11.display, n); + if (!visualinfo) + continue; + + pictFormat = XRenderFindVisualFormat(_glfw.x11.display, visualinfo->visual); + if( !pictFormat ) + continue; + + if( !pictFormat->direct.alphaMask ) + continue; + } + u->redBits = getFBConfigAttrib(n, GLX_RED_SIZE); u->greenBits = getFBConfigAttrib(n, GLX_GREEN_SIZE); u->blueBits = getFBConfigAttrib(n, GLX_BLUE_SIZE); @@ -118,6 +142,12 @@ static GLFWbool chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* result u->glx = n; usableCount++; } + // reiterate the selection loop without looking for transparency supporting + // formats if no matchig FB configs for a transparent window were found. + if( findTransparent && !usableCount ) { + findTransparent = GLFW_FALSE; + goto selectionloop; + } closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount); if (closest) @@ -152,7 +182,7 @@ static GLXContext createLegacyContext(_GLFWwindow* window, GLFWbool _glfwInitGLX(void) { int i; - const char* sonames[] = + const char* sonames_glx[] = { #if defined(__CYGWIN__) "libGL-1.so", @@ -163,14 +193,32 @@ GLFWbool _glfwInitGLX(void) NULL }; - - for (i = 0; sonames[i]; i++) + const char* sonames_xrender[] = { - _glfw.glx.handle = dlopen(sonames[i], RTLD_LAZY | RTLD_GLOBAL); +#if defined(__CYGWIN__) + "libXrender-1.so", +#else + "libXrender.so.1", + "libXrender.so", +#endif + NULL + }; + + + for (i = 0; sonames_glx[i]; i++) + { + _glfw.glx.handle = dlopen(sonames_glx[i], RTLD_LAZY | RTLD_GLOBAL); if (_glfw.glx.handle) break; } + for (i = 0; sonames_xrender[i]; i++) + { + _glfw.xrender.handle = dlopen(sonames_xrender[i], RTLD_LAZY | RTLD_GLOBAL); + if (_glfw.xrender.handle) + break; + } + if (!_glfw.glx.handle) { _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: Failed to load GLX"); @@ -230,6 +278,37 @@ GLFWbool _glfwInitGLX(void) return GLFW_FALSE; } + // Xrender support is optional and not a requirement for GLX + // to work. Xrender is required for selecting a FB config that + // supports a picture format with an alpha mask, which in turn + // is required for transparent windows. I Xrender is not supported + // the GLFW_TRANSPARENT window hint is ignored. + _glfw.xrender.errorBase = 0; + _glfw.xrender.eventBase = 0; + _glfw.xrender.major = 0; + _glfw.xrender.minor = 0; + if (_glfw.xrender.handle) do { + int errorBase, eventBase, major, minor; + _glfw.xrender.QueryExtension = + dlsym(_glfw.xrender.handle, "XRenderQueryExtension"); + _glfw.xrender.QueryVersion = + dlsym(_glfw.xrender.handle, "XRenderQueryVersion"); + _glfw.xrender.FindVisualFormat = + dlsym(_glfw.xrender.handle, "XRenderFindVisualFormat"); + + if ( !XRenderQueryExtension(_glfw.x11.display, &errorBase, &eventBase)) { + break; + } + if ( !XRenderQueryVersion(_glfw.x11.display, &major, &minor)) { + break; + } + + _glfw.xrender.errorBase = errorBase; + _glfw.xrender.eventBase = eventBase; + _glfw.xrender.major = major; + _glfw.xrender.minor = minor; + } while(0); + if (_glfwPlatformExtensionSupported("GLX_EXT_swap_control")) { _glfw.glx.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) @@ -324,7 +403,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window, if (ctxconfig->share) share = ctxconfig->share->context.glx.handle; - if (!chooseFBConfig(fbconfig, &native)) + if (!chooseFBConfig(fbconfig, &native, window->transparent)) { _glfwInputError(GLFW_FORMAT_UNAVAILABLE, "GLX: Failed to find a suitable GLXFBConfig"); @@ -507,14 +586,15 @@ void _glfwDestroyContextGLX(_GLFWwindow* window) // Returns the Visual and depth of the chosen GLXFBConfig // -GLFWbool _glfwChooseVisualGLX(const _GLFWctxconfig* ctxconfig, +GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig, + const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig, Visual** visual, int* depth) { GLXFBConfig native; XVisualInfo* result; - if (!chooseFBConfig(fbconfig, &native)) + if (!chooseFBConfig(fbconfig, &native, wndconfig->transparent)) { _glfwInputError(GLFW_FORMAT_UNAVAILABLE, "GLX: Failed to find a suitable GLXFBConfig"); @@ -530,7 +610,7 @@ GLFWbool _glfwChooseVisualGLX(const _GLFWctxconfig* ctxconfig, } *visual = result->visual; - *depth = result->depth; + *depth = result->depth; XFree(result); return GLFW_TRUE; diff --git a/src/glx_context.h b/src/glx_context.h index dc54c7973..81b7d1e6b 100644 --- a/src/glx_context.h +++ b/src/glx_context.h @@ -74,6 +74,7 @@ typedef struct __GLXFBConfig* GLXFBConfig; typedef struct __GLXcontext* GLXContext; typedef void (*__GLXextproc)(void); +// libGL.so function pointer typedefs typedef int (*PFNGLXGETFBCONFIGATTRIBPROC)(Display*,GLXFBConfig,int,int*); typedef const char* (*PFNGLXGETCLIENTSTRINGPROC)(Display*,int); typedef Bool (*PFNGLXQUERYEXTENSIONPROC)(Display*,int*,int*); @@ -93,7 +94,7 @@ typedef XVisualInfo* (*PFNGLXGETVISUALFROMFBCONFIGPROC)(Display*,GLXFBConfig); typedef GLXWindow (*PFNGLXCREATEWINDOWPROC)(Display*,GLXFBConfig,Window,const int*); typedef void (*PFNGLXDESTROYWINDOWPROC)(Display*,GLXWindow); -// libGL.so function pointer typedefs +// libGL.so function identifier overlays #define glXGetFBConfigs _glfw.glx.GetFBConfigs #define glXGetFBConfigAttrib _glfw.glx.GetFBConfigAttrib #define glXGetClientString _glfw.glx.GetClientString @@ -108,9 +109,19 @@ typedef void (*PFNGLXDESTROYWINDOWPROC)(Display*,GLXWindow); #define glXCreateWindow _glfw.glx.CreateWindow #define glXDestroyWindow _glfw.glx.DestroyWindow +// libXrender.so function pointer typedefs +typedef Bool (*PFNXRENDERQUERYEXTENSIONPROC)(Display*,int*,int*); +typedef Status (*PFNXRENDERQUERYVERSIONPROC)(Display*dpy,int*,int*); +typedef XRenderPictFormat* (*PFNXRENDERFINDVISUALFORMATPROC)(Display*,Visual const *); + +// libXrender.so function identifier overlays +#define XRenderQueryExtension _glfw.xrender.QueryExtension +#define XRenderQueryVersion _glfw.xrender.QueryVersion +#define XRenderFindVisualFormat _glfw.xrender.FindVisualFormat + #define _GLFW_PLATFORM_FBCONFIG GLXFBConfig glx #define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextGLX glx -#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryGLX glx +#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryGLX glx ; _GLFWlibraryXrender xrender // GLX-specific per-context data @@ -170,6 +181,23 @@ typedef struct _GLFWlibraryGLX } _GLFWlibraryGLX; +// Xrender-specific global data +// +typedef struct _GLFWlibraryXrender +{ + int major, minor; + int eventBase; + int errorBase; + + // dlopen handle for libGL.so.1 + void* handle; + + // Xrender functions (subset required for transparent window) + PFNXRENDERQUERYEXTENSIONPROC QueryExtension; + PFNXRENDERQUERYVERSIONPROC QueryVersion; + PFNXRENDERFINDVISUALFORMATPROC FindVisualFormat; +} _GLFWlibraryXrender; + GLFWbool _glfwInitGLX(void); void _glfwTerminateGLX(void); @@ -177,7 +205,8 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig); void _glfwDestroyContextGLX(_GLFWwindow* window); -GLFWbool _glfwChooseVisualGLX(const _GLFWctxconfig* ctxconfig, +GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig, + const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig, Visual** visual, int* depth); diff --git a/src/internal.h b/src/internal.h index 0e41fbd7c..7f7ac07ec 100644 --- a/src/internal.h +++ b/src/internal.h @@ -259,6 +259,7 @@ struct _GLFWwndconfig GLFWbool resizable; GLFWbool visible; GLFWbool decorated; + GLFWbool transparent; GLFWbool focused; GLFWbool autoIconify; GLFWbool floating; @@ -348,6 +349,7 @@ struct _GLFWwindow // Window settings and state GLFWbool resizable; GLFWbool decorated; + GLFWbool transparent; GLFWbool autoIconify; GLFWbool floating; GLFWbool closed; diff --git a/src/window.c b/src/window.c index f051370e1..11b9b0add 100644 --- a/src/window.c +++ b/src/window.c @@ -178,6 +178,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, window->monitor = wndconfig.monitor; window->resizable = wndconfig.resizable; window->decorated = wndconfig.decorated; + window->transparent = wndconfig.transparent; window->autoIconify = wndconfig.autoIconify; window->floating = wndconfig.floating; window->cursorMode = GLFW_CURSOR_NORMAL; @@ -256,6 +257,7 @@ void glfwDefaultWindowHints(void) _glfw.hints.window.resizable = GLFW_TRUE; _glfw.hints.window.visible = GLFW_TRUE; _glfw.hints.window.decorated = GLFW_TRUE; + _glfw.hints.window.transparent = GLFW_FALSE; _glfw.hints.window.focused = GLFW_TRUE; _glfw.hints.window.autoIconify = GLFW_TRUE; @@ -330,6 +332,9 @@ GLFWAPI void glfwWindowHint(int hint, int value) case GLFW_DECORATED: _glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE; break; + case GLFW_TRANSPARENT: + _glfw.hints.window.transparent = value ? GLFW_TRUE : GLFW_FALSE; + break; case GLFW_FOCUSED: _glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE; break; @@ -650,6 +655,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib) return window->resizable; case GLFW_DECORATED: return window->decorated; + case GLFW_TRANSPARENT: + return window->transparent; case GLFW_FLOATING: return window->floating; case GLFW_CLIENT_API: diff --git a/src/x11_window.c b/src/x11_window.c index 2f9130a74..a2b96a997 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -1431,7 +1431,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, else { #if defined(_GLFW_GLX) - if (!_glfwChooseVisualGLX(ctxconfig, fbconfig, &visual, &depth)) + if (!_glfwChooseVisualGLX(wndconfig, ctxconfig, fbconfig, &visual, &depth)) return GLFW_FALSE; #elif defined(_GLFW_EGL) if (!_glfwChooseVisualEGL(ctxconfig, fbconfig, &visual, &depth)) From da33cc3923e898860627076f4eeb03291237761a Mon Sep 17 00:00:00 2001 From: Wolfgang Draxinger Date: Mon, 22 Feb 2016 18:55:30 +0100 Subject: [PATCH 2/4] transparency flag reset should always be done --- src/glx_context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/glx_context.c b/src/glx_context.c index b4b8b589f..7d9cc0e1a 100644 --- a/src/glx_context.c +++ b/src/glx_context.c @@ -59,7 +59,7 @@ static GLFWbool chooseFBConfig( const char* vendor; GLFWbool trustWindowBit = GLFW_TRUE; - if (findTransparent && !(_glfw.xrender.major || _glfw.xrender.minor)) { + if ( !(_glfw.xrender.major || _glfw.xrender.minor) ) { findTransparent = GLFW_FALSE; } From de4835e0d6d720f6885f7bd29efbdb60b6990183 Mon Sep 17 00:00:00 2001 From: Wolfgang Draxinger Date: Mon, 22 Feb 2016 19:42:21 +0100 Subject: [PATCH 3/4] free visualinfo and picture format info structures (plug a memory leak) --- src/glx_context.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/glx_context.c b/src/glx_context.c index 7d9cc0e1a..fedfc50d4 100644 --- a/src/glx_context.c +++ b/src/glx_context.c @@ -79,7 +79,9 @@ static GLFWbool chooseFBConfig( usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig)); usableCount = 0; - + + XVisualInfo *visualinfo = NULL; + XRenderPictFormat *pictFormat = NULL; selectionloop: for (i = 0; i < nativeCount; i++) { @@ -98,13 +100,21 @@ selectionloop: } if( findTransparent ) { - XVisualInfo *visualinfo; - XRenderPictFormat *pictFormat; + if( visualinfo ) { + XFree( visualinfo ); + visualinfo = NULL; + } + visualinfo = glXGetVisualFromFBConfig(_glfw.x11.display, n); if (!visualinfo) continue; + if( pictFormat ) { + XFree( pictFormat ); + pictFormat = NULL; + } + pictFormat = XRenderFindVisualFormat(_glfw.x11.display, visualinfo->visual); if( !pictFormat ) continue; @@ -141,6 +151,15 @@ selectionloop: u->glx = n; usableCount++; + + if( visualinfo ) { + XFree( visualinfo ); + visualinfo = NULL; + } + if( pictFormat ) { + XFree( pictFormat ); + pictFormat = NULL; + } } // reiterate the selection loop without looking for transparency supporting // formats if no matchig FB configs for a transparent window were found. From 188891dffb28238e533f4f28dd1ec414e38c7e9b Mon Sep 17 00:00:00 2001 From: Wolfgang Draxinger Date: Mon, 22 Feb 2016 21:03:18 +0100 Subject: [PATCH 4/4] X11/EGL transparent window support (seems like Mesa EGL fbconfigs don't match with transparent picture formats) --- src/egl_context.c | 49 ++++++++++++++++++++++++--- src/egl_context.h | 3 +- src/glx_context.c | 83 ++++++---------------------------------------- src/glx_context.h | 30 +---------------- src/x11_init.c | 49 +++++++++++++++++++++++++++ src/x11_platform.h | 27 ++++++++++++++- src/x11_window.c | 2 +- 7 files changed, 133 insertions(+), 110 deletions(-) diff --git a/src/egl_context.c b/src/egl_context.c index 827ccbfd3..d3c35ef79 100644 --- a/src/egl_context.c +++ b/src/egl_context.c @@ -86,13 +86,21 @@ static int getConfigAttrib(EGLConfig config, int attrib) // static GLFWbool chooseFBConfigs(const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* desired, - EGLConfig* result) + EGLConfig* result, + GLFWbool findTransparent) { EGLConfig* nativeConfigs; _GLFWfbconfig* usableConfigs; const _GLFWfbconfig* closest; int i, nativeCount, usableCount; +#if defined(_GLFW_X11) + XVisualInfo visualTemplate = {0}; + if ( !(_glfw.xrender.major || _glfw.xrender.minor) ) { + findTransparent = GLFW_FALSE; + } +#endif // _GLFW_X11 + eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount); if (!nativeCount) { @@ -106,6 +114,7 @@ static GLFWbool chooseFBConfigs(const _GLFWctxconfig* ctxconfig, usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig)); usableCount = 0; +selectionloop: for (i = 0; i < nativeCount; i++) { const EGLConfig n = nativeConfigs[i]; @@ -121,8 +130,31 @@ static GLFWbool chooseFBConfigs(const _GLFWctxconfig* ctxconfig, #if defined(_GLFW_X11) // Only consider EGLConfigs with associated Visuals - if (!getConfigAttrib(n, EGL_NATIVE_VISUAL_ID)) + visualTemplate.visualid = getConfigAttrib(n, EGL_NATIVE_VISUAL_ID); + if (!visualTemplate.visualid) continue; + + if( findTransparent ) { + int n_vi; + XVisualInfo *visualinfo; + XRenderPictFormat *pictFormat; + + visualinfo = XGetVisualInfo(_glfw.x11.display, VisualIDMask, &visualTemplate, &n_vi); + if (!visualinfo) + continue; + + pictFormat = XRenderFindVisualFormat(_glfw.x11.display, visualinfo->visual); + if( !pictFormat ) { + XFree( visualinfo ); + continue; + } + + if( !pictFormat->direct.alphaMask ) { + XFree( visualinfo ); + continue; + } + XFree( visualinfo ); + } #endif // _GLFW_X11 if (ctxconfig->api == GLFW_OPENGL_ES_API) @@ -158,6 +190,12 @@ static GLFWbool chooseFBConfigs(const _GLFWctxconfig* ctxconfig, u->egl = n; usableCount++; } + // reiterate the selection loop without looking for transparency supporting + // formats if no matchig FB configs for a transparent window were found. + if( findTransparent && !usableCount ) { + findTransparent = GLFW_FALSE; + goto selectionloop; + } closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount); if (closest) @@ -297,7 +335,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, if (ctxconfig->share) share = ctxconfig->share->context.egl.handle; - if (!chooseFBConfigs(ctxconfig, fbconfig, &config)) + if (!chooseFBConfigs(ctxconfig, fbconfig, &config, window->transparent)) { _glfwInputError(GLFW_FORMAT_UNAVAILABLE, "EGL: Failed to find a suitable EGLConfig"); @@ -535,7 +573,8 @@ void _glfwDestroyContextEGL(_GLFWwindow* window) // Returns the Visual and depth of the chosen EGLConfig // #if defined(_GLFW_X11) -GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig, +GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig, + const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig, Visual** visual, int* depth) { @@ -545,7 +584,7 @@ GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig, EGLint visualID = 0, count = 0; const long vimask = VisualScreenMask | VisualIDMask; - if (!chooseFBConfigs(ctxconfig, fbconfig, &native)) + if (!chooseFBConfigs(ctxconfig, fbconfig, &native, wndconfig->transparent)) { _glfwInputError(GLFW_FORMAT_UNAVAILABLE, "EGL: Failed to find a suitable EGLConfig"); diff --git a/src/egl_context.h b/src/egl_context.h index 15d5a1258..b37263311 100644 --- a/src/egl_context.h +++ b/src/egl_context.h @@ -207,7 +207,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, const _GLFWfbconfig* fbconfig); void _glfwDestroyContextEGL(_GLFWwindow* window); #if defined(_GLFW_X11) -GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig, +GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig, + const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig, Visual** visual, int* depth); #endif /*_GLFW_X11*/ diff --git a/src/glx_context.c b/src/glx_context.c index fedfc50d4..ca225e244 100644 --- a/src/glx_context.c +++ b/src/glx_context.c @@ -80,8 +80,6 @@ static GLFWbool chooseFBConfig( usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig)); usableCount = 0; - XVisualInfo *visualinfo = NULL; - XRenderPictFormat *pictFormat = NULL; selectionloop: for (i = 0; i < nativeCount; i++) { @@ -100,27 +98,24 @@ selectionloop: } if( findTransparent ) { - - if( visualinfo ) { - XFree( visualinfo ); - visualinfo = NULL; - } + XVisualInfo *visualinfo; + XRenderPictFormat *pictFormat; visualinfo = glXGetVisualFromFBConfig(_glfw.x11.display, n); if (!visualinfo) continue; - if( pictFormat ) { - XFree( pictFormat ); - pictFormat = NULL; + pictFormat = XRenderFindVisualFormat(_glfw.x11.display, visualinfo->visual); + if( !pictFormat ) { + XFree( visualinfo ); + continue; } - pictFormat = XRenderFindVisualFormat(_glfw.x11.display, visualinfo->visual); - if( !pictFormat ) - continue; - - if( !pictFormat->direct.alphaMask ) + if( !pictFormat->direct.alphaMask ) { + XFree( visualinfo ); continue; + } + XFree( visualinfo ); } u->redBits = getFBConfigAttrib(n, GLX_RED_SIZE); @@ -151,15 +146,6 @@ selectionloop: u->glx = n; usableCount++; - - if( visualinfo ) { - XFree( visualinfo ); - visualinfo = NULL; - } - if( pictFormat ) { - XFree( pictFormat ); - pictFormat = NULL; - } } // reiterate the selection loop without looking for transparency supporting // formats if no matchig FB configs for a transparent window were found. @@ -212,17 +198,6 @@ GLFWbool _glfwInitGLX(void) NULL }; - const char* sonames_xrender[] = - { -#if defined(__CYGWIN__) - "libXrender-1.so", -#else - "libXrender.so.1", - "libXrender.so", -#endif - NULL - }; - for (i = 0; sonames_glx[i]; i++) { @@ -231,13 +206,6 @@ GLFWbool _glfwInitGLX(void) break; } - for (i = 0; sonames_xrender[i]; i++) - { - _glfw.xrender.handle = dlopen(sonames_xrender[i], RTLD_LAZY | RTLD_GLOBAL); - if (_glfw.xrender.handle) - break; - } - if (!_glfw.glx.handle) { _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: Failed to load GLX"); @@ -297,37 +265,6 @@ GLFWbool _glfwInitGLX(void) return GLFW_FALSE; } - // Xrender support is optional and not a requirement for GLX - // to work. Xrender is required for selecting a FB config that - // supports a picture format with an alpha mask, which in turn - // is required for transparent windows. I Xrender is not supported - // the GLFW_TRANSPARENT window hint is ignored. - _glfw.xrender.errorBase = 0; - _glfw.xrender.eventBase = 0; - _glfw.xrender.major = 0; - _glfw.xrender.minor = 0; - if (_glfw.xrender.handle) do { - int errorBase, eventBase, major, minor; - _glfw.xrender.QueryExtension = - dlsym(_glfw.xrender.handle, "XRenderQueryExtension"); - _glfw.xrender.QueryVersion = - dlsym(_glfw.xrender.handle, "XRenderQueryVersion"); - _glfw.xrender.FindVisualFormat = - dlsym(_glfw.xrender.handle, "XRenderFindVisualFormat"); - - if ( !XRenderQueryExtension(_glfw.x11.display, &errorBase, &eventBase)) { - break; - } - if ( !XRenderQueryVersion(_glfw.x11.display, &major, &minor)) { - break; - } - - _glfw.xrender.errorBase = errorBase; - _glfw.xrender.eventBase = eventBase; - _glfw.xrender.major = major; - _glfw.xrender.minor = minor; - } while(0); - if (_glfwPlatformExtensionSupported("GLX_EXT_swap_control")) { _glfw.glx.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) diff --git a/src/glx_context.h b/src/glx_context.h index 81b7d1e6b..cc3f22983 100644 --- a/src/glx_context.h +++ b/src/glx_context.h @@ -109,19 +109,9 @@ typedef void (*PFNGLXDESTROYWINDOWPROC)(Display*,GLXWindow); #define glXCreateWindow _glfw.glx.CreateWindow #define glXDestroyWindow _glfw.glx.DestroyWindow -// libXrender.so function pointer typedefs -typedef Bool (*PFNXRENDERQUERYEXTENSIONPROC)(Display*,int*,int*); -typedef Status (*PFNXRENDERQUERYVERSIONPROC)(Display*dpy,int*,int*); -typedef XRenderPictFormat* (*PFNXRENDERFINDVISUALFORMATPROC)(Display*,Visual const *); - -// libXrender.so function identifier overlays -#define XRenderQueryExtension _glfw.xrender.QueryExtension -#define XRenderQueryVersion _glfw.xrender.QueryVersion -#define XRenderFindVisualFormat _glfw.xrender.FindVisualFormat - #define _GLFW_PLATFORM_FBCONFIG GLXFBConfig glx #define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextGLX glx -#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryGLX glx ; _GLFWlibraryXrender xrender +#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryGLX glx // GLX-specific per-context data @@ -181,24 +171,6 @@ typedef struct _GLFWlibraryGLX } _GLFWlibraryGLX; -// Xrender-specific global data -// -typedef struct _GLFWlibraryXrender -{ - int major, minor; - int eventBase; - int errorBase; - - // dlopen handle for libGL.so.1 - void* handle; - - // Xrender functions (subset required for transparent window) - PFNXRENDERQUERYEXTENSIONPROC QueryExtension; - PFNXRENDERQUERYVERSIONPROC QueryVersion; - PFNXRENDERFINDVISUALFORMATPROC FindVisualFormat; -} _GLFWlibraryXrender; - - GLFWbool _glfwInitGLX(void); void _glfwTerminateGLX(void); GLFWbool _glfwCreateContextGLX(_GLFWwindow* window, diff --git a/src/x11_init.c b/src/x11_init.c index 0125a8b7b..7e2e8cd6f 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -474,6 +474,18 @@ static void detectEWMH(void) // static GLFWbool initExtensions(void) { + int i; + const char* sonames_xrender[] = + { +#if defined(__CYGWIN__) + "libXrender-1.so", +#else + "libXrender.so.1", + "libXrender.so", +#endif + NULL + }; + // Find or create window manager atoms _glfw.x11.WM_PROTOCOLS = XInternAtom(_glfw.x11.display, "WM_PROTOCOLS", @@ -615,6 +627,43 @@ static GLFWbool initExtensions(void) _glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", True); _glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", True); + // Xrender support is optional and not a requirement for GLX/EGL + // to work. Xrender is required for selecting a FB config that + // supports a picture format with an alpha mask, which in turn + // is required for transparent windows. I Xrender is not supported + // the GLFW_TRANSPARENT window hint is ignored. + for (i = 0; sonames_xrender[i]; i++) + { + _glfw.xrender.handle = dlopen(sonames_xrender[i], RTLD_LAZY | RTLD_GLOBAL); + if (_glfw.xrender.handle) + break; + } + _glfw.xrender.errorBase = 0; + _glfw.xrender.eventBase = 0; + _glfw.xrender.major = 0; + _glfw.xrender.minor = 0; + if (_glfw.xrender.handle) do { + int errorBase, eventBase, major, minor; + _glfw.xrender.QueryExtension = + dlsym(_glfw.xrender.handle, "XRenderQueryExtension"); + _glfw.xrender.QueryVersion = + dlsym(_glfw.xrender.handle, "XRenderQueryVersion"); + _glfw.xrender.FindVisualFormat = + dlsym(_glfw.xrender.handle, "XRenderFindVisualFormat"); + + if ( !XRenderQueryExtension(_glfw.x11.display, &errorBase, &eventBase)) { + break; + } + if ( !XRenderQueryVersion(_glfw.x11.display, &major, &minor)) { + break; + } + + _glfw.xrender.errorBase = errorBase; + _glfw.xrender.eventBase = eventBase; + _glfw.xrender.major = major; + _glfw.xrender.minor = minor; + } while(0); + return GLFW_TRUE; } diff --git a/src/x11_platform.h b/src/x11_platform.h index 8d791f074..6a95ea263 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -103,10 +103,20 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(Vk #define _glfw_dlsym(handle, name) dlsym(handle, name) #define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowX11 x11 -#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11 +#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11 ; _GLFWlibraryXrender xrender #define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorX11 x11 #define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorX11 x11 +// libXrender.so function pointer typedefs +typedef Bool (*PFNXRENDERQUERYEXTENSIONPROC)(Display*,int*,int*); +typedef Status (*PFNXRENDERQUERYVERSIONPROC)(Display*dpy,int*,int*); +typedef XRenderPictFormat* (*PFNXRENDERFINDVISUALFORMATPROC)(Display*,Visual const *); + +// libXrender.so function identifier overlays +#define XRenderQueryExtension _glfw.xrender.QueryExtension +#define XRenderQueryVersion _glfw.xrender.QueryVersion +#define XRenderFindVisualFormat _glfw.xrender.FindVisualFormat + // X11-specific per-window data // @@ -255,6 +265,21 @@ typedef struct _GLFWlibraryX11 } _GLFWlibraryX11; +// Xrender-specific global data +typedef struct _GLFWlibraryXrender +{ + int major, minor; + int eventBase; + int errorBase; + + // dlopen handle for libGL.so.1 + void* handle; + + // Xrender functions (subset required for transparent window) + PFNXRENDERQUERYEXTENSIONPROC QueryExtension; + PFNXRENDERQUERYVERSIONPROC QueryVersion; + PFNXRENDERFINDVISUALFORMATPROC FindVisualFormat; +} _GLFWlibraryXrender; // X11-specific per-monitor data // diff --git a/src/x11_window.c b/src/x11_window.c index a2b96a997..d85229328 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -1434,7 +1434,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, if (!_glfwChooseVisualGLX(wndconfig, ctxconfig, fbconfig, &visual, &depth)) return GLFW_FALSE; #elif defined(_GLFW_EGL) - if (!_glfwChooseVisualEGL(ctxconfig, fbconfig, &visual, &depth)) + if (!_glfwChooseVisualEGL(wndconfig, ctxconfig, fbconfig, &visual, &depth)) return GLFW_FALSE; #endif }