2 Simple DirectMedia Layer
3 Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
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.
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:
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.
21 #include "../../SDL_internal.h"
23 #if SDL_VIDEO_DRIVER_X11
25 #include "SDL_x11video.h"
26 #include "SDL_assert.h"
28 /* GLX implementation of SDL OpenGL support */
30 #if SDL_VIDEO_OPENGL_GLX
31 #include "SDL_loadso.h"
32 #include "SDL_x11opengles.h"
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"
42 #define DEFAULT_OPENGL "libGL.so.1"
46 #define GLX_NONE_EXT 0x8000
49 #ifndef GLX_ARB_multisample
50 #define GLX_ARB_multisample
51 #define GLX_SAMPLE_BUFFERS_ARB 100000
52 #define GLX_SAMPLES_ARB 100001
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
63 #ifndef GLX_EXT_visual_info
64 #define GLX_EXT_visual_info
65 #define GLX_X_VISUAL_TYPE_EXT 0x22
66 #define GLX_DIRECT_COLOR_EXT 0x8003
69 #ifndef GLX_ARB_create_context
70 #define GLX_ARB_create_context
71 #define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
72 #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
73 #define GLX_CONTEXT_FLAGS_ARB 0x2094
74 #define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001
75 #define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
77 /* Typedef for the GL 3.0 context creation function */
78 typedef GLXContext(*PFNGLXCREATECONTEXTATTRIBSARBPROC) (Display * dpy,
87 #ifndef GLX_ARB_create_context_profile
88 #define GLX_ARB_create_context_profile
89 #define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
90 #define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
91 #define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
94 #ifndef GLX_ARB_create_context_robustness
95 #define GLX_ARB_create_context_robustness
96 #define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
97 #define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
98 #define GLX_NO_RESET_NOTIFICATION_ARB 0x8261
99 #define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252
102 #ifndef GLX_EXT_create_context_es2_profile
103 #define GLX_EXT_create_context_es2_profile
104 #ifndef GLX_CONTEXT_ES2_PROFILE_BIT_EXT
105 #define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000002
109 #ifndef GLX_ARB_framebuffer_sRGB
110 #define GLX_ARB_framebuffer_sRGB
111 #ifndef GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB
112 #define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2
116 #ifndef GLX_EXT_swap_control
117 #define GLX_SWAP_INTERVAL_EXT 0x20F1
118 #define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2
121 #ifndef GLX_EXT_swap_control_tear
122 #define GLX_LATE_SWAPS_TEAR_EXT 0x20F3
125 #ifndef GLX_ARB_context_flush_control
126 #define GLX_ARB_context_flush_control
127 #define GLX_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
128 #define GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0x0000
129 #define GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
132 #define OPENGL_REQUIRES_DLOPEN
133 #if defined(OPENGL_REQUIRES_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
135 #define GL_LoadObject(X) dlopen(X, (RTLD_NOW|RTLD_GLOBAL))
136 #define GL_LoadFunction dlsym
137 #define GL_UnloadObject dlclose
139 #define GL_LoadObject SDL_LoadObject
140 #define GL_LoadFunction SDL_LoadFunction
141 #define GL_UnloadObject SDL_UnloadObject
144 static void X11_GL_InitExtensions(_THIS);
148 X11_GL_LoadLibrary(_THIS, const char *path)
153 if (_this->gl_data) {
154 return SDL_SetError("OpenGL context already created");
157 /* Load the OpenGL library */
159 path = SDL_getenv("SDL_OPENGL_LIBRARY");
162 path = DEFAULT_OPENGL;
164 _this->gl_config.dll_handle = GL_LoadObject(path);
165 if (!_this->gl_config.dll_handle) {
166 #if defined(OPENGL_REQUIRES_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
167 SDL_SetError("Failed loading %s: %s", path, dlerror());
171 SDL_strlcpy(_this->gl_config.driver_path, path,
172 SDL_arraysize(_this->gl_config.driver_path));
174 /* Allocate OpenGL memory */
176 (struct SDL_GLDriverData *) SDL_calloc(1,
179 if (!_this->gl_data) {
180 return SDL_OutOfMemory();
183 /* Load function pointers */
184 handle = _this->gl_config.dll_handle;
185 _this->gl_data->glXQueryExtension =
186 (Bool (*)(Display *, int *, int *))
187 GL_LoadFunction(handle, "glXQueryExtension");
188 _this->gl_data->glXGetProcAddress =
189 (void *(*)(const GLubyte *))
190 GL_LoadFunction(handle, "glXGetProcAddressARB");
191 _this->gl_data->glXChooseVisual =
192 (XVisualInfo * (*)(Display *, int, int *))
193 X11_GL_GetProcAddress(_this, "glXChooseVisual");
194 _this->gl_data->glXCreateContext =
195 (GLXContext(*)(Display *, XVisualInfo *, GLXContext, int))
196 X11_GL_GetProcAddress(_this, "glXCreateContext");
197 _this->gl_data->glXDestroyContext =
198 (void (*)(Display *, GLXContext))
199 X11_GL_GetProcAddress(_this, "glXDestroyContext");
200 _this->gl_data->glXMakeCurrent =
201 (int (*)(Display *, GLXDrawable, GLXContext))
202 X11_GL_GetProcAddress(_this, "glXMakeCurrent");
203 _this->gl_data->glXSwapBuffers =
204 (void (*)(Display *, GLXDrawable))
205 X11_GL_GetProcAddress(_this, "glXSwapBuffers");
206 _this->gl_data->glXQueryDrawable =
207 (void (*)(Display*,GLXDrawable,int,unsigned int*))
208 X11_GL_GetProcAddress(_this, "glXQueryDrawable");
210 if (!_this->gl_data->glXQueryExtension ||
211 !_this->gl_data->glXChooseVisual ||
212 !_this->gl_data->glXCreateContext ||
213 !_this->gl_data->glXDestroyContext ||
214 !_this->gl_data->glXMakeCurrent ||
215 !_this->gl_data->glXSwapBuffers) {
216 return SDL_SetError("Could not retrieve OpenGL functions");
219 display = ((SDL_VideoData *) _this->driverdata)->display;
220 if (!_this->gl_data->glXQueryExtension(display, &_this->gl_data->errorBase, &_this->gl_data->eventBase)) {
221 return SDL_SetError("GLX is not supported");
224 /* Initialize extensions */
225 X11_GL_InitExtensions(_this);
227 /* If we need a GL ES context and there's no
228 * GLX_EXT_create_context_es2_profile extension, switch over to X11_GLES functions
230 if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES &&
231 ! _this->gl_data->HAS_GLX_EXT_create_context_es2_profile ) {
232 #if SDL_VIDEO_OPENGL_EGL
233 X11_GL_UnloadLibrary(_this);
234 /* Better avoid conflicts! */
235 if (_this->gl_config.dll_handle != NULL ) {
236 GL_UnloadObject(_this->gl_config.dll_handle);
237 _this->gl_config.dll_handle = NULL;
239 _this->GL_LoadLibrary = X11_GLES_LoadLibrary;
240 _this->GL_GetProcAddress = X11_GLES_GetProcAddress;
241 _this->GL_UnloadLibrary = X11_GLES_UnloadLibrary;
242 _this->GL_CreateContext = X11_GLES_CreateContext;
243 _this->GL_MakeCurrent = X11_GLES_MakeCurrent;
244 _this->GL_SetSwapInterval = X11_GLES_SetSwapInterval;
245 _this->GL_GetSwapInterval = X11_GLES_GetSwapInterval;
246 _this->GL_SwapWindow = X11_GLES_SwapWindow;
247 _this->GL_DeleteContext = X11_GLES_DeleteContext;
248 return X11_GLES_LoadLibrary(_this, NULL);
250 return SDL_SetError("SDL not configured with EGL support");
258 X11_GL_GetProcAddress(_THIS, const char *proc)
260 if (_this->gl_data->glXGetProcAddress) {
261 return _this->gl_data->glXGetProcAddress((const GLubyte *) proc);
263 return GL_LoadFunction(_this->gl_config.dll_handle, proc);
267 X11_GL_UnloadLibrary(_THIS)
269 /* Don't actually unload the library, since it may have registered
270 * X11 shutdown hooks, per the notes at:
271 * http://dri.sourceforge.net/doc/DRIuserguide.html
274 GL_UnloadObject(_this->gl_config.dll_handle);
275 _this->gl_config.dll_handle = NULL;
278 /* Free OpenGL memory */
279 SDL_free(_this->gl_data);
280 _this->gl_data = NULL;
284 HasExtension(const char *extension, const char *extensions)
287 const char *where, *terminator;
292 /* Extension names should not have spaces. */
293 where = SDL_strchr(extension, ' ');
294 if (where || *extension == '\0')
297 /* It takes a bit of care to be fool-proof about parsing the
298 * OpenGL extensions string. Don't be fooled by sub-strings,
304 where = SDL_strstr(start, extension);
308 terminator = where + SDL_strlen(extension);
309 if (where == start || *(where - 1) == ' ')
310 if (*terminator == ' ' || *terminator == '\0')
319 X11_GL_InitExtensions(_THIS)
321 Display *display = ((SDL_VideoData *) _this->driverdata)->display;
322 const int screen = DefaultScreen(display);
323 const char *(*glXQueryExtensionsStringFunc) (Display *, int);
324 const char *extensions;
326 glXQueryExtensionsStringFunc =
327 (const char *(*)(Display *, int)) X11_GL_GetProcAddress(_this,
328 "glXQueryExtensionsString");
329 if (glXQueryExtensionsStringFunc) {
330 extensions = glXQueryExtensionsStringFunc(display, screen);
335 /* Check for GLX_EXT_swap_control(_tear) */
336 _this->gl_data->HAS_GLX_EXT_swap_control_tear = SDL_FALSE;
337 if (HasExtension("GLX_EXT_swap_control", extensions)) {
338 _this->gl_data->glXSwapIntervalEXT =
339 (void (*)(Display*,GLXDrawable,int))
340 X11_GL_GetProcAddress(_this, "glXSwapIntervalEXT");
341 if (HasExtension("GLX_EXT_swap_control_tear", extensions)) {
342 _this->gl_data->HAS_GLX_EXT_swap_control_tear = SDL_TRUE;
346 /* Check for GLX_MESA_swap_control */
347 if (HasExtension("GLX_MESA_swap_control", extensions)) {
348 _this->gl_data->glXSwapIntervalMESA =
349 (int(*)(int)) X11_GL_GetProcAddress(_this, "glXSwapIntervalMESA");
350 _this->gl_data->glXGetSwapIntervalMESA =
351 (int(*)(void)) X11_GL_GetProcAddress(_this,
352 "glXGetSwapIntervalMESA");
355 /* Check for GLX_SGI_swap_control */
356 if (HasExtension("GLX_SGI_swap_control", extensions)) {
357 _this->gl_data->glXSwapIntervalSGI =
358 (int (*)(int)) X11_GL_GetProcAddress(_this, "glXSwapIntervalSGI");
361 /* Check for GLX_ARB_create_context */
362 if (HasExtension("GLX_ARB_create_context", extensions)) {
363 _this->gl_data->glXCreateContextAttribsARB =
364 (GLXContext (*)(Display*,GLXFBConfig,GLXContext,Bool,const int *))
365 X11_GL_GetProcAddress(_this, "glXCreateContextAttribsARB");
366 _this->gl_data->glXChooseFBConfig =
367 (GLXFBConfig *(*)(Display *, int, const int *, int *))
368 X11_GL_GetProcAddress(_this, "glXChooseFBConfig");
371 /* Check for GLX_EXT_visual_rating */
372 if (HasExtension("GLX_EXT_visual_rating", extensions)) {
373 _this->gl_data->HAS_GLX_EXT_visual_rating = SDL_TRUE;
376 /* Check for GLX_EXT_visual_info */
377 if (HasExtension("GLX_EXT_visual_info", extensions)) {
378 _this->gl_data->HAS_GLX_EXT_visual_info = SDL_TRUE;
381 /* Check for GLX_EXT_create_context_es2_profile */
382 if (HasExtension("GLX_EXT_create_context_es2_profile", extensions)) {
383 _this->gl_data->HAS_GLX_EXT_create_context_es2_profile = SDL_TRUE;
386 /* Check for GLX_ARB_context_flush_control */
387 if (HasExtension("GLX_ARB_context_flush_control", extensions)) {
388 _this->gl_data->HAS_GLX_ARB_context_flush_control = SDL_TRUE;
392 /* glXChooseVisual and glXChooseFBConfig have some small differences in
393 * the attribute encoding, it can be chosen with the for_FBConfig parameter.
396 X11_GL_GetAttributes(_THIS, Display * display, int screen, int * attribs, int size, Bool for_FBConfig)
399 const int MAX_ATTRIBUTES = 64;
401 /* assert buffer is large enough to hold all SDL attributes. */
402 SDL_assert(size >= MAX_ATTRIBUTES);
404 /* Setup our GLX attributes according to the gl_config. */
406 attribs[i++] = GLX_RENDER_TYPE;
407 attribs[i++] = GLX_RGBA_BIT;
409 attribs[i++] = GLX_RGBA;
411 attribs[i++] = GLX_RED_SIZE;
412 attribs[i++] = _this->gl_config.red_size;
413 attribs[i++] = GLX_GREEN_SIZE;
414 attribs[i++] = _this->gl_config.green_size;
415 attribs[i++] = GLX_BLUE_SIZE;
416 attribs[i++] = _this->gl_config.blue_size;
418 if (_this->gl_config.alpha_size) {
419 attribs[i++] = GLX_ALPHA_SIZE;
420 attribs[i++] = _this->gl_config.alpha_size;
423 if (_this->gl_config.double_buffer) {
424 attribs[i++] = GLX_DOUBLEBUFFER;
430 attribs[i++] = GLX_DEPTH_SIZE;
431 attribs[i++] = _this->gl_config.depth_size;
433 if (_this->gl_config.stencil_size) {
434 attribs[i++] = GLX_STENCIL_SIZE;
435 attribs[i++] = _this->gl_config.stencil_size;
438 if (_this->gl_config.accum_red_size) {
439 attribs[i++] = GLX_ACCUM_RED_SIZE;
440 attribs[i++] = _this->gl_config.accum_red_size;
443 if (_this->gl_config.accum_green_size) {
444 attribs[i++] = GLX_ACCUM_GREEN_SIZE;
445 attribs[i++] = _this->gl_config.accum_green_size;
448 if (_this->gl_config.accum_blue_size) {
449 attribs[i++] = GLX_ACCUM_BLUE_SIZE;
450 attribs[i++] = _this->gl_config.accum_blue_size;
453 if (_this->gl_config.accum_alpha_size) {
454 attribs[i++] = GLX_ACCUM_ALPHA_SIZE;
455 attribs[i++] = _this->gl_config.accum_alpha_size;
458 if (_this->gl_config.stereo) {
459 attribs[i++] = GLX_STEREO;
465 if (_this->gl_config.multisamplebuffers) {
466 attribs[i++] = GLX_SAMPLE_BUFFERS_ARB;
467 attribs[i++] = _this->gl_config.multisamplebuffers;
470 if (_this->gl_config.multisamplesamples) {
471 attribs[i++] = GLX_SAMPLES_ARB;
472 attribs[i++] = _this->gl_config.multisamplesamples;
475 if (_this->gl_config.framebuffer_srgb_capable) {
476 attribs[i++] = GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB;
477 attribs[i++] = True; /* always needed, for_FBConfig or not! */
480 if (_this->gl_config.accelerated >= 0 &&
481 _this->gl_data->HAS_GLX_EXT_visual_rating) {
482 attribs[i++] = GLX_VISUAL_CAVEAT_EXT;
483 attribs[i++] = _this->gl_config.accelerated ? GLX_NONE_EXT :
487 /* If we're supposed to use DirectColor visuals, and we've got the
488 EXT_visual_info extension, then add GLX_X_VISUAL_TYPE_EXT. */
489 if (X11_UseDirectColorVisuals() &&
490 _this->gl_data->HAS_GLX_EXT_visual_info) {
491 attribs[i++] = GLX_X_VISUAL_TYPE_EXT;
492 attribs[i++] = GLX_DIRECT_COLOR_EXT;
497 SDL_assert(i <= MAX_ATTRIBUTES);
503 X11_GL_GetVisual(_THIS, Display * display, int screen)
509 if (!_this->gl_data) {
510 /* The OpenGL library wasn't loaded, SDL_GetError() should have info */
514 X11_GL_GetAttributes(_this, display, screen, attribs, 64, SDL_FALSE);
515 vinfo = _this->gl_data->glXChooseVisual(display, screen, attribs);
517 SDL_SetError("Couldn't find matching GLX visual");
522 #ifndef GLXBadContext
523 #define GLXBadContext 0
525 #ifndef GLXBadFBConfig
526 #define GLXBadFBConfig 9
528 #ifndef GLXBadProfileARB
529 #define GLXBadProfileARB 13
531 static int (*handler) (Display *, XErrorEvent *) = NULL;
532 static const char *errorHandlerOperation = NULL;
533 static int errorBase = 0;
534 static int errorCode = 0;
536 X11_GL_ErrorHandler(Display * d, XErrorEvent * e)
538 char *x11_error = NULL;
539 char x11_error_locale[256];
541 errorCode = e->error_code;
542 if (X11_XGetErrorText(d, errorCode, x11_error_locale, sizeof(x11_error_locale)) == Success)
544 x11_error = SDL_iconv_string("UTF-8", "", x11_error_locale, SDL_strlen(x11_error_locale)+1);
549 SDL_SetError("Could not %s: %s", errorHandlerOperation, x11_error);
554 SDL_SetError("Could not %s: %i (Base %i)\n", errorHandlerOperation, errorCode, errorBase);
561 X11_GL_CreateContext(_THIS, SDL_Window * window)
563 SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
564 Display *display = data->videodata->display;
566 ((SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata)->screen;
567 XWindowAttributes xattr;
568 XVisualInfo v, *vinfo;
570 GLXContext context = NULL, share_context;
572 if (_this->gl_config.share_with_current_context) {
573 share_context = (GLXContext)SDL_GL_GetCurrentContext();
575 share_context = NULL;
578 /* We do this to create a clean separation between X and GLX errors. */
579 X11_XSync(display, False);
580 errorHandlerOperation = "create GL context";
581 errorBase = _this->gl_data->errorBase;
583 handler = X11_XSetErrorHandler(X11_GL_ErrorHandler);
584 X11_XGetWindowAttributes(display, data->xwindow, &xattr);
586 v.visualid = X11_XVisualIDFromVisual(xattr.visual);
587 vinfo = X11_XGetVisualInfo(display, VisualScreenMask | VisualIDMask, &v, &n);
589 if (_this->gl_config.major_version < 3 &&
590 _this->gl_config.profile_mask == 0 &&
591 _this->gl_config.flags == 0) {
592 /* Create legacy context */
594 _this->gl_data->glXCreateContext(display, vinfo, share_context, True);
596 /* max 10 attributes plus terminator */
598 GLX_CONTEXT_MAJOR_VERSION_ARB,
599 _this->gl_config.major_version,
600 GLX_CONTEXT_MINOR_VERSION_ARB,
601 _this->gl_config.minor_version,
606 /* SDL profile bits match GLX profile bits */
607 if( _this->gl_config.profile_mask != 0 ) {
608 attribs[iattr++] = GLX_CONTEXT_PROFILE_MASK_ARB;
609 attribs[iattr++] = _this->gl_config.profile_mask;
612 /* SDL flags match GLX flags */
613 if( _this->gl_config.flags != 0 ) {
614 attribs[iattr++] = GLX_CONTEXT_FLAGS_ARB;
615 attribs[iattr++] = _this->gl_config.flags;
618 /* only set if glx extension is available */
619 if( _this->gl_data->HAS_GLX_ARB_context_flush_control ) {
620 attribs[iattr++] = GLX_CONTEXT_RELEASE_BEHAVIOR_ARB;
622 _this->gl_config.release_behavior ?
623 GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB :
624 GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB;
627 attribs[iattr++] = 0;
629 /* Get a pointer to the context creation function for GL 3.0 */
630 if (!_this->gl_data->glXCreateContextAttribsARB) {
631 SDL_SetError("OpenGL 3.0 and later are not supported by this system");
635 /* Create a GL 3.x context */
636 GLXFBConfig *framebuffer_config = NULL;
639 X11_GL_GetAttributes(_this,display,screen,glxAttribs,64,SDL_TRUE);
641 if (!_this->gl_data->glXChooseFBConfig
642 || !(framebuffer_config =
643 _this->gl_data->glXChooseFBConfig(display,
644 DefaultScreen(display), glxAttribs,
646 SDL_SetError("No good framebuffers found. OpenGL 3.0 and later unavailable");
648 context = _this->gl_data->glXCreateContextAttribsARB(display,
649 framebuffer_config[0],
650 share_context, True, attribs);
656 X11_XSync(display, False);
657 X11_XSetErrorHandler(handler);
660 if (errorCode == Success) {
661 SDL_SetError("Could not create GL context");
666 if (X11_GL_MakeCurrent(_this, window, context) < 0) {
667 X11_GL_DeleteContext(_this, context);
675 X11_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
677 Display *display = ((SDL_VideoData *) _this->driverdata)->display;
679 (context ? ((SDL_WindowData *) window->driverdata)->xwindow : None);
680 GLXContext glx_context = (GLXContext) context;
683 if (!_this->gl_data) {
684 return SDL_SetError("OpenGL not initialized");
687 /* We do this to create a clean separation between X and GLX errors. */
688 X11_XSync(display, False);
689 errorHandlerOperation = "make GL context current";
690 errorBase = _this->gl_data->errorBase;
692 handler = X11_XSetErrorHandler(X11_GL_ErrorHandler);
693 rc = _this->gl_data->glXMakeCurrent(display, drawable, glx_context);
694 X11_XSetErrorHandler(handler);
696 if (errorCode != Success) { /* uhoh, an X error was thrown! */
697 return -1; /* the error handler called SDL_SetError() already. */
698 } else if (!rc) { /* glxMakeCurrent() failed without throwing an X error */
699 return SDL_SetError("Unable to make GL context current");
706 0 is a valid argument to glxSwapInterval(MESA|EXT) and setting it to 0
707 will undo the effect of a previous call with a value that is greater
708 than zero (or at least that is what the docs say). OTOH, 0 is an invalid
709 argument to glxSwapIntervalSGI and it returns an error if you call it
710 with 0 as an argument.
713 static int swapinterval = -1;
715 X11_GL_SetSwapInterval(_THIS, int interval)
719 if ((interval < 0) && (!_this->gl_data->HAS_GLX_EXT_swap_control_tear)) {
720 SDL_SetError("Negative swap interval unsupported in this GL");
721 } else if (_this->gl_data->glXSwapIntervalEXT) {
722 Display *display = ((SDL_VideoData *) _this->driverdata)->display;
723 const SDL_WindowData *windowdata = (SDL_WindowData *)
724 SDL_GL_GetCurrentWindow()->driverdata;
726 Window drawable = windowdata->xwindow;
729 * This is a workaround for a bug in NVIDIA drivers. Bug has been reported
730 * and will be fixed in a future release (probably 319.xx).
732 * There's a bug where glXSetSwapIntervalEXT ignores updates because
733 * it has the wrong value cached. To work around it, we just run a no-op
734 * update to the current value.
736 int currentInterval = X11_GL_GetSwapInterval(_this);
737 _this->gl_data->glXSwapIntervalEXT(display, drawable, currentInterval);
738 _this->gl_data->glXSwapIntervalEXT(display, drawable, interval);
741 swapinterval = interval;
742 } else if (_this->gl_data->glXSwapIntervalMESA) {
743 status = _this->gl_data->glXSwapIntervalMESA(interval);
745 SDL_SetError("glxSwapIntervalMESA failed");
747 swapinterval = interval;
749 } else if (_this->gl_data->glXSwapIntervalSGI) {
750 status = _this->gl_data->glXSwapIntervalSGI(interval);
752 SDL_SetError("glxSwapIntervalSGI failed");
754 swapinterval = interval;
763 X11_GL_GetSwapInterval(_THIS)
765 if (_this->gl_data->glXSwapIntervalEXT) {
766 Display *display = ((SDL_VideoData *) _this->driverdata)->display;
767 const SDL_WindowData *windowdata = (SDL_WindowData *)
768 SDL_GL_GetCurrentWindow()->driverdata;
769 Window drawable = windowdata->xwindow;
770 unsigned int allow_late_swap_tearing = 0;
771 unsigned int interval = 0;
773 if (_this->gl_data->HAS_GLX_EXT_swap_control_tear) {
774 _this->gl_data->glXQueryDrawable(display, drawable,
775 GLX_LATE_SWAPS_TEAR_EXT,
776 &allow_late_swap_tearing);
779 _this->gl_data->glXQueryDrawable(display, drawable,
780 GLX_SWAP_INTERVAL_EXT, &interval);
782 if ((allow_late_swap_tearing) && (interval > 0)) {
783 return -((int) interval);
786 return (int) interval;
787 } else if (_this->gl_data->glXGetSwapIntervalMESA) {
788 return _this->gl_data->glXGetSwapIntervalMESA();
795 X11_GL_SwapWindow(_THIS, SDL_Window * window)
797 SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
798 Display *display = data->videodata->display;
800 _this->gl_data->glXSwapBuffers(display, data->xwindow);
804 X11_GL_DeleteContext(_THIS, SDL_GLContext context)
806 Display *display = ((SDL_VideoData *) _this->driverdata)->display;
807 GLXContext glx_context = (GLXContext) context;
809 if (!_this->gl_data) {
812 _this->gl_data->glXDestroyContext(display, glx_context);
813 X11_XSync(display, False);
816 #endif /* SDL_VIDEO_OPENGL_GLX */
818 #endif /* SDL_VIDEO_DRIVER_X11 */
820 /* vi: set ts=4 sw=4 expandtab: */