From 28c6fa192ace58f705f1b88d32a2a8a7587875a7 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 11 Feb 2013 17:02:13 -0800 Subject: [PATCH] Workaround for NVIDIA bug in glXSwapIntervalEXT. This works around a bug in NVIDIA's implementation of glXSwapIntervalEXT, where it ignores updates to what it *thinks* is the current value, even though glXQueryDrawable returns a different value. Bug reported to NVIDIA and will hopefully be a part of 319.xx. Also a fix for invalidly treating glXSwapIntervalEXT as having an int return value (it's void). --- build-scripts/ltmain.sh | 0 src/video/x11/SDL_x11opengl.c | 24 +++++++++++++++++------- src/video/x11/SDL_x11opengl.h | 2 +- 3 files changed, 18 insertions(+), 8 deletions(-) mode change 100644 => 100755 build-scripts/ltmain.sh diff --git a/build-scripts/ltmain.sh b/build-scripts/ltmain.sh old mode 100644 new mode 100755 diff --git a/src/video/x11/SDL_x11opengl.c b/src/video/x11/SDL_x11opengl.c index 9e80d0cbf..f9d4b5005 100644 --- a/src/video/x11/SDL_x11opengl.c +++ b/src/video/x11/SDL_x11opengl.c @@ -332,7 +332,7 @@ X11_GL_InitExtensions(_THIS) _this->gl_data->HAS_GLX_EXT_swap_control_tear = SDL_FALSE; if (HasExtension("GLX_EXT_swap_control", extensions)) { _this->gl_data->glXSwapIntervalEXT = - (int (*)(Display*,GLXDrawable,int)) + (void (*)(Display*,GLXDrawable,int)) X11_GL_GetProcAddress(_this, "glXSwapIntervalEXT"); if (HasExtension("GLX_EXT_swap_control_tear", extensions)) { _this->gl_data->HAS_GLX_EXT_swap_control_tear = SDL_TRUE; @@ -667,13 +667,23 @@ X11_GL_SetSwapInterval(_THIS, int interval) Display *display = ((SDL_VideoData *) _this->driverdata)->display; const SDL_WindowData *windowdata = (SDL_WindowData *) _this->current_glwin->driverdata; + Window drawable = windowdata->xwindow; - status = _this->gl_data->glXSwapIntervalEXT(display,drawable,interval); - if (status != 0) { - SDL_SetError("glxSwapIntervalEXT failed"); - } else { - swapinterval = interval; - } + + /* + * This is a workaround for a bug in NVIDIA drivers. Bug has been reported + * and will be fixed in a future release (probably 319.xx). + * + * There's a bug where glXSetSwapIntervalEXT ignores updates because + * it has the wrong value cached. To work around it, we just run a no-op + * update to the current value. + */ + int currentInterval = _this, X11_GL_GetSwapInterval(_this); + _this->gl_data->glXSwapIntervalEXT(display, drawable, currentInterval); + _this->gl_data->glXSwapIntervalEXT(display, drawable, interval); + + status = 0; + swapinterval = interval; } else if (_this->gl_data->glXSwapIntervalMESA) { status = _this->gl_data->glXSwapIntervalMESA(interval); if (status != 0) { diff --git a/src/video/x11/SDL_x11opengl.h b/src/video/x11/SDL_x11opengl.h index a786b773e..2b4780208 100644 --- a/src/video/x11/SDL_x11opengl.h +++ b/src/video/x11/SDL_x11opengl.h @@ -40,7 +40,7 @@ struct SDL_GLDriverData Bool(*glXMakeCurrent) (Display*,GLXDrawable,GLXContext); void (*glXSwapBuffers) (Display*, GLXDrawable); void (*glXQueryDrawable) (Display*,GLXDrawable,int,unsigned int*); - int (*glXSwapIntervalEXT) (Display*,GLXDrawable,int); + void (*glXSwapIntervalEXT) (Display*,GLXDrawable,int); int (*glXSwapIntervalSGI) (int); int (*glXSwapIntervalMESA) (int); int (*glXGetSwapIntervalMESA) (void);