Added workaround for broken Mesa GLX_ARB_create_context_profile.

This commit is contained in:
Camilla Berglund 2012-12-30 18:13:04 +01:00
parent ea1ddfd7a4
commit 9e9457767f
2 changed files with 66 additions and 27 deletions

View File

@ -38,6 +38,11 @@
void (*glXGetProcAddressEXT(const GLubyte* procName))(); void (*glXGetProcAddressEXT(const GLubyte* procName))();
#ifndef GLXBadProfileARB
#define GLXBadProfileARB 13
#endif
//======================================================================== //========================================================================
// Thread local storage attribute macro // Thread local storage attribute macro
//======================================================================== //========================================================================
@ -48,6 +53,12 @@ void (*glXGetProcAddressEXT(const GLubyte* procName))();
#endif #endif
//========================================================================
// The X error code as provided to the X error handler
//========================================================================
static unsigned long _glfwErrorCode = Success;
//======================================================================== //========================================================================
// The per-thread current context/window pointer // The per-thread current context/window pointer
//======================================================================== //========================================================================
@ -207,18 +218,48 @@ static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, unsigned int* found)
//======================================================================== //========================================================================
// Error handler for BadMatch errors when requesting context with // Error handler used when creating a context with the GLX_ARB_create_context
// unavailable OpenGL versions using the GLX_ARB_create_context extension // extension set
//======================================================================== //========================================================================
static int errorHandler(Display *display, XErrorEvent* event) static int errorHandler(Display *display, XErrorEvent* event)
{ {
_glfwErrorCode = event->error_code;
return 0; return 0;
} }
//======================================================================== //========================================================================
// Create the actual OpenGL context // Create the OpenGL context using legacy API
//========================================================================
static void createLegacyContext(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig,
GLXFBConfig fbconfig,
GLXContext share)
{
if (_glfwLibrary.GLX.SGIX_fbconfig)
{
window->GLX.context =
_glfwLibrary.GLX.CreateContextWithConfigSGIX(_glfwLibrary.X11.display,
fbconfig,
GLX_RGBA_TYPE,
share,
True);
}
else
{
window->GLX.context = glXCreateNewContext(_glfwLibrary.X11.display,
fbconfig,
GLX_RGBA_TYPE,
share,
True);
}
}
//========================================================================
// Create the OpenGL context
//======================================================================== //========================================================================
#define setGLXattrib(attribName, attribValue) \ #define setGLXattrib(attribName, attribValue) \
@ -386,6 +427,7 @@ static int createContext(_GLFWwindow* window,
// it because glXCreateContextAttribsARB generates a BadMatch error if // it because glXCreateContextAttribsARB generates a BadMatch error if
// the requested OpenGL version is unavailable (instead of a civilized // the requested OpenGL version is unavailable (instead of a civilized
// response like returning NULL) // response like returning NULL)
_glfwErrorCode = Success;
XSetErrorHandler(errorHandler); XSetErrorHandler(errorHandler);
window->GLX.context = window->GLX.context =
@ -397,36 +439,29 @@ static int createContext(_GLFWwindow* window,
// We are done, so unset the error handler again (see above) // We are done, so unset the error handler again (see above)
XSetErrorHandler(NULL); XSetErrorHandler(NULL);
if (window->GLX.context == NULL)
{
// HACK: This is a fallback for the broken Mesa implementation of
// GLX_ARB_create_context_profile, which fails default 1.0 context
// creation with a GLXBadProfileARB error in violation of the spec
if (_glfwErrorCode == _glfwLibrary.GLX.errorBase + GLXBadProfileARB &&
wndconfig->clientAPI == GLFW_OPENGL_API &&
wndconfig->glProfile == GLFW_OPENGL_NO_PROFILE &&
wndconfig->glForward == GL_FALSE)
{
createLegacyContext(window, wndconfig, *fbconfig, share);
}
}
} }
else else
{ createLegacyContext(window, wndconfig, *fbconfig, share);
if (_glfwLibrary.GLX.SGIX_fbconfig)
{
window->GLX.context =
_glfwLibrary.GLX.CreateContextWithConfigSGIX(_glfwLibrary.X11.display,
*fbconfig,
GLX_RGBA_TYPE,
share,
True);
}
else
{
window->GLX.context = glXCreateNewContext(_glfwLibrary.X11.display,
*fbconfig,
GLX_RGBA_TYPE,
share,
True);
}
}
XFree(fbconfig); XFree(fbconfig);
if (window->GLX.context == NULL) if (window->GLX.context == NULL)
{ {
// TODO: Handle all the various error codes here _glfwSetError(GLFW_PLATFORM_ERROR, "GLX: Failed to create context");
_glfwSetError(GLFW_PLATFORM_ERROR,
"GLX: Failed to create context");
return GL_FALSE; return GL_FALSE;
} }
@ -472,7 +507,9 @@ int _glfwInitOpenGL(void)
#endif #endif
// Check if GLX is supported on this display // Check if GLX is supported on this display
if (!glXQueryExtension(_glfwLibrary.X11.display, NULL, NULL)) if (!glXQueryExtension(_glfwLibrary.X11.display,
&_glfwLibrary.GLX.errorBase,
&_glfwLibrary.GLX.eventBase))
{ {
_glfwSetError(GLFW_API_UNAVAILABLE, "GLX: GLX support not found"); _glfwSetError(GLFW_API_UNAVAILABLE, "GLX: GLX support not found");
return GL_FALSE; return GL_FALSE;

View File

@ -90,6 +90,8 @@ typedef struct _GLFWlibraryGLX
{ {
// Server-side GLX version // Server-side GLX version
int majorVersion, minorVersion; int majorVersion, minorVersion;
int eventBase;
int errorBase;
// GLX extensions // GLX extensions
PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI; PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI;