From 12ca0ef15a15fbfef52992a4d23786c65c7b5202 Mon Sep 17 00:00:00 2001 From: Laurent Gomila Date: Wed, 10 Jul 2013 08:53:22 +0200 Subject: [PATCH] Fixed ContextSettings ignored when creating a 3.x/4.x OpenGL context on Linux (#258) --- src/SFML/Window/Linux/GlxContext.cpp | 115 +++++++++++++++++---------- 1 file changed, 71 insertions(+), 44 deletions(-) diff --git a/src/SFML/Window/Linux/GlxContext.cpp b/src/SFML/Window/Linux/GlxContext.cpp index acf54d6b..6454d781 100644 --- a/src/SFML/Window/Linux/GlxContext.cpp +++ b/src/SFML/Window/Linux/GlxContext.cpp @@ -215,69 +215,80 @@ XVisualInfo GlxContext::selectBestVisual(::Display* display, unsigned int bitsPe //////////////////////////////////////////////////////////// -void GlxContext::createContext(GlxContext* shared, unsigned int /*bitsPerPixel*/, const ContextSettings& settings) +void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings) { + XVisualInfo* visualInfo = NULL; + // Save the creation settings m_settings = settings; - // Retrieve the attributes of the target window - XWindowAttributes windowAttributes; - if (XGetWindowAttributes(m_display, m_window, &windowAttributes) == 0) - { - err() << "Failed to get the window attributes" << std::endl; - return; - } - - // Get its visual - XVisualInfo tpl; - tpl.screen = DefaultScreen(m_display); - tpl.visualid = XVisualIDFromVisual(windowAttributes.visual); - int nbVisuals = 0; - XVisualInfo* visualInfo = XGetVisualInfo(m_display, VisualIDMask | VisualScreenMask, &tpl, &nbVisuals); - // Get the context to share display lists with GLXContext toShare = shared ? shared->m_context : NULL; // Create the OpenGL context -- first try context versions >= 3.0 if it is requested (they require special code) - while (!m_context && (m_settings.majorVersion >= 3)) + if (m_settings.majorVersion >= 3) { const GLubyte* name = reinterpret_cast("glXCreateContextAttribsARB"); PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = reinterpret_cast(glXGetProcAddress(name)); if (glXCreateContextAttribsARB) { + // Select a GLXFB config that matches the requested context settings int nbConfigs = 0; - GLXFBConfig* configs = glXChooseFBConfig(m_display, DefaultScreen(m_display), NULL, &nbConfigs); + int fbAttributes[] = + { + GLX_DEPTH_SIZE, settings.depthBits, + GLX_STENCIL_SIZE, settings.stencilBits, + GLX_SAMPLE_BUFFERS, settings.antialiasingLevel > 0, + GLX_SAMPLES, settings.antialiasingLevel, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, bitsPerPixel == 32 ? 8 : 0, + GLX_DOUBLEBUFFER, True, + GLX_X_RENDERABLE, True, + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_CONFIG_CAVEAT, GLX_NONE, + None + }; + GLXFBConfig* configs = glXChooseFBConfig(m_display, DefaultScreen(m_display), fbAttributes, &nbConfigs); if (configs && nbConfigs) { - // Create the context - int attributes[] = + while (!m_context && (m_settings.majorVersion >= 3)) { - GLX_CONTEXT_MAJOR_VERSION_ARB, static_cast(m_settings.majorVersion), - GLX_CONTEXT_MINOR_VERSION_ARB, static_cast(m_settings.minorVersion), - GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, - 0, 0 - }; - m_context = glXCreateContextAttribsARB(m_display, configs[0], toShare, true, attributes); - } + // Create the context + int attributes[] = + { + GLX_CONTEXT_MAJOR_VERSION_ARB, static_cast(m_settings.majorVersion), + GLX_CONTEXT_MINOR_VERSION_ARB, static_cast(m_settings.minorVersion), + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, + 0, 0 + }; + m_context = glXCreateContextAttribsARB(m_display, configs[0], toShare, true, attributes); - if (configs) + if (m_context) + { + // Ok: retrieve the config's visual + visualInfo = glXGetVisualFromFBConfig(m_display, configs[0]); + } + else + { + // If we couldn't create the context, lower the version number and try again -- stop at 3.0 + // Invalid version numbers will be generated by this algorithm (like 3.9), but we really don't care + if (m_settings.minorVersion > 0) + { + // If the minor version is not 0, we decrease it and try again + m_settings.minorVersion--; + } + else + { + // If the minor version is 0, we decrease the major version + m_settings.majorVersion--; + m_settings.minorVersion = 9; + } + } + } XFree(configs); - } - - // If we couldn't create the context, lower the version number and try again -- stop at 3.0 - // Invalid version numbers will be generated by this algorithm (like 3.9), but we really don't care - if (!m_context) - { - if (m_settings.minorVersion > 0) - { - // If the minor version is not 0, we decrease it and try again - m_settings.minorVersion--; - } - else - { - // If the minor version is 0, we decrease the major version - m_settings.majorVersion--; - m_settings.minorVersion = 9; } } } @@ -289,6 +300,22 @@ void GlxContext::createContext(GlxContext* shared, unsigned int /*bitsPerPixel*/ m_settings.majorVersion = 2; m_settings.minorVersion = 0; + // Retrieve the attributes of the target window + XWindowAttributes windowAttributes; + if (XGetWindowAttributes(m_display, m_window, &windowAttributes) == 0) + { + err() << "Failed to get the window attributes" << std::endl; + return; + } + + // Get its visual + XVisualInfo tpl; + tpl.screen = DefaultScreen(m_display); + tpl.visualid = XVisualIDFromVisual(windowAttributes.visual); + int nbVisuals = 0; + visualInfo = XGetVisualInfo(m_display, VisualIDMask | VisualScreenMask, &tpl, &nbVisuals); + + // Create the context, using the target window's visual m_context = glXCreateContext(m_display, visualInfo, toShare, true); if (!m_context) {