• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //========================================================================
2 // GLFW 3.2 GLX - www.glfw.org
3 //------------------------------------------------------------------------
4 // Copyright (c) 2002-2006 Marcus Geelnard
5 // Copyright (c) 2006-2016 Camilla Berglund <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 //
getGLXFBConfigAttrib(GLXFBConfig fbconfig,int attrib)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 //
chooseGLXFBConfig(const _GLFWfbconfig * desired,GLXFBConfig * result)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 (strcmp(vendor, "Chromium") == 0)
63         trustWindowBit = GLFW_FALSE;
64 
65     nativeConfigs =
66         glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen, &nativeCount);
67     if (!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 //
createLegacyContextGLX(_GLFWwindow * window,GLXFBConfig fbconfig,GLXContext share)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 
makeContextCurrentGLX(_GLFWwindow * window)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     _glfwPlatformSetCurrentContext(window);
169 }
170 
swapBuffersGLX(_GLFWwindow * window)171 static void swapBuffersGLX(_GLFWwindow* window)
172 {
173     glXSwapBuffers(_glfw.x11.display, window->context.glx.window);
174 }
175 
swapIntervalGLX(int interval)176 static void swapIntervalGLX(int interval)
177 {
178     _GLFWwindow* window = _glfwPlatformGetCurrentContext();
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 
extensionSupportedGLX(const char * extension)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 
getProcAddressGLX(const char * procname)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 //
destroyContextGLX(_GLFWwindow * window)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 //
_glfwInitGLX(void)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_context_flush_control"))
401         _glfw.glx.ARB_context_flush_control = GLFW_TRUE;
402 
403     return GLFW_TRUE;
404 }
405 
406 // Terminate GLX
407 //
_glfwTerminateGLX(void)408 void _glfwTerminateGLX(void)
409 {
410     // NOTE: This function must not call any X11 functions, as it is called
411     //       after XCloseDisplay (see _glfwPlatformTerminate for details)
412 
413     if (_glfw.glx.handle)
414     {
415         dlclose(_glfw.glx.handle);
416         _glfw.glx.handle = NULL;
417     }
418 }
419 
420 #define setGLXattrib(attribName, attribValue) \
421 { \
422     attribs[index++] = attribName; \
423     attribs[index++] = attribValue; \
424     assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
425 }
426 
427 // Create the OpenGL or OpenGL ES context
428 //
_glfwCreateContextGLX(_GLFWwindow * window,const _GLFWctxconfig * ctxconfig,const _GLFWfbconfig * fbconfig)429 GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
430                                const _GLFWctxconfig* ctxconfig,
431                                const _GLFWfbconfig* fbconfig)
432 {
433     int attribs[40];
434     GLXFBConfig native = NULL;
435     GLXContext share = NULL;
436 
437     if (ctxconfig->share)
438         share = ctxconfig->share->context.glx.handle;
439 
440     if (!chooseGLXFBConfig(fbconfig, &native))
441     {
442         _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
443                         "GLX: Failed to find a suitable GLXFBConfig");
444         return GLFW_FALSE;
445     }
446 
447     if (ctxconfig->client == GLFW_OPENGL_ES_API)
448     {
449         if (!_glfw.glx.ARB_create_context ||
450             !_glfw.glx.ARB_create_context_profile ||
451             !_glfw.glx.EXT_create_context_es2_profile)
452         {
453             _glfwInputError(GLFW_API_UNAVAILABLE,
454                             "GLX: OpenGL ES requested but GLX_EXT_create_context_es2_profile is unavailable");
455             return GLFW_FALSE;
456         }
457     }
458 
459     if (ctxconfig->forward)
460     {
461         if (!_glfw.glx.ARB_create_context)
462         {
463             _glfwInputError(GLFW_VERSION_UNAVAILABLE,
464                             "GLX: Forward compatibility requested but GLX_ARB_create_context_profile is unavailable");
465             return GLFW_FALSE;
466         }
467     }
468 
469     if (ctxconfig->profile)
470     {
471         if (!_glfw.glx.ARB_create_context ||
472             !_glfw.glx.ARB_create_context_profile)
473         {
474             _glfwInputError(GLFW_VERSION_UNAVAILABLE,
475                             "GLX: An OpenGL profile requested but GLX_ARB_create_context_profile is unavailable");
476             return GLFW_FALSE;
477         }
478     }
479 
480     _glfwGrabErrorHandlerX11();
481 
482     if (_glfw.glx.ARB_create_context)
483     {
484         int index = 0, mask = 0, flags = 0;
485 
486         if (ctxconfig->client == GLFW_OPENGL_API)
487         {
488             if (ctxconfig->forward)
489                 flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
490 
491             if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
492                 mask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
493             else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
494                 mask |= GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
495         }
496         else
497             mask |= GLX_CONTEXT_ES2_PROFILE_BIT_EXT;
498 
499         if (ctxconfig->debug)
500             flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
501         if (ctxconfig->noerror)
502             flags |= GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR;
503 
504         if (ctxconfig->robustness)
505         {
506             if (_glfw.glx.ARB_create_context_robustness)
507             {
508                 if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
509                 {
510                     setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
511                                  GLX_NO_RESET_NOTIFICATION_ARB);
512                 }
513                 else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
514                 {
515                     setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
516                                  GLX_LOSE_CONTEXT_ON_RESET_ARB);
517                 }
518 
519                 flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB;
520             }
521         }
522 
523         if (ctxconfig->release)
524         {
525             if (_glfw.glx.ARB_context_flush_control)
526             {
527                 if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
528                 {
529                     setGLXattrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
530                                  GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
531                 }
532                 else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
533                 {
534                     setGLXattrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
535                                  GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
536                 }
537             }
538         }
539 
540         // NOTE: Only request an explicitly versioned context when necessary, as
541         //       explicitly requesting version 1.0 does not always return the
542         //       highest version supported by the driver
543         if (ctxconfig->major != 1 || ctxconfig->minor != 0)
544         {
545             setGLXattrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
546             setGLXattrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
547         }
548 
549         if (mask)
550             setGLXattrib(GLX_CONTEXT_PROFILE_MASK_ARB, mask);
551 
552         if (flags)
553             setGLXattrib(GLX_CONTEXT_FLAGS_ARB, flags);
554 
555         setGLXattrib(None, None);
556 
557         window->context.glx.handle =
558             _glfw.glx.CreateContextAttribsARB(_glfw.x11.display,
559                                               native,
560                                               share,
561                                               True,
562                                               attribs);
563 
564         // HACK: This is a fallback for broken versions of the Mesa
565         //       implementation of GLX_ARB_create_context_profile that fail
566         //       default 1.0 context creation with a GLXBadProfileARB error in
567         //       violation of the extension spec
568         if (!window->context.glx.handle)
569         {
570             if (_glfw.x11.errorCode == _glfw.glx.errorBase + GLXBadProfileARB &&
571                 ctxconfig->client == GLFW_OPENGL_API &&
572                 ctxconfig->profile == GLFW_OPENGL_ANY_PROFILE &&
573                 ctxconfig->forward == GLFW_FALSE)
574             {
575                 window->context.glx.handle =
576                     createLegacyContextGLX(window, native, share);
577             }
578         }
579     }
580     else
581     {
582         window->context.glx.handle =
583             createLegacyContextGLX(window, native, share);
584     }
585 
586     _glfwReleaseErrorHandlerX11();
587 
588     if (!window->context.glx.handle)
589     {
590         _glfwInputErrorX11(GLFW_VERSION_UNAVAILABLE, "GLX: Failed to create context");
591         return GLFW_FALSE;
592     }
593 
594     window->context.glx.window =
595         glXCreateWindow(_glfw.x11.display, native, window->x11.handle, NULL);
596     if (!window->context.glx.window)
597     {
598         _glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to create window");
599         return GLFW_FALSE;
600     }
601 
602     window->context.makeCurrent = makeContextCurrentGLX;
603     window->context.swapBuffers = swapBuffersGLX;
604     window->context.swapInterval = swapIntervalGLX;
605     window->context.extensionSupported = extensionSupportedGLX;
606     window->context.getProcAddress = getProcAddressGLX;
607     window->context.destroy = destroyContextGLX;
608 
609     return GLFW_TRUE;
610 }
611 
612 #undef setGLXattrib
613 
614 // Returns the Visual and depth of the chosen GLXFBConfig
615 //
_glfwChooseVisualGLX(const _GLFWctxconfig * ctxconfig,const _GLFWfbconfig * fbconfig,Visual ** visual,int * depth)616 GLFWbool _glfwChooseVisualGLX(const _GLFWctxconfig* ctxconfig,
617                               const _GLFWfbconfig* fbconfig,
618                               Visual** visual, int* depth)
619 {
620     GLXFBConfig native;
621     XVisualInfo* result;
622 
623     if (!chooseGLXFBConfig(fbconfig, &native))
624     {
625         _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
626                         "GLX: Failed to find a suitable GLXFBConfig");
627         return GLFW_FALSE;
628     }
629 
630     result = glXGetVisualFromFBConfig(_glfw.x11.display, native);
631     if (!result)
632     {
633         _glfwInputError(GLFW_PLATFORM_ERROR,
634                         "GLX: Failed to retrieve Visual for GLXFBConfig");
635         return GLFW_FALSE;
636     }
637 
638     *visual = result->visual;
639     *depth = result->depth;
640 
641     XFree(result);
642     return GLFW_TRUE;
643 }
644 
645 
646 //////////////////////////////////////////////////////////////////////////
647 //////                        GLFW native API                       //////
648 //////////////////////////////////////////////////////////////////////////
649 
glfwGetGLXContext(GLFWwindow * handle)650 GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* handle)
651 {
652     _GLFWwindow* window = (_GLFWwindow*) handle;
653     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
654 
655     if (window->context.client == GLFW_NO_API)
656     {
657         _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
658         return NULL;
659     }
660 
661     return window->context.glx.handle;
662 }
663 
glfwGetGLXWindow(GLFWwindow * handle)664 GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* handle)
665 {
666     _GLFWwindow* window = (_GLFWwindow*) handle;
667     _GLFW_REQUIRE_INIT_OR_RETURN(None);
668 
669     if (window->context.client == GLFW_NO_API)
670     {
671         _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
672         return None;
673     }
674 
675     return window->context.glx.window;
676 }
677 
678