src/video/x11/SDL_x11opengl.c
author Ryan C. Gordon <icculus@icculus.org>
Tue, 07 Feb 2012 02:11:15 -0500
changeset 6281 e46d6f4b469e
parent 6183 6d9a266e04bb
child 6282 64ae376becce
permissions -rwxr-xr-x
Replaced some assert macros with SDL_assert.
     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 #ifndef GLX_EXT_swap_control
    71 #define GLX_SWAP_INTERVAL_EXT              0x20F1
    72 #define GLX_MAX_SWAP_INTERVAL_EXT          0x20F2
    73 #endif
    74 
    75 /* Typedef for the GL 3.0 context creation function */
    76 typedef GLXContext(*PFNGLXCREATECONTEXTATTRIBSARBPROC) (Display * dpy,
    77                                                         GLXFBConfig config,
    78                                                         GLXContext
    79                                                         share_context,
    80                                                         Bool direct,
    81                                                         const int
    82                                                         *attrib_list);
    83 #endif
    84 
    85 #define OPENGL_REQUIRES_DLOPEN
    86 #if defined(OPENGL_REQUIRES_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
    87 #include <dlfcn.h>
    88 #define GL_LoadObject(X)	dlopen(X, (RTLD_NOW|RTLD_GLOBAL))
    89 #define GL_LoadFunction		dlsym
    90 #define GL_UnloadObject		dlclose
    91 #else
    92 #define GL_LoadObject	SDL_LoadObject
    93 #define GL_LoadFunction	SDL_LoadFunction
    94 #define GL_UnloadObject	SDL_UnloadObject
    95 #endif
    96 
    97 static void X11_GL_InitExtensions(_THIS);
    98 
    99 
   100 int
   101 X11_GL_LoadLibrary(_THIS, const char *path)
   102 {
   103     void *handle;
   104 
   105     /* Load the OpenGL library */
   106     if (path == NULL) {
   107         path = SDL_getenv("SDL_OPENGL_LIBRARY");
   108     }
   109     if (path == NULL) {
   110         path = DEFAULT_OPENGL;
   111     }
   112     _this->gl_config.dll_handle = GL_LoadObject(path);
   113     if (!_this->gl_config.dll_handle) {
   114 #if defined(OPENGL_REQUIRES_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
   115         SDL_SetError("Failed loading %s: %s", path, dlerror());
   116 #endif
   117         return -1;
   118     }
   119     SDL_strlcpy(_this->gl_config.driver_path, path,
   120                 SDL_arraysize(_this->gl_config.driver_path));
   121 
   122     /* Allocate OpenGL memory */
   123     _this->gl_data =
   124         (struct SDL_GLDriverData *) SDL_calloc(1,
   125                                                sizeof(struct
   126                                                       SDL_GLDriverData));
   127     if (!_this->gl_data) {
   128         SDL_OutOfMemory();
   129         return -1;
   130     }
   131 
   132     /* Load function pointers */
   133     handle = _this->gl_config.dll_handle;
   134     _this->gl_data->glXGetProcAddress =
   135         (void *(*)(const GLubyte *))
   136             GL_LoadFunction(handle, "glXGetProcAddressARB");
   137     _this->gl_data->glXChooseVisual =
   138         (XVisualInfo * (*)(Display *, int, int *))
   139             X11_GL_GetProcAddress(_this, "glXChooseVisual");
   140     _this->gl_data->glXCreateContext =
   141         (GLXContext(*)(Display *, XVisualInfo *, GLXContext, int))
   142             X11_GL_GetProcAddress(_this, "glXCreateContext");
   143     _this->gl_data->glXDestroyContext =
   144         (void (*)(Display *, GLXContext))
   145             X11_GL_GetProcAddress(_this, "glXDestroyContext");
   146     _this->gl_data->glXMakeCurrent =
   147         (int (*)(Display *, GLXDrawable, GLXContext))
   148             X11_GL_GetProcAddress(_this, "glXMakeCurrent");
   149     _this->gl_data->glXSwapBuffers =
   150         (void (*)(Display *, GLXDrawable))
   151             X11_GL_GetProcAddress(_this, "glXSwapBuffers");
   152     _this->gl_data->glXQueryDrawable =
   153         (void (*)(Display*,GLXDrawable,int,unsigned int*))
   154             X11_GL_GetProcAddress(_this, "glXQueryDrawable");
   155 
   156     if (!_this->gl_data->glXChooseVisual ||
   157         !_this->gl_data->glXCreateContext ||
   158         !_this->gl_data->glXDestroyContext ||
   159         !_this->gl_data->glXMakeCurrent ||
   160         !_this->gl_data->glXSwapBuffers) {
   161         SDL_SetError("Could not retrieve OpenGL functions");
   162         return -1;
   163     }
   164 
   165     /* Initialize extensions */
   166     X11_GL_InitExtensions(_this);
   167 
   168     return 0;
   169 }
   170 
   171 void *
   172 X11_GL_GetProcAddress(_THIS, const char *proc)
   173 {
   174     if (_this->gl_data->glXGetProcAddress) {
   175         return _this->gl_data->glXGetProcAddress((const GLubyte *) proc);
   176     }
   177     return GL_LoadFunction(_this->gl_config.dll_handle, proc);
   178 }
   179 
   180 void
   181 X11_GL_UnloadLibrary(_THIS)
   182 {
   183     /* Don't actually unload the library, since it may have registered
   184      * X11 shutdown hooks, per the notes at:
   185      * http://dri.sourceforge.net/doc/DRIuserguide.html
   186      */
   187 #if 0
   188     GL_UnloadObject(_this->gl_config.dll_handle);
   189     _this->gl_config.dll_handle = NULL;
   190 #endif
   191 
   192     /* Free OpenGL memory */
   193     if (_this->gl_data) {
   194         SDL_free(_this->gl_data);
   195         _this->gl_data = NULL;
   196     }
   197 }
   198 
   199 static SDL_bool
   200 HasExtension(const char *extension, const char *extensions)
   201 {
   202     const char *start;
   203     const char *where, *terminator;
   204 
   205     /* Extension names should not have spaces. */
   206     where = SDL_strchr(extension, ' ');
   207     if (where || *extension == '\0')
   208         return SDL_FALSE;
   209 
   210     if (!extensions)
   211         return SDL_FALSE;
   212 
   213     /* It takes a bit of care to be fool-proof about parsing the
   214      * OpenGL extensions string. Don't be fooled by sub-strings,
   215      * etc. */
   216 
   217     start = extensions;
   218 
   219     for (;;) {
   220         where = SDL_strstr(start, extension);
   221         if (!where)
   222             break;
   223 
   224         terminator = where + SDL_strlen(extension);
   225         if (where == start || *(where - 1) == ' ')
   226             if (*terminator == ' ' || *terminator == '\0')
   227                 return SDL_TRUE;
   228 
   229         start = terminator;
   230     }
   231     return SDL_FALSE;
   232 }
   233 
   234 static void
   235 X11_GL_InitExtensions(_THIS)
   236 {
   237     Display *display = ((SDL_VideoData *) _this->driverdata)->display;
   238     int screen = DefaultScreen(display);
   239     XVisualInfo *vinfo;
   240     XSetWindowAttributes xattr;
   241     Window w;
   242     GLXContext context;
   243     const char *(*glXQueryExtensionsStringFunc) (Display *, int);
   244     const char *extensions;
   245 
   246     vinfo = X11_GL_GetVisual(_this, display, screen);
   247     if (!vinfo) {
   248         return;
   249     }
   250     xattr.background_pixel = 0;
   251     xattr.border_pixel = 0;
   252     xattr.colormap =
   253         XCreateColormap(display, RootWindow(display, screen), vinfo->visual,
   254                         AllocNone);
   255     w = XCreateWindow(display, RootWindow(display, screen), 0, 0, 32, 32, 0,
   256                       vinfo->depth, InputOutput, vinfo->visual,
   257                       (CWBackPixel | CWBorderPixel | CWColormap), &xattr);
   258     context = _this->gl_data->glXCreateContext(display, vinfo, NULL, True);
   259     if (context) {
   260         _this->gl_data->glXMakeCurrent(display, w, context);
   261     }
   262     XFree(vinfo);
   263 
   264     glXQueryExtensionsStringFunc =
   265         (const char *(*)(Display *, int)) X11_GL_GetProcAddress(_this,
   266                                                                 "glXQueryExtensionsString");
   267     if (glXQueryExtensionsStringFunc) {
   268         extensions = glXQueryExtensionsStringFunc(display, screen);
   269     } else {
   270         extensions = NULL;
   271     }
   272 
   273     /* Check for GLX_EXT_swap_control */
   274     if (HasExtension("GLX_EXT_swap_control", extensions)) {
   275         _this->gl_data->glXSwapIntervalEXT =
   276             (int (*)(Display*,GLXDrawable,int))
   277                 X11_GL_GetProcAddress(_this, "glXSwapIntervalEXT");
   278     }
   279 
   280     /* Check for GLX_MESA_swap_control */
   281     if (HasExtension("GLX_MESA_swap_control", extensions)) {
   282         _this->gl_data->glXSwapIntervalMESA =
   283             (int(*)(int)) X11_GL_GetProcAddress(_this, "glXSwapIntervalMESA");
   284         _this->gl_data->glXGetSwapIntervalMESA =
   285             (int(*)(void)) X11_GL_GetProcAddress(_this,
   286                                                    "glXGetSwapIntervalMESA");
   287     }
   288 
   289     /* Check for GLX_SGI_swap_control */
   290     if (HasExtension("GLX_SGI_swap_control", extensions)) {
   291         _this->gl_data->glXSwapIntervalSGI =
   292             (int (*)(int)) X11_GL_GetProcAddress(_this, "glXSwapIntervalSGI");
   293     }
   294 
   295     /* Check for GLX_EXT_visual_rating */
   296     if (HasExtension("GLX_EXT_visual_rating", extensions)) {
   297         _this->gl_data->HAS_GLX_EXT_visual_rating = SDL_TRUE;
   298     }
   299 
   300     if (context) {
   301         _this->gl_data->glXMakeCurrent(display, None, NULL);
   302         _this->gl_data->glXDestroyContext(display, context);
   303     }
   304     XDestroyWindow(display, w);
   305     X11_PumpEvents(_this);
   306 }
   307 
   308 int 
   309 X11_GL_GetAttributes(_THIS, Display * display, int screen, int * attribs, int size)
   310 {
   311     int i = 0;
   312 
   313     /* assert buffer is large enough to hold all SDL attributes. */ 
   314     SDL_assert(size >= 32);
   315 
   316     /* Setup our GLX attributes according to the gl_config. */
   317     attribs[i++] = GLX_RGBA;
   318     attribs[i++] = GLX_RED_SIZE;
   319     attribs[i++] = _this->gl_config.red_size;
   320     attribs[i++] = GLX_GREEN_SIZE;
   321     attribs[i++] = _this->gl_config.green_size;
   322     attribs[i++] = GLX_BLUE_SIZE;
   323     attribs[i++] = _this->gl_config.blue_size;
   324 
   325     if (_this->gl_config.alpha_size) {
   326         attribs[i++] = GLX_ALPHA_SIZE;
   327         attribs[i++] = _this->gl_config.alpha_size;
   328     }
   329 
   330     if (_this->gl_config.buffer_size) {
   331         attribs[i++] = GLX_BUFFER_SIZE;
   332         attribs[i++] = _this->gl_config.buffer_size;
   333     }
   334 
   335     if (_this->gl_config.double_buffer) {
   336         attribs[i++] = GLX_DOUBLEBUFFER;
   337     }
   338 
   339     attribs[i++] = GLX_DEPTH_SIZE;
   340     attribs[i++] = _this->gl_config.depth_size;
   341 
   342     if (_this->gl_config.stencil_size) {
   343         attribs[i++] = GLX_STENCIL_SIZE;
   344         attribs[i++] = _this->gl_config.stencil_size;
   345     }
   346 
   347     if (_this->gl_config.accum_red_size) {
   348         attribs[i++] = GLX_ACCUM_RED_SIZE;
   349         attribs[i++] = _this->gl_config.accum_red_size;
   350     }
   351 
   352     if (_this->gl_config.accum_green_size) {
   353         attribs[i++] = GLX_ACCUM_GREEN_SIZE;
   354         attribs[i++] = _this->gl_config.accum_green_size;
   355     }
   356 
   357     if (_this->gl_config.accum_blue_size) {
   358         attribs[i++] = GLX_ACCUM_BLUE_SIZE;
   359         attribs[i++] = _this->gl_config.accum_blue_size;
   360     }
   361 
   362     if (_this->gl_config.accum_alpha_size) {
   363         attribs[i++] = GLX_ACCUM_ALPHA_SIZE;
   364         attribs[i++] = _this->gl_config.accum_alpha_size;
   365     }
   366 
   367     if (_this->gl_config.stereo) {
   368         attribs[i++] = GLX_STEREO;
   369     }
   370 
   371     if (_this->gl_config.multisamplebuffers) {
   372         attribs[i++] = GLX_SAMPLE_BUFFERS_ARB;
   373         attribs[i++] = _this->gl_config.multisamplebuffers;
   374     }
   375 
   376     if (_this->gl_config.multisamplesamples) {
   377         attribs[i++] = GLX_SAMPLES_ARB;
   378         attribs[i++] = _this->gl_config.multisamplesamples;
   379     }
   380 
   381     if (_this->gl_config.accelerated >= 0 &&
   382         _this->gl_data->HAS_GLX_EXT_visual_rating) {
   383         attribs[i++] = GLX_VISUAL_CAVEAT_EXT;
   384         attribs[i++] = _this->gl_config.accelerated ? GLX_NONE_EXT :
   385                                                       GLX_SLOW_VISUAL_EXT;
   386     }
   387 
   388     attribs[i++] = None;
   389  
   390     return i;
   391 }
   392 
   393 XVisualInfo *
   394 X11_GL_GetVisual(_THIS, Display * display, int screen)
   395 {
   396     XVisualInfo *vinfo;
   397 
   398     /* 64 seems nice. */
   399     const int max_attrs = 64;
   400     int attribs[max_attrs];
   401     const int i = X11_GL_GetAttributes(_this,display,screen,attribs,max_attrs);
   402     SDL_assert(i <= max_attrs);
   403 
   404     if (!_this->gl_data) {
   405         /* The OpenGL library wasn't loaded, SDL_GetError() should have info */
   406         return NULL;
   407     }
   408 
   409     vinfo = _this->gl_data->glXChooseVisual(display, screen, attribs);
   410     if (!vinfo) {
   411         SDL_SetError("Couldn't find matching GLX visual");
   412     }
   413     return vinfo;
   414 }
   415 
   416 SDL_GLContext
   417 X11_GL_CreateContext(_THIS, SDL_Window * window)
   418 {
   419     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   420     Display *display = data->videodata->display;
   421     int screen =
   422         ((SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata)->screen;
   423     XWindowAttributes xattr;
   424     XVisualInfo v, *vinfo;
   425     int n;
   426     GLXContext context = NULL;
   427 
   428     /* We do this to create a clean separation between X and GLX errors. */
   429     XSync(display, False);
   430     XGetWindowAttributes(display, data->xwindow, &xattr);
   431     v.screen = screen;
   432     v.visualid = XVisualIDFromVisual(xattr.visual);
   433     vinfo = XGetVisualInfo(display, VisualScreenMask | VisualIDMask, &v, &n);
   434     if (vinfo) {
   435         if (_this->gl_config.major_version < 3) {
   436             context =
   437                 _this->gl_data->glXCreateContext(display, vinfo, NULL, True);
   438         } else {
   439             /* If we want a GL 3.0 context or later we need to get a temporary
   440                context to grab the new context creation function */
   441             GLXContext temp_context =
   442                 _this->gl_data->glXCreateContext(display, vinfo, NULL, True);
   443             if (!temp_context) {
   444                 SDL_SetError("Could not create GL context");
   445                 return NULL;
   446             } else {
   447                 int attribs[] = {
   448                     GLX_CONTEXT_MAJOR_VERSION_ARB,
   449                     _this->gl_config.major_version,
   450                     GLX_CONTEXT_MINOR_VERSION_ARB,
   451                     _this->gl_config.minor_version,
   452                     0
   453                 };
   454 
   455                 /* Get a pointer to the context creation function for GL 3.0 */
   456                 PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs =
   457                     (PFNGLXCREATECONTEXTATTRIBSARBPROC) _this->gl_data->
   458                     glXGetProcAddress((GLubyte *)
   459                                       "glXCreateContextAttribsARB");
   460                 if (!glXCreateContextAttribs) {
   461                     SDL_SetError("GL 3.x is not supported");
   462                     context = temp_context;
   463                 } else {
   464                     int glxAttribs[64];
   465 
   466                     /* Create a GL 3.x context */
   467                     GLXFBConfig *framebuffer_config = NULL;
   468                     int fbcount = 0;
   469                     GLXFBConfig *(*glXChooseFBConfig) (Display * disp,
   470                                                        int screen,
   471                                                        const int *attrib_list,
   472                                                        int *nelements);
   473 
   474                     glXChooseFBConfig =
   475                         (GLXFBConfig *
   476                          (*)(Display *, int, const int *,
   477                              int *)) _this->gl_data->
   478                         glXGetProcAddress((GLubyte *) "glXChooseFBConfig");
   479 
   480                     X11_GL_GetAttributes(_this,display,screen,glxAttribs,64);
   481 
   482                     if (!glXChooseFBConfig
   483                         || !(framebuffer_config =
   484                              glXChooseFBConfig(display,
   485                                                DefaultScreen(display), glxAttribs,
   486                                                &fbcount))) {
   487                         SDL_SetError
   488                             ("No good framebuffers found. GL 3.x disabled");
   489                         context = temp_context;
   490                     } else {
   491                         context =
   492                             glXCreateContextAttribs(display,
   493                                                     framebuffer_config[0],
   494                                                     NULL, True, attribs);
   495                         _this->gl_data->glXDestroyContext(display,
   496                                                           temp_context);
   497                     }
   498                 }
   499             }
   500         }
   501         XFree(vinfo);
   502     }
   503     XSync(display, False);
   504 
   505     if (!context) {
   506         SDL_SetError("Could not create GL context");
   507         return NULL;
   508     }
   509 
   510     if (X11_GL_MakeCurrent(_this, window, context) < 0) {
   511         X11_GL_DeleteContext(_this, context);
   512         return NULL;
   513     }
   514 
   515     return context;
   516 }
   517 
   518 int
   519 X11_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
   520 {
   521     Display *display = ((SDL_VideoData *) _this->driverdata)->display;
   522     Window drawable =
   523         (window ? ((SDL_WindowData *) window->driverdata)->xwindow : None);
   524     GLXContext glx_context = (GLXContext) context;
   525     int status;
   526 
   527     status = 0;
   528     if (!_this->gl_data->glXMakeCurrent(display, drawable, glx_context)) {
   529         SDL_SetError("Unable to make GL context current");
   530         status = -1;
   531     }
   532     XSync(display, False);
   533 
   534     return (status);
   535 }
   536 
   537 /* 
   538    0 is a valid argument to glxSwapInterval(MESA|EXT) and setting it to 0
   539    will undo the effect of a previous call with a value that is greater
   540    than zero (or at least that is what the docs say). OTOH, 0 is an invalid
   541    argument to glxSwapIntervalSGI and it returns an error if you call it
   542    with 0 as an argument.
   543 */
   544 
   545 static int swapinterval = -1;
   546 int
   547 X11_GL_SetSwapInterval(_THIS, int interval)
   548 {
   549     int status;
   550 
   551     if (_this->gl_data->glXSwapIntervalEXT) {
   552         Display *display = ((SDL_VideoData *) _this->driverdata)->display;
   553         const SDL_WindowData *windowdata = (SDL_WindowData *)
   554             _this->current_glwin->driverdata;
   555         Window drawable = windowdata->xwindow;
   556         status = _this->gl_data->glXSwapIntervalEXT(display,drawable,interval);
   557         if (status != 0) {
   558             SDL_SetError("glxSwapIntervalEXT failed");
   559             status = -1;
   560         } else {
   561             swapinterval = interval;
   562         }
   563     } else if (_this->gl_data->glXSwapIntervalMESA) {
   564         status = _this->gl_data->glXSwapIntervalMESA(interval);
   565         if (status != 0) {
   566             SDL_SetError("glxSwapIntervalMESA failed");
   567             status = -1;
   568         } else {
   569             swapinterval = interval;
   570         }
   571     } else if (_this->gl_data->glXSwapIntervalSGI) {
   572         status = _this->gl_data->glXSwapIntervalSGI(interval);
   573         if (status != 0) {
   574             SDL_SetError("glxSwapIntervalSGI failed");
   575             status = -1;
   576         } else {
   577             swapinterval = interval;
   578         }
   579     } else {
   580         SDL_Unsupported();
   581         status = -1;
   582     }
   583     return status;
   584 }
   585 
   586 int
   587 X11_GL_GetSwapInterval(_THIS)
   588 {
   589     if (_this->gl_data->glXSwapIntervalEXT) {
   590         Display *display = ((SDL_VideoData *) _this->driverdata)->display;
   591         const SDL_WindowData *windowdata = (SDL_WindowData *)
   592             _this->current_glwin->driverdata;
   593         Window drawable = windowdata->xwindow;
   594         unsigned int value = 0;
   595         _this->gl_data->glXQueryDrawable(display, drawable,
   596                                          GLX_SWAP_INTERVAL_EXT, &value);
   597         return (int) value;
   598     } else if (_this->gl_data->glXGetSwapIntervalMESA) {
   599         return _this->gl_data->glXGetSwapIntervalMESA();
   600     } else {
   601         return swapinterval;
   602     }
   603 }
   604 
   605 void
   606 X11_GL_SwapWindow(_THIS, SDL_Window * window)
   607 {
   608     SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   609     Display *display = data->videodata->display;
   610 
   611     _this->gl_data->glXSwapBuffers(display, data->xwindow);
   612 }
   613 
   614 void
   615 X11_GL_DeleteContext(_THIS, SDL_GLContext context)
   616 {
   617     Display *display = ((SDL_VideoData *) _this->driverdata)->display;
   618     GLXContext glx_context = (GLXContext) context;
   619 
   620     _this->gl_data->glXDestroyContext(display, glx_context);
   621     XSync(display, False);
   622 }
   623 
   624 #endif /* SDL_VIDEO_OPENGL_GLX */
   625 
   626 #endif /* SDL_VIDEO_DRIVER_X11 */
   627 
   628 /* vi: set ts=4 sw=4 expandtab: */