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,11 +215,91 @@ 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;
// 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)
if (m_settings.majorVersion >= 3)
{
const GLubyte* name = reinterpret_cast<const GLubyte*>("glXCreateContextAttribsARB");
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = reinterpret_cast<PFNGLXCREATECONTEXTATTRIBSARBPROC>(glXGetProcAddress(name));
if (glXCreateContextAttribsARB)
{
// Select a GLXFB config that matches the requested context settings
int nbConfigs = 0;
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)
{
while (!m_context && (m_settings.majorVersion >= 3))
{
// Create the context
int attributes[] =
{
GLX_CONTEXT_MAJOR_VERSION_ARB, static_cast<int>(m_settings.majorVersion),
GLX_CONTEXT_MINOR_VERSION_ARB, static_cast<int>(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 (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 the OpenGL >= 3.0 context failed or if we don't want one, create a regular OpenGL 1.x/2.x context
if (!m_context)
{
// set the context version to 2.0 (arbitrary)
m_settings.majorVersion = 2;
m_settings.minorVersion = 0;
// Retrieve the attributes of the target window // Retrieve the attributes of the target window
XWindowAttributes windowAttributes; XWindowAttributes windowAttributes;
if (XGetWindowAttributes(m_display, m_window, &windowAttributes) == 0) if (XGetWindowAttributes(m_display, m_window, &windowAttributes) == 0)
@ -233,62 +313,9 @@ void GlxContext::createContext(GlxContext* shared, unsigned int /*bitsPerPixel*/
tpl.screen = DefaultScreen(m_display); tpl.screen = DefaultScreen(m_display);
tpl.visualid = XVisualIDFromVisual(windowAttributes.visual); tpl.visualid = XVisualIDFromVisual(windowAttributes.visual);
int nbVisuals = 0; int nbVisuals = 0;
XVisualInfo* visualInfo = XGetVisualInfo(m_display, VisualIDMask | VisualScreenMask, &tpl, &nbVisuals); 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))
{
const GLubyte* name = reinterpret_cast<const GLubyte*>("glXCreateContextAttribsARB");
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = reinterpret_cast<PFNGLXCREATECONTEXTATTRIBSARBPROC>(glXGetProcAddress(name));
if (glXCreateContextAttribsARB)
{
int nbConfigs = 0;
GLXFBConfig* configs = glXChooseFBConfig(m_display, DefaultScreen(m_display), NULL, &nbConfigs);
if (configs && nbConfigs)
{
// Create the context
int attributes[] =
{
GLX_CONTEXT_MAJOR_VERSION_ARB, static_cast<int>(m_settings.majorVersion),
GLX_CONTEXT_MINOR_VERSION_ARB, static_cast<int>(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)
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;
}
}
}
// If the OpenGL >= 3.0 context failed or if we don't want one, create a regular OpenGL 1.x/2.x context
if (!m_context)
{
// set the context version to 2.0 (arbitrary)
m_settings.majorVersion = 2;
m_settings.minorVersion = 0;
// 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)
{ {