Date: Sun, 11 May 2003 19:59:06 +0300
From: Pasi K?rkk?inen Subject: [PATCH] fix SDL OpenGL segfault with DRI/Mesa drivers and Glew Hello! The attached patch fixes a bug in SDL which causes SDL to crash in X11_GL_Shutdown() if you are using DRI/Mesa drivers AND glew (http://glew.sf.net). The bug is caused by a namespace collision affecting dlsym() to fetch wrong pointer for glXReleaseBuffersMESA() (uninitialized pointer from glew because the extension is NOT supported by the driver) and then SDL calling it in X11_GL_Shutdown(). SDL should check if the glXReleaseBuffersMESA() is really supported by the driver (from the extensions string) before calling it. Attached patch adds extension string parsing to check if glXReleaseBuffersMESA() is really supported (and this way prevents the segfault). Availability of the extensions should be _always_ checked from the extensions string rather than using dlsym()! Please add it to the next version of SDL. Thanks to gltron and author of glew to help fixing this. --HG-- extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%40639
This commit is contained in:
parent
31731b66ce
commit
44a5555c34
2 changed files with 71 additions and 3 deletions
|
@ -229,10 +229,44 @@ void X11_GL_Shutdown(_THIS)
|
||||||
|
|
||||||
#ifdef HAVE_OPENGL
|
#ifdef HAVE_OPENGL
|
||||||
|
|
||||||
|
static int ExtensionSupported(const char *extension, const char *all_extensions)
|
||||||
|
{
|
||||||
|
const GLubyte *extensions = NULL;
|
||||||
|
const GLubyte *start;
|
||||||
|
GLubyte *where, *terminator;
|
||||||
|
|
||||||
|
/* Extension names should not have spaces. */
|
||||||
|
where = (GLubyte *) strchr(extension, ' ');
|
||||||
|
if (where || *extension == '\0')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
extensions = glGetString(GL_EXTENSIONS);
|
||||||
|
/* It takes a bit of care to be fool-proof about parsing the
|
||||||
|
* OpenGL extensions string. Don't be fooled by sub-strings,
|
||||||
|
* etc. */
|
||||||
|
|
||||||
|
start = extensions;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
where = (GLubyte *) strstr((const char *) start, extension);
|
||||||
|
if (!where) break;
|
||||||
|
|
||||||
|
terminator = where + strlen(extension);
|
||||||
|
if (where == start || *(where - 1) == ' ')
|
||||||
|
if (*terminator == ' ' || *terminator == '\0') return 1;
|
||||||
|
|
||||||
|
start = terminator;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Make the current context active */
|
/* Make the current context active */
|
||||||
int X11_GL_MakeCurrent(_THIS)
|
int X11_GL_MakeCurrent(_THIS)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
const char *glx_extensions;
|
||||||
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
if ( ! this->gl_data->glXMakeCurrent(GFX_Display,
|
if ( ! this->gl_data->glXMakeCurrent(GFX_Display,
|
||||||
|
@ -242,6 +276,30 @@ int X11_GL_MakeCurrent(_THIS)
|
||||||
}
|
}
|
||||||
XSync( GFX_Display, False );
|
XSync( GFX_Display, False );
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The context is now current, check for glXReleaseBuffersMESA()
|
||||||
|
* extension. If extension is _not_ supported, destroy the pointer
|
||||||
|
* (to make sure it will not be called in X11_GL_Shutdown() ).
|
||||||
|
*
|
||||||
|
* DRI/Mesa drivers include glXReleaseBuffersMESA() in the libGL.so,
|
||||||
|
* but there's no need to call it (is is only needed for some old
|
||||||
|
* non-DRI drivers).
|
||||||
|
*
|
||||||
|
* When using for example glew (http://glew.sf.net), dlsym() for
|
||||||
|
* glXReleaseBuffersMESA() returns the pointer from the glew library
|
||||||
|
* (namespace conflict).
|
||||||
|
*
|
||||||
|
* The glXReleaseBuffersMESA() pointer in the glew is NULL, if the
|
||||||
|
* driver doesn't support this extension. So blindly calling it will
|
||||||
|
* cause segfault with DRI/Mesa drivers!
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
glx_extensions = this->gl_data->glXQueryExtensionsString(GFX_Display, SDL_Screen);
|
||||||
|
if (!ExtensionSupported("glXReleaseBuffersMESA", glx_extensions)) this->gl_data->glXReleaseBuffersMESA = NULL;
|
||||||
|
|
||||||
|
|
||||||
/* More Voodoo X server workarounds... Grr... */
|
/* More Voodoo X server workarounds... Grr... */
|
||||||
SDL_Lock_EventThread();
|
SDL_Lock_EventThread();
|
||||||
X11_CheckDGAMouse(this);
|
X11_CheckDGAMouse(this);
|
||||||
|
@ -382,16 +440,21 @@ int X11_GL_LoadLibrary(_THIS, const char* path)
|
||||||
(void (*)(Display *, GLXDrawable)) dlsym(handle, "glXSwapBuffers");
|
(void (*)(Display *, GLXDrawable)) dlsym(handle, "glXSwapBuffers");
|
||||||
this->gl_data->glXGetConfig =
|
this->gl_data->glXGetConfig =
|
||||||
(int (*)(Display *, XVisualInfo *, int, int *)) dlsym(handle, "glXGetConfig");
|
(int (*)(Display *, XVisualInfo *, int, int *)) dlsym(handle, "glXGetConfig");
|
||||||
|
this->gl_data->glXQueryExtensionsString =
|
||||||
|
(const char (*)(Display *, int)) dlsym(handle, "glXQueryExtensionsString");
|
||||||
|
|
||||||
/* We don't compare below for this in case we're not using Mesa. */
|
/* We don't compare below for this in case we're not using Mesa. */
|
||||||
this->gl_data->glXReleaseBuffersMESA =
|
this->gl_data->glXReleaseBuffersMESA =
|
||||||
(void (*)(Display *, GLXDrawable)) dlsym( handle, "glXReleaseBuffersMESA" );
|
(void (*)(Display *, GLXDrawable)) dlsym( handle, "glXReleaseBuffersMESA" );
|
||||||
|
|
||||||
|
|
||||||
if ( (this->gl_data->glXChooseVisual == NULL) ||
|
if ( (this->gl_data->glXChooseVisual == NULL) ||
|
||||||
(this->gl_data->glXCreateContext == NULL) ||
|
(this->gl_data->glXCreateContext == NULL) ||
|
||||||
(this->gl_data->glXDestroyContext == NULL) ||
|
(this->gl_data->glXDestroyContext == NULL) ||
|
||||||
(this->gl_data->glXMakeCurrent == NULL) ||
|
(this->gl_data->glXMakeCurrent == NULL) ||
|
||||||
(this->gl_data->glXSwapBuffers == NULL) ||
|
(this->gl_data->glXSwapBuffers == NULL) ||
|
||||||
(this->gl_data->glXGetConfig == NULL) ) {
|
(this->gl_data->glXGetConfig == NULL) ||
|
||||||
|
(this->gl_data->glXQueryExtensionsString == NULL)) {
|
||||||
SDL_SetError("Could not retrieve OpenGL functions");
|
SDL_SetError("Could not retrieve OpenGL functions");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,11 @@ struct SDL_PrivateGLData {
|
||||||
( Display* dpy,
|
( Display* dpy,
|
||||||
GLXDrawable drawable );
|
GLXDrawable drawable );
|
||||||
|
|
||||||
|
const char (*glXQueryExtensionsString)
|
||||||
|
( Display* dpy,
|
||||||
|
int screen);
|
||||||
|
|
||||||
|
|
||||||
#endif /* HAVE_OPENGL */
|
#endif /* HAVE_OPENGL */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue