diff --git a/util/test/demos/gl/gl_test_linux.cpp b/util/test/demos/gl/gl_test_linux.cpp index 989c6d91a..e4ad87d3a 100644 --- a/util/test/demos/gl/gl_test_linux.cpp +++ b/util/test/demos/gl/gl_test_linux.cpp @@ -29,6 +29,63 @@ #include "../linux/linux_window.h" +namespace +{ +int visual_id = 0; +}; + +static GLXFBConfig *GetGLXFBConfigs(Display *dpy) +{ + // GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB MUST be the last attrib so that we can remove it to retry + // if we find no srgb fbconfigs + static int visAttribs[] = {GLX_X_RENDERABLE, + True, + GLX_DRAWABLE_TYPE, + GLX_WINDOW_BIT, + GLX_RENDER_TYPE, + GLX_RGBA_BIT, + GLX_X_VISUAL_TYPE, + GLX_TRUE_COLOR, + GLX_RED_SIZE, + 8, + GLX_GREEN_SIZE, + 8, + GLX_BLUE_SIZE, + 8, + GLX_ALPHA_SIZE, + 8, + GLX_DEPTH_SIZE, + 0, + GLX_STENCIL_SIZE, + 0, + GLX_DOUBLEBUFFER, + True, + GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, + True, + 0}; + + int numCfgs = 0; + GLXFBConfig *fbcfg = glXChooseFBConfig(dpy, DefaultScreen(dpy), visAttribs, &numCfgs); + + if(fbcfg == NULL) + { + const size_t len = ARRAY_COUNT(visAttribs); + if(visAttribs[len - 3] != GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB) + { + TEST_ERROR( + "GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB isn't the last attribute, and no SRGB fbconfigs were " + "found!"); + } + else + { + visAttribs[len - 3] = 0; + fbcfg = glXChooseFBConfig(dpy, DefaultScreen(dpy), visAttribs, &numCfgs); + } + } + + return fbcfg; +} + void OpenGLGraphicsTest::Prepare(int argc, char **argv) { GraphicsTest::Prepare(argc, argv); @@ -58,7 +115,19 @@ bool OpenGLGraphicsTest::Init() gladLoadGLX(dpy, DefaultScreen(dpy)); - mainWindow = new X11Window(screenWidth, screenHeight, screenTitle); + // on some systems we need to choose a visual in advance that will be compatible if we want an + // RGBA backbuffer. Do that now + { + Display *display = X11Window::GetDisplay(); + + GLXFBConfig *fbcfg = GetGLXFBConfigs(display); + + glXGetFBConfigAttrib(display, fbcfg[0], GLX_VISUAL_ID, &visual_id); + + XFree(fbcfg); + } + + mainWindow = new X11Window(screenWidth, screenHeight, visual_id, screenTitle); mainContext = MakeContext(mainWindow, NULL); @@ -85,7 +154,7 @@ bool OpenGLGraphicsTest::Init() GraphicsWindow *OpenGLGraphicsTest::MakeWindow(int width, int height, const char *title) { - return new X11Window(width, height, title); + return new X11Window(width, height, visual_id, title); } void *OpenGLGraphicsTest::MakeContext(GraphicsWindow *win, void *share) @@ -118,50 +187,8 @@ void *OpenGLGraphicsTest::MakeContext(GraphicsWindow *win, void *share) else attribs[i++] = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; - // GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB MUST be the last attrib so that we can remove it to retry - // if we find no srgb fbconfigs - static int visAttribs[] = {GLX_X_RENDERABLE, - True, - GLX_DRAWABLE_TYPE, - GLX_WINDOW_BIT, - GLX_RENDER_TYPE, - GLX_RGBA_BIT, - GLX_X_VISUAL_TYPE, - GLX_TRUE_COLOR, - GLX_RED_SIZE, - 8, - GLX_GREEN_SIZE, - 8, - GLX_BLUE_SIZE, - 8, - GLX_ALPHA_SIZE, - 8, - GLX_DOUBLEBUFFER, - True, - GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, - True, - 0}; - - int numCfgs = 0; - GLXFBConfig *fbcfg = glXChooseFBConfig(x11win->xlib.display, DefaultScreen(x11win->xlib.display), - visAttribs, &numCfgs); - - if(fbcfg == NULL) - { - const size_t len = ARRAY_COUNT(visAttribs); - if(visAttribs[len - 3] != GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB) - { - TEST_ERROR( - "GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB isn't the last attribute, and no SRGB fbconfigs were " - "found!"); - } - else - { - visAttribs[len - 3] = 0; - fbcfg = glXChooseFBConfig(x11win->xlib.display, DefaultScreen(x11win->xlib.display), - visAttribs, &numCfgs); - } - } + Display *dpy = x11win->xlib.display; + GLXFBConfig *fbcfg = GetGLXFBConfigs(dpy); if(fbcfg == NULL) { @@ -169,19 +196,8 @@ void *OpenGLGraphicsTest::MakeContext(GraphicsWindow *win, void *share) return NULL; } - // Choose FB config with a GLX_VISUAL_ID that matches the X screen. - VisualID visualid_correct = - DefaultVisual(x11win->xlib.display, DefaultScreen(x11win->xlib.display))->visualid; - for(int i = 0; i < numCfgs; i++) - { - int visualid; - glXGetFBConfigAttrib(x11win->xlib.display, fbcfg[i], GLX_VISUAL_ID, &visualid); - if((VisualID)visualid == visualid_correct) - { - fbcfg[0] = fbcfg[i]; - break; - } - } + // we should have selected a compatible visual with the first fbcfg when creating the window, so + // we can use fbcfg[0] GLXContext ctx = glXCreateContextAttribsARB(x11win->xlib.display, fbcfg[0], (GLXContext)share, true, attribs); diff --git a/util/test/demos/linux/linux_window.cpp b/util/test/demos/linux/linux_window.cpp index 1d3c251b2..162810e97 100644 --- a/util/test/demos/linux/linux_window.cpp +++ b/util/test/demos/linux/linux_window.cpp @@ -54,7 +54,7 @@ Display *X11Window::GetDisplay() return display; } -X11Window::X11Window(int width, int height, const char *title) +X11Window::X11Window(int width, int height, int visualid_override, const char *title) { uint32_t value_mask, value_list[32]; @@ -65,8 +65,19 @@ X11Window::X11Window(int width, int height, const char *title) value_list[1] = XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY; + xcb_visualid_t visual = screen->root_visual; + + if(visualid_override) + { + visual = (xcb_visualid_t)visualid_override; + + value_mask |= XCB_CW_COLORMAP; + value_list[2] = xcb_generate_id(connection); + xcb_create_colormap(connection, XCB_COLORMAP_ALLOC_NONE, value_list[2], screen->root, visual); + } + xcb_create_window(connection, XCB_COPY_FROM_PARENT, window, screen->root, 0, 0, width, height, 0, - XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, value_mask, value_list); + XCB_WINDOW_CLASS_INPUT_OUTPUT, visual, value_mask, value_list); /* Magic code that will send notification when window is destroyed */ xcb_intern_atom_cookie_t cookie = xcb_intern_atom(connection, 1, 12, "WM_PROTOCOLS"); diff --git a/util/test/demos/linux/linux_window.h b/util/test/demos/linux/linux_window.h index 05091a4e2..fbfeff6f3 100644 --- a/util/test/demos/linux/linux_window.h +++ b/util/test/demos/linux/linux_window.h @@ -33,7 +33,7 @@ struct X11Window : public GraphicsWindow static void Init(); static Display *GetDisplay(); - X11Window(int width, int height, const char *title); + X11Window(int width, int height, int visualid_override, const char *title); ~X11Window(); void Resize(int width, int height); bool Update(); diff --git a/util/test/demos/vk/vk_test.cpp b/util/test/demos/vk/vk_test.cpp index 8859ed68f..7dec32415 100644 --- a/util/test/demos/vk/vk_test.cpp +++ b/util/test/demos/vk/vk_test.cpp @@ -513,7 +513,7 @@ VulkanWindow *VulkanGraphicsTest::MakeWindow(int width, int height, const char * #if defined(WIN32) GraphicsWindow *platWin = new Win32Window(width, height, title); #else - GraphicsWindow *platWin = new X11Window(width, height, title); + GraphicsWindow *platWin = new X11Window(width, height, 0, title); #endif return new VulkanWindow(this, platWin);