volviewer

Volumetric Data Toy Viewer
git clone anongit@rnpnr.xyz:volviewer.git
Log | Files | Refs | Feed | LICENSE

glx_context.c (23690B)


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