21 #include "../../SDL_internal.h"
23 #if SDL_VIDEO_DRIVER_X11
31 #if SDL_VIDEO_OPENGL_GLX
37 #define DEFAULT_OPENGL "libGL.so"
38 #elif defined(__MACOSX__)
39 #define DEFAULT_OPENGL "/opt/X11/lib/libGL.1.dylib"
40 #elif defined(__QNXNTO__)
41 #define DEFAULT_OPENGL "libGL.so.3"
43 #define DEFAULT_OPENGL "libGL.so.1"
47 #define GLX_NONE_EXT 0x8000
50 #ifndef GLX_ARB_multisample
51 #define GLX_ARB_multisample
52 #define GLX_SAMPLE_BUFFERS_ARB 100000
53 #define GLX_SAMPLES_ARB 100001
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
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
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
79 typedef GLXContext(*PFNGLXCREATECONTEXTATTRIBSARBPROC) (Display *
dpy,
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
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
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
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
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
124 #ifndef GLX_EXT_swap_control
125 #define GLX_SWAP_INTERVAL_EXT 0x20F1
126 #define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2
129 #ifndef GLX_EXT_swap_control_tear
130 #define GLX_LATE_SWAPS_TEAR_EXT 0x20F3
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
140 #define OPENGL_REQUIRES_DLOPEN
141 #if defined(OPENGL_REQUIRES_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
143 #define GL_LoadObject(X) dlopen(X, (RTLD_NOW|RTLD_GLOBAL))
144 #define GL_LoadFunction dlsym
145 #define GL_UnloadObject dlclose
147 #define GL_LoadObject SDL_LoadObject
148 #define GL_LoadFunction SDL_LoadFunction
149 #define GL_UnloadObject SDL_UnloadObject
152 static void X11_GL_InitExtensions(
_THIS);
155 X11_GL_LoadLibrary(
_THIS,
const char *
path)
169 path = DEFAULT_OPENGL;
173 #if defined(OPENGL_REQUIRES_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
193 (Bool (*)(Display *,
int *,
int *))
194 GL_LoadFunction(
handle,
"glXQueryExtension");
197 GL_LoadFunction(
handle,
"glXGetProcAddressARB");
199 (XVisualInfo * (*)(Display *,
int,
int *))
200 X11_GL_GetProcAddress(
_this,
"glXChooseVisual");
202 (GLXContext(*)(Display *, XVisualInfo *, GLXContext, int))
203 X11_GL_GetProcAddress(
_this,
"glXCreateContext");
205 (
void (*)(Display *, GLXContext))
206 X11_GL_GetProcAddress(
_this,
"glXDestroyContext");
208 (int (*)(Display *, GLXDrawable, GLXContext))
209 X11_GL_GetProcAddress(
_this,
"glXMakeCurrent");
211 (
void (*)(Display *, GLXDrawable))
212 X11_GL_GetProcAddress(
_this,
"glXSwapBuffers");
214 (
void (*)(Display*,GLXDrawable,int,
unsigned int*))
215 X11_GL_GetProcAddress(
_this,
"glXQueryDrawable");
223 return SDL_SetError(
"Could not retrieve OpenGL functions");
235 X11_GL_InitExtensions(
_this);
243 X11_GL_UseEGL(
_this) ) {
244 #if SDL_VIDEO_OPENGL_EGL
245 X11_GL_UnloadLibrary(
_this);
260 return X11_GLES_LoadLibrary(
_this,
NULL);
262 return SDL_SetError(
"SDL not configured with EGL support");
270 X11_GL_GetProcAddress(
_THIS,
const char *proc)
279 X11_GL_UnloadLibrary(
_THIS)
296 HasExtension(
const char *extension,
const char *extensions)
299 const char *where, *terminator;
306 if (where || *extension ==
'\0')
321 if (where ==
start || *(where - 1) ==
' ')
322 if (*terminator ==
' ' || *terminator ==
'\0')
331 X11_GL_InitExtensions(
_THIS)
335 XVisualInfo *vinfo =
NULL;
337 GLXContext prev_ctx = 0;
338 GLXDrawable prev_drawable = 0;
340 const char *(*glXQueryExtensionsStringFunc) (Display *, int);
341 const char *extensions;
345 GLXContext (*glXGetCurrentContextFunc) (
void) =
346 (GLXContext(*)(
void))
347 X11_GL_GetProcAddress(
_this,
"glXGetCurrentContext");
349 GLXDrawable (*glXGetCurrentDrawableFunc) (
void) =
350 (GLXDrawable(*)(
void))
351 X11_GL_GetProcAddress(
_this,
"glXGetCurrentDrawable");
353 if (glXGetCurrentContextFunc && glXGetCurrentDrawableFunc) {
354 XSetWindowAttributes xattr;
355 prev_ctx = glXGetCurrentContextFunc();
356 prev_drawable = glXGetCurrentDrawableFunc();
358 xattr.background_pixel = 0;
359 xattr.border_pixel = 0;
362 vinfo->visual, AllocNone);
364 32, 32, 0, vinfo->depth, InputOutput, vinfo->visual,
365 (CWBackPixel | CWBorderPixel | CWColormap), &xattr);
377 glXQueryExtensionsStringFunc =
378 (
const char *(*)(Display *,
int)) X11_GL_GetProcAddress(
_this,
379 "glXQueryExtensionsString");
380 if (glXQueryExtensionsStringFunc) {
388 if (HasExtension(
"GLX_EXT_swap_control", extensions)) {
390 (
void (*)(Display*,GLXDrawable,int))
391 X11_GL_GetProcAddress(
_this,
"glXSwapIntervalEXT");
392 if (HasExtension(
"GLX_EXT_swap_control_tear", extensions)) {
398 if (HasExtension(
"GLX_MESA_swap_control", extensions)) {
400 (int(*)(int)) X11_GL_GetProcAddress(
_this,
"glXSwapIntervalMESA");
402 (int(*)(
void)) X11_GL_GetProcAddress(
_this,
403 "glXGetSwapIntervalMESA");
407 if (HasExtension(
"GLX_SGI_swap_control", extensions)) {
409 (int (*)(int)) X11_GL_GetProcAddress(
_this,
"glXSwapIntervalSGI");
413 if (HasExtension(
"GLX_ARB_create_context", extensions)) {
415 (GLXContext (*)(Display*,GLXFBConfig,GLXContext,Bool,
const int *))
416 X11_GL_GetProcAddress(
_this,
"glXCreateContextAttribsARB");
418 (GLXFBConfig *(*)(Display *,
int,
const int *,
int *))
419 X11_GL_GetProcAddress(
_this,
"glXChooseFBConfig");
423 if (HasExtension(
"GLX_EXT_visual_rating", extensions)) {
428 if (HasExtension(
"GLX_EXT_visual_info", extensions)) {
433 if (HasExtension(
"GLX_EXT_create_context_es2_profile", extensions)) {
438 &
_this->
gl_data->es_profile_max_supported_version.major,
445 if (HasExtension(
"GLX_ARB_context_flush_control", extensions)) {
450 if (HasExtension(
"GLX_ARB_create_context_robustness", extensions)) {
455 if (HasExtension(
"GLX_ARB_create_context_no_error", extensions)) {
462 if (prev_ctx && prev_drawable) {
484 const int MAX_ATTRIBUTES = 64;
485 int *pvistypeattr =
NULL;
530 attribs[
i++] = GLX_ACCUM_GREEN_SIZE;
540 attribs[
i++] = GLX_ACCUM_ALPHA_SIZE;
552 attribs[
i++] = GLX_SAMPLE_BUFFERS_ARB;
562 attribs[
i++] = GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB;
568 attribs[
i++] = GLX_VISUAL_CAVEAT_EXT;
578 attribs[
i++] = GLX_X_VISUAL_TYPE_EXT;
579 attribs[
i++] = GLX_DIRECT_COLOR_EXT;
587 *_pvistypeattr = pvistypeattr;
599 int *pvistypeattr =
NULL;
609 if (!vinfo && (pvistypeattr !=
NULL)) {
610 *pvistypeattr = None;
620 static int (*handler) (Display *, XErrorEvent *) =
NULL;
621 static const char *errorHandlerOperation =
NULL;
622 static int errorBase = 0;
623 static int errorCode = 0;
625 X11_GL_ErrorHandler(Display *
d, XErrorEvent *
e)
627 char *x11_error =
NULL;
628 char x11_error_locale[256];
630 errorCode =
e->error_code;
631 if (X11_XGetErrorText(
d, errorCode, x11_error_locale,
sizeof(x11_error_locale)) == Success)
638 SDL_SetError(
"Could not %s: %s", errorHandlerOperation, x11_error);
643 SDL_SetError(
"Could not %s: %i (Base %i)", errorHandlerOperation, errorCode, errorBase);
674 XWindowAttributes xattr;
675 XVisualInfo
v, *vinfo;
682 share_context =
NULL;
687 errorHandlerOperation =
"create GL context";
690 handler = X11_XSetErrorHandler(X11_GL_ErrorHandler);
691 X11_XGetWindowAttributes(
display,
data->xwindow, &xattr);
693 v.visualid = X11_XVisualIDFromVisual(xattr.visual);
694 vinfo = X11_XGetVisualInfo(
display, VisualScreenMask | VisualIDMask, &
v, &
n);
705 GLX_CONTEXT_MAJOR_VERSION_ARB,
707 GLX_CONTEXT_MINOR_VERSION_ARB,
715 attribs[iattr++] = GLX_CONTEXT_PROFILE_MASK_ARB;
721 attribs[iattr++] = GLX_CONTEXT_FLAGS_ARB;
726 if(
_this->
gl_data->HAS_GLX_ARB_context_flush_control ) {
727 attribs[iattr++] = GLX_CONTEXT_RELEASE_BEHAVIOR_ARB;
730 GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB :
731 GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB;
735 if(
_this->
gl_data->HAS_GLX_ARB_create_context_robustness ) {
736 attribs[iattr++] = GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB;
739 GLX_LOSE_CONTEXT_ON_RESET_ARB :
740 GLX_NO_RESET_NOTIFICATION_ARB;
744 if(
_this->
gl_data->HAS_GLX_ARB_create_context_no_error ) {
745 attribs[iattr++] = GLX_CONTEXT_OPENGL_NO_ERROR_ARB;
753 SDL_SetError(
"OpenGL 3.0 and later are not supported by this system");
758 GLXFBConfig *framebuffer_config =
NULL;
760 int *pvistypeattr =
NULL;
766 DefaultScreen(
display), glxAttribs,
769 if (!framebuffer_config && (pvistypeattr !=
NULL)) {
770 *pvistypeattr = None;
772 DefaultScreen(
display), glxAttribs,
776 if (framebuffer_config) {
778 framebuffer_config[0],
780 X11_XFree(framebuffer_config);
788 X11_XSetErrorHandler(handler);
791 if (errorCode == Success) {
811 GLXContext glx_context = (GLXContext)
context;
820 errorHandlerOperation =
"make GL context current";
823 handler = X11_XSetErrorHandler(X11_GL_ErrorHandler);
825 X11_XSetErrorHandler(handler);
827 if (errorCode != Success) {
830 return SDL_SetError(
"Unable to make GL context current");
846 X11_GL_SetSwapInterval(
_THIS,
int interval)
850 if ((interval < 0) && (!
_this->
gl_data->HAS_GLX_EXT_swap_control_tear)) {
851 SDL_SetError(
"Negative swap interval unsupported in this GL");
857 Window drawable = windowdata->
xwindow;
867 int currentInterval = X11_GL_GetSwapInterval(
_this);
894 X11_GL_GetSwapInterval(
_THIS)
900 Window drawable = windowdata->
xwindow;
901 unsigned int allow_late_swap_tearing = 0;
902 unsigned int interval = 0;
906 GLX_LATE_SWAPS_TEAR_EXT,
907 &allow_late_swap_tearing);
911 GLX_SWAP_INTERVAL_EXT, &interval);
913 if ((allow_late_swap_tearing) && (interval > 0)) {
914 return -((int) interval);
917 return (
int) interval;
939 GLXContext glx_context = (GLXContext)
context;