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