Fixed ContextSettings ignored when creating a 3.x/4.x OpenGL context on Linux (#258)

This commit is contained in:
Laurent Gomila 2013-07-10 08:53:22 +02:00
parent c23d4a8385
commit 12ca0ef15a

View File

@ -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 // Save the creation settings
m_settings = 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 // Get the context to share display lists with
GLXContext toShare = shared ? shared->m_context : NULL; 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) // 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<const GLubyte*>("glXCreateContextAttribsARB"); const GLubyte* name = reinterpret_cast<const GLubyte*>("glXCreateContextAttribsARB");
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = reinterpret_cast<PFNGLXCREATECONTEXTATTRIBSARBPROC>(glXGetProcAddress(name)); PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = reinterpret_cast<PFNGLXCREATECONTEXTATTRIBSARBPROC>(glXGetProcAddress(name));
if (glXCreateContextAttribsARB) if (glXCreateContextAttribsARB)
{ {
// Select a GLXFB config that matches the requested context settings
int nbConfigs = 0; 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) if (configs && nbConfigs)
{ {
// Create the context while (!m_context && (m_settings.majorVersion >= 3))
int attributes[] =
{ {
GLX_CONTEXT_MAJOR_VERSION_ARB, static_cast<int>(m_settings.majorVersion), // Create the context
GLX_CONTEXT_MINOR_VERSION_ARB, static_cast<int>(m_settings.minorVersion), int attributes[] =
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, {
0, 0 GLX_CONTEXT_MAJOR_VERSION_ARB, static_cast<int>(m_settings.majorVersion),
}; GLX_CONTEXT_MINOR_VERSION_ARB, static_cast<int>(m_settings.minorVersion),
m_context = glXCreateContextAttribsARB(m_display, configs[0], toShare, true, attributes); 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); 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.majorVersion = 2;
m_settings.minorVersion = 0; 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); m_context = glXCreateContext(m_display, visualInfo, toShare, true);
if (!m_context) if (!m_context)
{ {