SDL 2.0
SDL_x11opengl.c
Go to the documentation of this file.
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2019 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#include "SDL_hints.h"
28
29/* GLX implementation of SDL OpenGL support */
30
31#if SDL_VIDEO_OPENGL_GLX
32#include "SDL_loadso.h"
33#include "SDL_x11opengles.h"
34
35#if defined(__IRIX__)
36/* IRIX doesn't have a GL library versioning system */
37#define DEFAULT_OPENGL "libGL.so"
38#elif defined(__MACOSX__)
39#define DEFAULT_OPENGL "/usr/X11R6/lib/libGL.1.dylib"
40#elif defined(__QNXNTO__)
41#define DEFAULT_OPENGL "libGL.so.3"
42#else
43#define DEFAULT_OPENGL "libGL.so.1"
44#endif
45
46#ifndef GLX_NONE_EXT
47#define GLX_NONE_EXT 0x8000
48#endif
49
50#ifndef GLX_ARB_multisample
51#define GLX_ARB_multisample
52#define GLX_SAMPLE_BUFFERS_ARB 100000
53#define GLX_SAMPLES_ARB 100001
54#endif
55
56#ifndef GLX_EXT_visual_rating
57#define GLX_EXT_visual_rating
58#define GLX_VISUAL_CAVEAT_EXT 0x20
59#define GLX_NONE_EXT 0x8000
60#define GLX_SLOW_VISUAL_EXT 0x8001
61#define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D
62#endif
63
64#ifndef GLX_EXT_visual_info
65#define GLX_EXT_visual_info
66#define GLX_X_VISUAL_TYPE_EXT 0x22
67#define GLX_DIRECT_COLOR_EXT 0x8003
68#endif
69
70#ifndef GLX_ARB_create_context
71#define GLX_ARB_create_context
72#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
73#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
74#define GLX_CONTEXT_FLAGS_ARB 0x2094
75#define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001
76#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
77
78/* Typedef for the GL 3.0 context creation function */
79typedef GLXContext(*PFNGLXCREATECONTEXTATTRIBSARBPROC) (Display * dpy,
80 GLXFBConfig config,
81 GLXContext
82 share_context,
83 Bool direct,
84 const int
86#endif
87
88#ifndef GLX_ARB_create_context_profile
89#define GLX_ARB_create_context_profile
90#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
91#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
92#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
93#endif
94
95#ifndef GLX_ARB_create_context_robustness
96#define GLX_ARB_create_context_robustness
97#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
98#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
99#define GLX_NO_RESET_NOTIFICATION_ARB 0x8261
100#define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252
101#endif
102
103#ifndef GLX_EXT_create_context_es2_profile
104#define GLX_EXT_create_context_es2_profile
105#ifndef GLX_CONTEXT_ES2_PROFILE_BIT_EXT
106#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000002
107#endif
108#endif
109
110#ifndef GLX_ARB_framebuffer_sRGB
111#define GLX_ARB_framebuffer_sRGB
112#ifndef GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB
113#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2
114#endif
115#endif
116
117#ifndef GLX_ARB_create_context_no_error
118#define GLX_ARB_create_context_no_error
119#ifndef GLX_CONTEXT_OPENGL_NO_ERROR_ARB
120#define GLX_CONTEXT_OPENGL_NO_ERROR_ARB 0x31B3
121#endif
122#endif
123
124#ifndef GLX_EXT_swap_control
125#define GLX_SWAP_INTERVAL_EXT 0x20F1
126#define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2
127#endif
128
129#ifndef GLX_EXT_swap_control_tear
130#define GLX_LATE_SWAPS_TEAR_EXT 0x20F3
131#endif
132
133#ifndef GLX_ARB_context_flush_control
134#define GLX_ARB_context_flush_control
135#define GLX_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
136#define GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0x0000
137#define GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
138#endif
139
140#define OPENGL_REQUIRES_DLOPEN
141#if defined(OPENGL_REQUIRES_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
142#include <dlfcn.h>
143#define GL_LoadObject(X) dlopen(X, (RTLD_NOW|RTLD_GLOBAL))
144#define GL_LoadFunction dlsym
145#define GL_UnloadObject dlclose
146#else
147#define GL_LoadObject SDL_LoadObject
148#define GL_LoadFunction SDL_LoadFunction
149#define GL_UnloadObject SDL_UnloadObject
150#endif
151
152static void X11_GL_InitExtensions(_THIS);
153
154int
155X11_GL_LoadLibrary(_THIS, const char *path)
156{
157 Display *display;
158 void *handle;
159
160 if (_this->gl_data) {
161 return SDL_SetError("OpenGL context already created");
162 }
163
164 /* Load the OpenGL library */
165 if (path == NULL) {
166 path = SDL_getenv("SDL_OPENGL_LIBRARY");
167 }
168 if (path == NULL) {
169 path = DEFAULT_OPENGL;
170 }
171 _this->gl_config.dll_handle = GL_LoadObject(path);
172 if (!_this->gl_config.dll_handle) {
173#if defined(OPENGL_REQUIRES_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
174 SDL_SetError("Failed loading %s: %s", path, dlerror());
175#endif
176 return -1;
177 }
180
181 /* Allocate OpenGL memory */
182 _this->gl_data =
183 (struct SDL_GLDriverData *) SDL_calloc(1,
184 sizeof(struct
186 if (!_this->gl_data) {
187 return SDL_OutOfMemory();
188 }
189
190 /* Load function pointers */
192 _this->gl_data->glXQueryExtension =
193 (Bool (*)(Display *, int *, int *))
194 GL_LoadFunction(handle, "glXQueryExtension");
195 _this->gl_data->glXGetProcAddress =
196 (void *(*)(const GLubyte *))
197 GL_LoadFunction(handle, "glXGetProcAddressARB");
198 _this->gl_data->glXChooseVisual =
199 (XVisualInfo * (*)(Display *, int, int *))
200 X11_GL_GetProcAddress(_this, "glXChooseVisual");
201 _this->gl_data->glXCreateContext =
202 (GLXContext(*)(Display *, XVisualInfo *, GLXContext, int))
203 X11_GL_GetProcAddress(_this, "glXCreateContext");
204 _this->gl_data->glXDestroyContext =
205 (void (*)(Display *, GLXContext))
206 X11_GL_GetProcAddress(_this, "glXDestroyContext");
207 _this->gl_data->glXMakeCurrent =
208 (int (*)(Display *, GLXDrawable, GLXContext))
209 X11_GL_GetProcAddress(_this, "glXMakeCurrent");
210 _this->gl_data->glXSwapBuffers =
211 (void (*)(Display *, GLXDrawable))
212 X11_GL_GetProcAddress(_this, "glXSwapBuffers");
213 _this->gl_data->glXQueryDrawable =
214 (void (*)(Display*,GLXDrawable,int,unsigned int*))
215 X11_GL_GetProcAddress(_this, "glXQueryDrawable");
216
217 if (!_this->gl_data->glXQueryExtension ||
218 !_this->gl_data->glXChooseVisual ||
219 !_this->gl_data->glXCreateContext ||
220 !_this->gl_data->glXDestroyContext ||
221 !_this->gl_data->glXMakeCurrent ||
222 !_this->gl_data->glXSwapBuffers) {
223 return SDL_SetError("Could not retrieve OpenGL functions");
224 }
225
226 display = ((SDL_VideoData *) _this->driverdata)->display;
227 if (!_this->gl_data->glXQueryExtension(display, &_this->gl_data->errorBase, &_this->gl_data->eventBase)) {
228 return SDL_SetError("GLX is not supported");
229 }
230
231 /* Initialize extensions */
232 /* See lengthy comment about the inc/dec in
233 ../windows/SDL_windowsopengl.c. */
235 X11_GL_InitExtensions(_this);
237
238 /* If we need a GL ES context and there's no
239 * GLX_EXT_create_context_es2_profile extension, switch over to X11_GLES functions
240 */
242 X11_GL_UseEGL(_this) ) {
243#if SDL_VIDEO_OPENGL_EGL
244 X11_GL_UnloadLibrary(_this);
245 /* Better avoid conflicts! */
246 if (_this->gl_config.dll_handle != NULL ) {
247 GL_UnloadObject(_this->gl_config.dll_handle);
249 }
250 _this->GL_LoadLibrary = X11_GLES_LoadLibrary;
251 _this->GL_GetProcAddress = X11_GLES_GetProcAddress;
252 _this->GL_UnloadLibrary = X11_GLES_UnloadLibrary;
253 _this->GL_CreateContext = X11_GLES_CreateContext;
254 _this->GL_MakeCurrent = X11_GLES_MakeCurrent;
255 _this->GL_SetSwapInterval = X11_GLES_SetSwapInterval;
256 _this->GL_GetSwapInterval = X11_GLES_GetSwapInterval;
257 _this->GL_SwapWindow = X11_GLES_SwapWindow;
258 _this->GL_DeleteContext = X11_GLES_DeleteContext;
259 return X11_GLES_LoadLibrary(_this, NULL);
260#else
261 return SDL_SetError("SDL not configured with EGL support");
262#endif
263 }
264
265 return 0;
266}
267
268void *
269X11_GL_GetProcAddress(_THIS, const char *proc)
270{
271 if (_this->gl_data->glXGetProcAddress) {
272 return _this->gl_data->glXGetProcAddress((const GLubyte *) proc);
273 }
274 return GL_LoadFunction(_this->gl_config.dll_handle, proc);
275}
276
277void
278X11_GL_UnloadLibrary(_THIS)
279{
280 /* Don't actually unload the library, since it may have registered
281 * X11 shutdown hooks, per the notes at:
282 * http://dri.sourceforge.net/doc/DRIuserguide.html
283 */
284#if 0
285 GL_UnloadObject(_this->gl_config.dll_handle);
287#endif
288
289 /* Free OpenGL memory */
291 _this->gl_data = NULL;
292}
293
294static SDL_bool
295HasExtension(const char *extension, const char *extensions)
296{
297 const char *start;
298 const char *where, *terminator;
299
300 if (!extensions)
301 return SDL_FALSE;
302
303 /* Extension names should not have spaces. */
304 where = SDL_strchr(extension, ' ');
305 if (where || *extension == '\0')
306 return SDL_FALSE;
307
308 /* It takes a bit of care to be fool-proof about parsing the
309 * OpenGL extensions string. Don't be fooled by sub-strings,
310 * etc. */
311
312 start = extensions;
313
314 for (;;) {
315 where = SDL_strstr(start, extension);
316 if (!where)
317 break;
318
319 terminator = where + SDL_strlen(extension);
320 if (where == start || *(where - 1) == ' ')
321 if (*terminator == ' ' || *terminator == '\0')
322 return SDL_TRUE;
323
324 start = terminator;
325 }
326 return SDL_FALSE;
327}
328
329static void
330X11_GL_InitExtensions(_THIS)
331{
332 Display *display = ((SDL_VideoData *) _this->driverdata)->display;
333 const int screen = DefaultScreen(display);
334 XVisualInfo *vinfo = NULL;
335 Window w = 0;
336 GLXContext prev_ctx = 0;
337 GLXDrawable prev_drawable = 0;
338 GLXContext context = 0;
339 const char *(*glXQueryExtensionsStringFunc) (Display *, int);
340 const char *extensions;
341
342 vinfo = X11_GL_GetVisual(_this, display, screen);
343 if (vinfo) {
344 GLXContext (*glXGetCurrentContextFunc) (void) =
345 (GLXContext(*)(void))
346 X11_GL_GetProcAddress(_this, "glXGetCurrentContext");
347
348 GLXDrawable (*glXGetCurrentDrawableFunc) (void) =
349 (GLXDrawable(*)(void))
350 X11_GL_GetProcAddress(_this, "glXGetCurrentDrawable");
351
352 if (glXGetCurrentContextFunc && glXGetCurrentDrawableFunc) {
353 XSetWindowAttributes xattr;
354 prev_ctx = glXGetCurrentContextFunc();
355 prev_drawable = glXGetCurrentDrawableFunc();
356
357 xattr.background_pixel = 0;
358 xattr.border_pixel = 0;
359 xattr.colormap =
360 X11_XCreateColormap(display, RootWindow(display, screen),
361 vinfo->visual, AllocNone);
362 w = X11_XCreateWindow(display, RootWindow(display, screen), 0, 0,
363 32, 32, 0, vinfo->depth, InputOutput, vinfo->visual,
364 (CWBackPixel | CWBorderPixel | CWColormap), &xattr);
365
366 context = _this->gl_data->glXCreateContext(display, vinfo,
367 NULL, True);
368 if (context) {
369 _this->gl_data->glXMakeCurrent(display, w, context);
370 }
371 }
372
373 X11_XFree(vinfo);
374 }
375
376 glXQueryExtensionsStringFunc =
377 (const char *(*)(Display *, int)) X11_GL_GetProcAddress(_this,
378 "glXQueryExtensionsString");
379 if (glXQueryExtensionsStringFunc) {
380 extensions = glXQueryExtensionsStringFunc(display, screen);
381 } else {
382 extensions = NULL;
383 }
384
385 /* Check for GLX_EXT_swap_control(_tear) */
386 _this->gl_data->HAS_GLX_EXT_swap_control_tear = SDL_FALSE;
387 if (HasExtension("GLX_EXT_swap_control", extensions)) {
388 _this->gl_data->glXSwapIntervalEXT =
389 (void (*)(Display*,GLXDrawable,int))
390 X11_GL_GetProcAddress(_this, "glXSwapIntervalEXT");
391 if (HasExtension("GLX_EXT_swap_control_tear", extensions)) {
392 _this->gl_data->HAS_GLX_EXT_swap_control_tear = SDL_TRUE;
393 }
394 }
395
396 /* Check for GLX_MESA_swap_control */
397 if (HasExtension("GLX_MESA_swap_control", extensions)) {
398 _this->gl_data->glXSwapIntervalMESA =
399 (int(*)(int)) X11_GL_GetProcAddress(_this, "glXSwapIntervalMESA");
400 _this->gl_data->glXGetSwapIntervalMESA =
401 (int(*)(void)) X11_GL_GetProcAddress(_this,
402 "glXGetSwapIntervalMESA");
403 }
404
405 /* Check for GLX_SGI_swap_control */
406 if (HasExtension("GLX_SGI_swap_control", extensions)) {
407 _this->gl_data->glXSwapIntervalSGI =
408 (int (*)(int)) X11_GL_GetProcAddress(_this, "glXSwapIntervalSGI");
409 }
410
411 /* Check for GLX_ARB_create_context */
412 if (HasExtension("GLX_ARB_create_context", extensions)) {
413 _this->gl_data->glXCreateContextAttribsARB =
414 (GLXContext (*)(Display*,GLXFBConfig,GLXContext,Bool,const int *))
415 X11_GL_GetProcAddress(_this, "glXCreateContextAttribsARB");
416 _this->gl_data->glXChooseFBConfig =
417 (GLXFBConfig *(*)(Display *, int, const int *, int *))
418 X11_GL_GetProcAddress(_this, "glXChooseFBConfig");
419 }
420
421 /* Check for GLX_EXT_visual_rating */
422 if (HasExtension("GLX_EXT_visual_rating", extensions)) {
423 _this->gl_data->HAS_GLX_EXT_visual_rating = SDL_TRUE;
424 }
425
426 /* Check for GLX_EXT_visual_info */
427 if (HasExtension("GLX_EXT_visual_info", extensions)) {
428 _this->gl_data->HAS_GLX_EXT_visual_info = SDL_TRUE;
429 }
430
431 /* Check for GLX_EXT_create_context_es2_profile */
432 if (HasExtension("GLX_EXT_create_context_es2_profile", extensions)) {
433 /* this wants to call glGetString(), so it needs a context. */
434 /* !!! FIXME: it would be nice not to make a context here though! */
435 if (context) {
437 &_this->gl_data->es_profile_max_supported_version.major,
438 &_this->gl_data->es_profile_max_supported_version.minor
439 );
440 }
441 }
442
443 /* Check for GLX_ARB_context_flush_control */
444 if (HasExtension("GLX_ARB_context_flush_control", extensions)) {
445 _this->gl_data->HAS_GLX_ARB_context_flush_control = SDL_TRUE;
446 }
447
448 /* Check for GLX_ARB_create_context_robustness */
449 if (HasExtension("GLX_ARB_create_context_robustness", extensions)) {
450 _this->gl_data->HAS_GLX_ARB_create_context_robustness = SDL_TRUE;
451 }
452
453 /* Check for GLX_ARB_create_context_no_error */
454 if (HasExtension("GLX_ARB_create_context_no_error", extensions)) {
455 _this->gl_data->HAS_GLX_ARB_create_context_no_error = SDL_TRUE;
456 }
457
458 if (context) {
459 _this->gl_data->glXMakeCurrent(display, None, NULL);
460 _this->gl_data->glXDestroyContext(display, context);
461 if (prev_ctx && prev_drawable) {
462 _this->gl_data->glXMakeCurrent(display, prev_drawable, prev_ctx);
463 }
464 }
465
466 if (w) {
467 X11_XDestroyWindow(display, w);
468 }
470}
471
472/* glXChooseVisual and glXChooseFBConfig have some small differences in
473 * the attribute encoding, it can be chosen with the for_FBConfig parameter.
474 * Some targets fail if you use GLX_X_VISUAL_TYPE_EXT/GLX_DIRECT_COLOR_EXT,
475 * so it gets specified last if used and is pointed to by *_pvistypeattr.
476 * In case of failure, if that pointer is not NULL, set that pointer to None
477 * and try again.
478 */
479static int
480X11_GL_GetAttributes(_THIS, Display * display, int screen, int * attribs, int size, Bool for_FBConfig, int **_pvistypeattr)
481{
482 int i = 0;
483 const int MAX_ATTRIBUTES = 64;
484 int *pvistypeattr = NULL;
485
486 /* assert buffer is large enough to hold all SDL attributes. */
487 SDL_assert(size >= MAX_ATTRIBUTES);
488
489 /* Setup our GLX attributes according to the gl_config. */
490 if( for_FBConfig ) {
491 attribs[i++] = GLX_RENDER_TYPE;
492 attribs[i++] = GLX_RGBA_BIT;
493 } else {
494 attribs[i++] = GLX_RGBA;
495 }
496 attribs[i++] = GLX_RED_SIZE;
498 attribs[i++] = GLX_GREEN_SIZE;
500 attribs[i++] = GLX_BLUE_SIZE;
502
504 attribs[i++] = GLX_ALPHA_SIZE;
506 }
507
509 attribs[i++] = GLX_DOUBLEBUFFER;
510 if( for_FBConfig ) {
511 attribs[i++] = True;
512 }
513 }
514
515 attribs[i++] = GLX_DEPTH_SIZE;
517
519 attribs[i++] = GLX_STENCIL_SIZE;
521 }
522
524 attribs[i++] = GLX_ACCUM_RED_SIZE;
526 }
527
529 attribs[i++] = GLX_ACCUM_GREEN_SIZE;
531 }
532
534 attribs[i++] = GLX_ACCUM_BLUE_SIZE;
536 }
537
539 attribs[i++] = GLX_ACCUM_ALPHA_SIZE;
541 }
542
543 if (_this->gl_config.stereo) {
544 attribs[i++] = GLX_STEREO;
545 if( for_FBConfig ) {
546 attribs[i++] = True;
547 }
548 }
549
551 attribs[i++] = GLX_SAMPLE_BUFFERS_ARB;
553 }
554
556 attribs[i++] = GLX_SAMPLES_ARB;
558 }
559
561 attribs[i++] = GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB;
562 attribs[i++] = True; /* always needed, for_FBConfig or not! */
563 }
564
565 if (_this->gl_config.accelerated >= 0 &&
566 _this->gl_data->HAS_GLX_EXT_visual_rating) {
567 attribs[i++] = GLX_VISUAL_CAVEAT_EXT;
568 attribs[i++] = _this->gl_config.accelerated ? GLX_NONE_EXT :
569 GLX_SLOW_VISUAL_EXT;
570 }
571
572 /* If we're supposed to use DirectColor visuals, and we've got the
573 EXT_visual_info extension, then add GLX_X_VISUAL_TYPE_EXT. */
575 _this->gl_data->HAS_GLX_EXT_visual_info) {
576 pvistypeattr = &attribs[i];
577 attribs[i++] = GLX_X_VISUAL_TYPE_EXT;
578 attribs[i++] = GLX_DIRECT_COLOR_EXT;
579 }
580
581 attribs[i++] = None;
582
583 SDL_assert(i <= MAX_ATTRIBUTES);
584
585 if (_pvistypeattr) {
586 *_pvistypeattr = pvistypeattr;
587 }
588
589 return i;
590}
591
592XVisualInfo *
593X11_GL_GetVisual(_THIS, Display * display, int screen)
594{
595 /* 64 seems nice. */
596 int attribs[64];
597 XVisualInfo *vinfo;
598 int *pvistypeattr = NULL;
599
600 if (!_this->gl_data) {
601 /* The OpenGL library wasn't loaded, SDL_GetError() should have info */
602 return NULL;
603 }
604
605 X11_GL_GetAttributes(_this, display, screen, attribs, 64, SDL_FALSE, &pvistypeattr);
606 vinfo = _this->gl_data->glXChooseVisual(display, screen, attribs);
607
608 if (!vinfo && (pvistypeattr != NULL)) {
609 *pvistypeattr = None;
610 vinfo = _this->gl_data->glXChooseVisual(display, screen, attribs);
611 }
612
613 if (!vinfo) {
614 SDL_SetError("Couldn't find matching GLX visual");
615 }
616 return vinfo;
617}
618
619static int (*handler) (Display *, XErrorEvent *) = NULL;
620static const char *errorHandlerOperation = NULL;
621static int errorBase = 0;
622static int errorCode = 0;
623static int
624X11_GL_ErrorHandler(Display * d, XErrorEvent * e)
625{
626 char *x11_error = NULL;
627 char x11_error_locale[256];
628
629 errorCode = e->error_code;
630 if (X11_XGetErrorText(d, errorCode, x11_error_locale, sizeof(x11_error_locale)) == Success)
631 {
632 x11_error = SDL_iconv_string("UTF-8", "", x11_error_locale, SDL_strlen(x11_error_locale)+1);
633 }
634
635 if (x11_error)
636 {
637 SDL_SetError("Could not %s: %s", errorHandlerOperation, x11_error);
638 SDL_free(x11_error);
639 }
640 else
641 {
642 SDL_SetError("Could not %s: %i (Base %i)", errorHandlerOperation, errorCode, errorBase);
643 }
644
645 return (0);
646}
647
649X11_GL_UseEGL(_THIS)
650{
653
655 || _this->gl_config.major_version == 1 /* No GLX extension for OpenGL ES 1.x profiles. */
656 || _this->gl_config.major_version > _this->gl_data->es_profile_max_supported_version.major
657 || (_this->gl_config.major_version == _this->gl_data->es_profile_max_supported_version.major
658 && _this->gl_config.minor_version > _this->gl_data->es_profile_max_supported_version.minor));
659}
660
662X11_GL_CreateContext(_THIS, SDL_Window * window)
663{
664 SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
665 Display *display = data->videodata->display;
666 int screen =
668 XWindowAttributes xattr;
669 XVisualInfo v, *vinfo;
670 int n;
671 GLXContext context = NULL, share_context;
672
674 share_context = (GLXContext)SDL_GL_GetCurrentContext();
675 } else {
676 share_context = NULL;
677 }
678
679 /* We do this to create a clean separation between X and GLX errors. */
680 X11_XSync(display, False);
681 errorHandlerOperation = "create GL context";
682 errorBase = _this->gl_data->errorBase;
683 errorCode = Success;
684 handler = X11_XSetErrorHandler(X11_GL_ErrorHandler);
685 X11_XGetWindowAttributes(display, data->xwindow, &xattr);
686 v.screen = screen;
687 v.visualid = X11_XVisualIDFromVisual(xattr.visual);
688 vinfo = X11_XGetVisualInfo(display, VisualScreenMask | VisualIDMask, &v, &n);
689 if (vinfo) {
690 if (_this->gl_config.major_version < 3 &&
692 _this->gl_config.flags == 0) {
693 /* Create legacy context */
694 context =
695 _this->gl_data->glXCreateContext(display, vinfo, share_context, True);
696 } else {
697 /* max 14 attributes plus terminator */
698 int attribs[15] = {
699 GLX_CONTEXT_MAJOR_VERSION_ARB,
701 GLX_CONTEXT_MINOR_VERSION_ARB,
703 0
704 };
705 int iattr = 4;
706
707 /* SDL profile bits match GLX profile bits */
708 if( _this->gl_config.profile_mask != 0 ) {
709 attribs[iattr++] = GLX_CONTEXT_PROFILE_MASK_ARB;
711 }
712
713 /* SDL flags match GLX flags */
714 if( _this->gl_config.flags != 0 ) {
715 attribs[iattr++] = GLX_CONTEXT_FLAGS_ARB;
716 attribs[iattr++] = _this->gl_config.flags;
717 }
718
719 /* only set if glx extension is available */
720 if( _this->gl_data->HAS_GLX_ARB_context_flush_control ) {
721 attribs[iattr++] = GLX_CONTEXT_RELEASE_BEHAVIOR_ARB;
722 attribs[iattr++] =
724 GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB :
725 GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB;
726 }
727
728 /* only set if glx extension is available */
729 if( _this->gl_data->HAS_GLX_ARB_create_context_robustness ) {
730 attribs[iattr++] = GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB;
731 attribs[iattr++] =
733 GLX_LOSE_CONTEXT_ON_RESET_ARB :
734 GLX_NO_RESET_NOTIFICATION_ARB;
735 }
736
737 /* only set if glx extension is available */
738 if( _this->gl_data->HAS_GLX_ARB_create_context_no_error ) {
739 attribs[iattr++] = GLX_CONTEXT_OPENGL_NO_ERROR_ARB;
740 attribs[iattr++] = _this->gl_config.no_error;
741 }
742
743 attribs[iattr++] = 0;
744
745 /* Get a pointer to the context creation function for GL 3.0 */
746 if (!_this->gl_data->glXCreateContextAttribsARB) {
747 SDL_SetError("OpenGL 3.0 and later are not supported by this system");
748 } else {
749 int glxAttribs[64];
750
751 /* Create a GL 3.x context */
752 GLXFBConfig *framebuffer_config = NULL;
753 int fbcount = 0;
754 int *pvistypeattr = NULL;
755
756 X11_GL_GetAttributes(_this,display,screen,glxAttribs,64,SDL_TRUE,&pvistypeattr);
757
758 if (_this->gl_data->glXChooseFBConfig) {
759 framebuffer_config = _this->gl_data->glXChooseFBConfig(display,
760 DefaultScreen(display), glxAttribs,
761 &fbcount);
762
763 if (!framebuffer_config && (pvistypeattr != NULL)) {
764 *pvistypeattr = None;
765 framebuffer_config = _this->gl_data->glXChooseFBConfig(display,
766 DefaultScreen(display), glxAttribs,
767 &fbcount);
768 }
769
770 if (framebuffer_config) {
771 context = _this->gl_data->glXCreateContextAttribsARB(display,
772 framebuffer_config[0],
773 share_context, True, attribs);
774 X11_XFree(framebuffer_config);
775 }
776 }
777 }
778 }
779 X11_XFree(vinfo);
780 }
781 X11_XSync(display, False);
782 X11_XSetErrorHandler(handler);
783
784 if (!context) {
785 if (errorCode == Success) {
786 SDL_SetError("Could not create GL context");
787 }
788 return NULL;
789 }
790
791 if (X11_GL_MakeCurrent(_this, window, context) < 0) {
792 X11_GL_DeleteContext(_this, context);
793 return NULL;
794 }
795
796 return context;
797}
798
799int
800X11_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
801{
802 Display *display = ((SDL_VideoData *) _this->driverdata)->display;
803 Window drawable =
804 (context ? ((SDL_WindowData *) window->driverdata)->xwindow : None);
805 GLXContext glx_context = (GLXContext) context;
806 int rc;
807
808 if (!_this->gl_data) {
809 return SDL_SetError("OpenGL not initialized");
810 }
811
812 /* We do this to create a clean separation between X and GLX errors. */
813 X11_XSync(display, False);
814 errorHandlerOperation = "make GL context current";
815 errorBase = _this->gl_data->errorBase;
816 errorCode = Success;
817 handler = X11_XSetErrorHandler(X11_GL_ErrorHandler);
818 rc = _this->gl_data->glXMakeCurrent(display, drawable, glx_context);
819 X11_XSetErrorHandler(handler);
820
821 if (errorCode != Success) { /* uhoh, an X error was thrown! */
822 return -1; /* the error handler called SDL_SetError() already. */
823 } else if (!rc) { /* glXMakeCurrent() failed without throwing an X error */
824 return SDL_SetError("Unable to make GL context current");
825 }
826
827 return 0;
828}
829
830/*
831 0 is a valid argument to glXSwapInterval(MESA|EXT) and setting it to 0
832 will undo the effect of a previous call with a value that is greater
833 than zero (or at least that is what the docs say). OTOH, 0 is an invalid
834 argument to glXSwapIntervalSGI and it returns an error if you call it
835 with 0 as an argument.
836*/
837
838static int swapinterval = 0;
839int
840X11_GL_SetSwapInterval(_THIS, int interval)
841{
842 int status = -1;
843
844 if ((interval < 0) && (!_this->gl_data->HAS_GLX_EXT_swap_control_tear)) {
845 SDL_SetError("Negative swap interval unsupported in this GL");
846 } else if (_this->gl_data->glXSwapIntervalEXT) {
847 Display *display = ((SDL_VideoData *) _this->driverdata)->display;
848 const SDL_WindowData *windowdata = (SDL_WindowData *)
849 SDL_GL_GetCurrentWindow()->driverdata;
850
851 Window drawable = windowdata->xwindow;
852
853 /*
854 * This is a workaround for a bug in NVIDIA drivers. Bug has been reported
855 * and will be fixed in a future release (probably 319.xx).
856 *
857 * There's a bug where glXSetSwapIntervalEXT ignores updates because
858 * it has the wrong value cached. To work around it, we just run a no-op
859 * update to the current value.
860 */
861 int currentInterval = X11_GL_GetSwapInterval(_this);
862 _this->gl_data->glXSwapIntervalEXT(display, drawable, currentInterval);
863 _this->gl_data->glXSwapIntervalEXT(display, drawable, interval);
864
865 status = 0;
866 swapinterval = interval;
867 } else if (_this->gl_data->glXSwapIntervalMESA) {
868 status = _this->gl_data->glXSwapIntervalMESA(interval);
869 if (status != 0) {
870 SDL_SetError("glXSwapIntervalMESA failed");
871 } else {
872 swapinterval = interval;
873 }
874 } else if (_this->gl_data->glXSwapIntervalSGI) {
875 status = _this->gl_data->glXSwapIntervalSGI(interval);
876 if (status != 0) {
877 SDL_SetError("glXSwapIntervalSGI failed");
878 } else {
879 swapinterval = interval;
880 }
881 } else {
883 }
884 return status;
885}
886
887int
888X11_GL_GetSwapInterval(_THIS)
889{
890 if (_this->gl_data->glXSwapIntervalEXT) {
891 Display *display = ((SDL_VideoData *) _this->driverdata)->display;
892 const SDL_WindowData *windowdata = (SDL_WindowData *)
893 SDL_GL_GetCurrentWindow()->driverdata;
894 Window drawable = windowdata->xwindow;
895 unsigned int allow_late_swap_tearing = 0;
896 unsigned int interval = 0;
897
898 if (_this->gl_data->HAS_GLX_EXT_swap_control_tear) {
899 _this->gl_data->glXQueryDrawable(display, drawable,
900 GLX_LATE_SWAPS_TEAR_EXT,
901 &allow_late_swap_tearing);
902 }
903
904 _this->gl_data->glXQueryDrawable(display, drawable,
905 GLX_SWAP_INTERVAL_EXT, &interval);
906
907 if ((allow_late_swap_tearing) && (interval > 0)) {
908 return -((int) interval);
909 }
910
911 return (int) interval;
912 } else if (_this->gl_data->glXGetSwapIntervalMESA) {
913 return _this->gl_data->glXGetSwapIntervalMESA();
914 } else {
915 return swapinterval;
916 }
917}
918
919int
920X11_GL_SwapWindow(_THIS, SDL_Window * window)
921{
922 SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
923 Display *display = data->videodata->display;
924
925 _this->gl_data->glXSwapBuffers(display, data->xwindow);
926 return 0;
927}
928
929void
930X11_GL_DeleteContext(_THIS, SDL_GLContext context)
931{
932 Display *display = ((SDL_VideoData *) _this->driverdata)->display;
933 GLXContext glx_context = (GLXContext) context;
934
935 if (!_this->gl_data) {
936 return;
937 }
938 _this->gl_data->glXDestroyContext(display, glx_context);
939 X11_XSync(display, False);
940}
941
942#endif /* SDL_VIDEO_OPENGL_GLX */
943
944#endif /* SDL_VIDEO_DRIVER_X11 */
945
946/* vi: set ts=4 sw=4 expandtab: */
#define _THIS
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define SDL_SetError
#define SDL_strchr
#define SDL_GL_GetCurrentWindow
#define SDL_getenv
#define SDL_strlen
#define SDL_strlcpy
#define SDL_free
#define SDL_iconv_string
#define SDL_strstr
#define SDL_GetHintBoolean
#define SDL_calloc
#define SDL_GL_GetCurrentContext
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
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
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 SDL_OutOfMemory()
Definition: SDL_error.h:52
#define SDL_Unsupported()
Definition: SDL_error.h:53
#define SDL_HINT_OPENGL_ES_DRIVER
A variable controlling what driver to use for OpenGL ES contexts.
Definition: SDL_hints.h:1024
unsigned char GLubyte
Definition: SDL_opengl.h:183
const GLdouble * v
Definition: SDL_opengl.h:2064
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
GLuint start
Definition: SDL_opengl.h:1571
GLsizeiptr size
GLsizei const GLchar *const * path
GLdouble n
const GLint * attribs
GLubyte GLubyte GLubyte GLubyte w
SDL_bool
Definition: SDL_stdinc.h:162
@ SDL_TRUE
Definition: SDL_stdinc.h:164
@ SDL_FALSE
Definition: SDL_stdinc.h:163
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
Definition: SDL_video.c:1089
void SDL_GL_DeduceMaxSupportedESProfile(int *major, int *minor)
Definition: SDL_video.c:3044
static SDL_VideoDevice * _this
Definition: SDL_video.c:118
void * SDL_GLContext
An opaque handle to an OpenGL context.
Definition: SDL_video.h:193
@ SDL_GL_CONTEXT_PROFILE_ES
Definition: SDL_video.h:233
void X11_PumpEvents(_THIS)
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display dpy)
Definition: SDL_x11sym.h:44
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
SDL_bool X11_UseDirectColorVisuals(void)
#define NULL
Definition: begin_code.h:167
EGLConfig config
Definition: eglext.h:433
EGLImageKHR EGLint EGLint * handle
Definition: eglext.h:937
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
EGLenum const EGLAttribKHR * attrib_list
Definition: eglext.h:63
uint32_t swapinterval
Definition: SDL_pspgl_c.h:36
EGLDisplay display
Definition: SDL_pspgl_c.h:33
int framebuffer_srgb_capable
Definition: SDL_sysvideo.h:350
char driver_path[256]
Definition: SDL_sysvideo.h:354
void(* GL_DeleteContext)(_THIS, SDL_GLContext context)
Definition: SDL_sysvideo.h:264
int(* GL_MakeCurrent)(_THIS, SDL_Window *window, SDL_GLContext context)
Definition: SDL_sysvideo.h:259
SDL_GLContext(* GL_CreateContext)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:258
int(* GL_SetSwapInterval)(_THIS, int interval)
Definition: SDL_sysvideo.h:261
void(* GL_UnloadLibrary)(_THIS)
Definition: SDL_sysvideo.h:257
int(* GL_GetSwapInterval)(_THIS)
Definition: SDL_sysvideo.h:262
int(* GL_LoadLibrary)(_THIS, const char *path)
Definition: SDL_sysvideo.h:255
int(* GL_SwapWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:263
struct SDL_VideoDevice::@262 gl_config
void *(* GL_GetProcAddress)(_THIS, const char *proc)
Definition: SDL_sysvideo.h:256
struct SDL_GLDriverData * gl_data
Definition: SDL_sysvideo.h:382
int share_with_current_context
Definition: SDL_sysvideo.h:347
The type used to identify a window.
Definition: SDL_sysvideo.h:74
SDL_Renderer * screen
static screen_context_t context
Definition: video.c:25