SDL  2.0
SDL_x11opengl.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2016 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_internal.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_EXT_visual_info
64 #define GLX_EXT_visual_info
65 #define GLX_X_VISUAL_TYPE_EXT 0x22
66 #define GLX_DIRECT_COLOR_EXT 0x8003
67 #endif
68 
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
76 
77 /* Typedef for the GL 3.0 context creation function */
78 typedef GLXContext(*PFNGLXCREATECONTEXTATTRIBSARBPROC) (Display * dpy,
79  GLXFBConfig config,
80  GLXContext
81  share_context,
82  Bool direct,
83  const int
84  *attrib_list);
85 #endif
86 
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
92 #endif
93 
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
100 #endif
101 
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
106 #endif
107 #endif
108 
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
113 #endif
114 #endif
115 
116 #ifndef GLX_EXT_swap_control
117 #define GLX_SWAP_INTERVAL_EXT 0x20F1
118 #define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2
119 #endif
120 
121 #ifndef GLX_EXT_swap_control_tear
122 #define GLX_LATE_SWAPS_TEAR_EXT 0x20F3
123 #endif
124 
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
130 #endif
131 
132 #define OPENGL_REQUIRES_DLOPEN
133 #if defined(OPENGL_REQUIRES_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
134 #include <dlfcn.h>
135 #define GL_LoadObject(X) dlopen(X, (RTLD_NOW|RTLD_GLOBAL))
136 #define GL_LoadFunction dlsym
137 #define GL_UnloadObject dlclose
138 #else
139 #define GL_LoadObject SDL_LoadObject
140 #define GL_LoadFunction SDL_LoadFunction
141 #define GL_UnloadObject SDL_UnloadObject
142 #endif
143 
144 static void X11_GL_InitExtensions(_THIS);
145 
146 
147 int
148 X11_GL_LoadLibrary(_THIS, const char *path)
149 {
150  Display *display;
151  void *handle;
152 
153  if (_this->gl_data) {
154  return SDL_SetError("OpenGL context already created");
155  }
156 
157  /* Load the OpenGL library */
158  if (path == NULL) {
159  path = SDL_getenv("SDL_OPENGL_LIBRARY");
160  }
161  if (path == NULL) {
162  path = DEFAULT_OPENGL;
163  }
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());
168 #endif
169  return -1;
170  }
173 
174  /* Allocate OpenGL memory */
175  _this->gl_data =
176  (struct SDL_GLDriverData *) SDL_calloc(1,
177  sizeof(struct
179  if (!_this->gl_data) {
180  return SDL_OutOfMemory();
181  }
182 
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");
209 
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");
217  }
218 
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");
222  }
223 
224  /* Initialize extensions */
225  X11_GL_InitExtensions(_this);
226 
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
229  */
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);
238  }
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);
249 #else
250  return SDL_SetError("SDL not configured with EGL support");
251 #endif
252  }
253 
254  return 0;
255 }
256 
257 void *
258 X11_GL_GetProcAddress(_THIS, const char *proc)
259 {
260  if (_this->gl_data->glXGetProcAddress) {
261  return _this->gl_data->glXGetProcAddress((const GLubyte *) proc);
262  }
263  return GL_LoadFunction(_this->gl_config.dll_handle, proc);
264 }
265 
266 void
267 X11_GL_UnloadLibrary(_THIS)
268 {
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
272  */
273 #if 0
274  GL_UnloadObject(_this->gl_config.dll_handle);
276 #endif
277 
278  /* Free OpenGL memory */
280  _this->gl_data = NULL;
281 }
282 
283 static SDL_bool
284 HasExtension(const char *extension, const char *extensions)
285 {
286  const char *start;
287  const char *where, *terminator;
288 
289  if (!extensions)
290  return SDL_FALSE;
291 
292  /* Extension names should not have spaces. */
293  where = SDL_strchr(extension, ' ');
294  if (where || *extension == '\0')
295  return SDL_FALSE;
296 
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,
299  * etc. */
300 
301  start = extensions;
302 
303  for (;;) {
304  where = SDL_strstr(start, extension);
305  if (!where)
306  break;
307 
308  terminator = where + SDL_strlen(extension);
309  if (where == start || *(where - 1) == ' ')
310  if (*terminator == ' ' || *terminator == '\0')
311  return SDL_TRUE;
312 
313  start = terminator;
314  }
315  return SDL_FALSE;
316 }
317 
318 static void
319 X11_GL_InitExtensions(_THIS)
320 {
321  Display *display = ((SDL_VideoData *) _this->driverdata)->display;
322  const int screen = DefaultScreen(display);
323  const char *(*glXQueryExtensionsStringFunc) (Display *, int);
324  const char *extensions;
325 
326  glXQueryExtensionsStringFunc =
327  (const char *(*)(Display *, int)) X11_GL_GetProcAddress(_this,
328  "glXQueryExtensionsString");
329  if (glXQueryExtensionsStringFunc) {
330  extensions = glXQueryExtensionsStringFunc(display, screen);
331  } else {
332  extensions = NULL;
333  }
334 
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;
343  }
344  }
345 
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");
353  }
354 
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");
359  }
360 
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");
369  }
370 
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;
374  }
375 
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;
379  }
380 
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;
384  }
385 
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;
389  }
390 }
391 
392 /* glXChooseVisual and glXChooseFBConfig have some small differences in
393  * the attribute encoding, it can be chosen with the for_FBConfig parameter.
394  */
395 static int
396 X11_GL_GetAttributes(_THIS, Display * display, int screen, int * attribs, int size, Bool for_FBConfig)
397 {
398  int i = 0;
399  const int MAX_ATTRIBUTES = 64;
400 
401  /* assert buffer is large enough to hold all SDL attributes. */
402  SDL_assert(size >= MAX_ATTRIBUTES);
403 
404  /* Setup our GLX attributes according to the gl_config. */
405  if( for_FBConfig ) {
406  attribs[i++] = GLX_RENDER_TYPE;
407  attribs[i++] = GLX_RGBA_BIT;
408  } else {
409  attribs[i++] = GLX_RGBA;
410  }
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;
417 
418  if (_this->gl_config.alpha_size) {
419  attribs[i++] = GLX_ALPHA_SIZE;
420  attribs[i++] = _this->gl_config.alpha_size;
421  }
422 
424  attribs[i++] = GLX_DOUBLEBUFFER;
425  if( for_FBConfig ) {
426  attribs[i++] = True;
427  }
428  }
429 
430  attribs[i++] = GLX_DEPTH_SIZE;
431  attribs[i++] = _this->gl_config.depth_size;
432 
434  attribs[i++] = GLX_STENCIL_SIZE;
435  attribs[i++] = _this->gl_config.stencil_size;
436  }
437 
439  attribs[i++] = GLX_ACCUM_RED_SIZE;
440  attribs[i++] = _this->gl_config.accum_red_size;
441  }
442 
444  attribs[i++] = GLX_ACCUM_GREEN_SIZE;
445  attribs[i++] = _this->gl_config.accum_green_size;
446  }
447 
449  attribs[i++] = GLX_ACCUM_BLUE_SIZE;
450  attribs[i++] = _this->gl_config.accum_blue_size;
451  }
452 
454  attribs[i++] = GLX_ACCUM_ALPHA_SIZE;
455  attribs[i++] = _this->gl_config.accum_alpha_size;
456  }
457 
458  if (_this->gl_config.stereo) {
459  attribs[i++] = GLX_STEREO;
460  if( for_FBConfig ) {
461  attribs[i++] = True;
462  }
463  }
464 
466  attribs[i++] = GLX_SAMPLE_BUFFERS_ARB;
467  attribs[i++] = _this->gl_config.multisamplebuffers;
468  }
469 
471  attribs[i++] = GLX_SAMPLES_ARB;
472  attribs[i++] = _this->gl_config.multisamplesamples;
473  }
474 
476  attribs[i++] = GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB;
477  attribs[i++] = True; /* always needed, for_FBConfig or not! */
478  }
479 
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 :
484  GLX_SLOW_VISUAL_EXT;
485  }
486 
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. */
490  _this->gl_data->HAS_GLX_EXT_visual_info) {
491  attribs[i++] = GLX_X_VISUAL_TYPE_EXT;
492  attribs[i++] = GLX_DIRECT_COLOR_EXT;
493  }
494 
495  attribs[i++] = None;
496 
497  SDL_assert(i <= MAX_ATTRIBUTES);
498 
499  return i;
500 }
501 
502 XVisualInfo *
503 X11_GL_GetVisual(_THIS, Display * display, int screen)
504 {
505  /* 64 seems nice. */
506  int attribs[64];
507  XVisualInfo *vinfo;
508 
509  if (!_this->gl_data) {
510  /* The OpenGL library wasn't loaded, SDL_GetError() should have info */
511  return NULL;
512  }
513 
514  X11_GL_GetAttributes(_this, display, screen, attribs, 64, SDL_FALSE);
515  vinfo = _this->gl_data->glXChooseVisual(display, screen, attribs);
516  if (!vinfo) {
517  SDL_SetError("Couldn't find matching GLX visual");
518  }
519  return vinfo;
520 }
521 
522 #ifndef GLXBadContext
523 #define GLXBadContext 0
524 #endif
525 #ifndef GLXBadFBConfig
526 #define GLXBadFBConfig 9
527 #endif
528 #ifndef GLXBadProfileARB
529 #define GLXBadProfileARB 13
530 #endif
531 static int (*handler) (Display *, XErrorEvent *) = NULL;
532 static const char *errorHandlerOperation = NULL;
533 static int errorBase = 0;
534 static int errorCode = 0;
535 static int
536 X11_GL_ErrorHandler(Display * d, XErrorEvent * e)
537 {
538  char *x11_error = NULL;
539  char x11_error_locale[256];
540 
541  errorCode = e->error_code;
542  if (X11_XGetErrorText(d, errorCode, x11_error_locale, sizeof(x11_error_locale)) == Success)
543  {
544  x11_error = SDL_iconv_string("UTF-8", "", x11_error_locale, SDL_strlen(x11_error_locale)+1);
545  }
546 
547  if (x11_error)
548  {
549  SDL_SetError("Could not %s: %s", errorHandlerOperation, x11_error);
550  SDL_free(x11_error);
551  }
552  else
553  {
554  SDL_SetError("Could not %s: %i (Base %i)\n", errorHandlerOperation, errorCode, errorBase);
555  }
556 
557  return (0);
558 }
559 
561 X11_GL_CreateContext(_THIS, SDL_Window * window)
562 {
564  Display *display = data->videodata->display;
565  int screen =
566  ((SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata)->screen;
567  XWindowAttributes xattr;
568  XVisualInfo v, *vinfo;
569  int n;
570  GLXContext context = NULL, share_context;
571 
573  share_context = (GLXContext)SDL_GL_GetCurrentContext();
574  } else {
575  share_context = NULL;
576  }
577 
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;
582  errorCode = Success;
583  handler = X11_XSetErrorHandler(X11_GL_ErrorHandler);
584  X11_XGetWindowAttributes(display, data->xwindow, &xattr);
585  v.screen = screen;
586  v.visualid = X11_XVisualIDFromVisual(xattr.visual);
587  vinfo = X11_XGetVisualInfo(display, VisualScreenMask | VisualIDMask, &v, &n);
588  if (vinfo) {
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 */
593  context =
594  _this->gl_data->glXCreateContext(display, vinfo, share_context, True);
595  } else {
596  /* max 10 attributes plus terminator */
597  int attribs[11] = {
598  GLX_CONTEXT_MAJOR_VERSION_ARB,
600  GLX_CONTEXT_MINOR_VERSION_ARB,
602  0
603  };
604  int iattr = 4;
605 
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;
610  }
611 
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;
616  }
617 
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;
621  attribs[iattr++] =
623  GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB :
624  GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB;
625  }
626 
627  attribs[iattr++] = 0;
628 
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");
632  } else {
633  int glxAttribs[64];
634 
635  /* Create a GL 3.x context */
636  GLXFBConfig *framebuffer_config = NULL;
637  int fbcount = 0;
638 
639  X11_GL_GetAttributes(_this,display,screen,glxAttribs,64,SDL_TRUE);
640 
641  if (!_this->gl_data->glXChooseFBConfig
642  || !(framebuffer_config =
643  _this->gl_data->glXChooseFBConfig(display,
644  DefaultScreen(display), glxAttribs,
645  &fbcount))) {
646  SDL_SetError("No good framebuffers found. OpenGL 3.0 and later unavailable");
647  } else {
648  context = _this->gl_data->glXCreateContextAttribsARB(display,
649  framebuffer_config[0],
650  share_context, True, attribs);
651  }
652  }
653  }
654  X11_XFree(vinfo);
655  }
656  X11_XSync(display, False);
657  X11_XSetErrorHandler(handler);
658 
659  if (!context) {
660  if (errorCode == Success) {
661  SDL_SetError("Could not create GL context");
662  }
663  return NULL;
664  }
665 
666  if (X11_GL_MakeCurrent(_this, window, context) < 0) {
667  X11_GL_DeleteContext(_this, context);
668  return NULL;
669  }
670 
671  return context;
672 }
673 
674 int
675 X11_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
676 {
677  Display *display = ((SDL_VideoData *) _this->driverdata)->display;
678  Window drawable =
679  (context ? ((SDL_WindowData *) window->driverdata)->xwindow : None);
680  GLXContext glx_context = (GLXContext) context;
681  int rc;
682 
683  if (!_this->gl_data) {
684  return SDL_SetError("OpenGL not initialized");
685  }
686 
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;
691  errorCode = Success;
692  handler = X11_XSetErrorHandler(X11_GL_ErrorHandler);
693  rc = _this->gl_data->glXMakeCurrent(display, drawable, glx_context);
694  X11_XSetErrorHandler(handler);
695 
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");
700  }
701 
702  return 0;
703 }
704 
705 /*
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.
711 */
712 
713 static int swapinterval = 0;
714 int
715 X11_GL_SetSwapInterval(_THIS, int interval)
716 {
717  int status = -1;
718 
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;
725 
726  Window drawable = windowdata->xwindow;
727 
728  /*
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).
731  *
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.
735  */
736  int currentInterval = X11_GL_GetSwapInterval(_this);
737  _this->gl_data->glXSwapIntervalEXT(display, drawable, currentInterval);
738  _this->gl_data->glXSwapIntervalEXT(display, drawable, interval);
739 
740  status = 0;
741  swapinterval = interval;
742  } else if (_this->gl_data->glXSwapIntervalMESA) {
743  status = _this->gl_data->glXSwapIntervalMESA(interval);
744  if (status != 0) {
745  SDL_SetError("glXSwapIntervalMESA failed");
746  } else {
747  swapinterval = interval;
748  }
749  } else if (_this->gl_data->glXSwapIntervalSGI) {
750  status = _this->gl_data->glXSwapIntervalSGI(interval);
751  if (status != 0) {
752  SDL_SetError("glXSwapIntervalSGI failed");
753  } else {
754  swapinterval = interval;
755  }
756  } else {
757  SDL_Unsupported();
758  }
759  return status;
760 }
761 
762 int
763 X11_GL_GetSwapInterval(_THIS)
764 {
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;
772 
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);
777  }
778 
779  _this->gl_data->glXQueryDrawable(display, drawable,
780  GLX_SWAP_INTERVAL_EXT, &interval);
781 
782  if ((allow_late_swap_tearing) && (interval > 0)) {
783  return -((int) interval);
784  }
785 
786  return (int) interval;
787  } else if (_this->gl_data->glXGetSwapIntervalMESA) {
788  return _this->gl_data->glXGetSwapIntervalMESA();
789  } else {
790  return swapinterval;
791  }
792 }
793 
794 void
795 X11_GL_SwapWindow(_THIS, SDL_Window * window)
796 {
797  SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
798  Display *display = data->videodata->display;
799 
800  _this->gl_data->glXSwapBuffers(display, data->xwindow);
801 }
802 
803 void
804 X11_GL_DeleteContext(_THIS, SDL_GLContext context)
805 {
806  Display *display = ((SDL_VideoData *) _this->driverdata)->display;
807  GLXContext glx_context = (GLXContext) context;
808 
809  if (!_this->gl_data) {
810  return;
811  }
812  _this->gl_data->glXDestroyContext(display, glx_context);
813  X11_XSync(display, False);
814 }
815 
816 #endif /* SDL_VIDEO_OPENGL_GLX */
817 
818 #endif /* SDL_VIDEO_DRIVER_X11 */
819 
820 /* vi: set ts=4 sw=4 expandtab: */
#define SDL_strlcpy
const GLint * attribs
uint32_t swapinterval
Definition: SDL_pspgl_c.h:36
GLdouble n
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 SDL_AssertionHandler void SDL_SpinLock SDL_atomic_t int int return SDL_atomic_t return void void void return void return int return SDL_AudioSpec SDL_AudioSpec return int int return return int SDL_RWops int SDL_AudioSpec Uint8 Uint32 * e
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display dpy)
Definition: SDL_x11sym.h:44
struct wl_display * display
static SDL_Window * window
SDL_bool X11_UseDirectColorVisuals(void)
int(* GL_SetSwapInterval)(_THIS, int interval)
Definition: SDL_sysvideo.h:253
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1967
GLuint start
Definition: SDL_opengl.h:1564
void(* GL_SwapWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:255
EGLDisplay display
Definition: SDL_pspgl_c.h:33
GLsizeiptr size
int(* GL_LoadLibrary)(_THIS, const char *path)
Definition: SDL_sysvideo.h:247
struct SDL_GLDriverData * gl_data
Definition: SDL_sysvideo.h:346
#define SDL_strchr
static SDL_VideoDevice * _this
Definition: SDL_video.c:118
const GLdouble * v
Definition: SDL_opengl.h:2057
void * SDL_calloc(size_t nmemb, size_t size)
void * SDL_GLContext
An opaque handle to an OpenGL context.
Definition: SDL_video.h:172
SDL_GLContext(* GL_CreateContext)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:250
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 SDL_AssertionHandler void SDL_SpinLock SDL_atomic_t int int return SDL_atomic_t return void void void return void return int return SDL_AudioSpec SDL_AudioSpec return int int return return int SDL_RWops int SDL_AudioSpec Uint8 ** d
#define _THIS
struct SDL_VideoData * videodata
int(* GL_MakeCurrent)(_THIS, SDL_Window *window, SDL_GLContext context)
Definition: SDL_sysvideo.h:251
void SDL_free(void *mem)
char driver_path[256]
Definition: SDL_sysvideo.h:329
int framebuffer_srgb_capable
Definition: SDL_sysvideo.h:326
unsigned char GLubyte
Definition: SDL_opengl.h:176
#define SDL_getenv
void(* GL_UnloadLibrary)(_THIS)
Definition: SDL_sysvideo.h:249
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
int share_with_current_context
Definition: SDL_sysvideo.h:324
#define SDL_assert(condition)
Definition: SDL_assert.h:167
#define NULL
Definition: begin_code.h:143
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:130
#define SDL_GL_GetCurrentContext
#define SDL_SetError
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 void
#define SDL_GL_GetCurrentWindow
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
Definition: SDL_video.c:1058
#define SDL_strlen
The type used to identify a window.
Definition: SDL_sysvideo.h:71
#define SDL_iconv_string
struct SDL_VideoDevice::@28 gl_config
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:90
GLsizei const GLchar *const * path
void * driverdata
Definition: SDL_sysvideo.h:109
void(* GL_DeleteContext)(_THIS, SDL_GLContext context)
Definition: SDL_sysvideo.h:256
EGLContext context
Definition: SDL_pspgl_c.h:34
int(* GL_GetSwapInterval)(_THIS)
Definition: SDL_sysvideo.h:254
SDL_Renderer * screen
#define SDL_Unsupported()
Definition: SDL_error.h:53
void *(* GL_GetProcAddress)(_THIS, const char *proc)
Definition: SDL_sysvideo.h:248
#define SDL_strstr