Removed separate GLXFBConfig selection during context creation (it is chosen to match the window's already selected visual), reverted to conservative context creation only using glXCreateContextAttribsARB when absolutely necessary.

This commit is contained in:
binary1248 2015-03-23 16:03:47 +01:00
parent 3996faa54c
commit cee6263a01

View File

@ -303,89 +303,11 @@ void GlxContext::setVerticalSyncEnabled(bool enabled)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
XVisualInfo GlxContext::selectBestVisual(::Display* display, unsigned int bitsPerPixel, const ContextSettings& settings) XVisualInfo GlxContext::selectBestVisual(::Display* display, unsigned int bitsPerPixel, const ContextSettings& settings)
{ {
// First try to get a visual via an associated GLXFBConfig (requires GLX 1.3 or greater)
// There are no GLX versions prior to 1.0
int major, minor;
if (glXQueryVersion(display, &major, &minor) && ((major > 1) || (minor >= 3)))
{
// Select a GLXFB config that matches the requested context settings
int nbConfigs = 0;
int fbAttributes[] =
{
GLX_DEPTH_SIZE, static_cast<int>(settings.depthBits),
GLX_STENCIL_SIZE, static_cast<int>(settings.stencilBits),
GLX_SAMPLE_BUFFERS, settings.antialiasingLevel > 0,
GLX_SAMPLES, static_cast<int>(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(display, DefaultScreen(display), fbAttributes, &nbConfigs);
int bestScore = 0xFFFF;
XVisualInfo bestVisual;
for (int i = 0; configs && (i < nbConfigs); ++i)
{
XVisualInfo* visual = glXGetVisualFromFBConfig(display, configs[i]);
// We only want FBConfigs with associated X visuals (most have one)
if (!visual)
continue;
// Check mandatory attributes
int doubleBuffer;
glXGetFBConfigAttrib(display, configs[i], GLX_DOUBLEBUFFER, &doubleBuffer);
if (!doubleBuffer)
continue;
// Extract the components of the current visual
int red, green, blue, alpha, depth, stencil, multiSampling, samples;
glXGetFBConfigAttrib(display, configs[i], GLX_RED_SIZE, &red);
glXGetFBConfigAttrib(display, configs[i], GLX_GREEN_SIZE, &green);
glXGetFBConfigAttrib(display, configs[i], GLX_BLUE_SIZE, &blue);
glXGetFBConfigAttrib(display, configs[i], GLX_ALPHA_SIZE, &alpha);
glXGetFBConfigAttrib(display, configs[i], GLX_DEPTH_SIZE, &depth);
glXGetFBConfigAttrib(display, configs[i], GLX_STENCIL_SIZE, &stencil);
glXGetFBConfigAttrib(display, configs[i], GLX_SAMPLE_BUFFERS_ARB, &multiSampling);
glXGetFBConfigAttrib(display, configs[i], GLX_SAMPLES_ARB, &samples);
// Evaluate the visual
int color = red + green + blue + alpha;
int score = evaluateFormat(bitsPerPixel, settings, color, depth, stencil, multiSampling ? samples : 0);
// If it's better than the current best, make it the new best
if (score < bestScore)
{
bestScore = score;
bestVisual = *visual;
}
XFree(visual);
}
XFree(configs);
if (bestScore < 0xFFFF)
return bestVisual;
}
// Retrieve all the visuals // Retrieve all the visuals
int count; int count;
XVisualInfo* visuals = XGetVisualInfo(display, 0, NULL, &count); XVisualInfo* visuals = XGetVisualInfo(display, 0, NULL, &count);
if (visuals) if (visuals)
{ {
#if defined(GLX_DEBUGGING)
GlxErrorHandler handler(display);
#endif
// Evaluate all the returned visuals, and pick the best one // Evaluate all the returned visuals, and pick the best one
int bestScore = 0xFFFF; int bestScore = 0xFFFF;
XVisualInfo bestVisual; XVisualInfo bestVisual;
@ -420,11 +342,6 @@ XVisualInfo GlxContext::selectBestVisual(::Display* display, unsigned int bitsPe
} }
} }
#if defined(GLX_DEBUGGING)
if (glxErrorOccurred)
err() << "GLX error in GlxContext::selectBestVisual()" << std::endl;
#endif
// Free the array of visuals // Free the array of visuals
XFree(visuals); XFree(visuals);
@ -445,6 +362,21 @@ void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, co
// 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 visuals
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;
@ -460,104 +392,47 @@ void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, co
if (shared) if (shared)
ensureExtensionsInit(m_display, DefaultScreen(m_display)); ensureExtensionsInit(m_display, DefaultScreen(m_display));
// Create the OpenGL context -- first try using glXCreateContextAttribsARB (requires GLX 1.3 or greater) // Check if glXCreateContextAttribsARB is available (requires GLX 1.3 or greater)
if ((sfglx_ext_ARB_create_context == sfglx_LOAD_SUCCEEDED) && ((major > 1) || (minor >= 3))) bool hasCreateContextArb = (sfglx_ext_ARB_create_context == sfglx_LOAD_SUCCEEDED) && ((major > 1) || (minor >= 3));
// Check if we need to use glXCreateContextAttribsARB
bool needCreateContextArb = false;
if (m_settings.attributeFlags)
needCreateContextArb = true;
else if (m_settings.majorVersion >= 3)
needCreateContextArb = true;
// Create the OpenGL context -- first try using glXCreateContextAttribsARB if we need to
if (hasCreateContextArb && needCreateContextArb)
{ {
// Select a GLXFB config that matches the requested context settings // Get a GLXFBConfig that matches the the window's visual, for glXCreateContextAttribsARB
GLXFBConfig* config = NULL;
// We don't supply attributes to match against, since
// the visual we are matching against was already
// deemed suitable in selectBestVisual()
int nbConfigs = 0; int nbConfigs = 0;
GLXFBConfig* configs = NULL; GLXFBConfig* configs = glXChooseFBConfig(m_display, DefaultScreen(m_display), NULL, &nbConfigs);
// Check if multisampling is supported
if (sfglx_ext_ARB_multisample == sfglx_LOAD_SUCCEEDED)
{
int fbAttributes[] =
{
GLX_DEPTH_SIZE, static_cast<int>(settings.depthBits),
GLX_STENCIL_SIZE, static_cast<int>(settings.stencilBits),
GLX_SAMPLE_BUFFERS_ARB, (settings.antialiasingLevel > 0) ? 1 : 0,
GLX_SAMPLES_ARB, static_cast<int>(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
};
configs = glXChooseFBConfig(m_display, DefaultScreen(m_display), fbAttributes, &nbConfigs);
}
else
{
m_settings.antialiasingLevel = 0;
int fbAttributes[] =
{
GLX_DEPTH_SIZE, static_cast<int>(settings.depthBits),
GLX_STENCIL_SIZE, static_cast<int>(settings.stencilBits),
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
};
configs = glXChooseFBConfig(m_display, DefaultScreen(m_display), fbAttributes, &nbConfigs);
}
int bestScore = 0xFFFF;
GLXFBConfig* bestConfig;
for (int i = 0; configs && (i < nbConfigs); ++i) for (int i = 0; configs && (i < nbConfigs); ++i)
{ {
XVisualInfo* visual = glXGetVisualFromFBConfig(m_display, configs[i]); XVisualInfo* visual = glXGetVisualFromFBConfig(m_display, configs[i]);
// We only want FBConfigs with associated X visuals (most have one)
// We do this to match what was used during window creation
if (!visual) if (!visual)
continue; continue;
// We won't need the visual for glXCreateContextAttribsARB, so get rid of it if (visual->visualid == visualInfo->visualid)
XFree(visual);
// Check mandatory attributes
int doubleBuffer;
glXGetFBConfigAttrib(m_display, configs[i], GLX_DOUBLEBUFFER, &doubleBuffer);
if (!doubleBuffer)
continue;
// Extract the components of the current visual
int red, green, blue, alpha, depth, stencil, multiSampling, samples;
glXGetFBConfigAttrib(m_display, configs[i], GLX_RED_SIZE, &red);
glXGetFBConfigAttrib(m_display, configs[i], GLX_GREEN_SIZE, &green);
glXGetFBConfigAttrib(m_display, configs[i], GLX_BLUE_SIZE, &blue);
glXGetFBConfigAttrib(m_display, configs[i], GLX_ALPHA_SIZE, &alpha);
glXGetFBConfigAttrib(m_display, configs[i], GLX_DEPTH_SIZE, &depth);
glXGetFBConfigAttrib(m_display, configs[i], GLX_STENCIL_SIZE, &stencil);
glXGetFBConfigAttrib(m_display, configs[i], GLX_SAMPLE_BUFFERS_ARB, &multiSampling);
glXGetFBConfigAttrib(m_display, configs[i], GLX_SAMPLES_ARB, &samples);
// Evaluate the visual
int color = red + green + blue + alpha;
int score = evaluateFormat(bitsPerPixel, settings, color, depth, stencil, multiSampling ? samples : 0);
// If it's better than the current best, make it the new best
if (score < bestScore)
{ {
bestScore = score; config = &configs[i];
bestConfig = &configs[i]; break;
} }
} }
if (bestScore < 0xFFFF) if (!config)
{ err() << "Failed to get GLXFBConfig which corresponds to the window's visual" << std::endl;
while (!m_context && m_settings.majorVersion)
while (config && !m_context && m_settings.majorVersion)
{ {
// Check if setting the profile is supported // Check if setting the profile is supported
if (sfglx_ext_ARB_create_context_profile == sfglx_LOAD_SUCCEEDED) if (sfglx_ext_ARB_create_context_profile == sfglx_LOAD_SUCCEEDED)
@ -579,7 +454,7 @@ void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, co
// On an error, glXCreateContextAttribsARB will return 0 anyway // On an error, glXCreateContextAttribsARB will return 0 anyway
GlxErrorHandler handler(m_display); GlxErrorHandler handler(m_display);
m_context = glXCreateContextAttribsARB(m_display, *bestConfig, toShare, true, attributes); m_context = glXCreateContextAttribsARB(m_display, *config, toShare, true, attributes);
} }
else else
{ {
@ -601,31 +476,10 @@ void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, co
// On an error, glXCreateContextAttribsARB will return 0 anyway // On an error, glXCreateContextAttribsARB will return 0 anyway
GlxErrorHandler handler(m_display); GlxErrorHandler handler(m_display);
m_context = glXCreateContextAttribsARB(m_display, *bestConfig, toShare, true, attributes); m_context = glXCreateContextAttribsARB(m_display, *config, toShare, true, attributes);
} }
if (m_context) if (!m_context)
{
#if defined(GLX_DEBUGGING)
GlxErrorHandler handler(m_display);
#endif
// Update the creation settings from the chosen format
int depth, stencil, multiSampling, samples;
glXGetFBConfigAttrib(m_display, *bestConfig, GLX_DEPTH_SIZE, &depth);
glXGetFBConfigAttrib(m_display, *bestConfig, GLX_STENCIL_SIZE, &stencil);
glXGetFBConfigAttrib(m_display, *bestConfig, GLX_SAMPLE_BUFFERS_ARB, &multiSampling);
glXGetFBConfigAttrib(m_display, *bestConfig, GLX_SAMPLES_ARB, &samples);
m_settings.depthBits = static_cast<unsigned int>(depth);
m_settings.stencilBits = static_cast<unsigned int>(stencil);
m_settings.antialiasingLevel = multiSampling ? samples : 0;
#if defined(GLX_DEBUGGING)
if (glxErrorOccurred)
err() << "GLX error in GlxContext::createContext()" << std::endl;
#endif
}
else
{ {
// If we couldn't create the context, first try disabling flags, // If we couldn't create the context, first try disabling flags,
// then lower the version number and try again -- stop at 0.0 // then lower the version number and try again -- stop at 0.0
@ -655,11 +509,6 @@ void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, co
if (configs) if (configs)
XFree(configs); XFree(configs);
} }
}
#if defined(GLX_DEBUGGING)
GlxErrorHandler handler(m_display);
#endif
// If glXCreateContextAttribsARB failed, use glXCreateContext // If glXCreateContextAttribsARB failed, use glXCreateContext
if (!m_context) if (!m_context)
@ -669,29 +518,25 @@ void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, co
m_settings.minorVersion = 1; m_settings.minorVersion = 1;
m_settings.attributeFlags = ContextSettings::Default; m_settings.attributeFlags = ContextSettings::Default;
// Retrieve the attributes of the target window #if defined(GLX_DEBUGGING)
XWindowAttributes windowAttributes; GlxErrorHandler handler(m_display);
if (XGetWindowAttributes(m_display, m_window, &windowAttributes) == 0) #endif
{
err() << "Failed to get the window attributes" << std::endl;
return;
}
// Get its visuals
XVisualInfo tpl;
tpl.screen = DefaultScreen(m_display);
tpl.visualid = XVisualIDFromVisual(windowAttributes.visual);
int nbVisuals = 0;
XVisualInfo* visualInfo = XGetVisualInfo(m_display, VisualIDMask | VisualScreenMask, &tpl, &nbVisuals);
// Create the context, using the target window's visual // 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 defined(GLX_DEBUGGING)
if (glxErrorOccurred)
err() << "GLX error in GlxContext::createContext()" << std::endl;
#endif
}
if (!m_context) if (!m_context)
{ {
err() << "Failed to create an OpenGL context for this window" << std::endl; err() << "Failed to create an OpenGL context for this window" << std::endl;
return;
} }
else
{
// Update the creation settings from the chosen format // Update the creation settings from the chosen format
int depth, stencil, multiSampling, samples; int depth, stencil, multiSampling, samples;
glXGetConfig(m_display, visualInfo, GLX_DEPTH_SIZE, &depth); glXGetConfig(m_display, visualInfo, GLX_DEPTH_SIZE, &depth);
@ -711,15 +556,10 @@ void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, co
m_settings.depthBits = static_cast<unsigned int>(depth); m_settings.depthBits = static_cast<unsigned int>(depth);
m_settings.stencilBits = static_cast<unsigned int>(stencil); m_settings.stencilBits = static_cast<unsigned int>(stencil);
m_settings.antialiasingLevel = multiSampling ? samples : 0; m_settings.antialiasingLevel = multiSampling ? samples : 0;
}
// Free the visual info // Free the visual info
XFree(visualInfo); XFree(visualInfo);
}
#if defined(GLX_DEBUGGING)
if (glxErrorOccurred)
err() << "GLX error in GlxContext::createContext()" << std::endl;
#endif
} }
} // namespace priv } // namespace priv