src/video/x11/SDL_x11opengl.c
author Ryan C. Gordon <icculus@icculus.org>
Wed, 11 Jul 2012 22:20:02 -0400
changeset 6360 efd48af40ec3
parent 6359 b2a768065c32
child 6370 93187f7f7d5d
permissions -rwxr-xr-x
Patched to compile on FreeBSD 8.2.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "SDL_config.h"
    22 
    23 #if SDL_VIDEO_DRIVER_X11
    24 
    25 #include "SDL_x11video.h"
    26 #include "SDL_assert.h"
    27 
    28 /* GLX implementation of SDL OpenGL support */
    29 
    30 #if SDL_VIDEO_OPENGL_GLX
    31 #include "SDL_loadso.h"
    32 
    33 #if defined(__IRIX__)
    34 /* IRIX doesn't have a GL library versioning system */
    35 #define DEFAULT_OPENGL	"libGL.so"
    36 #elif defined(__MACOSX__)
    37 #define DEFAULT_OPENGL	"/usr/X11R6/lib/libGL.1.dylib"
    38 #elif defined(__QNXNTO__)
    39 #define DEFAULT_OPENGL	"libGL.so.3"
    40 #else
    41 #define DEFAULT_OPENGL	"libGL.so.1"
    42 #endif
    43 
    44 #ifndef GLX_NONE_EXT
    45 #define GLX_NONE_EXT                       0x8000
    46 #endif
    47 
    48 #ifndef GLX_ARB_multisample
    49 #define GLX_ARB_multisample
    50 #define GLX_SAMPLE_BUFFERS_ARB             100000
    51 #define GLX_SAMPLES_ARB                    100001
    52 #endif
    53 
    54 #ifndef GLX_EXT_visual_rating
    55 #define GLX_EXT_visual_rating
    56 #define GLX_VISUAL_CAVEAT_EXT              0x20
    57 #define GLX_NONE_EXT                       0x8000
    58 #define GLX_SLOW_VISUAL_EXT                0x8001
    59 #define GLX_NON_CONFORMANT_VISUAL_EXT      0x800D
    60 #endif
    61 
    62 #ifndef GLX_ARB_create_context
    63 #define GLX_ARB_create_context
    64 #define GLX_CONTEXT_MAJOR_VERSION_ARB      0x2091
    65 #define GLX_CONTEXT_MINOR_VERSION_ARB      0x2092
    66 #define GLX_CONTEXT_FLAGS_ARB              0x2094
    67 #define GLX_CONTEXT_DEBUG_BIT_ARB          0x0001
    68 #define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
    69 
    70 /* Typedef for the GL 3.0 context creation function */
    71 typedef GLXContext(*PFNGLXCREATECONTEXTATTRIBSARBPROC) (Display * dpy,
    72                                                         GLXFBConfig config,
    73                                                         GLXContext
    74                                                         share_context,
    75                                                         Bool direct,
    76                                                         const int
    77                                                         *attrib_list);
    78 #endif
    79 
    80 #ifndef GLX_ARB_create_context_profile
    81 #define GLX_ARB_create_context_profile
    82 #define GLX_CONTEXT_PROFILE_MASK_ARB       0x9126
    83 #define GLX_CONTEXT_CORE_PROFILE_BIT_ARB   0x00000001
    84 #define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
    85 #endif
    86 
    87 #ifndef GLX_ARB_create_context_robustness
    88 #define GLX_ARB_create_context_robustness
    89 #define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB  0x00000004
    90 #define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB     0x8256
    91 #define GLX_NO_RESET_NOTIFICATION_ARB                   0x8261
    92 #define GLX_LOSE_CONTEXT_ON_RESET_ARB                   0x8252
    93 #endif
    94 
    95 #ifndef GLX_EXT_create_context_es2_profile
    96 #define GLX_EXT_create_context_es2_profile
    97 #define GLX_CONTEXT_ES2_PROFILE_BIT_EXT    0x00000002
    98 #endif
    99 
   100 #ifndef GLX_EXT_swap_control
   101 #define GLX_SWAP_INTERVAL_EXT              0x20F1
   102 #define GLX_MAX_SWAP_INTERVAL_EXT          0x20F2
   103 #endif
   104 
   105 #define OPENGL_REQUIRES_DLOPEN
   106 #if defined(OPENGL_REQUIRES_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
   107 #include <dlfcn.h>
   108 #define GL_LoadObject(X)	dlopen(X, (RTLD_NOW|RTLD_GLOBAL))
   109 #define GL_LoadFunction		dlsym
   110 #define GL_UnloadObject		dlclose
   111 #else
   112 #define GL_LoadObject	SDL_LoadObject
   113 #define GL_LoadFunction	SDL_LoadFunction
   114 #define GL_UnloadObject	SDL_UnloadObject
   115 #endif
   116 
   117 static void X11_GL_InitExtensions(_THIS);
   118 
   119 
   120 int
   121 X11_GL_LoadLibrary(_THIS, const char *path)
   122 {
   123     void *handle;
   124 
   125     /* Load the OpenGL library */
   126     if (path == NULL) {
   127         path = SDL_getenv("SDL_OPENGL_LIBRARY");
   128     }
   129     if (path == NULL) {
   130         path = DEFAULT_OPENGL;
   131     }
   132     _this->gl_config.dll_handle = GL_LoadObject(path);
   133     if (!_this->gl_config.dll_handle) {
   134 #if defined(OPENGL_REQUIRES_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
   135         SDL_SetError("Failed loading %s: %s", path, dlerror());
   136 #endif
   137         return -1;
   138     }
   139     SDL_strlcpy(_this->gl_config.driver_path, path,
   140                 SDL_arraysize(_this->gl_config.driver_path));
   141 
   142     /* Allocate OpenGL memory */
   143     _this->gl_data =
   144         (struct SDL_GLDriverData *) SDL_calloc(1,
   145                                                sizeof(struct
   146                                                       SDL_GLDriverData));
   147     if (!_this->gl_data) {
   148         SDL_OutOfMemory();
   149         return -1;
   150     }
   151 
   152     /* Load function pointers */
   153     handle = _this->gl_config.dll_handle;
   154     _this->gl_data->glXGetProcAddress =
   155         (void *(*)(const GLubyte *))
   156             GL_LoadFunction(handle, "glXGetProcAddressARB");
   157     _this->gl_data->glXChooseVisual =
   158         (XVisualInfo * (*)(Display *, int, int *))
   159             X11_GL_GetProcAddress(_this, "glXChooseVisual");
   160     _this->gl_data->glXCreateContext =
   161         (GLXContext(*)(Display *, XVisualInfo *, GLXContext, int))
   162             X11_GL_GetProcAddress(_this, "glXCreateContext");
   163     _this->gl_data->glXDestroyContext =
   164         (void (*)(Display *, GLXContext))
   165             X11_GL_GetProcAddress(_this, "glXDestroyContext");
   166     _this->gl_data->glXMakeCurrent =
   167         (int (*)(Display *, GLXDrawable, GLXContext))
   168             X11_GL_GetProcAddress(_this, "glXMakeCurrent");
   169     _this->gl_data->glXSwapBuffers =
   170         (void (*)(Display *, GLXDrawable))
   171             X11_GL_GetProcAddress(_this, "glXSwapBuffers");
   172     _this->gl_data->glXQueryDrawable =
   173         (void (*)(Display*,GLXDrawable,int,unsigned int*))
   174             X11_GL_GetProcAddress(_this, "glXQueryDrawable");
   175 
   176     if (!_this->gl_data->glXChooseVisual ||
   177         !_this->gl_data->glXCreateContext ||
   178         !_this->gl_data->glXDestroyContext ||
   179         !_this->gl_data->glXMakeCurrent ||
   180         !_this->gl_data->glXSwapBuffers) {
   181         SDL_SetError("Could not retrieve OpenGL functions");
   182         return -1;
   183     }
   184 
   185     /* Initialize extensions */
   186     X11_GL_InitExtensions(_this);
   187 
   188     return 0;
   189 }
   190 
   191 void *
   192 X11_GL_GetProcAddress(_THIS, const char *proc)
   193 {
   194     if (_this->gl_data->glXGetProcAddress) {
   195         return _this->gl_data->glXGetProcAddress((const GLubyte *) proc);
   196     }
   197     return GL_LoadFunction(_this->gl_config.dll_handle, proc);
   198 }
   199 
   200 void
   201 X11_GL_UnloadLibrary(_THIS)
   202 {
   203     /* Don't actually unload the library, since it may have registered
   204      * X11 shutdown hooks, per the notes at:
   205      * http://dri.sourceforge.net/doc/DRIuserguide.html
   206      */
   207 #if 0
   208     GL_UnloadObject(_this->gl_config.dll_handle);
   209     _this->gl_config.dll_handle = NULL;
   210 #endif
   211 
   212     /* Free OpenGL memory */
   213     if (_this->gl_data) {
   214         SDL_free(_this->gl_data);
   215         _this->gl_data = NULL;
   216     }
   217 }
   218 
   219 static SDL_bool
   220 HasExtension(const char *extension, const char *extensions)
   221 {
   222     const char *start;
   223     const char *where, *terminator;
   224 
   225     /* Extension names should not have spaces. */
   226     where = SDL_strchr(extension, ' ');
   227     if (where || *extension == '\0')
   228         return SDL_FALSE;
   229 
   230     if (!extensions)
   231         return SDL_FALSE;
   232 
   233     /* It takes a bit of care to be fool-proof about parsing the
   234      * OpenGL extensions string. Don't be fooled by sub-strings,
   235      * etc. */
   236 
   237     start = extensions;
   238 
   239     for (;;) {
   240         where = SDL_strstr(start, extension);
   241         if (!where)
   242             break;
   243 
   244         terminator = where + SDL_strlen(extension);
   245         if (where == start || *(where - 1) == ' ')
   246             if (*terminator == ' ' || *terminator == '\0')
   247                 return SDL_TRUE;
   248 
   249         start = terminator;
   250     }
   251     return SDL_FALSE;
   252 }
   253 
   254 static void
   255 X11_GL_InitExtensions(_THIS)
   256 {
   257     Display *display = ((SDL_VideoData *) _this->driverdata)->display;
   258     int screen = DefaultScreen(display);
   259     XVisualInfo *vinfo;
   260     XSetWindowAttributes xattr;
   261     Window w;
   262     GLXContext context;
   263     const char *(*glXQueryExtensionsStringFunc) (Display *, int);
   264     const char *extensions;
   265 
   266     vinfo = X11_GL_GetVisual(_this, display, screen);
   267     if (!vinfo) {
   268         return;
   269     }
   270     xattr.background_pixel = 0;
   271     xattr.border_pixel = 0;
   272     xattr.colormap =
   273         XCreateColormap(display, RootWindow(display, screen), vinfo->visual,
   274                         AllocNone);
   275     w = XCreateWindow(display, RootWindow(display, screen), 0, 0, 32, 32, 0,
   276                       vinfo->depth, InputOutput, vinfo->visual,
   277                       (CWBackPixel | CWBorderPixel | CWColormap), &xattr);
   278     context = _this->gl_data->glXCreateContext(display, vinfo, NULL, True);
   279     if (context) {
   280         _this->gl_data->glXMakeCurrent(display, w, context);
   281     }
   282     XFree(vinfo);
   283 
   284     glXQueryExtensionsStringFunc =
   285         (const char *(*)(Display *, int)) X11_GL_GetProcAddress(_this,
   286                                                                 "glXQueryExtensionsString");
   287     if (glXQueryExtensionsStringFunc) {
   288         extensions = glXQueryExtensionsStringFunc(display, screen);
   289     } else {
   290         extensions = NULL;
   291     }
   292 
   293     /* Check for GLX_EXT_swap_control */
   294     if (HasExtension("GLX_EXT_swap_control", extensions)) {
   295         _this->gl_data->glXSwapIntervalEXT =
   296             (int (*)(Display*,GLXDrawable,int))
   297                 X11_GL_GetProcAddress(_this, "glXSwapIntervalEXT");
   298     }
   299 
   300     /* Check for GLX_MESA_swap_control */
   301     if (HasExtension("GLX_MESA_swap_control", extensions)) {
   302         _this->gl_data->glXSwapIntervalMESA =
   303             (int(*)(int)) X11_GL_GetProcAddress(_this, "glXSwapIntervalMESA");
   304         _this->gl_data->glXGetSwapIntervalMESA =
   305             (int(*)(void)) X11_GL_GetProcAddress(_this,
   306                                                    "glXGetSwapIntervalMESA");
   307     }
   308 
   309     /* Check for GLX_SGI_swap_control */
   310     if (HasExtension("GLX_SGI_swap_control", extensions)) {
   311         _this->gl_data->glXSwapIntervalSGI =
   312             (int (*)(int)) X11_GL_GetProcAddress(_this, "glXSwapIntervalSGI");
   313     }
   314 
   315     /* Check for GLX_EXT_visual_rating */
   316     if (HasExtension("GLX_EXT_visual_rating", extensions)) {
   317         _this->gl_data->HAS_GLX_EXT_visual_rating = SDL_TRUE;
   318     }
   319 
   320     if (context) {
   321         _this->gl_data->glXMakeCurrent(display, None, NULL);
   322         _this->gl_data->glXDestroyContext(display, context);
   323     }
   324     XDestroyWindow(display, w);
   325     X11_PumpEvents(_this);
   326 }
   327 
   328 /* glXChooseVisual and glXChooseFBConfig have some small differences in
   329  * the attribute encoding, it can be chosen with the for_FBConfig parameter. 
   330  */
   331 int 
   332 X11_GL_GetAttributes(_THIS, Display * display, int screen, int * attribs, int size, Bool for_FBConfig)
   333 {
   334     int i = 0;
   335 
   336     /* assert buffer is large enough to hold all SDL attributes. */ 
   337     SDL_assert(size >= 32);
   338 
   339     /* Setup our GLX attributes according to the gl_config. */
   340     if( for_FBConfig ) {
   341         attribs[i++] = GLX_RENDER_TYPE;
   342 	attribs[i++] = GLX_RGBA_BIT;
   343     } else {
   344         attribs[i++] = GLX_RGBA;
   345     }
   346     attribs[i++] = GLX_RED_SIZE;
   347     attribs[i++] = _this->gl_config.red_size;
   348     attribs[i++] = GLX_GREEN_SIZE;
   349     attribs[i++] = _this->gl_config.green_size;
   350     attribs[i++] = GLX_BLUE_SIZE;
   351     attribs[i++] = _this->gl_config.blue_size;
   352 
   353     if (_this->gl_config.alpha_size) {
   354         attribs[i++] = GLX_ALPHA_SIZE;
   355         attribs[i++] = _this->gl_config.alpha_size;
   356     }
   357 
   358     if (_this->gl_config.double_buffer) {
   359         attribs[i++] = GLX_DOUBLEBUFFER;
   360 	if( for_FBConfig )
   361 	    attribs[i++] = True;
   362     }
   363 
   364     attribs[i++] = GLX_DEPTH_SIZE;
   365     attribs[i++] = _this->gl_config.depth_size;
   366 
   367     if (_this->gl_config.stencil_size) {
   368         attribs[i++] = GLX_STENCIL_SIZE;
   369         attribs[i++] = _this->gl_config.stencil_size;
   370     }
   371 
   372     if (_this->gl_config.accum_red_size) {
   373         attribs[i++] = GLX_ACCUM_RED_SIZE;
   374         attribs[i++] = _this->gl_config.accum_red_size;
   375     }
   376 
   377     if (_this->gl_config.accum_green_size) {
   378         attribs[i++] = GLX_ACCUM_GREEN_SIZE;
   379         attribs[i++] = _this->gl_config.accum_green_size;
   380     }
   381 
   382     if (_this->gl_config.accum_blue_size) {
   383         attribs[i++] = GLX_ACCUM_BLUE_SIZE;
   384         attribs[i++] = _this->gl_config.accum_blue_size;
   385     }
   386 
   387     if (_this->gl_config.accum_alpha_size) {
   388         attribs[i++] = GLX_ACCUM_ALPHA_SIZE;
   389         attribs[i++] = _this->gl_config.accum_alpha_size;
   390     }
   391 
   392     if (_this->gl_config.stereo) {
   393         attribs[i++] = GLX_STEREO;
   394 	if( for_FBConfig )
   395 	    attribs[i++] = True;
   396     }
   397 
   398     if (_this->gl_config.multisamplebuffers) {
   399         attribs[i++] = GLX_SAMPLE_BUFFERS_ARB;
   400         attribs[i++] = _this->gl_config.multisamplebuffers;
   401     }
   402 
   403     if (_this->gl_config.multisamplesamples) {
   404         attribs[i++] = GLX_SAMPLES_ARB;
   405         attribs[i++] = _this->gl_config.multisamplesamples;
   406     }
   407 
   408     if (_this->gl_config.accelerated >= 0 &&
   409         _this->gl_data->HAS_GLX_EXT_visual_rating) {
   410         attribs[i++] = GLX_VISUAL_CAVEAT_EXT;
   411         attribs[i++] = _this->gl_config.accelerated ? GLX_NONE_EXT :
   412                                                       GLX_SLOW_VISUAL_EXT;
   413     }
   414 
   415     attribs[i++] = None;
   416  
   417     return i;
   418 }
   419 
   420 XVisualInfo *
   421 X11_GL_GetVisual(_THIS, Display * display, int screen)
   422 {
   423     XVisualInfo *vinfo;
   424 
   425     /* 64 seems nice. */
   426     int attribs[64];
   427     X11_GL_GetAttributes(_this,display,screen,attribs,64,SDL_FALSE);
   428 
   429     if (!_this->gl_data) {
   430         /* The OpenGL library wasn't loaded, SDL_GetError() should have info */
   431         return NULL;
   432     }
   433 
   434     vinfo = _this->gl_data->glXChooseVisual(display, screen, attribs);
   435     if (!vinfo) {
   436         SDL_SetError("Couldn't find matching GLX visual");
   437     }
   438     return vinfo;
   439 }
   440 
   441 SDL_GLContext
   442 X11_GL_CreateContext(_THIS, SDL_Window * window)
   443 {
   444     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   445     Display *display = data->videodata->display;
   446     int screen =
   447         ((SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata)->screen;
   448     XWindowAttributes xattr;
   449     XVisualInfo v, *vinfo;
   450     int n;
   451     GLXContext context = NULL;
   452 
   453     /* We do this to create a clean separation between X and GLX errors. */
   454     XSync(display, False);
   455     XGetWindowAttributes(display, data->xwindow, &xattr);
   456     v.screen = screen;
   457     v.visualid = XVisualIDFromVisual(xattr.visual);
   458     vinfo = XGetVisualInfo(display, VisualScreenMask | VisualIDMask, &v, &n);
   459     if (vinfo) {
   460         if (_this->gl_config.major_version < 3) {
   461             context =
   462                 _this->gl_data->glXCreateContext(display, vinfo, NULL, True);
   463         } else {
   464             /* If we want a GL 3.0 context or later we need to get a temporary
   465                context to grab the new context creation function */
   466             GLXContext temp_context =
   467                 _this->gl_data->glXCreateContext(display, vinfo, NULL, True);
   468             if (!temp_context) {
   469                 SDL_SetError("Could not create GL context");
   470                 return NULL;
   471             } else {
   472 	        /* max 8 attributes plus terminator */
   473                 int attribs[9] = {
   474                     GLX_CONTEXT_MAJOR_VERSION_ARB,
   475                     _this->gl_config.major_version,
   476                     GLX_CONTEXT_MINOR_VERSION_ARB,
   477                     _this->gl_config.minor_version,
   478                     0
   479                 };
   480 		int iattr = 4;
   481 
   482 		/* SDL profile bits match GLX profile bits */
   483 		if( _this->gl_config.profile_mask != 0 ) {
   484 		    attribs[iattr++] = GLX_CONTEXT_PROFILE_MASK_ARB;
   485 		    attribs[iattr++] = _this->gl_config.profile_mask;
   486 		}
   487 
   488 		/* SDL flags match GLX flags */
   489 		if( _this->gl_config.flags != 0 ) {
   490 		    attribs[iattr++] = GLX_CONTEXT_FLAGS_ARB;
   491 		    attribs[iattr++] = _this->gl_config.flags;
   492 		}
   493 
   494 		attribs[iattr++] = 0;
   495 
   496                 /* Get a pointer to the context creation function for GL 3.0 */
   497                 PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs =
   498                     (PFNGLXCREATECONTEXTATTRIBSARBPROC) _this->gl_data->
   499                     glXGetProcAddress((GLubyte *)
   500                                       "glXCreateContextAttribsARB");
   501                 if (!glXCreateContextAttribs) {
   502                     SDL_SetError("GL 3.x is not supported");
   503                     context = temp_context;
   504                 } else {
   505                     int glxAttribs[64];
   506 
   507                     /* Create a GL 3.x context */
   508                     GLXFBConfig *framebuffer_config = NULL;
   509                     int fbcount = 0;
   510                     GLXFBConfig *(*glXChooseFBConfig) (Display * disp,
   511                                                        int screen,
   512                                                        const int *attrib_list,
   513                                                        int *nelements);
   514 
   515                     glXChooseFBConfig =
   516                         (GLXFBConfig *
   517                          (*)(Display *, int, const int *,
   518                              int *)) _this->gl_data->
   519                         glXGetProcAddress((GLubyte *) "glXChooseFBConfig");
   520 
   521                     X11_GL_GetAttributes(_this,display,screen,glxAttribs,64,SDL_TRUE);
   522 
   523                     if (!glXChooseFBConfig
   524                         || !(framebuffer_config =
   525                              glXChooseFBConfig(display,
   526                                                DefaultScreen(display), glxAttribs,
   527                                                &fbcount))) {
   528                         SDL_SetError
   529                             ("No good framebuffers found. GL 3.x disabled");
   530                         context = temp_context;
   531                     } else {
   532                         context =
   533                             glXCreateContextAttribs(display,
   534                                                     framebuffer_config[0],
   535                                                     NULL, True, attribs);
   536                         _this->gl_data->glXDestroyContext(display,
   537                                                           temp_context);
   538                     }
   539                 }
   540             }
   541         }
   542         XFree(vinfo);
   543     }
   544     XSync(display, False);
   545 
   546     if (!context) {
   547         SDL_SetError("Could not create GL context");
   548         return NULL;
   549     }
   550 
   551     if (X11_GL_MakeCurrent(_this, window, context) < 0) {
   552         X11_GL_DeleteContext(_this, context);
   553         return NULL;
   554     }
   555 
   556     return context;
   557 }
   558 
   559 int
   560 X11_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
   561 {
   562     Display *display = ((SDL_VideoData *) _this->driverdata)->display;
   563     Window drawable =
   564         (window ? ((SDL_WindowData *) window->driverdata)->xwindow : None);
   565     GLXContext glx_context = (GLXContext) context;
   566     int status;
   567 
   568     status = 0;
   569     if (!_this->gl_data->glXMakeCurrent(display, drawable, glx_context)) {
   570         SDL_SetError("Unable to make GL context current");
   571         status = -1;
   572     }
   573     XSync(display, False);
   574 
   575     return (status);
   576 }
   577 
   578 /* 
   579    0 is a valid argument to glxSwapInterval(MESA|EXT) and setting it to 0
   580    will undo the effect of a previous call with a value that is greater
   581    than zero (or at least that is what the docs say). OTOH, 0 is an invalid
   582    argument to glxSwapIntervalSGI and it returns an error if you call it
   583    with 0 as an argument.
   584 */
   585 
   586 static int swapinterval = -1;
   587 int
   588 X11_GL_SetSwapInterval(_THIS, int interval)
   589 {
   590     int status;
   591 
   592     if (_this->gl_data->glXSwapIntervalEXT) {
   593         Display *display = ((SDL_VideoData *) _this->driverdata)->display;
   594         const SDL_WindowData *windowdata = (SDL_WindowData *)
   595             _this->current_glwin->driverdata;
   596         Window drawable = windowdata->xwindow;
   597         status = _this->gl_data->glXSwapIntervalEXT(display,drawable,interval);
   598         if (status != 0) {
   599             SDL_SetError("glxSwapIntervalEXT failed");
   600             status = -1;
   601         } else {
   602             swapinterval = interval;
   603         }
   604     } else if (_this->gl_data->glXSwapIntervalMESA) {
   605         status = _this->gl_data->glXSwapIntervalMESA(interval);
   606         if (status != 0) {
   607             SDL_SetError("glxSwapIntervalMESA failed");
   608             status = -1;
   609         } else {
   610             swapinterval = interval;
   611         }
   612     } else if (_this->gl_data->glXSwapIntervalSGI) {
   613         status = _this->gl_data->glXSwapIntervalSGI(interval);
   614         if (status != 0) {
   615             SDL_SetError("glxSwapIntervalSGI failed");
   616             status = -1;
   617         } else {
   618             swapinterval = interval;
   619         }
   620     } else {
   621         SDL_Unsupported();
   622         status = -1;
   623     }
   624     return status;
   625 }
   626 
   627 int
   628 X11_GL_GetSwapInterval(_THIS)
   629 {
   630     if (_this->gl_data->glXSwapIntervalEXT) {
   631         Display *display = ((SDL_VideoData *) _this->driverdata)->display;
   632         const SDL_WindowData *windowdata = (SDL_WindowData *)
   633             _this->current_glwin->driverdata;
   634         Window drawable = windowdata->xwindow;
   635         unsigned int value = 0;
   636         _this->gl_data->glXQueryDrawable(display, drawable,
   637                                          GLX_SWAP_INTERVAL_EXT, &value);
   638         return (int) value;
   639     } else if (_this->gl_data->glXGetSwapIntervalMESA) {
   640         return _this->gl_data->glXGetSwapIntervalMESA();
   641     } else {
   642         return swapinterval;
   643     }
   644 }
   645 
   646 void
   647 X11_GL_SwapWindow(_THIS, SDL_Window * window)
   648 {
   649     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   650     Display *display = data->videodata->display;
   651 
   652     _this->gl_data->glXSwapBuffers(display, data->xwindow);
   653 }
   654 
   655 void
   656 X11_GL_DeleteContext(_THIS, SDL_GLContext context)
   657 {
   658     Display *display = ((SDL_VideoData *) _this->driverdata)->display;
   659     GLXContext glx_context = (GLXContext) context;
   660 
   661     _this->gl_data->glXDestroyContext(display, glx_context);
   662     XSync(display, False);
   663 }
   664 
   665 #endif /* SDL_VIDEO_OPENGL_GLX */
   666 
   667 #endif /* SDL_VIDEO_DRIVER_X11 */
   668 
   669 /* vi: set ts=4 sw=4 expandtab: */