comparison src/video/x11/SDL_x11gl.c @ 638:b0108e9dea53

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.
author Sam Lantinga <slouken@libsdl.org>
date Sat, 28 Jun 2003 17:27:33 +0000
parents d6e7d7006062
children 564716cfb502
comparison
equal deleted inserted replaced
637:6862d4294870 638:b0108e9dea53
227 #endif /* HAVE_OPENGL */ 227 #endif /* HAVE_OPENGL */
228 } 228 }
229 229
230 #ifdef HAVE_OPENGL 230 #ifdef HAVE_OPENGL
231 231
232 static int ExtensionSupported(const char *extension, const char *all_extensions)
233 {
234 const GLubyte *extensions = NULL;
235 const GLubyte *start;
236 GLubyte *where, *terminator;
237
238 /* Extension names should not have spaces. */
239 where = (GLubyte *) strchr(extension, ' ');
240 if (where || *extension == '\0')
241 return 0;
242
243 extensions = glGetString(GL_EXTENSIONS);
244 /* It takes a bit of care to be fool-proof about parsing the
245 * OpenGL extensions string. Don't be fooled by sub-strings,
246 * etc. */
247
248 start = extensions;
249
250 for (;;)
251 {
252 where = (GLubyte *) strstr((const char *) start, extension);
253 if (!where) break;
254
255 terminator = where + strlen(extension);
256 if (where == start || *(where - 1) == ' ')
257 if (*terminator == ' ' || *terminator == '\0') return 1;
258
259 start = terminator;
260 }
261
262 return 0;
263 }
264
232 /* Make the current context active */ 265 /* Make the current context active */
233 int X11_GL_MakeCurrent(_THIS) 266 int X11_GL_MakeCurrent(_THIS)
234 { 267 {
235 int retval; 268 int retval;
236 269 const char *glx_extensions;
270
237 retval = 0; 271 retval = 0;
238 if ( ! this->gl_data->glXMakeCurrent(GFX_Display, 272 if ( ! this->gl_data->glXMakeCurrent(GFX_Display,
239 SDL_Window, glx_context) ) { 273 SDL_Window, glx_context) ) {
240 SDL_SetError("Unable to make GL context current"); 274 SDL_SetError("Unable to make GL context current");
241 retval = -1; 275 retval = -1;
242 } 276 }
243 XSync( GFX_Display, False ); 277 XSync( GFX_Display, False );
244 278
279
280 /*
281 * The context is now current, check for glXReleaseBuffersMESA()
282 * extension. If extension is _not_ supported, destroy the pointer
283 * (to make sure it will not be called in X11_GL_Shutdown() ).
284 *
285 * DRI/Mesa drivers include glXReleaseBuffersMESA() in the libGL.so,
286 * but there's no need to call it (is is only needed for some old
287 * non-DRI drivers).
288 *
289 * When using for example glew (http://glew.sf.net), dlsym() for
290 * glXReleaseBuffersMESA() returns the pointer from the glew library
291 * (namespace conflict).
292 *
293 * The glXReleaseBuffersMESA() pointer in the glew is NULL, if the
294 * driver doesn't support this extension. So blindly calling it will
295 * cause segfault with DRI/Mesa drivers!
296 *
297 */
298
299 glx_extensions = this->gl_data->glXQueryExtensionsString(GFX_Display, SDL_Screen);
300 if (!ExtensionSupported("glXReleaseBuffersMESA", glx_extensions)) this->gl_data->glXReleaseBuffersMESA = NULL;
301
302
245 /* More Voodoo X server workarounds... Grr... */ 303 /* More Voodoo X server workarounds... Grr... */
246 SDL_Lock_EventThread(); 304 SDL_Lock_EventThread();
247 X11_CheckDGAMouse(this); 305 X11_CheckDGAMouse(this);
248 SDL_Unlock_EventThread(); 306 SDL_Unlock_EventThread();
249 307
380 (int (*)(Display *, GLXDrawable, GLXContext)) dlsym(handle, "glXMakeCurrent"); 438 (int (*)(Display *, GLXDrawable, GLXContext)) dlsym(handle, "glXMakeCurrent");
381 this->gl_data->glXSwapBuffers = 439 this->gl_data->glXSwapBuffers =
382 (void (*)(Display *, GLXDrawable)) dlsym(handle, "glXSwapBuffers"); 440 (void (*)(Display *, GLXDrawable)) dlsym(handle, "glXSwapBuffers");
383 this->gl_data->glXGetConfig = 441 this->gl_data->glXGetConfig =
384 (int (*)(Display *, XVisualInfo *, int, int *)) dlsym(handle, "glXGetConfig"); 442 (int (*)(Display *, XVisualInfo *, int, int *)) dlsym(handle, "glXGetConfig");
443 this->gl_data->glXQueryExtensionsString =
444 (const char (*)(Display *, int)) dlsym(handle, "glXQueryExtensionsString");
445
385 /* We don't compare below for this in case we're not using Mesa. */ 446 /* We don't compare below for this in case we're not using Mesa. */
386 this->gl_data->glXReleaseBuffersMESA = 447 this->gl_data->glXReleaseBuffersMESA =
387 (void (*)(Display *, GLXDrawable)) dlsym( handle, "glXReleaseBuffersMESA" ); 448 (void (*)(Display *, GLXDrawable)) dlsym( handle, "glXReleaseBuffersMESA" );
388 449
450
389 if ( (this->gl_data->glXChooseVisual == NULL) || 451 if ( (this->gl_data->glXChooseVisual == NULL) ||
390 (this->gl_data->glXCreateContext == NULL) || 452 (this->gl_data->glXCreateContext == NULL) ||
391 (this->gl_data->glXDestroyContext == NULL) || 453 (this->gl_data->glXDestroyContext == NULL) ||
392 (this->gl_data->glXMakeCurrent == NULL) || 454 (this->gl_data->glXMakeCurrent == NULL) ||
393 (this->gl_data->glXSwapBuffers == NULL) || 455 (this->gl_data->glXSwapBuffers == NULL) ||
394 (this->gl_data->glXGetConfig == NULL) ) { 456 (this->gl_data->glXGetConfig == NULL) ||
457 (this->gl_data->glXQueryExtensionsString == NULL)) {
395 SDL_SetError("Could not retrieve OpenGL functions"); 458 SDL_SetError("Could not retrieve OpenGL functions");
396 return -1; 459 return -1;
397 } 460 }
398 461
399 this->gl_config.dll_handle = handle; 462 this->gl_config.dll_handle = handle;