diff --git a/src/internal.h b/src/internal.h index 681df74d..5293caf4 100644 --- a/src/internal.h +++ b/src/internal.h @@ -51,6 +51,17 @@ #define GLFW_STICK 2 +//======================================================================== +// Internal type declarations +//======================================================================== + +typedef struct _GLFWhints _GLFWhints; +typedef struct _GLFWwndconfig _GLFWwndconfig; +typedef struct _GLFWfbconfig _GLFWfbconfig; +typedef struct _GLFWwindow _GLFWwindow; +typedef struct _GLFWlibrary _GLFWlibrary; + + //------------------------------------------------------------------------ // Platform specific definitions goes in platform.h (which also includes // glfw.h) @@ -75,12 +86,6 @@ #error "No supported platform selected" #endif -typedef struct _GLFWhints _GLFWhints; -typedef struct _GLFWwndconfig _GLFWwndconfig; -typedef struct _GLFWfbconfig _GLFWfbconfig; -typedef struct _GLFWwindow _GLFWwindow; -typedef struct _GLFWlibrary _GLFWlibrary; - //------------------------------------------------------------------------ // Window hints, set by glfwOpenWindowHint and consumed by glfwOpenWindow diff --git a/src/x11_init.c b/src/x11_init.c index 3cb94e54..372fc2dd 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -35,33 +35,6 @@ #include -//======================================================================== -// Dynamically load libraries -//======================================================================== - -static void initLibraries(void) -{ -#ifdef _GLFW_DLOPEN_LIBGL - int i; - char* libGL_names[ ] = - { - "libGL.so", - "libGL.so.1", - "/usr/lib/libGL.so", - "/usr/lib/libGL.so.1", - NULL - }; - - for (i = 0; libGL_names[i] != NULL; i++) - { - _glfwLibrary.GLX.libGL = dlopen(libGL_names[i], RTLD_LAZY | RTLD_GLOBAL); - if (_glfwLibrary.GLX.libGL) - break; - } -#endif -} - - //======================================================================== // Translate an X11 key code to a GLFW key code. //======================================================================== @@ -560,22 +533,6 @@ static GLboolean initDisplay(void) _glfwLibrary.X11.RandR.available = GL_FALSE; #endif /*_GLFW_HAS_XRANDR*/ - // Check if GLX is supported on this display - if (!glXQueryExtension(_glfwLibrary.X11.display, NULL, NULL)) - { - _glfwSetError(GLFW_OPENGL_UNAVAILABLE, "X11/GLX: GLX supported not found"); - return GL_FALSE; - } - - if (!glXQueryVersion(_glfwLibrary.X11.display, - &_glfwLibrary.GLX.majorVersion, - &_glfwLibrary.GLX.minorVersion)) - { - _glfwSetError(GLFW_OPENGL_UNAVAILABLE, - "X11/GLX: Failed to query GLX version"); - return GL_FALSE; - } - // Check if Xkb is supported on this display #if defined(_GLFW_HAS_XKB) _glfwLibrary.X11.Xkb.majorVersion = 1; @@ -682,13 +639,13 @@ int _glfwPlatformInit(void) _glfwInitGammaRamp(); + if (!_glfwInitOpenGL()) + return GL_FALSE; + initEWMH(); _glfwLibrary.X11.cursor = createNULLCursor(); - // Try to load libGL.so if necessary - initLibraries(); - _glfwInitJoysticks(); // Start the timer @@ -716,14 +673,7 @@ int _glfwPlatformTerminate(void) _glfwTerminateJoysticks(); - // Unload libGL.so if necessary -#ifdef _GLFW_DLOPEN_LIBGL - if (_glfwLibrary.GLX.libGL != NULL) - { - dlclose(_glfwLibrary.GLX.libGL); - _glfwLibrary.GLX.libGL = NULL; - } -#endif + _glfwTerminateOpenGL(); // Free clipboard memory if (_glfwLibrary.X11.selection.string) diff --git a/src/x11_opengl.c b/src/x11_opengl.c index fd8bd313..582fbe20 100644 --- a/src/x11_opengl.c +++ b/src/x11_opengl.c @@ -30,15 +30,653 @@ #include "internal.h" +#include + // This is the only glXGetProcAddress variant not declared by glxext.h void (*glXGetProcAddressEXT(const GLubyte* procName))(); +//======================================================================== +// Returns the specified attribute of the specified GLXFBConfig +// NOTE: Do not call this unless we have found GLX 1.3+ or GLX_SGIX_fbconfig +//======================================================================== + +static int getFBConfigAttrib(_GLFWwindow* window, GLXFBConfig fbconfig, int attrib) +{ + int value; + + if (_glfwLibrary.GLX.SGIX_fbconfig) + { + _glfwLibrary.GLX.GetFBConfigAttribSGIX(_glfwLibrary.X11.display, + fbconfig, attrib, &value); + } + else + glXGetFBConfigAttrib(_glfwLibrary.X11.display, fbconfig, attrib, &value); + + return value; +} + + +//======================================================================== +// Return a list of available and usable framebuffer configs +//======================================================================== + +static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, unsigned int* found) +{ + GLXFBConfig* fbconfigs; + _GLFWfbconfig* result; + int i, count = 0; + const char* vendor; + GLboolean trustWindowBit = GL_TRUE; + + *found = 0; + + if (_glfwLibrary.GLX.majorVersion == 1 && _glfwLibrary.GLX.minorVersion < 3) + { + if (!_glfwLibrary.GLX.SGIX_fbconfig) + { + _glfwSetError(GLFW_OPENGL_UNAVAILABLE, + "X11/GLX: GLXFBConfig support not found"); + return NULL; + } + } + + vendor = glXGetClientString(_glfwLibrary.X11.display, GLX_VENDOR); + + if (strcmp(vendor, "Chromium") == 0) + { + // This is a (hopefully temporary) workaround for Chromium (VirtualBox + // GL) not setting the window bit on any GLXFBConfigs + trustWindowBit = GL_FALSE; + } + + if (_glfwLibrary.GLX.SGIX_fbconfig) + { + fbconfigs = _glfwLibrary.GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + NULL, + &count); + if (!count) + { + _glfwSetError(GLFW_OPENGL_UNAVAILABLE, + "X11/GLX: No GLXFBConfigs returned"); + return NULL; + } + } + else + { + fbconfigs = glXGetFBConfigs(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + &count); + if (!count) + { + _glfwSetError(GLFW_OPENGL_UNAVAILABLE, + "X11/GLX: No GLXFBConfigs returned"); + return NULL; + } + } + + result = (_GLFWfbconfig*) malloc(sizeof(_GLFWfbconfig) * count); + if (!result) + { + _glfwSetError(GLFW_OUT_OF_MEMORY, + "X11/GLX: Failed to allocate _GLFWfbconfig array"); + return NULL; + } + + for (i = 0; i < count; i++) + { + if (!getFBConfigAttrib(window, fbconfigs[i], GLX_DOUBLEBUFFER) || + !getFBConfigAttrib(window, fbconfigs[i], GLX_VISUAL_ID)) + { + // Only consider double-buffered GLXFBConfigs with associated visuals + continue; + } + + if (!(getFBConfigAttrib(window, + fbconfigs[i], + GLX_RENDER_TYPE) & GLX_RGBA_BIT)) + { + // Only consider RGBA GLXFBConfigs + continue; + } + + if (!(getFBConfigAttrib(window, fbconfigs[i], GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT)) + { + if (trustWindowBit) + { + // Only consider window GLXFBConfigs + continue; + } + } + + result[*found].redBits = getFBConfigAttrib(window, fbconfigs[i], GLX_RED_SIZE); + result[*found].greenBits = getFBConfigAttrib(window, fbconfigs[i], GLX_GREEN_SIZE); + result[*found].blueBits = getFBConfigAttrib(window, fbconfigs[i], GLX_BLUE_SIZE); + + result[*found].alphaBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ALPHA_SIZE); + result[*found].depthBits = getFBConfigAttrib(window, fbconfigs[i], GLX_DEPTH_SIZE); + result[*found].stencilBits = getFBConfigAttrib(window, fbconfigs[i], GLX_STENCIL_SIZE); + + result[*found].accumRedBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_RED_SIZE); + result[*found].accumGreenBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_GREEN_SIZE); + result[*found].accumBlueBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_BLUE_SIZE); + result[*found].accumAlphaBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_ALPHA_SIZE); + + result[*found].auxBuffers = getFBConfigAttrib(window, fbconfigs[i], GLX_AUX_BUFFERS); + result[*found].stereo = getFBConfigAttrib(window, fbconfigs[i], GLX_STEREO); + + if (_glfwLibrary.GLX.ARB_multisample) + result[*found].samples = getFBConfigAttrib(window, fbconfigs[i], GLX_SAMPLES); + else + result[*found].samples = 0; + + result[*found].platformID = (GLFWintptr) getFBConfigAttrib(window, fbconfigs[i], GLX_FBCONFIG_ID); + + (*found)++; + } + + XFree(fbconfigs); + + return result; +} + + +//======================================================================== +// Error handler for BadMatch errors when requesting context with +// unavailable OpenGL versions using the GLX_ARB_create_context extension +//======================================================================== + +static int errorHandler(Display *display, XErrorEvent* event) +{ + return 0; +} + + +//======================================================================== +// Read back framebuffer parameters from the context +//======================================================================== + +static void refreshContextParams(_GLFWwindow* window, GLXFBConfigID fbconfigID) +{ + int dummy; + GLXFBConfig* fbconfig; + + int attribs[] = { GLX_FBCONFIG_ID, fbconfigID, None }; + + if (_glfwLibrary.GLX.SGIX_fbconfig) + { + fbconfig = _glfwLibrary.GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + attribs, + &dummy); + } + else + { + fbconfig = glXChooseFBConfig(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + attribs, + &dummy); + } + + if (fbconfig == NULL) + { + // This should never ever happen + // TODO: Flag this as an error and propagate up + _glfwSetError(GLFW_PLATFORM_ERROR, "X11/GLX: Cannot find known " + "GLXFBConfig by ID. This cannot " + "happen. Have a nice day.\n"); + abort(); + } + + // There is no clear definition of an "accelerated" context on X11/GLX, and + // true sounds better than false, so we hardcode true here + window->accelerated = GL_TRUE; + + window->redBits = getFBConfigAttrib(window, *fbconfig, GLX_RED_SIZE); + window->greenBits = getFBConfigAttrib(window, *fbconfig, GLX_GREEN_SIZE); + window->blueBits = getFBConfigAttrib(window, *fbconfig, GLX_BLUE_SIZE); + + window->alphaBits = getFBConfigAttrib(window, *fbconfig, GLX_ALPHA_SIZE); + window->depthBits = getFBConfigAttrib(window, *fbconfig, GLX_DEPTH_SIZE); + window->stencilBits = getFBConfigAttrib(window, *fbconfig, GLX_STENCIL_SIZE); + + window->accumRedBits = getFBConfigAttrib(window, *fbconfig, GLX_ACCUM_RED_SIZE); + window->accumGreenBits = getFBConfigAttrib(window, *fbconfig, GLX_ACCUM_GREEN_SIZE); + window->accumBlueBits = getFBConfigAttrib(window, *fbconfig, GLX_ACCUM_BLUE_SIZE); + window->accumAlphaBits = getFBConfigAttrib(window, *fbconfig, GLX_ACCUM_ALPHA_SIZE); + + window->auxBuffers = getFBConfigAttrib(window, *fbconfig, GLX_AUX_BUFFERS); + window->stereo = getFBConfigAttrib(window, *fbconfig, GLX_STEREO) ? GL_TRUE : GL_FALSE; + + // Get FSAA buffer sample count + if (_glfwLibrary.GLX.ARB_multisample) + window->samples = getFBConfigAttrib(window, *fbconfig, GLX_SAMPLES); + else + window->samples = 0; + + XFree(fbconfig); +} + + +//======================================================================== +// Create the actual OpenGL context +//======================================================================== + +#define setGLXattrib(attribs, index, attribName, attribValue) \ + attribs[index++] = attribName; \ + attribs[index++] = attribValue; + +static int createContext(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + GLXFBConfigID fbconfigID) +{ + int attribs[40]; + int dummy, index; + GLXFBConfig* fbconfig; + GLXContext share = NULL; + + if (wndconfig->share) + share = wndconfig->share->GLX.context; + + // Retrieve the previously selected GLXFBConfig + { + index = 0; + + setGLXattrib(attribs, index, GLX_FBCONFIG_ID, (int) fbconfigID); + setGLXattrib(attribs, index, None, None); + + if (_glfwLibrary.GLX.SGIX_fbconfig) + { + fbconfig = _glfwLibrary.GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + attribs, + &dummy); + } + else + { + fbconfig = glXChooseFBConfig(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + attribs, + &dummy); + } + + if (fbconfig == NULL) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "X11/GLX: Failed to retrieve the selected GLXFBConfig"); + return GL_FALSE; + } + } + + // Retrieve the corresponding visual + if (_glfwLibrary.GLX.SGIX_fbconfig) + { + window->GLX.visual = _glfwLibrary.GLX.GetVisualFromFBConfigSGIX(_glfwLibrary.X11.display, + *fbconfig); + } + else + { + window->GLX.visual = glXGetVisualFromFBConfig(_glfwLibrary.X11.display, + *fbconfig); + } + + if (window->GLX.visual == NULL) + { + XFree(fbconfig); + + _glfwSetError(GLFW_PLATFORM_ERROR, + "X11/GLX: Failed to retrieve visual for GLXFBConfig"); + return GL_FALSE; + } + + if (_glfwLibrary.GLX.ARB_create_context) + { + index = 0; + + if (wndconfig->glMajor != 1 || wndconfig->glMinor != 0) + { + // Request an explicitly versioned context + + setGLXattrib(attribs, index, GLX_CONTEXT_MAJOR_VERSION_ARB, wndconfig->glMajor); + setGLXattrib(attribs, index, GLX_CONTEXT_MINOR_VERSION_ARB, wndconfig->glMinor); + } + + if (wndconfig->glForward || wndconfig->glDebug || wndconfig->glRobustness) + { + int flags = 0; + + if (wndconfig->glForward) + flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; + + if (wndconfig->glDebug) + flags |= GLX_CONTEXT_DEBUG_BIT_ARB; + + if (wndconfig->glRobustness) + flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB; + + setGLXattrib(attribs, index, GLX_CONTEXT_FLAGS_ARB, flags); + } + + if (wndconfig->glProfile) + { + int flags = 0; + + if (!_glfwLibrary.GLX.ARB_create_context_profile) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE, + "X11/GLX: An OpenGL profile requested but " + "GLX_ARB_create_context_profile is unavailable"); + return GL_FALSE; + } + + if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE && + !_glfwLibrary.GLX.EXT_create_context_es2_profile) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE, + "X11/GLX: OpenGL ES 2.x profile requested but " + "GLX_EXT_create_context_es2_profile is unavailable"); + return GL_FALSE; + } + + if (wndconfig->glProfile == GLFW_OPENGL_CORE_PROFILE) + flags = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; + else if (wndconfig->glProfile == GLFW_OPENGL_COMPAT_PROFILE) + flags = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; + else if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE) + flags = GLX_CONTEXT_ES2_PROFILE_BIT_EXT; + + setGLXattrib(attribs, index, GLX_CONTEXT_PROFILE_MASK_ARB, flags); + } + + if (wndconfig->glRobustness) + { + int strategy; + + if (!_glfwLibrary.GLX.ARB_create_context_robustness) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE, + "X11/GLX: An OpenGL robustness strategy was " + "requested but GLX_ARB_create_context_robustness " + "is unavailable"); + return GL_FALSE; + } + + if (wndconfig->glRobustness == GLFW_OPENGL_NO_RESET_NOTIFICATION) + strategy = GLX_NO_RESET_NOTIFICATION_ARB; + else if (wndconfig->glRobustness == GLFW_OPENGL_LOSE_CONTEXT_ON_RESET) + strategy = GLX_LOSE_CONTEXT_ON_RESET_ARB; + + setGLXattrib(attribs, + index, + GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, + strategy); + } + + setGLXattrib(attribs, index, None, None); + + // This is the only place we set an Xlib error handler, and we only do + // it because glXCreateContextAttribsARB generates a BadMatch error if + // the requested OpenGL version is unavailable (instead of a civilized + // response like returning NULL) + XSetErrorHandler(errorHandler); + + window->GLX.context = + _glfwLibrary.GLX.CreateContextAttribsARB(_glfwLibrary.X11.display, + *fbconfig, + share, + True, + attribs); + + // We are done, so unset the error handler again (see above) + XSetErrorHandler(NULL); + } + else + { + if (_glfwLibrary.GLX.SGIX_fbconfig) + { + window->GLX.context = + _glfwLibrary.GLX.CreateContextWithConfigSGIX(_glfwLibrary.X11.display, + *fbconfig, + GLX_RGBA_TYPE, + share, + True); + } + else + { + window->GLX.context = glXCreateNewContext(_glfwLibrary.X11.display, + *fbconfig, + GLX_RGBA_TYPE, + share, + True); + } + } + + XFree(fbconfig); + + if (window->GLX.context == NULL) + { + // TODO: Handle all the various error codes here + + _glfwSetError(GLFW_PLATFORM_ERROR, + "X11/GLX: Failed to create OpenGL context"); + return GL_FALSE; + } + + refreshContextParams(window, fbconfigID); + + return GL_TRUE; +} + +#undef setGLXattrib + + ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// +//======================================================================== +// Initialize GLX +//======================================================================== + +int _glfwInitOpenGL(void) +{ +#ifdef _GLFW_DLOPEN_LIBGL + int i; + char* libGL_names[ ] = + { + "libGL.so", + "libGL.so.1", + "/usr/lib/libGL.so", + "/usr/lib/libGL.so.1", + NULL + }; + + for (i = 0; libGL_names[i] != NULL; i++) + { + _glfwLibrary.GLX.libGL = dlopen(libGL_names[i], RTLD_LAZY | RTLD_GLOBAL); + if (_glfwLibrary.GLX.libGL) + break; + } + + if (!_glfwLibrary.GLX.libGL) + { + _glfwSetError(GLFW_PLATFORM_ERROR, "X11/GLX: Failed to find libGL"); + return GL_FALSE; + } +#endif + + // Check if GLX is supported on this display + if (!glXQueryExtension(_glfwLibrary.X11.display, NULL, NULL)) + { + _glfwSetError(GLFW_OPENGL_UNAVAILABLE, "X11/GLX: GLX supported not found"); + return GL_FALSE; + } + + if (!glXQueryVersion(_glfwLibrary.X11.display, + &_glfwLibrary.GLX.majorVersion, + &_glfwLibrary.GLX.minorVersion)) + { + _glfwSetError(GLFW_OPENGL_UNAVAILABLE, + "X11/GLX: Failed to query GLX version"); + return GL_FALSE; + } + + if (_glfwPlatformExtensionSupported("GLX_EXT_swap_control")) + { + _glfwLibrary.GLX.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) + _glfwPlatformGetProcAddress("glXSwapIntervalEXT"); + + if (_glfwLibrary.GLX.SwapIntervalEXT) + _glfwLibrary.GLX.EXT_swap_control = GL_TRUE; + } + + if (_glfwPlatformExtensionSupported("GLX_SGI_swap_control")) + { + _glfwLibrary.GLX.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) + _glfwPlatformGetProcAddress("glXSwapIntervalSGI"); + + if (_glfwLibrary.GLX.SwapIntervalSGI) + _glfwLibrary.GLX.SGI_swap_control = GL_TRUE; + } + + if (_glfwPlatformExtensionSupported("GLX_SGIX_fbconfig")) + { + _glfwLibrary.GLX.GetFBConfigAttribSGIX = (PFNGLXGETFBCONFIGATTRIBSGIXPROC) + _glfwPlatformGetProcAddress("glXGetFBConfigAttribSGIX"); + _glfwLibrary.GLX.ChooseFBConfigSGIX = (PFNGLXCHOOSEFBCONFIGSGIXPROC) + _glfwPlatformGetProcAddress("glXChooseFBConfigSGIX"); + _glfwLibrary.GLX.CreateContextWithConfigSGIX = (PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) + _glfwPlatformGetProcAddress("glXCreateContextWithConfigSGIX"); + _glfwLibrary.GLX.GetVisualFromFBConfigSGIX = (PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) + _glfwPlatformGetProcAddress("glXGetVisualFromFBConfigSGIX"); + + if (_glfwLibrary.GLX.GetFBConfigAttribSGIX && + _glfwLibrary.GLX.ChooseFBConfigSGIX && + _glfwLibrary.GLX.CreateContextWithConfigSGIX && + _glfwLibrary.GLX.GetVisualFromFBConfigSGIX) + { + _glfwLibrary.GLX.SGIX_fbconfig = GL_TRUE; + } + } + + if (_glfwPlatformExtensionSupported("GLX_ARB_multisample")) + _glfwLibrary.GLX.ARB_multisample = GL_TRUE; + + if (_glfwPlatformExtensionSupported("GLX_ARB_create_context")) + { + _glfwLibrary.GLX.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) + _glfwPlatformGetProcAddress("glXCreateContextAttribsARB"); + + if (_glfwLibrary.GLX.CreateContextAttribsARB) + _glfwLibrary.GLX.ARB_create_context = GL_TRUE; + } + + if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_robustness")) + _glfwLibrary.GLX.ARB_create_context_robustness = GL_TRUE; + + if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_profile")) + _glfwLibrary.GLX.ARB_create_context_profile = GL_TRUE; + + if (_glfwPlatformExtensionSupported("GLX_EXT_create_context_es2_profile")) + _glfwLibrary.GLX.EXT_create_context_es2_profile = GL_TRUE; + + return GL_TRUE; +} + + +//======================================================================== +// Terminate GLX +//======================================================================== + +void _glfwTerminateOpenGL(void) +{ + // Unload libGL.so if necessary +#ifdef _GLFW_DLOPEN_LIBGL + if (_glfwLibrary.GLX.libGL != NULL) + { + dlclose(_glfwLibrary.GLX.libGL); + _glfwLibrary.GLX.libGL = NULL; + } +#endif +} + + +//======================================================================== +// Prepare for creation of the OpenGL context +//======================================================================== + +int _glfwCreateContext(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWfbconfig* fbconfig) +{ + _GLFWfbconfig closest; + + // Choose the best available fbconfig + { + unsigned int fbcount; + _GLFWfbconfig* fbconfigs; + const _GLFWfbconfig* result; + + fbconfigs = getFBConfigs(window, &fbcount); + if (!fbconfigs) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "X11/GLX: No usable GLXFBConfigs found"); + return GL_FALSE; + } + + result = _glfwChooseFBConfig(fbconfig, fbconfigs, fbcount); + if (!result) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "X11/GLX: No GLXFBConfig matched the criteria"); + + free(fbconfigs); + return GL_FALSE; + } + + closest = *result; + free(fbconfigs); + } + + return createContext(window, wndconfig, closest.platformID); +} + + +//======================================================================== +// Destroy the OpenGL context +//======================================================================== + +void _glfwDestroyContext(_GLFWwindow* window) +{ + if (window->GLX.visual) + { + XFree(window->GLX.visual); + window->GLX.visual = NULL; + } + + if (window->GLX.context) + { + // Release and destroy the context + glXMakeCurrent(_glfwLibrary.X11.display, None, NULL); + glXDestroyContext(_glfwLibrary.X11.display, window->GLX.context); + window->GLX.context = NULL; + } +} + + +//======================================================================== +// Return the X visual associated with the specified context +//======================================================================== + +XVisualInfo* _glfwGetContextVisual(_GLFWwindow* window) +{ + return window->GLX.visual; +} + + //======================================================================== // Make the OpenGL context associated with the specified window current //======================================================================== @@ -75,14 +713,14 @@ void _glfwPlatformSwapInterval(int interval) { _GLFWwindow* window = _glfwLibrary.currentWindow; - if (window->GLX.EXT_swap_control) + if (_glfwLibrary.GLX.EXT_swap_control) { - window->GLX.SwapIntervalEXT(_glfwLibrary.X11.display, - window->X11.handle, - interval); + _glfwLibrary.GLX.SwapIntervalEXT(_glfwLibrary.X11.display, + window->X11.handle, + interval); } - else if (window->GLX.SGI_swap_control) - window->GLX.SwapIntervalSGI(interval); + else if (_glfwLibrary.GLX.SGI_swap_control) + _glfwLibrary.GLX.SwapIntervalSGI(interval); } diff --git a/src/x11_platform.h b/src/x11_platform.h index 4cb20668..f87287b1 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -113,27 +113,9 @@ typedef intptr_t GLFWintptr; //------------------------------------------------------------------------ typedef struct _GLFWcontextGLX { - GLXFBConfigID fbconfigID; // ID of selected GLXFBConfig GLXContext context; // OpenGL rendering context XVisualInfo* visual; // Visual for selected GLXFBConfig - // GLX extensions - PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI; - PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT; - PFNGLXGETFBCONFIGATTRIBSGIXPROC GetFBConfigAttribSGIX; - PFNGLXCHOOSEFBCONFIGSGIXPROC ChooseFBConfigSGIX; - PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC CreateContextWithConfigSGIX; - PFNGLXGETVISUALFROMFBCONFIGSGIXPROC GetVisualFromFBConfigSGIX; - PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB; - GLboolean SGIX_fbconfig; - GLboolean SGI_swap_control; - GLboolean EXT_swap_control; - GLboolean ARB_multisample; - GLboolean ARB_create_context; - GLboolean ARB_create_context_profile; - GLboolean ARB_create_context_robustness; - GLboolean EXT_create_context_es2_profile; - } _GLFWcontextGLX; @@ -257,6 +239,23 @@ typedef struct _GLFWlibraryGLX // Server-side GLX version int majorVersion, minorVersion; + // GLX extensions + PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI; + PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT; + PFNGLXGETFBCONFIGATTRIBSGIXPROC GetFBConfigAttribSGIX; + PFNGLXCHOOSEFBCONFIGSGIXPROC ChooseFBConfigSGIX; + PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC CreateContextWithConfigSGIX; + PFNGLXGETVISUALFROMFBCONFIGSGIXPROC GetVisualFromFBConfigSGIX; + PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB; + GLboolean SGIX_fbconfig; + GLboolean SGI_swap_control; + GLboolean EXT_swap_control; + GLboolean ARB_multisample; + GLboolean ARB_create_context; + GLboolean ARB_create_context_profile; + GLboolean ARB_create_context_robustness; + GLboolean EXT_create_context_es2_profile; + #if defined(_GLFW_DLOPEN_LIBGL) void* libGL; // dlopen handle for libGL.so #endif @@ -287,6 +286,15 @@ void _glfwInitTimer(void); void _glfwInitGammaRamp(void); void _glfwTerminateGammaRamp(void); +// OpenGL support +int _glfwInitOpenGL(void); +void _glfwTerminateOpenGL(void); +int _glfwCreateContext(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWfbconfig* fbconfig); +void _glfwDestroyContext(_GLFWwindow* window); +XVisualInfo* _glfwGetContextVisual(_GLFWwindow* window); + // Fullscreen support int _glfwGetClosestVideoMode(int* width, int* height, int* rate); void _glfwSetVideoModeMODE(int mode, int rate); diff --git a/src/x11_window.c b/src/x11_window.c index c6e1fa74..9ec54493 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -43,17 +43,6 @@ #define Button6 6 #define Button7 7 -//======================================================================== -// Error handler for BadMatch errors when requesting context with -// unavailable OpenGL versions using the GLX_ARB_create_context extension -//======================================================================== - -static int errorHandler(Display *display, XErrorEvent* event) -{ - return 0; -} - - //======================================================================== // Checks whether the event is a MapNotify for the specified window //======================================================================== @@ -98,433 +87,6 @@ static int translateChar(XKeyEvent* event) } -//======================================================================== -// Returns the specified attribute of the specified GLXFBConfig -// NOTE: Do not call this unless we have found GLX 1.3+ or GLX_SGIX_fbconfig -//======================================================================== - -static int getFBConfigAttrib(_GLFWwindow* window, GLXFBConfig fbconfig, int attrib) -{ - int value; - - if (window->GLX.SGIX_fbconfig) - { - window->GLX.GetFBConfigAttribSGIX(_glfwLibrary.X11.display, - fbconfig, attrib, &value); - } - else - glXGetFBConfigAttrib(_glfwLibrary.X11.display, fbconfig, attrib, &value); - - return value; -} - - -//======================================================================== -// Return a list of available and usable framebuffer configs -//======================================================================== - -static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, unsigned int* found) -{ - GLXFBConfig* fbconfigs; - _GLFWfbconfig* result; - int i, count = 0; - const char* vendor; - GLboolean trustWindowBit = GL_TRUE; - - *found = 0; - - if (_glfwLibrary.GLX.majorVersion == 1 && _glfwLibrary.GLX.minorVersion < 3) - { - if (!window->GLX.SGIX_fbconfig) - { - _glfwSetError(GLFW_OPENGL_UNAVAILABLE, - "X11/GLX: GLXFBConfig support not found"); - return NULL; - } - } - - vendor = glXGetClientString(_glfwLibrary.X11.display, GLX_VENDOR); - - if (strcmp(vendor, "Chromium") == 0) - { - // This is a (hopefully temporary) workaround for Chromium (VirtualBox - // GL) not setting the window bit on any GLXFBConfigs - trustWindowBit = GL_FALSE; - } - - if (window->GLX.SGIX_fbconfig) - { - fbconfigs = window->GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - NULL, - &count); - if (!count) - { - _glfwSetError(GLFW_OPENGL_UNAVAILABLE, - "X11/GLX: No GLXFBConfigs returned"); - return NULL; - } - } - else - { - fbconfigs = glXGetFBConfigs(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - &count); - if (!count) - { - _glfwSetError(GLFW_OPENGL_UNAVAILABLE, - "X11/GLX: No GLXFBConfigs returned"); - return NULL; - } - } - - result = (_GLFWfbconfig*) malloc(sizeof(_GLFWfbconfig) * count); - if (!result) - { - _glfwSetError(GLFW_OUT_OF_MEMORY, - "X11/GLX: Failed to allocate _GLFWfbconfig array"); - return NULL; - } - - for (i = 0; i < count; i++) - { - if (!getFBConfigAttrib(window, fbconfigs[i], GLX_DOUBLEBUFFER) || - !getFBConfigAttrib(window, fbconfigs[i], GLX_VISUAL_ID)) - { - // Only consider double-buffered GLXFBConfigs with associated visuals - continue; - } - - if (!(getFBConfigAttrib(window, - fbconfigs[i], - GLX_RENDER_TYPE) & GLX_RGBA_BIT)) - { - // Only consider RGBA GLXFBConfigs - continue; - } - - if (!(getFBConfigAttrib(window, - fbconfigs[i], - GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT)) - { - if (trustWindowBit) - { - // Only consider window GLXFBConfigs - continue; - } - } - - result[*found].redBits = getFBConfigAttrib(window, fbconfigs[i], GLX_RED_SIZE); - result[*found].greenBits = getFBConfigAttrib(window, fbconfigs[i], GLX_GREEN_SIZE); - result[*found].blueBits = getFBConfigAttrib(window, fbconfigs[i], GLX_BLUE_SIZE); - - result[*found].alphaBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ALPHA_SIZE); - result[*found].depthBits = getFBConfigAttrib(window, fbconfigs[i], GLX_DEPTH_SIZE); - result[*found].stencilBits = getFBConfigAttrib(window, fbconfigs[i], GLX_STENCIL_SIZE); - - result[*found].accumRedBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_RED_SIZE); - result[*found].accumGreenBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_GREEN_SIZE); - result[*found].accumBlueBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_BLUE_SIZE); - result[*found].accumAlphaBits = getFBConfigAttrib(window, fbconfigs[i], GLX_ACCUM_ALPHA_SIZE); - - result[*found].auxBuffers = getFBConfigAttrib(window, fbconfigs[i], GLX_AUX_BUFFERS); - result[*found].stereo = getFBConfigAttrib(window, fbconfigs[i], GLX_STEREO); - - if (window->GLX.ARB_multisample) - result[*found].samples = getFBConfigAttrib(window, fbconfigs[i], GLX_SAMPLES); - else - result[*found].samples = 0; - - result[*found].platformID = (GLFWintptr) getFBConfigAttrib(window, fbconfigs[i], GLX_FBCONFIG_ID); - - (*found)++; - } - - XFree(fbconfigs); - - return result; -} - - -//======================================================================== -// Create the OpenGL context -//======================================================================== - -#define setGLXattrib(attribs, index, attribName, attribValue) \ - attribs[index++] = attribName; \ - attribs[index++] = attribValue; - -static int createContext(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - GLXFBConfigID fbconfigID) -{ - int attribs[40]; - int dummy, index; - GLXFBConfig* fbconfig; - GLXContext share = NULL; - - if (wndconfig->share) - share = wndconfig->share->GLX.context; - - // Retrieve the previously selected GLXFBConfig - { - index = 0; - - setGLXattrib(attribs, index, GLX_FBCONFIG_ID, (int) fbconfigID); - setGLXattrib(attribs, index, None, None); - - if (window->GLX.SGIX_fbconfig) - { - fbconfig = window->GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - attribs, - &dummy); - } - else - { - fbconfig = glXChooseFBConfig(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - attribs, - &dummy); - } - - if (fbconfig == NULL) - { - _glfwSetError(GLFW_PLATFORM_ERROR, - "X11/GLX: Failed to retrieve the selected GLXFBConfig"); - return GL_FALSE; - } - } - - // Retrieve the corresponding visual - if (window->GLX.SGIX_fbconfig) - { - window->GLX.visual = window->GLX.GetVisualFromFBConfigSGIX(_glfwLibrary.X11.display, - *fbconfig); - } - else - { - window->GLX.visual = glXGetVisualFromFBConfig(_glfwLibrary.X11.display, - *fbconfig); - } - - if (window->GLX.visual == NULL) - { - XFree(fbconfig); - - _glfwSetError(GLFW_PLATFORM_ERROR, - "X11/GLX: Failed to retrieve visual for GLXFBConfig"); - return GL_FALSE; - } - - if (window->GLX.ARB_create_context) - { - index = 0; - - if (wndconfig->glMajor != 1 || wndconfig->glMinor != 0) - { - // Request an explicitly versioned context - - setGLXattrib(attribs, index, GLX_CONTEXT_MAJOR_VERSION_ARB, wndconfig->glMajor); - setGLXattrib(attribs, index, GLX_CONTEXT_MINOR_VERSION_ARB, wndconfig->glMinor); - } - - if (wndconfig->glForward || wndconfig->glDebug || wndconfig->glRobustness) - { - int flags = 0; - - if (wndconfig->glForward) - flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; - - if (wndconfig->glDebug) - flags |= GLX_CONTEXT_DEBUG_BIT_ARB; - - if (wndconfig->glRobustness) - flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB; - - setGLXattrib(attribs, index, GLX_CONTEXT_FLAGS_ARB, flags); - } - - if (wndconfig->glProfile) - { - int flags = 0; - - if (!window->GLX.ARB_create_context_profile) - { - _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "X11/GLX: An OpenGL profile requested but " - "GLX_ARB_create_context_profile is unavailable"); - return GL_FALSE; - } - - if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE && - !window->GLX.EXT_create_context_es2_profile) - { - _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "X11/GLX: OpenGL ES 2.x profile requested but " - "GLX_EXT_create_context_es2_profile is unavailable"); - return GL_FALSE; - } - - if (wndconfig->glProfile == GLFW_OPENGL_CORE_PROFILE) - flags = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; - else if (wndconfig->glProfile == GLFW_OPENGL_COMPAT_PROFILE) - flags = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; - else if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE) - flags = GLX_CONTEXT_ES2_PROFILE_BIT_EXT; - - setGLXattrib(attribs, index, GLX_CONTEXT_PROFILE_MASK_ARB, flags); - } - - if (wndconfig->glRobustness) - { - int strategy; - - if (!window->GLX.ARB_create_context_robustness) - { - _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "X11/GLX: An OpenGL robustness strategy was " - "requested but GLX_ARB_create_context_robustness " - "is unavailable"); - return GL_FALSE; - } - - if (wndconfig->glRobustness == GLFW_OPENGL_NO_RESET_NOTIFICATION) - strategy = GLX_NO_RESET_NOTIFICATION_ARB; - else if (wndconfig->glRobustness == GLFW_OPENGL_LOSE_CONTEXT_ON_RESET) - strategy = GLX_LOSE_CONTEXT_ON_RESET_ARB; - - setGLXattrib(attribs, - index, - GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, - strategy); - } - - setGLXattrib(attribs, index, None, None); - - // This is the only place we set an Xlib error handler, and we only do - // it because glXCreateContextAttribsARB generates a BadMatch error if - // the requested OpenGL version is unavailable (instead of a civilized - // response like returning NULL) - XSetErrorHandler(errorHandler); - - window->GLX.context = - window->GLX.CreateContextAttribsARB(_glfwLibrary.X11.display, - *fbconfig, - share, - True, - attribs); - - // We are done, so unset the error handler again (see above) - XSetErrorHandler(NULL); - } - else - { - if (window->GLX.SGIX_fbconfig) - { - window->GLX.context = - window->GLX.CreateContextWithConfigSGIX(_glfwLibrary.X11.display, - *fbconfig, - GLX_RGBA_TYPE, - share, - True); - } - else - { - window->GLX.context = glXCreateNewContext(_glfwLibrary.X11.display, - *fbconfig, - GLX_RGBA_TYPE, - share, - True); - } - } - - XFree(fbconfig); - - if (window->GLX.context == NULL) - { - // TODO: Handle all the various error codes here - - _glfwSetError(GLFW_PLATFORM_ERROR, - "X11/GLX: Failed to create OpenGL context"); - return GL_FALSE; - } - - window->GLX.fbconfigID = fbconfigID; - - return GL_TRUE; -} - -#undef setGLXattrib - - -//======================================================================== -// Initialize GLX-specific extensions -//======================================================================== - -static void initGLXExtensions(_GLFWwindow* window) -{ - if (_glfwPlatformExtensionSupported("GLX_EXT_swap_control")) - { - window->GLX.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) - _glfwPlatformGetProcAddress("glXSwapIntervalEXT"); - - if (window->GLX.SwapIntervalEXT) - window->GLX.EXT_swap_control = GL_TRUE; - } - - if (_glfwPlatformExtensionSupported("GLX_SGI_swap_control")) - { - window->GLX.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) - _glfwPlatformGetProcAddress("glXSwapIntervalSGI"); - - if (window->GLX.SwapIntervalSGI) - window->GLX.SGI_swap_control = GL_TRUE; - } - - if (_glfwPlatformExtensionSupported("GLX_SGIX_fbconfig")) - { - window->GLX.GetFBConfigAttribSGIX = (PFNGLXGETFBCONFIGATTRIBSGIXPROC) - _glfwPlatformGetProcAddress("glXGetFBConfigAttribSGIX"); - window->GLX.ChooseFBConfigSGIX = (PFNGLXCHOOSEFBCONFIGSGIXPROC) - _glfwPlatformGetProcAddress("glXChooseFBConfigSGIX"); - window->GLX.CreateContextWithConfigSGIX = (PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) - _glfwPlatformGetProcAddress("glXCreateContextWithConfigSGIX"); - window->GLX.GetVisualFromFBConfigSGIX = (PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) - _glfwPlatformGetProcAddress("glXGetVisualFromFBConfigSGIX"); - - if (window->GLX.GetFBConfigAttribSGIX && - window->GLX.ChooseFBConfigSGIX && - window->GLX.CreateContextWithConfigSGIX && - window->GLX.GetVisualFromFBConfigSGIX) - { - window->GLX.SGIX_fbconfig = GL_TRUE; - } - } - - if (_glfwPlatformExtensionSupported("GLX_ARB_multisample")) - window->GLX.ARB_multisample = GL_TRUE; - - if (_glfwPlatformExtensionSupported("GLX_ARB_create_context")) - { - window->GLX.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) - _glfwPlatformGetProcAddress("glXCreateContextAttribsARB"); - - if (window->GLX.CreateContextAttribsARB) - window->GLX.ARB_create_context = GL_TRUE; - } - - if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_robustness")) - window->GLX.ARB_create_context_robustness = GL_TRUE; - - if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_profile")) - window->GLX.ARB_create_context_profile = GL_TRUE; - - if (_glfwPlatformExtensionSupported("GLX_EXT_create_context_es2_profile")) - window->GLX.EXT_create_context_es2_profile = GL_TRUE; -} - - //======================================================================== // Create the X11 window (and its colormap) //======================================================================== @@ -535,13 +97,14 @@ static GLboolean createWindow(_GLFWwindow* window, XEvent event; unsigned long wamask; XSetWindowAttributes wa; + XVisualInfo* visual = _glfwGetContextVisual(window); // Every window needs a colormap // Create one based on the visual used by the current context window->X11.colormap = XCreateColormap(_glfwLibrary.X11.display, _glfwLibrary.X11.root, - window->GLX.visual->visual, + visual->visual, AllocNone); // Create the actual window @@ -571,9 +134,9 @@ static GLboolean createWindow(_GLFWwindow* window, 0, 0, // Upper left corner of this window on root window->width, window->height, 0, // Border width - window->GLX.visual->depth, // Color depth + visual->depth, // Color depth InputOutput, - window->GLX.visual->visual, + visual->visual, wamask, &wa ); @@ -1355,42 +918,10 @@ int _glfwPlatformOpenWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWfbconfig* fbconfig) { - _GLFWfbconfig closest; - window->refreshRate = wndconfig->refreshRate; window->resizable = wndconfig->resizable; - initGLXExtensions(window); - - // Choose the best available fbconfig - { - unsigned int fbcount; - _GLFWfbconfig* fbconfigs; - const _GLFWfbconfig* result; - - fbconfigs = getFBConfigs(window, &fbcount); - if (!fbconfigs) - { - _glfwSetError(GLFW_PLATFORM_ERROR, - "X11/GLX: No usable GLXFBConfigs found"); - return GL_FALSE; - } - - result = _glfwChooseFBConfig(fbconfig, fbconfigs, fbcount); - if (!result) - { - _glfwSetError(GLFW_PLATFORM_ERROR, - "X11/GLX: No GLXFBConfig matched the criteria"); - - free(fbconfigs); - return GL_FALSE; - } - - closest = *result; - free(fbconfigs); - } - - if (!createContext(window, wndconfig, (GLXFBConfigID) closest.platformID)) + if (!_glfwCreateContext(window, wndconfig, fbconfig)) return GL_FALSE; if (!createWindow(window, wndconfig)) @@ -1447,19 +978,7 @@ void _glfwPlatformCloseWindow(_GLFWwindow* window) if (window->mode == GLFW_FULLSCREEN) leaveFullscreenMode(window); - if (window->GLX.context) - { - // Release and destroy the context - glXMakeCurrent(_glfwLibrary.X11.display, None, NULL); - glXDestroyContext(_glfwLibrary.X11.display, window->GLX.context); - window->GLX.context = NULL; - } - - if (window->GLX.visual) - { - XFree(window->GLX.visual); - window->GLX.visual = NULL; - } + _glfwDestroyContext(window); if (window->X11.handle) { @@ -1620,8 +1139,6 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window) void _glfwPlatformRefreshWindowParams(void) { - int dummy; - GLXFBConfig* fbconfig; #if defined(_GLFW_HAS_XRANDR) XRRScreenConfiguration* sc; #endif /*_GLFW_HAS_XRANDR*/ @@ -1632,58 +1149,6 @@ void _glfwPlatformRefreshWindowParams(void) #endif /*_GLFW_HAS_XF86VIDMODE*/ _GLFWwindow* window = _glfwLibrary.currentWindow; - int attribs[] = { GLX_FBCONFIG_ID, window->GLX.fbconfigID, None }; - - if (window->GLX.SGIX_fbconfig) - { - fbconfig = window->GLX.ChooseFBConfigSGIX(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - attribs, - &dummy); - } - else - { - fbconfig = glXChooseFBConfig(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - attribs, - &dummy); - } - - if (fbconfig == NULL) - { - // This should never ever happen - // TODO: Flag this as an error and propagate up - fprintf(stderr, "Cannot find known GLXFBConfig by ID. " - "This cannot happen. Have a nice day.\n"); - abort(); - } - - // There is no clear definition of an "accelerated" context on X11/GLX, and - // true sounds better than false, so we hardcode true here - window->accelerated = GL_TRUE; - - window->redBits = getFBConfigAttrib(window, *fbconfig, GLX_RED_SIZE); - window->greenBits = getFBConfigAttrib(window, *fbconfig, GLX_GREEN_SIZE); - window->blueBits = getFBConfigAttrib(window, *fbconfig, GLX_BLUE_SIZE); - - window->alphaBits = getFBConfigAttrib(window, *fbconfig, GLX_ALPHA_SIZE); - window->depthBits = getFBConfigAttrib(window, *fbconfig, GLX_DEPTH_SIZE); - window->stencilBits = getFBConfigAttrib(window, *fbconfig, GLX_STENCIL_SIZE); - - window->accumRedBits = getFBConfigAttrib(window, *fbconfig, GLX_ACCUM_RED_SIZE); - window->accumGreenBits = getFBConfigAttrib(window, *fbconfig, GLX_ACCUM_GREEN_SIZE); - window->accumBlueBits = getFBConfigAttrib(window, *fbconfig, GLX_ACCUM_BLUE_SIZE); - window->accumAlphaBits = getFBConfigAttrib(window, *fbconfig, GLX_ACCUM_ALPHA_SIZE); - - window->auxBuffers = getFBConfigAttrib(window, *fbconfig, GLX_AUX_BUFFERS); - window->stereo = getFBConfigAttrib(window, *fbconfig, GLX_STEREO) ? GL_TRUE : GL_FALSE; - - // Get FSAA buffer sample count - if (window->GLX.ARB_multisample) - window->samples = getFBConfigAttrib(window, *fbconfig, GLX_SAMPLES); - else - window->samples = 0; - // Retrieve refresh rate if possible if (_glfwLibrary.X11.RandR.available) { @@ -1710,8 +1175,6 @@ void _glfwPlatformRefreshWindowParams(void) // Zero means unknown according to the GLFW spec window->refreshRate = 0; } - - XFree(fbconfig); }