src/video/x11/SDL_x11opengl.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 07 Jan 2012 23:33:15 -0500
changeset 6181 e29f01fa2750
parent 6138 4c64952a58fb
child 6183 6d9a266e04bb
permissions -rwxr-xr-x
Fixed bug 1313 - Segfault on SDL_CreateWindow when gl lib cannot be loaded

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