diff --git a/cpp/display/display_glx.cpp b/cpp/display/display_glx.cpp index eb7112f..514218f 100644 --- a/cpp/display/display_glx.cpp +++ b/cpp/display/display_glx.cpp @@ -27,22 +27,6 @@ static bool rk_error_occured = false; #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 typedef GLXContext (*rk_CreateContextAttribsFunc)(Display *, GLXFBConfig, GLXContext, Bool, int const *); -static int const rk_visual_attribs[] = { - GLX_CONFIG_CAVEAT, GLX_NONE, - 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, 24, - GLX_STENCIL_SIZE, 8, - GLX_DOUBLEBUFFER, True, - None -}; - static int const rk_context_attribs[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, 2, @@ -60,7 +44,7 @@ static void rk_glx_printf( printf("[GLX] %s\n", messsage); } -static bool rk_extension_supported( +bool rk_extension_supported( char const * extensions, char const * extension) { char const * where = strchr(extension, ' '); @@ -142,40 +126,77 @@ rk_display_t rk_create_display( } int fb_count = 0; - GLXFBConfig * const fb_configs = glXChooseFBConfig( - display->display, DefaultScreen(display->display), rk_visual_attribs, &fb_count); + GLXFBConfig * fb_configs; + bool const srgb_ext = rk_extension_supported(glx_exts, "GLX_EXT_framebuffer_sRGB"); + if (srgb_ext) { + rk_glx_printf("GLX_EXT_framebuffer_sRGB extension supported."); + int const visual_attribs[] = { GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, True, GLX_DOUBLEBUFFER, True, None }; + fb_configs = glXChooseFBConfig(display->display, DefaultScreen(display->display), visual_attribs, &fb_count); + } else { + int const visual_attribs[] = { GLX_DOUBLEBUFFER, True, None }; + fb_configs = glXChooseFBConfig(display->display, DefaultScreen(display->display), visual_attribs, &fb_count); + } printf("[GLX] Found %d framebuffer configs.\n", fb_count); if (!fb_configs || !fb_count) { rk_glx_printf("Failed to retrieve framebuffer configs."); rk_destroy_display(reinterpret_cast(display)); return nullptr; } - GLXFBConfig const fb_config = fb_configs[0]; - XFree(fb_configs); - int red_size = 0; - glXGetFBConfigAttrib(display->display, fb_config, GLX_RED_SIZE, &red_size); - int green_size = 0; - glXGetFBConfigAttrib(display->display, fb_config, GLX_GREEN_SIZE, &green_size); - int blue_size = 0; - glXGetFBConfigAttrib(display->display, fb_config, GLX_BLUE_SIZE, &blue_size); - int alpha_size = 0; - glXGetFBConfigAttrib(display->display, fb_config, GLX_ALPHA_SIZE, &alpha_size); - int depth_size = 0; - glXGetFBConfigAttrib(display->display, fb_config, GLX_DEPTH_SIZE, &depth_size); - int stencil_size = 0; - glXGetFBConfigAttrib(display->display, fb_config, GLX_STENCIL_SIZE, &stencil_size); - printf("[GLX] Select framebuffer config R%dG%dB%dA%d D%dS%d.\n", - red_size, green_size, blue_size, alpha_size, depth_size, stencil_size); + GLXFBConfig fb_config; + int rs = 0; + int gs = 0; + int bs = 0; + int as = 0; + int ds = 0; + int ss = 0; + for (int fb_index = 0; fb_index < fb_count; ++fb_index) { + GLXFBConfig _config = fb_configs[fb_index]; + int _rs = 0; + int _gs = 0; + int _bs = 0; + int _as = 0; + int _ds = 0; + int _ss = 0; + glXGetFBConfigAttrib(display->display, _config, GLX_RED_SIZE, &_rs); + glXGetFBConfigAttrib(display->display, _config, GLX_GREEN_SIZE, &_gs); + glXGetFBConfigAttrib(display->display, _config, GLX_BLUE_SIZE, &_bs); + glXGetFBConfigAttrib(display->display, _config, GLX_ALPHA_SIZE, &_as); + glXGetFBConfigAttrib(display->display, _config, GLX_DEPTH_SIZE, &_ds); + glXGetFBConfigAttrib(display->display, _config, GLX_STENCIL_SIZE, &_ss); + if ((_rs >= rs && _gs >= gs && _bs >= bs && _as >= as && _ds >= ds && _ss >= ss) && + (_rs > rs || _gs > gs || _bs > bs || _as > as || _ds > ds || _ss > ss)) { + XVisualInfo * const vi = glXGetVisualFromFBConfig(display->display, _config); + if (vi) { + XFree(vi); + rs = _rs; + gs = _gs; + bs = _bs; + as = _as; + ds = _ds; + ss = _ss; + fb_config = _config; + } + } + } + printf("[RK] Select framebuffer config R%dG%dB%dA%d D%dS%d.\n", rs, gs, bs, as, ds, ss); + if (srgb_ext) { + int srgb = 0; + glXGetFBConfigAttrib(display->display, fb_config, GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, &srgb); + if (srgb) { + rk_glx_printf("sRGB framebuffer selected."); + } + } XVisualInfo * const vi = glXGetVisualFromFBConfig(display->display, fb_config); - display->colormap = XCreateColormap( - display->display, RootWindow(display->display, vi->screen), vi->visual, AllocNone); - XSetWindowAttributes swa; - swa.colormap = display->colormap; - swa.event_mask = RK_EVENTS_MASK; - display->window = XCreateWindow(display->display, RootWindow(display->display, vi->screen), - 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask, &swa); + Window root = RootWindow(display->display, vi->screen); + display->colormap = XCreateColormap(display->display, root, vi->visual, AllocNone); + XSetWindowAttributes win_attributes; + win_attributes.colormap = display->colormap; + win_attributes.event_mask = RK_EVENTS_MASK; + display->window = XCreateWindow(display->display, root, + 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask, &win_attributes); XFree(vi); + XFree(fb_configs); if (!display->window) { rk_x11_printf("Failed to create window."); rk_destroy_display(reinterpret_cast(display)); @@ -199,6 +220,12 @@ rk_display_t rk_create_display( rk_glx_printf("Warning: Rendering context is indirect."); } glXMakeCurrent(display->display, display->window, display->context); + if (srgb_ext) { + glEnable(GL_FRAMEBUFFER_SRGB_EXT); + if (glIsEnabled(GL_FRAMEBUFFER_SRGB_EXT)) { + rk_glx_printf("sRGB framebuffer enabled."); + } + } return reinterpret_cast(display); } diff --git a/cpp/display/display_glx.hpp b/cpp/display/display_glx.hpp index 80252a8..9fce4a5 100644 --- a/cpp/display/display_glx.hpp +++ b/cpp/display/display_glx.hpp @@ -26,6 +26,10 @@ struct rk_display_glx : public rk_display_x11 { typedef void (*rk_func_ptr)(); +extern bool rk_extension_supported( + char const * extensions, + char const * extension); + extern rk_func_ptr rk_resolve_extension( char const * extensions, char const * extension,