Workaround for NVIDIA bug in glXSwapIntervalEXT.
authorSam Lantinga <slouken@libsdl.org>
Mon, 11 Feb 2013 17:02:13 -0800
changeset 684697eb26e2dee0
parent 6845 e14535915e3e
child 6847 c0fa29d3fade
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
src/video/x11/SDL_x11opengl.c
src/video/x11/SDL_x11opengl.h
     1.1 --- a/src/video/x11/SDL_x11opengl.c	Mon Feb 11 16:51:00 2013 -0800
     1.2 +++ b/src/video/x11/SDL_x11opengl.c	Mon Feb 11 17:02:13 2013 -0800
     1.3 @@ -332,7 +332,7 @@
     1.4      _this->gl_data->HAS_GLX_EXT_swap_control_tear = SDL_FALSE;
     1.5      if (HasExtension("GLX_EXT_swap_control", extensions)) {
     1.6          _this->gl_data->glXSwapIntervalEXT =
     1.7 -            (int (*)(Display*,GLXDrawable,int))
     1.8 +            (void (*)(Display*,GLXDrawable,int))
     1.9                  X11_GL_GetProcAddress(_this, "glXSwapIntervalEXT");
    1.10          if (HasExtension("GLX_EXT_swap_control_tear", extensions)) {
    1.11              _this->gl_data->HAS_GLX_EXT_swap_control_tear = SDL_TRUE;
    1.12 @@ -667,13 +667,23 @@
    1.13          Display *display = ((SDL_VideoData *) _this->driverdata)->display;
    1.14          const SDL_WindowData *windowdata = (SDL_WindowData *)
    1.15              _this->current_glwin->driverdata;
    1.16 +
    1.17          Window drawable = windowdata->xwindow;
    1.18 -        status = _this->gl_data->glXSwapIntervalEXT(display,drawable,interval);
    1.19 -        if (status != 0) {
    1.20 -            SDL_SetError("glxSwapIntervalEXT failed");
    1.21 -        } else {
    1.22 -            swapinterval = interval;
    1.23 -        }
    1.24 +
    1.25 +        /*
    1.26 +         * This is a workaround for a bug in NVIDIA drivers. Bug has been reported
    1.27 +         * and will be fixed in a future release (probably 319.xx).
    1.28 +         *
    1.29 +         * There's a bug where glXSetSwapIntervalEXT ignores updates because
    1.30 +         * it has the wrong value cached. To work around it, we just run a no-op
    1.31 +         * update to the current value.
    1.32 +         */
    1.33 +        int currentInterval = _this, X11_GL_GetSwapInterval(_this);
    1.34 +        _this->gl_data->glXSwapIntervalEXT(display, drawable, currentInterval);
    1.35 +        _this->gl_data->glXSwapIntervalEXT(display, drawable, interval);
    1.36 +
    1.37 +        status = 0;
    1.38 +        swapinterval = interval;
    1.39      } else if (_this->gl_data->glXSwapIntervalMESA) {
    1.40          status = _this->gl_data->glXSwapIntervalMESA(interval);
    1.41          if (status != 0) {
     2.1 --- a/src/video/x11/SDL_x11opengl.h	Mon Feb 11 16:51:00 2013 -0800
     2.2 +++ b/src/video/x11/SDL_x11opengl.h	Mon Feb 11 17:02:13 2013 -0800
     2.3 @@ -40,7 +40,7 @@
     2.4      Bool(*glXMakeCurrent) (Display*,GLXDrawable,GLXContext);
     2.5      void (*glXSwapBuffers) (Display*, GLXDrawable);
     2.6      void (*glXQueryDrawable) (Display*,GLXDrawable,int,unsigned int*);
     2.7 -    int (*glXSwapIntervalEXT) (Display*,GLXDrawable,int);
     2.8 +    void (*glXSwapIntervalEXT) (Display*,GLXDrawable,int);
     2.9      int (*glXSwapIntervalSGI) (int);
    2.10      int (*glXSwapIntervalMESA) (int);
    2.11      int (*glXGetSwapIntervalMESA) (void);