SDL_x11opengl.c
Go to the documentation of this file.
/*
Simple DirectMedia Layer
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_DRIVER_X11
#include "SDL_x11video.h"
#include "SDL_assert.h"
/* GLX implementation of SDL OpenGL support */
#if SDL_VIDEO_OPENGL_GLX
#include "SDL_loadso.h"
#include "SDL_x11opengles.h"
#if defined(__IRIX__)
/* IRIX doesn't have a GL library versioning system */
#define DEFAULT_OPENGL "libGL.so"
#elif defined(__MACOSX__)
#define DEFAULT_OPENGL "/usr/X11R6/lib/libGL.1.dylib"
#elif defined(__QNXNTO__)
#define DEFAULT_OPENGL "libGL.so.3"
#else
#define DEFAULT_OPENGL "libGL.so.1"
#endif
#ifndef GLX_NONE_EXT
#define GLX_NONE_EXT 0x8000
#endif
#ifndef GLX_ARB_multisample
#define GLX_ARB_multisample
#define GLX_SAMPLE_BUFFERS_ARB 100000
#define GLX_SAMPLES_ARB 100001
#endif
#ifndef GLX_EXT_visual_rating
#define GLX_EXT_visual_rating
#define GLX_VISUAL_CAVEAT_EXT 0x20
#define GLX_NONE_EXT 0x8000
#define GLX_SLOW_VISUAL_EXT 0x8001
#define GLX_NON_CONFORMANT_VISUAL_EXT 0x800D
#endif
#ifndef GLX_EXT_visual_info
#define GLX_EXT_visual_info
#define GLX_X_VISUAL_TYPE_EXT 0x22
#define GLX_DIRECT_COLOR_EXT 0x8003
#endif
#ifndef GLX_ARB_create_context
#define GLX_ARB_create_context
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
#define GLX_CONTEXT_FLAGS_ARB 0x2094
#define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001
#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
/* Typedef for the GL 3.0 context creation function */
typedef GLXContext(*PFNGLXCREATECONTEXTATTRIBSARBPROC) (Display * dpy,
GLXFBConfig config,
GLXContext
share_context,
Bool direct,
const int
*attrib_list);
#endif
#ifndef GLX_ARB_create_context_profile
#define GLX_ARB_create_context_profile
#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
#endif
#ifndef GLX_ARB_create_context_robustness
#define GLX_ARB_create_context_robustness
#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
#define GLX_NO_RESET_NOTIFICATION_ARB 0x8261
#define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252
#endif
#ifndef GLX_EXT_create_context_es2_profile
#define GLX_EXT_create_context_es2_profile
#ifndef GLX_CONTEXT_ES2_PROFILE_BIT_EXT
#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000002
#endif
#endif
#ifndef GLX_ARB_framebuffer_sRGB
#define GLX_ARB_framebuffer_sRGB
#ifndef GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB
#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2
#endif
#endif
#ifndef GLX_EXT_swap_control
#define GLX_SWAP_INTERVAL_EXT 0x20F1
#define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2
#endif
#ifndef GLX_EXT_swap_control_tear
#define GLX_LATE_SWAPS_TEAR_EXT 0x20F3
#endif
#ifndef GLX_ARB_context_flush_control
#define GLX_ARB_context_flush_control
#define GLX_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
#define GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0x0000
#define GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
#endif
#define OPENGL_REQUIRES_DLOPEN
#if defined(OPENGL_REQUIRES_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
#include <dlfcn.h>
#define GL_LoadObject(X) dlopen(X, (RTLD_NOW|RTLD_GLOBAL))
#define GL_LoadFunction dlsym
#define GL_UnloadObject dlclose
#else
#define GL_LoadObject SDL_LoadObject
#define GL_LoadFunction SDL_LoadFunction
#define GL_UnloadObject SDL_UnloadObject
#endif
static void X11_GL_InitExtensions(_THIS);
int
X11_GL_LoadLibrary(_THIS, const char *path)
{
Display *display;
void *handle;
if (_this->gl_data) {
return SDL_SetError("OpenGL context already created");
}
/* Load the OpenGL library */
if (path == NULL) {
path = SDL_getenv("SDL_OPENGL_LIBRARY");
}
if (path == NULL) {
path = DEFAULT_OPENGL;
}
_this->gl_config.dll_handle = GL_LoadObject(path);
if (!_this->gl_config.dll_handle) {
#if defined(OPENGL_REQUIRES_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
SDL_SetError("Failed loading %s: %s", path, dlerror());
#endif
return -1;
}
SDL_strlcpy(_this->gl_config.driver_path, path,
SDL_arraysize(_this->gl_config.driver_path));
/* Allocate OpenGL memory */
_this->gl_data =
(struct SDL_GLDriverData *) SDL_calloc(1,
sizeof(struct
SDL_GLDriverData));
if (!_this->gl_data) {
return SDL_OutOfMemory();
}
/* Load function pointers */
handle = _this->gl_config.dll_handle;
_this->gl_data->glXQueryExtension =
(Bool (*)(Display *, int *, int *))
GL_LoadFunction(handle, "glXQueryExtension");
_this->gl_data->glXGetProcAddress =
(void *(*)(const GLubyte *))
GL_LoadFunction(handle, "glXGetProcAddressARB");
_this->gl_data->glXChooseVisual =
(XVisualInfo * (*)(Display *, int, int *))
X11_GL_GetProcAddress(_this, "glXChooseVisual");
_this->gl_data->glXCreateContext =
(GLXContext(*)(Display *, XVisualInfo *, GLXContext, int))
X11_GL_GetProcAddress(_this, "glXCreateContext");
_this->gl_data->glXDestroyContext =
(void (*)(Display *, GLXContext))
X11_GL_GetProcAddress(_this, "glXDestroyContext");
_this->gl_data->glXMakeCurrent =
(int (*)(Display *, GLXDrawable, GLXContext))
X11_GL_GetProcAddress(_this, "glXMakeCurrent");
_this->gl_data->glXSwapBuffers =
(void (*)(Display *, GLXDrawable))
X11_GL_GetProcAddress(_this, "glXSwapBuffers");
_this->gl_data->glXQueryDrawable =
(void (*)(Display*,GLXDrawable,int,unsigned int*))
X11_GL_GetProcAddress(_this, "glXQueryDrawable");
if (!_this->gl_data->glXQueryExtension ||
!_this->gl_data->glXChooseVisual ||
!_this->gl_data->glXCreateContext ||
!_this->gl_data->glXDestroyContext ||
!_this->gl_data->glXMakeCurrent ||
!_this->gl_data->glXSwapBuffers) {
return SDL_SetError("Could not retrieve OpenGL functions");
}
display = ((SDL_VideoData *) _this->driverdata)->display;
if (!_this->gl_data->glXQueryExtension(display, &_this->gl_data->errorBase, &_this->gl_data->eventBase)) {
return SDL_SetError("GLX is not supported");
}
/* Initialize extensions */
X11_GL_InitExtensions(_this);
/* If we need a GL ES context and there's no
* GLX_EXT_create_context_es2_profile extension, switch over to X11_GLES functions
*/
if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES &&
! _this->gl_data->HAS_GLX_EXT_create_context_es2_profile ) {
#if SDL_VIDEO_OPENGL_EGL
X11_GL_UnloadLibrary(_this);
/* Better avoid conflicts! */
if (_this->gl_config.dll_handle != NULL ) {
GL_UnloadObject(_this->gl_config.dll_handle);
_this->gl_config.dll_handle = NULL;
}
_this->GL_LoadLibrary = X11_GLES_LoadLibrary;
_this->GL_GetProcAddress = X11_GLES_GetProcAddress;
_this->GL_UnloadLibrary = X11_GLES_UnloadLibrary;
_this->GL_CreateContext = X11_GLES_CreateContext;
_this->GL_MakeCurrent = X11_GLES_MakeCurrent;
_this->GL_SetSwapInterval = X11_GLES_SetSwapInterval;
_this->GL_GetSwapInterval = X11_GLES_GetSwapInterval;
_this->GL_SwapWindow = X11_GLES_SwapWindow;
_this->GL_DeleteContext = X11_GLES_DeleteContext;
return X11_GLES_LoadLibrary(_this, NULL);
#else
return SDL_SetError("SDL not configured with EGL support");
#endif
}
return 0;
}
void *
X11_GL_GetProcAddress(_THIS, const char *proc)
{
if (_this->gl_data->glXGetProcAddress) {
return _this->gl_data->glXGetProcAddress((const GLubyte *) proc);
}
return GL_LoadFunction(_this->gl_config.dll_handle, proc);
}
void
X11_GL_UnloadLibrary(_THIS)
{
/* Don't actually unload the library, since it may have registered
* X11 shutdown hooks, per the notes at:
* http://dri.sourceforge.net/doc/DRIuserguide.html
*/
#if 0
GL_UnloadObject(_this->gl_config.dll_handle);
_this->gl_config.dll_handle = NULL;
#endif
/* Free OpenGL memory */
SDL_free(_this->gl_data);
_this->gl_data = NULL;
}
static SDL_bool
HasExtension(const char *extension, const char *extensions)
{
const char *start;
const char *where, *terminator;
if (!extensions)
return SDL_FALSE;
/* Extension names should not have spaces. */
where = SDL_strchr(extension, ' ');
if (where || *extension == '\0')
return SDL_FALSE;
/* It takes a bit of care to be fool-proof about parsing the
* OpenGL extensions string. Don't be fooled by sub-strings,
* etc. */
start = extensions;
for (;;) {
where = SDL_strstr(start, extension);
if (!where)
break;
terminator = where + SDL_strlen(extension);
if (where == start || *(where - 1) == ' ')
if (*terminator == ' ' || *terminator == '\0')
return SDL_TRUE;
start = terminator;
}
return SDL_FALSE;
}
static void
X11_GL_InitExtensions(_THIS)
{
Display *display = ((SDL_VideoData *) _this->driverdata)->display;
const int screen = DefaultScreen(display);
const char *(*glXQueryExtensionsStringFunc) (Display *, int);
const char *extensions;
glXQueryExtensionsStringFunc =
(const char *(*)(Display *, int)) X11_GL_GetProcAddress(_this,
"glXQueryExtensionsString");
if (glXQueryExtensionsStringFunc) {
extensions = glXQueryExtensionsStringFunc(display, screen);
} else {
extensions = NULL;
}
/* Check for GLX_EXT_swap_control(_tear) */
_this->gl_data->HAS_GLX_EXT_swap_control_tear = SDL_FALSE;
if (HasExtension("GLX_EXT_swap_control", extensions)) {
_this->gl_data->glXSwapIntervalEXT =
(void (*)(Display*,GLXDrawable,int))
X11_GL_GetProcAddress(_this, "glXSwapIntervalEXT");
if (HasExtension("GLX_EXT_swap_control_tear", extensions)) {
_this->gl_data->HAS_GLX_EXT_swap_control_tear = SDL_TRUE;
}
}
/* Check for GLX_MESA_swap_control */
if (HasExtension("GLX_MESA_swap_control", extensions)) {
_this->gl_data->glXSwapIntervalMESA =
(int(*)(int)) X11_GL_GetProcAddress(_this, "glXSwapIntervalMESA");
_this->gl_data->glXGetSwapIntervalMESA =
(int(*)(void)) X11_GL_GetProcAddress(_this,
"glXGetSwapIntervalMESA");
}
/* Check for GLX_SGI_swap_control */
if (HasExtension("GLX_SGI_swap_control", extensions)) {
_this->gl_data->glXSwapIntervalSGI =
(int (*)(int)) X11_GL_GetProcAddress(_this, "glXSwapIntervalSGI");
}
/* Check for GLX_ARB_create_context */
if (HasExtension("GLX_ARB_create_context", extensions)) {
_this->gl_data->glXCreateContextAttribsARB =
(GLXContext (*)(Display*,GLXFBConfig,GLXContext,Bool,const int *))
X11_GL_GetProcAddress(_this, "glXCreateContextAttribsARB");
_this->gl_data->glXChooseFBConfig =
(GLXFBConfig *(*)(Display *, int, const int *, int *))
X11_GL_GetProcAddress(_this, "glXChooseFBConfig");
}
/* Check for GLX_EXT_visual_rating */
if (HasExtension("GLX_EXT_visual_rating", extensions)) {
_this->gl_data->HAS_GLX_EXT_visual_rating = SDL_TRUE;
}
/* Check for GLX_EXT_visual_info */
if (HasExtension("GLX_EXT_visual_info", extensions)) {
_this->gl_data->HAS_GLX_EXT_visual_info = SDL_TRUE;
}
/* Check for GLX_EXT_create_context_es2_profile */
if (HasExtension("GLX_EXT_create_context_es2_profile", extensions)) {
_this->gl_data->HAS_GLX_EXT_create_context_es2_profile = SDL_TRUE;
}
/* Check for GLX_ARB_context_flush_control */
if (HasExtension("GLX_ARB_context_flush_control", extensions)) {
_this->gl_data->HAS_GLX_ARB_context_flush_control = SDL_TRUE;
}
}
/* glXChooseVisual and glXChooseFBConfig have some small differences in
* the attribute encoding, it can be chosen with the for_FBConfig parameter.
*/
static int
X11_GL_GetAttributes(_THIS, Display * display, int screen, int * attribs, int size, Bool for_FBConfig)
{
int i = 0;
const int MAX_ATTRIBUTES = 64;
/* assert buffer is large enough to hold all SDL attributes. */
SDL_assert(size >= MAX_ATTRIBUTES);
/* Setup our GLX attributes according to the gl_config. */
if( for_FBConfig ) {
attribs[i++] = GLX_RENDER_TYPE;
attribs[i++] = GLX_RGBA_BIT;
} else {
attribs[i++] = GLX_RGBA;
}
attribs[i++] = GLX_RED_SIZE;
attribs[i++] = _this->gl_config.red_size;
attribs[i++] = GLX_GREEN_SIZE;
attribs[i++] = _this->gl_config.green_size;
attribs[i++] = GLX_BLUE_SIZE;
attribs[i++] = _this->gl_config.blue_size;
if (_this->gl_config.alpha_size) {
attribs[i++] = GLX_ALPHA_SIZE;
attribs[i++] = _this->gl_config.alpha_size;
}
if (_this->gl_config.double_buffer) {
attribs[i++] = GLX_DOUBLEBUFFER;
if( for_FBConfig ) {
attribs[i++] = True;
}
}
attribs[i++] = GLX_DEPTH_SIZE;
attribs[i++] = _this->gl_config.depth_size;
if (_this->gl_config.stencil_size) {
attribs[i++] = GLX_STENCIL_SIZE;
attribs[i++] = _this->gl_config.stencil_size;
}
if (_this->gl_config.accum_red_size) {
attribs[i++] = GLX_ACCUM_RED_SIZE;
attribs[i++] = _this->gl_config.accum_red_size;
}
if (_this->gl_config.accum_green_size) {
attribs[i++] = GLX_ACCUM_GREEN_SIZE;
attribs[i++] = _this->gl_config.accum_green_size;
}
if (_this->gl_config.accum_blue_size) {
attribs[i++] = GLX_ACCUM_BLUE_SIZE;
attribs[i++] = _this->gl_config.accum_blue_size;
}
if (_this->gl_config.accum_alpha_size) {
attribs[i++] = GLX_ACCUM_ALPHA_SIZE;
attribs[i++] = _this->gl_config.accum_alpha_size;
}
if (_this->gl_config.stereo) {
attribs[i++] = GLX_STEREO;
if( for_FBConfig ) {
attribs[i++] = True;
}
}
if (_this->gl_config.multisamplebuffers) {
attribs[i++] = GLX_SAMPLE_BUFFERS_ARB;
attribs[i++] = _this->gl_config.multisamplebuffers;
}
if (_this->gl_config.multisamplesamples) {
attribs[i++] = GLX_SAMPLES_ARB;
attribs[i++] = _this->gl_config.multisamplesamples;
}
if (_this->gl_config.framebuffer_srgb_capable) {
attribs[i++] = GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB;
attribs[i++] = True; /* always needed, for_FBConfig or not! */
}
if (_this->gl_config.accelerated >= 0 &&
_this->gl_data->HAS_GLX_EXT_visual_rating) {
attribs[i++] = GLX_VISUAL_CAVEAT_EXT;
attribs[i++] = _this->gl_config.accelerated ? GLX_NONE_EXT :
GLX_SLOW_VISUAL_EXT;
}
/* If we're supposed to use DirectColor visuals, and we've got the
EXT_visual_info extension, then add GLX_X_VISUAL_TYPE_EXT. */
if (X11_UseDirectColorVisuals() &&
_this->gl_data->HAS_GLX_EXT_visual_info) {
attribs[i++] = GLX_X_VISUAL_TYPE_EXT;
attribs[i++] = GLX_DIRECT_COLOR_EXT;
}
attribs[i++] = None;
SDL_assert(i <= MAX_ATTRIBUTES);
return i;
}
XVisualInfo *
X11_GL_GetVisual(_THIS, Display * display, int screen)
{
/* 64 seems nice. */
int attribs[64];
XVisualInfo *vinfo;
if (!_this->gl_data) {
/* The OpenGL library wasn't loaded, SDL_GetError() should have info */
return NULL;
}
X11_GL_GetAttributes(_this, display, screen, attribs, 64, SDL_FALSE);
vinfo = _this->gl_data->glXChooseVisual(display, screen, attribs);
if (!vinfo) {
SDL_SetError("Couldn't find matching GLX visual");
}
return vinfo;
}
#ifndef GLXBadContext
#define GLXBadContext 0
#endif
#ifndef GLXBadFBConfig
#define GLXBadFBConfig 9
#endif
#ifndef GLXBadProfileARB
#define GLXBadProfileARB 13
#endif
static int (*handler) (Display *, XErrorEvent *) = NULL;
static const char *errorHandlerOperation = NULL;
static int errorBase = 0;
static int errorCode = 0;
static int
X11_GL_ErrorHandler(Display * d, XErrorEvent * e)
{
char *x11_error = NULL;
char x11_error_locale[256];
errorCode = e->error_code;
if (X11_XGetErrorText(d, errorCode, x11_error_locale, sizeof(x11_error_locale)) == Success)
{
x11_error = SDL_iconv_string("UTF-8", "", x11_error_locale, SDL_strlen(x11_error_locale)+1);
}
if (x11_error)
{
SDL_SetError("Could not %s: %s", errorHandlerOperation, x11_error);
SDL_free(x11_error);
}
else
{
SDL_SetError("Could not %s: %i (Base %i)\n", errorHandlerOperation, errorCode, errorBase);
}
return (0);
}
SDL_GLContext
X11_GL_CreateContext(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
Display *display = data->videodata->display;
int screen =
((SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata)->screen;
XWindowAttributes xattr;
XVisualInfo v, *vinfo;
int n;
GLXContext context = NULL, share_context;
if (_this->gl_config.share_with_current_context) {
share_context = (GLXContext)SDL_GL_GetCurrentContext();
} else {
share_context = NULL;
}
/* We do this to create a clean separation between X and GLX errors. */
X11_XSync(display, False);
errorHandlerOperation = "create GL context";
errorBase = _this->gl_data->errorBase;
errorCode = Success;
handler = X11_XSetErrorHandler(X11_GL_ErrorHandler);
X11_XGetWindowAttributes(display, data->xwindow, &xattr);
v.screen = screen;
v.visualid = X11_XVisualIDFromVisual(xattr.visual);
vinfo = X11_XGetVisualInfo(display, VisualScreenMask | VisualIDMask, &v, &n);
if (vinfo) {
if (_this->gl_config.major_version < 3 &&
_this->gl_config.profile_mask == 0 &&
_this->gl_config.flags == 0) {
/* Create legacy context */
context =
_this->gl_data->glXCreateContext(display, vinfo, share_context, True);
} else {
/* max 10 attributes plus terminator */
int attribs[11] = {
GLX_CONTEXT_MAJOR_VERSION_ARB,
_this->gl_config.major_version,
GLX_CONTEXT_MINOR_VERSION_ARB,
_this->gl_config.minor_version,
0
};
int iattr = 4;
/* SDL profile bits match GLX profile bits */
if( _this->gl_config.profile_mask != 0 ) {
attribs[iattr++] = GLX_CONTEXT_PROFILE_MASK_ARB;
attribs[iattr++] = _this->gl_config.profile_mask;
}
/* SDL flags match GLX flags */
if( _this->gl_config.flags != 0 ) {
attribs[iattr++] = GLX_CONTEXT_FLAGS_ARB;
attribs[iattr++] = _this->gl_config.flags;
}
/* only set if glx extension is available */
if( _this->gl_data->HAS_GLX_ARB_context_flush_control ) {
attribs[iattr++] = GLX_CONTEXT_RELEASE_BEHAVIOR_ARB;
attribs[iattr++] =
_this->gl_config.release_behavior ?
GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB :
GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB;
}
attribs[iattr++] = 0;
/* Get a pointer to the context creation function for GL 3.0 */
if (!_this->gl_data->glXCreateContextAttribsARB) {
SDL_SetError("OpenGL 3.0 and later are not supported by this system");
} else {
int glxAttribs[64];
/* Create a GL 3.x context */
GLXFBConfig *framebuffer_config = NULL;
int fbcount = 0;
X11_GL_GetAttributes(_this,display,screen,glxAttribs,64,SDL_TRUE);
if (!_this->gl_data->glXChooseFBConfig
|| !(framebuffer_config =
_this->gl_data->glXChooseFBConfig(display,
DefaultScreen(display), glxAttribs,
&fbcount))) {
SDL_SetError("No good framebuffers found. OpenGL 3.0 and later unavailable");
} else {
context = _this->gl_data->glXCreateContextAttribsARB(display,
framebuffer_config[0],
share_context, True, attribs);
}
}
}
X11_XFree(vinfo);
}
X11_XSync(display, False);
X11_XSetErrorHandler(handler);
if (!context) {
if (errorCode == Success) {
SDL_SetError("Could not create GL context");
}
return NULL;
}
if (X11_GL_MakeCurrent(_this, window, context) < 0) {
X11_GL_DeleteContext(_this, context);
return NULL;
}
return context;
}
int
X11_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
{
Display *display = ((SDL_VideoData *) _this->driverdata)->display;
Window drawable =
(context ? ((SDL_WindowData *) window->driverdata)->xwindow : None);
GLXContext glx_context = (GLXContext) context;
int rc;
if (!_this->gl_data) {
return SDL_SetError("OpenGL not initialized");
}
/* We do this to create a clean separation between X and GLX errors. */
X11_XSync(display, False);
errorHandlerOperation = "make GL context current";
errorBase = _this->gl_data->errorBase;
errorCode = Success;
handler = X11_XSetErrorHandler(X11_GL_ErrorHandler);
rc = _this->gl_data->glXMakeCurrent(display, drawable, glx_context);
X11_XSetErrorHandler(handler);
if (errorCode != Success) { /* uhoh, an X error was thrown! */
return -1; /* the error handler called SDL_SetError() already. */
} else if (!rc) { /* glxMakeCurrent() failed without throwing an X error */
return SDL_SetError("Unable to make GL context current");
}
return 0;
}
/*
0 is a valid argument to glxSwapInterval(MESA|EXT) and setting it to 0
will undo the effect of a previous call with a value that is greater
than zero (or at least that is what the docs say). OTOH, 0 is an invalid
argument to glxSwapIntervalSGI and it returns an error if you call it
with 0 as an argument.
*/
static int swapinterval = -1;
int
X11_GL_SetSwapInterval(_THIS, int interval)
{
int status = -1;
if ((interval < 0) && (!_this->gl_data->HAS_GLX_EXT_swap_control_tear)) {
SDL_SetError("Negative swap interval unsupported in this GL");
} else if (_this->gl_data->glXSwapIntervalEXT) {
Display *display = ((SDL_VideoData *) _this->driverdata)->display;
const SDL_WindowData *windowdata = (SDL_WindowData *)
SDL_GL_GetCurrentWindow()->driverdata;
Window drawable = windowdata->xwindow;
/*
* This is a workaround for a bug in NVIDIA drivers. Bug has been reported
* and will be fixed in a future release (probably 319.xx).
*
* There's a bug where glXSetSwapIntervalEXT ignores updates because
* it has the wrong value cached. To work around it, we just run a no-op
* update to the current value.
*/
int currentInterval = X11_GL_GetSwapInterval(_this);
_this->gl_data->glXSwapIntervalEXT(display, drawable, currentInterval);
_this->gl_data->glXSwapIntervalEXT(display, drawable, interval);
status = 0;
swapinterval = interval;
} else if (_this->gl_data->glXSwapIntervalMESA) {
status = _this->gl_data->glXSwapIntervalMESA(interval);
if (status != 0) {
SDL_SetError("glxSwapIntervalMESA failed");
} else {
swapinterval = interval;
}
} else if (_this->gl_data->glXSwapIntervalSGI) {
status = _this->gl_data->glXSwapIntervalSGI(interval);
if (status != 0) {
SDL_SetError("glxSwapIntervalSGI failed");
} else {
swapinterval = interval;
}
} else {
SDL_Unsupported();
}
return status;
}
int
X11_GL_GetSwapInterval(_THIS)
{
if (_this->gl_data->glXSwapIntervalEXT) {
Display *display = ((SDL_VideoData *) _this->driverdata)->display;
const SDL_WindowData *windowdata = (SDL_WindowData *)
SDL_GL_GetCurrentWindow()->driverdata;
Window drawable = windowdata->xwindow;
unsigned int allow_late_swap_tearing = 0;
unsigned int interval = 0;
if (_this->gl_data->HAS_GLX_EXT_swap_control_tear) {
_this->gl_data->glXQueryDrawable(display, drawable,
GLX_LATE_SWAPS_TEAR_EXT,
&allow_late_swap_tearing);
}
_this->gl_data->glXQueryDrawable(display, drawable,
GLX_SWAP_INTERVAL_EXT, &interval);
if ((allow_late_swap_tearing) && (interval > 0)) {
return -((int) interval);
}
return (int) interval;
} else if (_this->gl_data->glXGetSwapIntervalMESA) {
return _this->gl_data->glXGetSwapIntervalMESA();
} else {
return swapinterval;
}
}
void
X11_GL_SwapWindow(_THIS, SDL_Window * window)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
Display *display = data->videodata->display;
_this->gl_data->glXSwapBuffers(display, data->xwindow);
}
void
X11_GL_DeleteContext(_THIS, SDL_GLContext context)
{
Display *display = ((SDL_VideoData *) _this->driverdata)->display;
GLXContext glx_context = (GLXContext) context;
if (!_this->gl_data) {
return;
}
_this->gl_data->glXDestroyContext(display, glx_context);
X11_XSync(display, False);
}
#endif /* SDL_VIDEO_OPENGL_GLX */
#endif /* SDL_VIDEO_DRIVER_X11 */
/* vi: set ts=4 sw=4 expandtab: */
SDL_strlcpy
#define SDL_strlcpy
Definition: SDL_dynapi_overrides.h:400
SDL_VideoDevice::accum_alpha_size
int accum_alpha_size
Definition: SDL_sysvideo.h:302
attribs
const GLint * attribs
Definition: SDL_opengl_glext.h:9688
SDL_VideoDevice::accum_blue_size
int accum_blue_size
Definition: SDL_sysvideo.h:301
SDL_GLDriverData::swapinterval
uint32_t swapinterval
Definition: SDL_pspgl_c.h:36
n
GLdouble n
Definition: SDL_opengl_glext.h:1952
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 Uint32 * e
Definition: SDL_dynapi_procs.h:121
SDL_VideoDevice::minor_version
int minor_version
Definition: SDL_sysvideo.h:308
SDL_VideoDevice::blue_size
int blue_size
Definition: SDL_sysvideo.h:293
SDL_VideoDevice::accum_red_size
int accum_red_size
Definition: SDL_sysvideo.h:299
dpy
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display dpy)
Definition: SDL_x11sym.h:36
SDL_VideoData::display
struct wl_display * display
Definition: SDL_waylandvideo.h:40
window
SDL_Window * window
Definition: testautomation_render.c:26
SDL_WindowData::xwindow
Window xwindow
Definition: SDL_x11window.h:46
X11_UseDirectColorVisuals
SDL_bool X11_UseDirectColorVisuals(void)
SDL_VideoDevice::driverdata
void * driverdata
Definition: SDL_sysvideo.h:332
SDL_VideoDevice::GL_SetSwapInterval
int(* GL_SetSwapInterval)(_THIS, int interval)
Definition: SDL_sysvideo.h:240
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1967
SDL_VideoDevice::profile_mask
int profile_mask
Definition: SDL_sysvideo.h:310
SDL_x11opengles.h
start
GLuint start
Definition: SDL_opengl.h:1564
SDL_VideoDevice::GL_SwapWindow
void(* GL_SwapWindow)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:242
SDL_GLDriverData::display
EGLDisplay display
Definition: SDL_pspgl_c.h:33
size
GLsizeiptr size
Definition: SDL_opengl_glext.h:537
SDL_VideoDevice::GL_LoadLibrary
int(* GL_LoadLibrary)(_THIS, const char *path)
Definition: SDL_sysvideo.h:234
SDL_DisplayData
Definition: SDL_cocoamodes.h:26
SDL_VideoDevice::stereo
int stereo
Definition: SDL_sysvideo.h:303
SDL_VideoDevice::gl_data
struct SDL_GLDriverData * gl_data
Definition: SDL_sysvideo.h:333
SDL_WindowData
Definition: SDL_androidwindow.h:34
SDL_strchr
#define SDL_strchr
Definition: SDL_dynapi_overrides.h:407
_this
static SDL_VideoDevice * _this
Definition: SDL_video.c:114
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:126
SDL_VideoDevice::gl_config
struct SDL_VideoDevice::@29 gl_config
v
const GLdouble * v
Definition: SDL_opengl.h:2057
SDL_VideoDevice::accelerated
int accelerated
Definition: SDL_sysvideo.h:306
SDL_VideoDevice::multisamplebuffers
int multisamplebuffers
Definition: SDL_sysvideo.h:304
SDL_VideoDevice::multisamplesamples
int multisamplesamples
Definition: SDL_sysvideo.h:305
SDL_VideoDevice::major_version
int major_version
Definition: SDL_sysvideo.h:307
SDL_calloc
void * SDL_calloc(size_t nmemb, size_t size)
SDL_GLContext
void * SDL_GLContext
An opaque handle to an OpenGL context.
Definition: SDL_video.h:164
SDL_VideoDevice::GL_CreateContext
SDL_GLContext(* GL_CreateContext)(_THIS, SDL_Window *window)
Definition: SDL_sysvideo.h:237
d
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
Definition: SDL_dynapi_procs.h:121
SDL_VideoDevice::depth_size
int depth_size
Definition: SDL_sysvideo.h:295
SDL_VideoDevice::red_size
int red_size
Definition: SDL_sysvideo.h:291
_THIS
#define _THIS
Definition: SDL_alsa_audio.h:31
SDL_WindowData::videodata
struct SDL_VideoData * videodata
Definition: SDL_cocoawindow.h:116
SDL_VideoDevice::GL_MakeCurrent
int(* GL_MakeCurrent)(_THIS, SDL_Window *window, SDL_GLContext context)
Definition: SDL_sysvideo.h:238
SDL_VideoDevice::double_buffer
int double_buffer
Definition: SDL_sysvideo.h:298
SDL_free
void SDL_free(void *mem)
SDL_VideoDevice::driver_path
char driver_path[256]
Definition: SDL_sysvideo.h:316
SDL_VideoDevice::dll_handle
void * dll_handle
Definition: SDL_sysvideo.h:317
SDL_VideoDevice::green_size
int green_size
Definition: SDL_sysvideo.h:292
SDL_VideoDevice::alpha_size
int alpha_size
Definition: SDL_sysvideo.h:294
SDL_TRUE
Definition: SDL_stdinc.h:129
SDL_VideoDevice::framebuffer_srgb_capable
int framebuffer_srgb_capable
Definition: SDL_sysvideo.h:313
GLubyte
unsigned char GLubyte
Definition: SDL_opengl.h:176
SDL_getenv
#define SDL_getenv
Definition: SDL_dynapi_overrides.h:384
SDL_VideoDevice::release_behavior
int release_behavior
Definition: SDL_sysvideo.h:312
SDL_VideoDevice::GL_UnloadLibrary
void(* GL_UnloadLibrary)(_THIS)
Definition: SDL_sysvideo.h:236
SDL_VideoDevice::stencil_size
int stencil_size
Definition: SDL_sysvideo.h:297
i
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:42
SDL_VideoDevice::share_with_current_context
int share_with_current_context
Definition: SDL_sysvideo.h:311
SDL_assert
#define SDL_assert(condition)
Definition: SDL_assert.h:167
NULL
#define NULL
Definition: begin_code.h:143
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_GL_GetCurrentContext
#define SDL_GL_GetCurrentContext
Definition: SDL_dynapi_overrides.h:566
SDL_VideoDevice::flags
int flags
Definition: SDL_sysvideo.h:309
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:36
SDL_loadso.h
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 void
Definition: SDL_dynapi_procs.h:93
SDL_GL_GetCurrentWindow
#define SDL_GL_GetCurrentWindow
Definition: SDL_dynapi_overrides.h:565
SDL_GLDriverData
Definition: SDL_pspgl_c.h:32
SDL_GetDisplayForWindow
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
Definition: SDL_video.c:1039
SDL_strlen
#define SDL_strlen
Definition: SDL_dynapi_overrides.h:399
SDL_Window
The type used to identify a window.
Definition: SDL_sysvideo.h:71
SDL_iconv_string
#define SDL_iconv_string
Definition: SDL_dynapi_overrides.h:447
SDL_FALSE
Definition: SDL_stdinc.h:128
SDL_x11video.h
SDL_VideoData
Definition: SDL_androidvideo.h:35
SDL_arraysize
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:93
path
GLsizei const GLchar *const * path
Definition: SDL_opengl_glext.h:3730
SDL_VideoDevice::accum_green_size
int accum_green_size
Definition: SDL_sysvideo.h:300
SDL_Window::driverdata
void * driverdata
Definition: SDL_sysvideo.h:106
SDL_VideoDevice::GL_DeleteContext
void(* GL_DeleteContext)(_THIS, SDL_GLContext context)
Definition: SDL_sysvideo.h:243
SDL_GLDriverData::context
EGLContext context
Definition: SDL_pspgl_c.h:34
SDL_VideoDevice::GL_GetSwapInterval
int(* GL_GetSwapInterval)(_THIS)
Definition: SDL_sysvideo.h:241
SDL_GL_CONTEXT_PROFILE_ES
Definition: SDL_video.h:202
screen
SDL_Renderer * screen
Definition: testgamecontroller.c:64
SDL_Unsupported
#define SDL_Unsupported()
Definition: SDL_error.h:53
SDL_VideoDevice::GL_GetProcAddress
void *(* GL_GetProcAddress)(_THIS, const char *proc)
Definition: SDL_sysvideo.h:235
SDL_strstr
#define SDL_strstr
Definition: SDL_dynapi_overrides.h:409
SDL_VideoDisplay::driverdata
void * driverdata
Definition: SDL_sysvideo.h:133
SDL_assert.h