Mercurial > sdl-ios-xcode
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; |