medfall

A super great game engine
Log | Files | Refs

glx_context.cc (21841B)


      1 //========================================================================
      2 // GLFW 3.3 GLX - www.glfw.org
      3 //------------------------------------------------------------------------
      4 // Copyright (c) 2002-2006 Marcus Geelnard
      5 // Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
      6 //
      7 // This software is provided 'as-is', without any express or implied
      8 // warranty. In no event will the authors be held liable for any damages
      9 // arising from the use of this software.
     10 //
     11 // Permission is granted to anyone to use this software for any purpose,
     12 // including commercial applications, and to alter it and redistribute it
     13 // freely, subject to the following restrictions:
     14 //
     15 // 1. The origin of this software must not be misrepresented; you must not
     16 //    claim that you wrote the original software. If you use this software
     17 //    in a product, an acknowledgment in the product documentation would
     18 //    be appreciated but is not required.
     19 //
     20 // 2. Altered source versions must be plainly marked as such, and must not
     21 //    be misrepresented as being the original software.
     22 //
     23 // 3. This notice may not be removed or altered from any source
     24 //    distribution.
     25 //
     26 //========================================================================
     27 
     28 #include "internal.h"
     29 
     30 #include <string.h>
     31 #include <stdlib.h>
     32 #include <assert.h>
     33 
     34 #ifndef GLXBadProfileARB
     35  #define GLXBadProfileARB 13
     36 #endif
     37 
     38 
     39 // Returns the specified attribute of the specified GLXFBConfig
     40 //
     41 static int getGLXFBConfigAttrib(GLXFBConfig fbconfig, int attrib)
     42 {
     43     int value;
     44     glXGetFBConfigAttrib(_glfw.x11.display, fbconfig, attrib, &value);
     45     return value;
     46 }
     47 
     48 // Return the GLXFBConfig most closely matching the specified hints
     49 //
     50 static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* result)
     51 {
     52     GLXFBConfig* nativeConfigs;
     53     _GLFWfbconfig* usableConfigs;
     54     const _GLFWfbconfig* closest;
     55     int i, nativeCount, usableCount;
     56     const char* vendor;
     57     GLFWbool trustWindowBit = GLFW_TRUE;
     58 
     59     // HACK: This is a (hopefully temporary) workaround for Chromium
     60     //       (VirtualBox GL) not setting the window bit on any GLXFBConfigs
     61     vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR);
     62     if (vendor && strcmp(vendor, "Chromium") == 0)
     63         trustWindowBit = GLFW_FALSE;
     64 
     65     nativeConfigs =
     66         glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen, &nativeCount);
     67     if (!nativeConfigs || !nativeCount)
     68     {
     69         _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned");
     70         return GLFW_FALSE;
     71     }
     72 
     73     usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
     74     usableCount = 0;
     75 
     76     for (i = 0;  i < nativeCount;  i++)
     77     {
     78         const GLXFBConfig n = nativeConfigs[i];
     79         _GLFWfbconfig* u = usableConfigs + usableCount;
     80 
     81         // Only consider RGBA GLXFBConfigs
     82         if (!(getGLXFBConfigAttrib(n, GLX_RENDER_TYPE) & GLX_RGBA_BIT))
     83             continue;
     84 
     85         // Only consider window GLXFBConfigs
     86         if (!(getGLXFBConfigAttrib(n, GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT))
     87         {
     88             if (trustWindowBit)
     89                 continue;
     90         }
     91 
     92         u->redBits = getGLXFBConfigAttrib(n, GLX_RED_SIZE);
     93         u->greenBits = getGLXFBConfigAttrib(n, GLX_GREEN_SIZE);
     94         u->blueBits = getGLXFBConfigAttrib(n, GLX_BLUE_SIZE);
     95 
     96         u->alphaBits = getGLXFBConfigAttrib(n, GLX_ALPHA_SIZE);
     97         u->depthBits = getGLXFBConfigAttrib(n, GLX_DEPTH_SIZE);
     98         u->stencilBits = getGLXFBConfigAttrib(n, GLX_STENCIL_SIZE);
     99 
    100         u->accumRedBits = getGLXFBConfigAttrib(n, GLX_ACCUM_RED_SIZE);
    101         u->accumGreenBits = getGLXFBConfigAttrib(n, GLX_ACCUM_GREEN_SIZE);
    102         u->accumBlueBits = getGLXFBConfigAttrib(n, GLX_ACCUM_BLUE_SIZE);
    103         u->accumAlphaBits = getGLXFBConfigAttrib(n, GLX_ACCUM_ALPHA_SIZE);
    104 
    105         u->auxBuffers = getGLXFBConfigAttrib(n, GLX_AUX_BUFFERS);
    106 
    107         if (getGLXFBConfigAttrib(n, GLX_STEREO))
    108             u->stereo = GLFW_TRUE;
    109         if (getGLXFBConfigAttrib(n, GLX_DOUBLEBUFFER))
    110             u->doublebuffer = GLFW_TRUE;
    111 
    112         if (_glfw.glx.ARB_multisample)
    113             u->samples = getGLXFBConfigAttrib(n, GLX_SAMPLES);
    114 
    115         if (_glfw.glx.ARB_framebuffer_sRGB || _glfw.glx.EXT_framebuffer_sRGB)
    116             u->sRGB = getGLXFBConfigAttrib(n, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB);
    117 
    118         u->handle = (uintptr_t) n;
    119         usableCount++;
    120     }
    121 
    122     closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
    123     if (closest)
    124         *result = (GLXFBConfig) closest->handle;
    125 
    126     XFree(nativeConfigs);
    127     free(usableConfigs);
    128 
    129     return closest != NULL;
    130 }
    131 
    132 // Create the OpenGL context using legacy API
    133 //
    134 static GLXContext createLegacyContextGLX(_GLFWwindow* window,
    135                                          GLXFBConfig fbconfig,
    136                                          GLXContext share)
    137 {
    138     return glXCreateNewContext(_glfw.x11.display,
    139                                fbconfig,
    140                                GLX_RGBA_TYPE,
    141                                share,
    142                                True);
    143 }
    144 
    145 static void makeContextCurrentGLX(_GLFWwindow* window)
    146 {
    147     if (window)
    148     {
    149         if (!glXMakeCurrent(_glfw.x11.display,
    150                             window->context.glx.window,
    151                             window->context.glx.handle))
    152         {
    153             _glfwInputError(GLFW_PLATFORM_ERROR,
    154                             "GLX: Failed to make context current");
    155             return;
    156         }
    157     }
    158     else
    159     {
    160         if (!glXMakeCurrent(_glfw.x11.display, None, NULL))
    161         {
    162             _glfwInputError(GLFW_PLATFORM_ERROR,
    163                             "GLX: Failed to clear current context");
    164             return;
    165         }
    166     }
    167 
    168     _glfwPlatformSetTls(&_glfw.contextSlot, window);
    169 }
    170 
    171 static void swapBuffersGLX(_GLFWwindow* window)
    172 {
    173     glXSwapBuffers(_glfw.x11.display, window->context.glx.window);
    174 }
    175 
    176 static void swapIntervalGLX(int interval)
    177 {
    178     _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
    179 
    180     if (_glfw.glx.EXT_swap_control)
    181     {
    182         _glfw.glx.SwapIntervalEXT(_glfw.x11.display,
    183                                   window->context.glx.window,
    184                                   interval);
    185     }
    186     else if (_glfw.glx.MESA_swap_control)
    187         _glfw.glx.SwapIntervalMESA(interval);
    188     else if (_glfw.glx.SGI_swap_control)
    189     {
    190         if (interval > 0)
    191             _glfw.glx.SwapIntervalSGI(interval);
    192     }
    193 }
    194 
    195 static int extensionSupportedGLX(const char* extension)
    196 {
    197     const char* extensions =
    198         glXQueryExtensionsString(_glfw.x11.display, _glfw.x11.screen);
    199     if (extensions)
    200     {
    201         if (_glfwStringInExtensionString(extension, extensions))
    202             return GLFW_TRUE;
    203     }
    204 
    205     return GLFW_FALSE;
    206 }
    207 
    208 static GLFWglproc getProcAddressGLX(const char* procname)
    209 {
    210     if (_glfw.glx.GetProcAddress)
    211         return _glfw.glx.GetProcAddress((const GLubyte*) procname);
    212     else if (_glfw.glx.GetProcAddressARB)
    213         return _glfw.glx.GetProcAddressARB((const GLubyte*) procname);
    214     else
    215         return dlsym(_glfw.glx.handle, procname);
    216 }
    217 
    218 // Destroy the OpenGL context
    219 //
    220 static void destroyContextGLX(_GLFWwindow* window)
    221 {
    222     if (window->context.glx.window)
    223     {
    224         glXDestroyWindow(_glfw.x11.display, window->context.glx.window);
    225         window->context.glx.window = None;
    226     }
    227 
    228     if (window->context.glx.handle)
    229     {
    230         glXDestroyContext(_glfw.x11.display, window->context.glx.handle);
    231         window->context.glx.handle = NULL;
    232     }
    233 }
    234 
    235 
    236 //////////////////////////////////////////////////////////////////////////
    237 //////                       GLFW internal API                      //////
    238 //////////////////////////////////////////////////////////////////////////
    239 
    240 // Initialize GLX
    241 //
    242 GLFWbool _glfwInitGLX(void)
    243 {
    244     int i;
    245     const char* sonames[] =
    246     {
    247 #if defined(__CYGWIN__)
    248         "libGL-1.so",
    249 #else
    250         "libGL.so.1",
    251         "libGL.so",
    252 #endif
    253         NULL
    254     };
    255 
    256     if (_glfw.glx.handle)
    257         return GLFW_TRUE;
    258 
    259     for (i = 0;  sonames[i];  i++)
    260     {
    261         _glfw.glx.handle = dlopen(sonames[i], RTLD_LAZY | RTLD_GLOBAL);
    262         if (_glfw.glx.handle)
    263             break;
    264     }
    265 
    266     if (!_glfw.glx.handle)
    267     {
    268         _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: Failed to load GLX");
    269         return GLFW_FALSE;
    270     }
    271 
    272     _glfw.glx.GetFBConfigs =
    273         dlsym(_glfw.glx.handle, "glXGetFBConfigs");
    274     _glfw.glx.GetFBConfigAttrib =
    275         dlsym(_glfw.glx.handle, "glXGetFBConfigAttrib");
    276     _glfw.glx.GetClientString =
    277         dlsym(_glfw.glx.handle, "glXGetClientString");
    278     _glfw.glx.QueryExtension =
    279         dlsym(_glfw.glx.handle, "glXQueryExtension");
    280     _glfw.glx.QueryVersion =
    281         dlsym(_glfw.glx.handle, "glXQueryVersion");
    282     _glfw.glx.DestroyContext =
    283         dlsym(_glfw.glx.handle, "glXDestroyContext");
    284     _glfw.glx.MakeCurrent =
    285         dlsym(_glfw.glx.handle, "glXMakeCurrent");
    286     _glfw.glx.SwapBuffers =
    287         dlsym(_glfw.glx.handle, "glXSwapBuffers");
    288     _glfw.glx.QueryExtensionsString =
    289         dlsym(_glfw.glx.handle, "glXQueryExtensionsString");
    290     _glfw.glx.CreateNewContext =
    291         dlsym(_glfw.glx.handle, "glXCreateNewContext");
    292     _glfw.glx.CreateWindow =
    293         dlsym(_glfw.glx.handle, "glXCreateWindow");
    294     _glfw.glx.DestroyWindow =
    295         dlsym(_glfw.glx.handle, "glXDestroyWindow");
    296     _glfw.glx.GetProcAddress =
    297         dlsym(_glfw.glx.handle, "glXGetProcAddress");
    298     _glfw.glx.GetProcAddressARB =
    299         dlsym(_glfw.glx.handle, "glXGetProcAddressARB");
    300     _glfw.glx.GetVisualFromFBConfig =
    301         dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig");
    302 
    303     if (!_glfw.glx.GetFBConfigs ||
    304         !_glfw.glx.GetFBConfigAttrib ||
    305         !_glfw.glx.GetClientString ||
    306         !_glfw.glx.QueryExtension ||
    307         !_glfw.glx.QueryVersion ||
    308         !_glfw.glx.DestroyContext ||
    309         !_glfw.glx.MakeCurrent ||
    310         !_glfw.glx.SwapBuffers ||
    311         !_glfw.glx.QueryExtensionsString ||
    312         !_glfw.glx.CreateNewContext ||
    313         !_glfw.glx.CreateWindow ||
    314         !_glfw.glx.DestroyWindow ||
    315         !_glfw.glx.GetProcAddress ||
    316         !_glfw.glx.GetProcAddressARB ||
    317         !_glfw.glx.GetVisualFromFBConfig)
    318     {
    319         _glfwInputError(GLFW_PLATFORM_ERROR,
    320                         "GLX: Failed to load required entry points");
    321         return GLFW_FALSE;
    322     }
    323 
    324     if (!glXQueryExtension(_glfw.x11.display,
    325                            &_glfw.glx.errorBase,
    326                            &_glfw.glx.eventBase))
    327     {
    328         _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: GLX extension not found");
    329         return GLFW_FALSE;
    330     }
    331 
    332     if (!glXQueryVersion(_glfw.x11.display, &_glfw.glx.major, &_glfw.glx.minor))
    333     {
    334         _glfwInputError(GLFW_API_UNAVAILABLE,
    335                         "GLX: Failed to query GLX version");
    336         return GLFW_FALSE;
    337     }
    338 
    339     if (_glfw.glx.major == 1 && _glfw.glx.minor < 3)
    340     {
    341         _glfwInputError(GLFW_API_UNAVAILABLE,
    342                         "GLX: GLX version 1.3 is required");
    343         return GLFW_FALSE;
    344     }
    345 
    346     if (extensionSupportedGLX("GLX_EXT_swap_control"))
    347     {
    348         _glfw.glx.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)
    349             getProcAddressGLX("glXSwapIntervalEXT");
    350 
    351         if (_glfw.glx.SwapIntervalEXT)
    352             _glfw.glx.EXT_swap_control = GLFW_TRUE;
    353     }
    354 
    355     if (extensionSupportedGLX("GLX_SGI_swap_control"))
    356     {
    357         _glfw.glx.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)
    358             getProcAddressGLX("glXSwapIntervalSGI");
    359 
    360         if (_glfw.glx.SwapIntervalSGI)
    361             _glfw.glx.SGI_swap_control = GLFW_TRUE;
    362     }
    363 
    364     if (extensionSupportedGLX("GLX_MESA_swap_control"))
    365     {
    366         _glfw.glx.SwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC)
    367             getProcAddressGLX("glXSwapIntervalMESA");
    368 
    369         if (_glfw.glx.SwapIntervalMESA)
    370             _glfw.glx.MESA_swap_control = GLFW_TRUE;
    371     }
    372 
    373     if (extensionSupportedGLX("GLX_ARB_multisample"))
    374         _glfw.glx.ARB_multisample = GLFW_TRUE;
    375 
    376     if (extensionSupportedGLX("GLX_ARB_framebuffer_sRGB"))
    377         _glfw.glx.ARB_framebuffer_sRGB = GLFW_TRUE;
    378 
    379     if (extensionSupportedGLX("GLX_EXT_framebuffer_sRGB"))
    380         _glfw.glx.EXT_framebuffer_sRGB = GLFW_TRUE;
    381 
    382     if (extensionSupportedGLX("GLX_ARB_create_context"))
    383     {
    384         _glfw.glx.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
    385             getProcAddressGLX("glXCreateContextAttribsARB");
    386 
    387         if (_glfw.glx.CreateContextAttribsARB)
    388             _glfw.glx.ARB_create_context = GLFW_TRUE;
    389     }
    390 
    391     if (extensionSupportedGLX("GLX_ARB_create_context_robustness"))
    392         _glfw.glx.ARB_create_context_robustness = GLFW_TRUE;
    393 
    394     if (extensionSupportedGLX("GLX_ARB_create_context_profile"))
    395         _glfw.glx.ARB_create_context_profile = GLFW_TRUE;
    396 
    397     if (extensionSupportedGLX("GLX_EXT_create_context_es2_profile"))
    398         _glfw.glx.EXT_create_context_es2_profile = GLFW_TRUE;
    399 
    400     if (extensionSupportedGLX("GLX_ARB_create_context_no_error"))
    401         _glfw.glx.ARB_create_context_no_error = GLFW_TRUE;
    402 
    403     if (extensionSupportedGLX("GLX_ARB_context_flush_control"))
    404         _glfw.glx.ARB_context_flush_control = GLFW_TRUE;
    405 
    406     return GLFW_TRUE;
    407 }
    408 
    409 // Terminate GLX
    410 //
    411 void _glfwTerminateGLX(void)
    412 {
    413     // NOTE: This function must not call any X11 functions, as it is called
    414     //       after XCloseDisplay (see _glfwPlatformTerminate for details)
    415 
    416     if (_glfw.glx.handle)
    417     {
    418         dlclose(_glfw.glx.handle);
    419         _glfw.glx.handle = NULL;
    420     }
    421 }
    422 
    423 #define setAttrib(a, v) \
    424 { \
    425     assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
    426     attribs[index++] = a; \
    427     attribs[index++] = v; \
    428 }
    429 
    430 // Create the OpenGL or OpenGL ES context
    431 //
    432 GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
    433                                const _GLFWctxconfig* ctxconfig,
    434                                const _GLFWfbconfig* fbconfig)
    435 {
    436     int attribs[40];
    437     GLXFBConfig native = NULL;
    438     GLXContext share = NULL;
    439 
    440     if (ctxconfig->share)
    441         share = ctxconfig->share->context.glx.handle;
    442 
    443     if (!chooseGLXFBConfig(fbconfig, &native))
    444     {
    445         _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
    446                         "GLX: Failed to find a suitable GLXFBConfig");
    447         return GLFW_FALSE;
    448     }
    449 
    450     if (ctxconfig->client == GLFW_OPENGL_ES_API)
    451     {
    452         if (!_glfw.glx.ARB_create_context ||
    453             !_glfw.glx.ARB_create_context_profile ||
    454             !_glfw.glx.EXT_create_context_es2_profile)
    455         {
    456             _glfwInputError(GLFW_API_UNAVAILABLE,
    457                             "GLX: OpenGL ES requested but GLX_EXT_create_context_es2_profile is unavailable");
    458             return GLFW_FALSE;
    459         }
    460     }
    461 
    462     if (ctxconfig->forward)
    463     {
    464         if (!_glfw.glx.ARB_create_context)
    465         {
    466             _glfwInputError(GLFW_VERSION_UNAVAILABLE,
    467                             "GLX: Forward compatibility requested but GLX_ARB_create_context_profile is unavailable");
    468             return GLFW_FALSE;
    469         }
    470     }
    471 
    472     if (ctxconfig->profile)
    473     {
    474         if (!_glfw.glx.ARB_create_context ||
    475             !_glfw.glx.ARB_create_context_profile)
    476         {
    477             _glfwInputError(GLFW_VERSION_UNAVAILABLE,
    478                             "GLX: An OpenGL profile requested but GLX_ARB_create_context_profile is unavailable");
    479             return GLFW_FALSE;
    480         }
    481     }
    482 
    483     _glfwGrabErrorHandlerX11();
    484 
    485     if (_glfw.glx.ARB_create_context)
    486     {
    487         int index = 0, mask = 0, flags = 0;
    488 
    489         if (ctxconfig->client == GLFW_OPENGL_API)
    490         {
    491             if (ctxconfig->forward)
    492                 flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
    493 
    494             if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
    495                 mask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
    496             else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
    497                 mask |= GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
    498         }
    499         else
    500             mask |= GLX_CONTEXT_ES2_PROFILE_BIT_EXT;
    501 
    502         if (ctxconfig->debug)
    503             flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
    504 
    505         if (ctxconfig->robustness)
    506         {
    507             if (_glfw.glx.ARB_create_context_robustness)
    508             {
    509                 if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
    510                 {
    511                     setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
    512                               GLX_NO_RESET_NOTIFICATION_ARB);
    513                 }
    514                 else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
    515                 {
    516                     setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
    517                               GLX_LOSE_CONTEXT_ON_RESET_ARB);
    518                 }
    519 
    520                 flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB;
    521             }
    522         }
    523 
    524         if (ctxconfig->release)
    525         {
    526             if (_glfw.glx.ARB_context_flush_control)
    527             {
    528                 if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
    529                 {
    530                     setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
    531                               GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
    532                 }
    533                 else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
    534                 {
    535                     setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
    536                               GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
    537                 }
    538             }
    539         }
    540 
    541         if (ctxconfig->noerror)
    542         {
    543             if (_glfw.glx.ARB_create_context_no_error)
    544                 setAttrib(GLX_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
    545         }
    546 
    547         // NOTE: Only request an explicitly versioned context when necessary, as
    548         //       explicitly requesting version 1.0 does not always return the
    549         //       highest version supported by the driver
    550         if (ctxconfig->major != 1 || ctxconfig->minor != 0)
    551         {
    552             setAttrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
    553             setAttrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
    554         }
    555 
    556         if (mask)
    557             setAttrib(GLX_CONTEXT_PROFILE_MASK_ARB, mask);
    558 
    559         if (flags)
    560             setAttrib(GLX_CONTEXT_FLAGS_ARB, flags);
    561 
    562         setAttrib(None, None);
    563 
    564         window->context.glx.handle =
    565             _glfw.glx.CreateContextAttribsARB(_glfw.x11.display,
    566                                               native,
    567                                               share,
    568                                               True,
    569                                               attribs);
    570 
    571         // HACK: This is a fallback for broken versions of the Mesa
    572         //       implementation of GLX_ARB_create_context_profile that fail
    573         //       default 1.0 context creation with a GLXBadProfileARB error in
    574         //       violation of the extension spec
    575         if (!window->context.glx.handle)
    576         {
    577             if (_glfw.x11.errorCode == _glfw.glx.errorBase + GLXBadProfileARB &&
    578                 ctxconfig->client == GLFW_OPENGL_API &&
    579                 ctxconfig->profile == GLFW_OPENGL_ANY_PROFILE &&
    580                 ctxconfig->forward == GLFW_FALSE)
    581             {
    582                 window->context.glx.handle =
    583                     createLegacyContextGLX(window, native, share);
    584             }
    585         }
    586     }
    587     else
    588     {
    589         window->context.glx.handle =
    590             createLegacyContextGLX(window, native, share);
    591     }
    592 
    593     _glfwReleaseErrorHandlerX11();
    594 
    595     if (!window->context.glx.handle)
    596     {
    597         _glfwInputErrorX11(GLFW_VERSION_UNAVAILABLE, "GLX: Failed to create context");
    598         return GLFW_FALSE;
    599     }
    600 
    601     window->context.glx.window =
    602         glXCreateWindow(_glfw.x11.display, native, window->x11.handle, NULL);
    603     if (!window->context.glx.window)
    604     {
    605         _glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to create window");
    606         return GLFW_FALSE;
    607     }
    608 
    609     window->context.makeCurrent = makeContextCurrentGLX;
    610     window->context.swapBuffers = swapBuffersGLX;
    611     window->context.swapInterval = swapIntervalGLX;
    612     window->context.extensionSupported = extensionSupportedGLX;
    613     window->context.getProcAddress = getProcAddressGLX;
    614     window->context.destroy = destroyContextGLX;
    615 
    616     return GLFW_TRUE;
    617 }
    618 
    619 #undef setAttrib
    620 
    621 // Returns the Visual and depth of the chosen GLXFBConfig
    622 //
    623 GLFWbool _glfwChooseVisualGLX(const _GLFWctxconfig* ctxconfig,
    624                               const _GLFWfbconfig* fbconfig,
    625                               Visual** visual, int* depth)
    626 {
    627     GLXFBConfig native;
    628     XVisualInfo* result;
    629 
    630     if (!chooseGLXFBConfig(fbconfig, &native))
    631     {
    632         _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
    633                         "GLX: Failed to find a suitable GLXFBConfig");
    634         return GLFW_FALSE;
    635     }
    636 
    637     result = glXGetVisualFromFBConfig(_glfw.x11.display, native);
    638     if (!result)
    639     {
    640         _glfwInputError(GLFW_PLATFORM_ERROR,
    641                         "GLX: Failed to retrieve Visual for GLXFBConfig");
    642         return GLFW_FALSE;
    643     }
    644 
    645     *visual = result->visual;
    646     *depth = result->depth;
    647 
    648     XFree(result);
    649     return GLFW_TRUE;
    650 }
    651 
    652 
    653 //////////////////////////////////////////////////////////////////////////
    654 //////                        GLFW native API                       //////
    655 //////////////////////////////////////////////////////////////////////////
    656 
    657 GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* handle)
    658 {
    659     _GLFWwindow* window = (_GLFWwindow*) handle;
    660     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
    661 
    662     if (window->context.client == GLFW_NO_API)
    663     {
    664         _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
    665         return NULL;
    666     }
    667 
    668     return window->context.glx.handle;
    669 }
    670 
    671 GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* handle)
    672 {
    673     _GLFWwindow* window = (_GLFWwindow*) handle;
    674     _GLFW_REQUIRE_INIT_OR_RETURN(None);
    675 
    676     if (window->context.client == GLFW_NO_API)
    677     {
    678         _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
    679         return None;
    680     }
    681 
    682     return window->context.glx.window;
    683 }
    684