From f5cf86769a91fecdf7ebeddba77719c03a5b6455 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 28 Jul 2015 00:12:50 -0400 Subject: [PATCH] x11: Catch fatal X errors when calling glXMakeCurrent(). In extremely rare cases, probably due to misconfigured drivers, one might see this happen, and rather than terminate the process, we try to recover by reporting an error to the app. Fixes Bugzilla #3068. --- src/video/x11/SDL_x11opengl.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/video/x11/SDL_x11opengl.c b/src/video/x11/SDL_x11opengl.c index 7f907e638..a431ae742 100644 --- a/src/video/x11/SDL_x11opengl.c +++ b/src/video/x11/SDL_x11opengl.c @@ -529,10 +529,11 @@ X11_GL_GetVisual(_THIS, Display * display, int screen) #define GLXBadProfileARB 13 #endif static int (*handler) (Display *, XErrorEvent *) = NULL; +static const char *errorHandlerOperation = NULL; static int errorBase = 0; static int errorCode = 0; static int -X11_GL_CreateContextErrorHandler(Display * d, XErrorEvent * e) +X11_GL_ErrorHandler(Display * d, XErrorEvent * e) { char *x11_error = NULL; char x11_error_locale[256]; @@ -545,12 +546,12 @@ X11_GL_CreateContextErrorHandler(Display * d, XErrorEvent * e) if (x11_error) { - SDL_SetError("Could not create GL context: %s", x11_error); + SDL_SetError("Could not %s: %s", errorHandlerOperation, x11_error); SDL_free(x11_error); } else { - SDL_SetError("Could not create GL context: %i (Base %i)\n", errorCode, errorBase); + SDL_SetError("Could not %s: %i (Base %i)\n", errorHandlerOperation, errorCode, errorBase); } return (0); @@ -576,9 +577,10 @@ X11_GL_CreateContext(_THIS, SDL_Window * window) /* We do this to create a clean separation between X and GLX errors. */ X11_XSync(display, False); + errorHandlerOperation = "create GL context"; errorBase = _this->gl_data->errorBase; errorCode = Success; - handler = X11_XSetErrorHandler(X11_GL_CreateContextErrorHandler); + handler = X11_XSetErrorHandler(X11_GL_ErrorHandler); X11_XGetWindowAttributes(display, data->xwindow, &xattr); v.screen = screen; v.visualid = X11_XVisualIDFromVisual(xattr.visual); @@ -676,12 +678,24 @@ X11_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context) Window drawable = (context ? ((SDL_WindowData *) window->driverdata)->xwindow : None); GLXContext glx_context = (GLXContext) context; + int rc; if (!_this->gl_data) { return SDL_SetError("OpenGL not initialized"); } - if (!_this->gl_data->glXMakeCurrent(display, drawable, glx_context)) { + /* We do this to create a clean separation between X and GLX errors. */ + X11_XSync(display, False); + errorHandlerOperation = "make GL context current"; + errorBase = _this->gl_data->errorBase; + errorCode = Success; + handler = X11_XSetErrorHandler(X11_GL_ErrorHandler); + rc = _this->gl_data->glXMakeCurrent(display, drawable, glx_context); + X11_XSetErrorHandler(handler); + + if (errorCode != Success) { /* uhoh, an X error was thrown! */ + return -1; /* the error handler called SDL_SetError() already. */ + } else if (!rc) { /* glxMakeCurrent() failed without throwing an X error */ return SDL_SetError("Unable to make GL context current"); }