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