From 0faa39147090dc84ea3c75f0df48739ec82b2e44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=40roxlu=20=E2=98=BE?= Date: Wed, 31 Jul 2019 18:30:45 +0200 Subject: [PATCH] Copy GLXFBConfig from shared context. (#1456) * Copy GLXFBConfig from shared context. * Style fixes --- filament/backend/src/opengl/PlatformGLX.cpp | 105 +++++++++++++++++--- 1 file changed, 92 insertions(+), 13 deletions(-) diff --git a/filament/backend/src/opengl/PlatformGLX.cpp b/filament/backend/src/opengl/PlatformGLX.cpp index ad6d58b8c7..92d086efd5 100644 --- a/filament/backend/src/opengl/PlatformGLX.cpp +++ b/filament/backend/src/opengl/PlatformGLX.cpp @@ -46,6 +46,31 @@ struct GLXFunctions { PFNGLXCREATEPBUFFERPROC createPbuffer; PFNGLXDESTROYPBUFFERPROC destroyPbuffer; PFNGLXMAKECONTEXTCURRENTPROC setCurrentContext; + + /* + When creating a shared GL context, we query the used + GLX_FBCONFIG_ID to make sure our display framebuffer + attributes match; otherwise making our context current + results in a BadMatch + https://gist.github.com/roxlu/c282d642c353ce96ef19b6359c741bcb + */ + PFNGLXQUERYCONTEXTPROC queryContext; + + /* + When creating a shared GL context, we select the matching + GLXFBConfig that is used by the shared GL context. `getFBConfigs` + will return all the available GLXFBConfigs. + */ + PFNGLXGETFBCONFIGSPROC getFbConfigs; + + /* + When creating a shared GL contect, we iterate over the + available GLXFBConfigs that are returned by `getFBConfigs`, + we use `getFbConfigAttrib` to find the matching + `GLX_FBCONFIG_ID`. + */ + PFNGLXGETFBCONFIGATTRIBPROC getFbConfigAttrib; + GLX_DESTROY_CONTEXT destroyContext; GLX_SWAP_BUFFERS swapBuffers; void* library; @@ -85,6 +110,12 @@ static bool loadLibraries() { g_glx.swapBuffers = (GLX_SWAP_BUFFERS) getProcAddress((const GLubyte*) "glXSwapBuffers"); + g_glx.queryContext = (PFNGLXQUERYCONTEXTPROC) + getProcAddress((const GLubyte*) "glXQueryContext"); + g_glx.getFbConfigs = (PFNGLXGETFBCONFIGSPROC) + getProcAddress((const GLubyte*) "glXGetFBConfigs"); + g_glx.getFbConfigAttrib = (PFNGLXGETFBCONFIGATTRIBPROC) + getProcAddress((const GLubyte*) "glXGetFBConfigAttrib"); g_x11.library = dlopen(LIBRARY_X11, RTLD_LOCAL | RTLD_NOW); if (!g_x11.library) { @@ -105,36 +136,84 @@ Driver* PlatformGLX::createDriver(void* const sharedGLContext) noexcept { loadLibraries(); // Get the display device mGLXDisplay = g_x11.openDisplay(NULL); - if (!mGLXDisplay) { - printf("Failed to open X display\n"); + if (mGLXDisplay == nullptr) { + utils::slog.e << "Failed to open X display. (exiting)." << utils::io::endl; exit(1); } - // Create a context - static int attribs[] = { GLX_DOUBLEBUFFER, True, None }; + if (sharedGLContext != nullptr) { + + int r = -1; + int usedFbId = -1; + GLXContext sharedCtx = (GLXContext)((void*)sharedGLContext); + + r = g_glx.queryContext(mGLXDisplay, sharedCtx, GLX_FBCONFIG_ID, &usedFbId); + if (r != 0) { + utils::slog.e << "Failed to get GLX_FBCONFIG_ID from shared GL context." << utils::io::endl; + return nullptr; + } + + int numConfigs = 0; + GLXFBConfig* fbConfigs = g_glx.getFbConfigs(mGLXDisplay, 0, &numConfigs); + + if (fbConfigs == nullptr) { + utils::slog.e << "Failed to get the available GLXFBConfigs." << utils::io::endl; + return nullptr; + } - int config_count = 0; - mGLXConfig = g_glx.chooseFbConfig(mGLXDisplay, DefaultScreen(mGLXDisplay), - attribs, &config_count); - if (mGLXConfig == nullptr || config_count == 0) { - return nullptr; + int fbId = 0; + int fbIndex = -1; + + for (int i = 0; i < numConfigs; ++i) { + + r = g_glx.getFbConfigAttrib(mGLXDisplay, fbConfigs[i], GLX_FBCONFIG_ID, &fbId); + if (r != 0) { + utils::slog.e << "Failed to get GLX_FBCONFIG_ID for entry " << i << "." << utils::io::endl; + continue; + } + + if (fbId == usedFbId) { + fbIndex = i; + break; + } + } + + if (fbIndex < 0) { + utils::slog.e << "Failed to find an `GLXFBConfig` with the requested ID." << utils::io::endl; + return nullptr; + } + + mGLXConfig = fbConfigs + fbIndex; + } + else { + + // Create a context + static int attribs[] = { GLX_DOUBLEBUFFER, True, None }; + + int configCount = 0; + mGLXConfig = g_glx.chooseFbConfig(mGLXDisplay, DefaultScreen(mGLXDisplay), + attribs, &configCount); + if (mGLXConfig == nullptr || configCount == 0) { + return nullptr; + } } PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = (PFNGLXCREATECONTEXTATTRIBSARBPROC) getProcAddress((GLubyte*) "glXCreateContextAttribsARB"); - if (glXCreateContextAttribs == NULL) { - utils::slog.i << "Unable to retrieve function pointer" << utils::io::endl; + if (glXCreateContextAttribs == nullptr) { + utils::slog.i << "Unable to retrieve function pointer for `glXCreateContextAttribs()`." << utils::io::endl; return nullptr; } - int context_attribs[] = { + int contextAttribs[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, 4, GLX_CONTEXT_MINOR_VERSION_ARB, 1, GL_NONE }; + mGLXContext = g_glx.createContext(mGLXDisplay, mGLXConfig[0], - (GLXContext) sharedGLContext, True, context_attribs); + (GLXContext) sharedGLContext, True, contextAttribs); int pbufferAttribs[] = { GLX_PBUFFER_WIDTH, 1,