1 /// Translated from C to D
2 module glfw3.egl_context;
3 
4 extern(C): @nogc: nothrow: __gshared:
5 //========================================================================
6 // GLFW 3.3 EGL - 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 // Please use C89 style variable declarations in this file because VS 2010
32 //========================================================================
33 
34 // HEADER
35 version (_GLFW_WIN32) {
36     alias EGLNativeDisplayType = HDC;
37     alias EGLNativeWindowType = HWND;
38 } else version (_GLFW_COCOA) {
39     alias EGLNativeDisplayType = void*;
40     alias EGLNativeWindowType = id ;
41 } else version (_GLFW_X11) {
42     alias EGLNativeDisplayType = Display*;
43     alias EGLNativeWindowType = Window;
44 } else version (_GLFW_WAYLAND) {
45     alias EGLNativeDisplayType = wl_display*;
46     alias EGLNativeWindowType = wl_egl_window*;
47 } else {
48     static assert(0, "No supported EGL platform selected");
49 }
50 
51 enum EGL_SUCCESS = 0x3000;
52 enum EGL_NOT_INITIALIZED = 0x3001;
53 enum EGL_BAD_ACCESS = 0x3002;
54 enum EGL_BAD_ALLOC = 0x3003;
55 enum EGL_BAD_ATTRIBUTE = 0x3004;
56 enum EGL_BAD_CONFIG = 0x3005;
57 enum EGL_BAD_CONTEXT = 0x3006;
58 enum EGL_BAD_CURRENT_SURFACE = 0x3007;
59 enum EGL_BAD_DISPLAY = 0x3008;
60 enum EGL_BAD_MATCH = 0x3009;
61 enum EGL_BAD_NATIVE_PIXMAP = 0x300a;
62 enum EGL_BAD_NATIVE_WINDOW = 0x300b;
63 enum EGL_BAD_PARAMETER = 0x300c;
64 enum EGL_BAD_SURFACE = 0x300d;
65 enum EGL_CONTEXT_LOST = 0x300e;
66 enum EGL_COLOR_BUFFER_TYPE = 0x303f;
67 enum EGL_RGB_BUFFER = 0x308e;
68 enum EGL_SURFACE_TYPE = 0x3033;
69 enum EGL_WINDOW_BIT = 0x0004;
70 enum EGL_RENDERABLE_TYPE = 0x3040;
71 enum EGL_OPENGL_ES_BIT = 0x0001;
72 enum EGL_OPENGL_ES2_BIT = 0x0004;
73 enum EGL_OPENGL_BIT = 0x0008;
74 enum EGL_ALPHA_SIZE = 0x3021;
75 enum EGL_BLUE_SIZE = 0x3022;
76 enum EGL_GREEN_SIZE = 0x3023;
77 enum EGL_RED_SIZE = 0x3024;
78 enum EGL_DEPTH_SIZE = 0x3025;
79 enum EGL_STENCIL_SIZE = 0x3026;
80 enum EGL_SAMPLES = 0x3031;
81 enum EGL_OPENGL_ES_API = 0x30a0;
82 enum EGL_OPENGL_API = 0x30a2;
83 enum EGL_NONE = 0x3038;
84 enum EGL_EXTENSIONS = 0x3055;
85 enum EGL_CONTEXT_CLIENT_VERSION = 0x3098;
86 enum EGL_NATIVE_VISUAL_ID = 0x302e;
87 enum EGL_NO_SURFACE = (cast(EGLSurface) 0);
88 enum EGL_NO_DISPLAY = (cast(EGLDisplay) 0);
89 enum EGL_NO_CONTEXT = (cast(EGLContext) 0);
90 enum EGL_DEFAULT_DISPLAY = (cast(EGLNativeDisplayType) 0);
91 
92 enum EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR = 0x00000002;
93 enum EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR = 0x00000001;
94 enum EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR = 0x00000002;
95 enum EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR = 0x00000001;
96 enum EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR = 0x31bd;
97 enum EGL_NO_RESET_NOTIFICATION_KHR = 0x31be;
98 enum EGL_LOSE_CONTEXT_ON_RESET_KHR = 0x31bf;
99 enum EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR = 0x00000004;
100 enum EGL_CONTEXT_MAJOR_VERSION_KHR = 0x3098;
101 enum EGL_CONTEXT_MINOR_VERSION_KHR = 0x30fb;
102 enum EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR = 0x30fd;
103 enum EGL_CONTEXT_FLAGS_KHR = 0x30fc;
104 enum EGL_CONTEXT_OPENGL_NO_ERROR_KHR = 0x31b3;
105 enum EGL_GL_COLORSPACE_KHR = 0x309d;
106 enum EGL_GL_COLORSPACE_SRGB_KHR = 0x3089;
107 enum EGL_CONTEXT_RELEASE_BEHAVIOR_KHR = 0x2097;
108 enum EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR = 0;
109 enum EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR = 0x2098;
110 
111 alias int EGLint;
112 alias uint EGLBoolean;
113 alias uint EGLenum;
114 alias void* EGLConfig;
115 alias void* EGLContext;
116 alias void* EGLDisplay;
117 alias void* EGLSurface;
118 
119 // EGL function pointer typedefs
120 extern(System) {
121     alias EGLBoolean function(EGLDisplay, EGLConfig, EGLint, EGLint*) PFN_eglGetConfigAttrib;
122     alias EGLBoolean function(EGLDisplay, EGLConfig*, EGLint, EGLint*) PFN_eglGetConfigs;
123     alias EGLDisplay function(EGLNativeDisplayType) PFN_eglGetDisplay;
124     alias EGLint function() PFN_eglGetError;
125     alias EGLBoolean function(EGLDisplay, EGLint*, EGLint*) PFN_eglInitialize;
126     alias EGLBoolean function(EGLDisplay) PFN_eglTerminate;
127     alias EGLBoolean function(EGLenum) PFN_eglBindAPI;
128     alias EGLContext function(EGLDisplay, EGLConfig, EGLContext, const(EGLint)*) PFN_eglCreateContext;
129     alias EGLBoolean function(EGLDisplay, EGLSurface) PFN_eglDestroySurface;
130     alias EGLBoolean function(EGLDisplay, EGLContext) PFN_eglDestroyContext;
131     alias EGLSurface function(EGLDisplay, EGLConfig, EGLNativeWindowType, const(EGLint)*) PFN_eglCreateWindowSurface;
132     alias EGLBoolean function(EGLDisplay, EGLSurface, EGLSurface, EGLContext) PFN_eglMakeCurrent;
133     alias EGLBoolean function(EGLDisplay, EGLSurface) PFN_eglSwapBuffers;
134     alias EGLBoolean function(EGLDisplay, EGLint) PFN_eglSwapInterval;
135     alias const(char)* function(EGLDisplay, EGLint) PFN_eglQueryString;
136     alias GLFWglproc function(const(char)*) PFN_eglGetProcAddress;
137 }
138 alias eglGetConfigAttrib = _glfw.egl.GetConfigAttrib;
139 alias eglGetConfigs = _glfw.egl.GetConfigs;
140 alias eglGetDisplay = _glfw.egl.GetDisplay;
141 alias eglGetError = _glfw.egl.GetError;
142 alias eglInitialize = _glfw.egl.Initialize;
143 alias eglTerminate = _glfw.egl.Terminate;
144 alias eglBindAPI = _glfw.egl.BindAPI;
145 alias eglCreateContext = _glfw.egl.CreateContext;
146 alias eglDestroySurface = _glfw.egl.DestroySurface;
147 alias eglDestroyContext = _glfw.egl.DestroyContext;
148 alias eglCreateWindowSurface = _glfw.egl.CreateWindowSurface;
149 alias eglMakeCurrent = _glfw.egl.MakeCurrent;
150 alias eglSwapBuffers = _glfw.egl.SwapBuffers;
151 alias eglSwapInterval = _glfw.egl.SwapInterval;
152 alias eglQueryString = _glfw.egl.QueryString;
153 alias eglGetProcAddress = _glfw.egl.GetProcAddress;
154 
155 mixin template _GLFW_EGL_CONTEXT_STATE() {        _GLFWcontextEGL egl;}
156 mixin template _GLFW_EGL_LIBRARY_CONTEXT_STATE() {_GLFWlibraryEGL egl;}
157 
158 // EGL-specific per-context data
159 //
160 struct _GLFWcontextEGL {
161    EGLConfig config;
162    EGLContext handle;
163    EGLSurface surface;
164 
165    void* client;
166 
167 }/+alias _GLFWcontextEGL _GLFWcontextEGL;+/
168 
169 // EGL-specific global data
170 //
171 struct _GLFWlibraryEGL {
172     EGLDisplay display;
173     EGLint major;EGLint minor;
174     GLFWbool prefix;
175 
176     GLFWbool KHR_create_context;
177     GLFWbool KHR_create_context_no_error;
178     GLFWbool KHR_gl_colorspace;
179     GLFWbool KHR_get_all_proc_addresses;
180     GLFWbool KHR_context_flush_control;
181 
182     void* handle;
183 
184     PFN_eglGetConfigAttrib GetConfigAttrib;
185     PFN_eglGetConfigs GetConfigs;
186     PFN_eglGetDisplay GetDisplay;
187     PFN_eglGetError GetError;
188     PFN_eglInitialize Initialize;
189     PFN_eglTerminate Terminate;
190     PFN_eglBindAPI BindAPI;
191     PFN_eglCreateContext CreateContext;
192     PFN_eglDestroySurface DestroySurface;
193     PFN_eglDestroyContext DestroyContext;
194     PFN_eglCreateWindowSurface CreateWindowSurface;
195     PFN_eglMakeCurrent MakeCurrent;
196     PFN_eglSwapBuffers SwapBuffers;
197     PFN_eglSwapInterval SwapInterval;
198     PFN_eglQueryString QueryString;
199     PFN_eglGetProcAddress GetProcAddress;
200 
201 }/+alias _GLFWlibraryEGL _GLFWlibraryEGL;+/
202 
203 
204 GLFWbool _glfwInitEGL();
205 void _glfwTerminateEGL();
206 GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, const(_GLFWctxconfig)* ctxconfig, const(_GLFWfbconfig)* fbconfig);
207 version (_GLFW_X11) {
208     GLFWbool _glfwChooseVisualEGL(const(_GLFWwndconfig)* wndconfig, const(_GLFWctxconfig)* ctxconfig, const(_GLFWfbconfig)* fbconfig, Visual** visual, int* depth);
209 } /*_GLFW_X11*/
210 
211 //////////////////////
212 
213 import glfw3.internal;
214 
215 import core.stdc.stdio;
216 import core.stdc.string;
217 import core.stdc.stdlib;
218 import core.stdc.assert_;
219 import core.stdc.stdint;
220 
221 // Return a description of the specified EGL error
222 //
223 static const(char)* getEGLErrorString(EGLint error) {
224     switch (error)
225     {
226         case EGL_SUCCESS:
227             return "Success";
228         case EGL_NOT_INITIALIZED:
229             return "EGL is not or could not be initialized";
230         case EGL_BAD_ACCESS:
231             return "EGL cannot access a requested resource";
232         case EGL_BAD_ALLOC:
233             return "EGL failed to allocate resources for the requested operation";
234         case EGL_BAD_ATTRIBUTE:
235             return "An unrecognized attribute or attribute value was passed in the attribute list";
236         case EGL_BAD_CONTEXT:
237             return "An EGLContext argument does not name a valid EGL rendering context";
238         case EGL_BAD_CONFIG:
239             return "An EGLConfig argument does not name a valid EGL frame buffer configuration";
240         case EGL_BAD_CURRENT_SURFACE:
241             return "The current surface of the calling thread is a window, pixel buffer or pixmap that is no longer valid";
242         case EGL_BAD_DISPLAY:
243             return "An EGLDisplay argument does not name a valid EGL display connection";
244         case EGL_BAD_SURFACE:
245             return "An EGLSurface argument does not name a valid surface configured for GL rendering";
246         case EGL_BAD_MATCH:
247             return "Arguments are inconsistent";
248         case EGL_BAD_PARAMETER:
249             return "One or more argument values are invalid";
250         case EGL_BAD_NATIVE_PIXMAP:
251             return "A NativePixmapType argument does not refer to a valid native pixmap";
252         case EGL_BAD_NATIVE_WINDOW:
253             return "A NativeWindowType argument does not refer to a valid native window";
254         case EGL_CONTEXT_LOST:
255             return "The application must destroy all contexts and reinitialise";
256         default:
257             return "ERROR: UNKNOWN EGL ERROR";
258     }
259 }
260 
261 // Returns the specified attribute of the specified EGLConfig
262 //
263 static int getEGLConfigAttrib(EGLConfig config, int attrib) {
264     int value;
265     _glfw.egl.GetConfigAttrib(_glfw.egl.display, config, attrib, &value);
266     return value;
267 }
268 
269 // Return the EGLConfig most closely matching the specified hints
270 //
271 static GLFWbool chooseEGLConfig(const(_GLFWctxconfig)* ctxconfig, const(_GLFWfbconfig)* desired, EGLConfig* result) {
272     EGLConfig* nativeConfigs;
273     _GLFWfbconfig* usableConfigs;
274     const(_GLFWfbconfig)* closest;
275     int i;int nativeCount;int usableCount;
276 
277     _glfw.egl.GetConfigs(_glfw.egl.display, null, 0, &nativeCount);
278     if (!nativeCount)
279     {
280         _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: No EGLConfigs returned");
281         return GLFW_FALSE;
282     }
283 
284     nativeConfigs = cast(typeof(nativeConfigs)) calloc(nativeCount, EGLConfig.sizeof);
285     _glfw.egl.GetConfigs(_glfw.egl.display, nativeConfigs, nativeCount, &nativeCount);
286 
287     usableConfigs = cast(typeof(usableConfigs)) calloc(nativeCount, _GLFWfbconfig.sizeof);
288     usableCount = 0;
289 
290     for (i = 0;  i < nativeCount;  i++)
291     {
292         EGLConfig n = nativeConfigs[i];
293         _GLFWfbconfig* u = usableConfigs + usableCount;
294 
295         // Only consider RGB(A) EGLConfigs
296         if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER)
297             continue;
298 
299         // Only consider window EGLConfigs
300         if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))
301             continue;
302 
303         version (_GLFW_X11)
304         {
305             XVisualInfo vi = XVisualInfo(null);
306 
307             // Only consider EGLConfigs with associated Visuals
308             vi.visualid = getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID);
309             if (!vi.visualid)
310                 continue;
311 
312             if (desired.transparent)
313             {
314                 int count;
315                 XVisualInfo* vis = XGetVisualInfo(_glfw.x11.display, VisualIDMask, &vi, &count);
316                 if (vis)
317                 {
318                     u.transparent = _glfwIsVisualTransparentX11(vis[0].visual);
319                     XFree(vis);
320                 }
321             }
322         }
323 
324         if (ctxconfig.client == GLFW_OPENGL_ES_API)
325         {
326             if (ctxconfig.major == 1)
327             {
328                 if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT))
329                     continue;
330             }
331             else
332             {
333                 if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT))
334                     continue;
335             }
336         }
337         else if (ctxconfig.client == GLFW_OPENGL_API)
338         {
339             if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT))
340                 continue;
341         }
342 
343         u.redBits = getEGLConfigAttrib(n, EGL_RED_SIZE);
344         u.greenBits = getEGLConfigAttrib(n, EGL_GREEN_SIZE);
345         u.blueBits = getEGLConfigAttrib(n, EGL_BLUE_SIZE);
346 
347         u.alphaBits = getEGLConfigAttrib(n, EGL_ALPHA_SIZE);
348         u.depthBits = getEGLConfigAttrib(n, EGL_DEPTH_SIZE);
349         u.stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE);
350 
351         u.samples = getEGLConfigAttrib(n, EGL_SAMPLES);
352         u.doublebuffer = GLFW_TRUE;
353 
354         u.handle = cast(uintptr_t) n;
355         usableCount++;
356     }
357 
358     closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
359     if (closest)
360         *result = cast(EGLConfig) closest.handle;
361 
362     free(nativeConfigs);
363     free(usableConfigs);
364 
365     return closest != null;
366 }
367 
368 static void makeContextCurrentEGL(_GLFWwindow* window) {
369     if (window)
370     {
371         if (!_glfw.egl.MakeCurrent(_glfw.egl.display,
372                             window.context.egl.surface,
373                             window.context.egl.surface,
374                             window.context.egl.handle))
375         {
376             _glfwInputError(GLFW_PLATFORM_ERROR,
377                             "EGL: Failed to make context current: %s",
378                             getEGLErrorString(_glfw.egl.GetError()));
379             return;
380         }
381     }
382     else
383     {
384         if (!_glfw.egl.MakeCurrent(_glfw.egl.display,
385                             EGL_NO_SURFACE,
386                             EGL_NO_SURFACE,
387                             EGL_NO_CONTEXT))
388         {
389             _glfwInputError(GLFW_PLATFORM_ERROR,
390                             "EGL: Failed to clear current context: %s",
391                             getEGLErrorString(_glfw.egl.GetError()));
392             return;
393         }
394     }
395 
396     _glfwPlatformSetTls(&_glfw.contextSlot, window);
397 }
398 
399 static void swapBuffersEGL(_GLFWwindow* window) {
400     if (window != _glfwPlatformGetTls(&_glfw.contextSlot))
401     {
402         _glfwInputError(GLFW_PLATFORM_ERROR,
403                         "EGL: The context must be current on the calling thread when swapping buffers");
404         return;
405     }
406 
407     _glfw.egl.SwapBuffers(_glfw.egl.display, window.context.egl.surface);
408 }
409 
410 static void swapIntervalEGL(int interval) {
411     _glfw.egl.SwapInterval(_glfw.egl.display, interval);
412 }
413 
414 static int extensionSupportedEGL(const(char)* extension) {
415     const(char)* extensions = _glfw.egl.QueryString(_glfw.egl.display, EGL_EXTENSIONS);
416     if (extensions)
417     {
418         if (_glfwStringInExtensionString(extension, extensions))
419             return GLFW_TRUE;
420     }
421 
422     return GLFW_FALSE;
423 }
424 
425 static GLFWglproc getProcAddressEGL(const(char)* procname) {
426     auto window = cast(_GLFWwindow*) _glfwPlatformGetTls(&_glfw.contextSlot);
427 
428     if (window.context.egl.client)
429     {
430         GLFWglproc proc = cast(GLFWglproc) _glfw_dlsym(window.context.egl.client,
431                                                    procname);
432         if (proc)
433             return proc;
434     }
435 
436     return _glfw.egl.GetProcAddress(procname);
437 }
438 
439 static void destroyContextEGL(_GLFWwindow* window) {
440     // NOTE: Do not unload libGL.so.1 while the X11 display is still open,
441     //       as it will make XCloseDisplay segfault
442     version (_GLFW_X11) {
443         const bool condition = window.context.client != GLFW_OPENGL_API;
444     } else {
445         const bool condition = true;
446     }
447     if (condition)
448     {
449         if (window.context.egl.client)
450         {
451             _glfw_dlclose(window.context.egl.client);
452             window.context.egl.client = null;
453         }
454     }
455 
456     if (window.context.egl.surface)
457     {
458         _glfw.egl.DestroySurface(_glfw.egl.display, window.context.egl.surface);
459         window.context.egl.surface = EGL_NO_SURFACE;
460     }
461 
462     if (window.context.egl.handle)
463     {
464         _glfw.egl.DestroyContext(_glfw.egl.display, window.context.egl.handle);
465         window.context.egl.handle = EGL_NO_CONTEXT;
466     }
467 }
468 
469 
470 //////////////////////////////////////////////////////////////////////////
471 //////                       GLFW internal API                      //////
472 //////////////////////////////////////////////////////////////////////////
473 
474 // Initialize EGL
475 //
476 GLFWbool _glfwInitEGL() {
477     int i;
478     version(_GLFW_WIN32) {
479         static immutable char*[] sonames = ["libEGL.dll", "EGL.dll", null];
480     } else version(_GLFW_COCOA) {
481         static immutable char*[] sonames = ["libEGL.dylib", null];
482     } else version(Cygwin) {
483         static immutable char*[] sonames = ["libEGL-1.so", null];
484     } else {
485         static immutable char*[] sonames = ["libEGL.so.1",null];
486     }
487 
488     if (_glfw.egl.handle)
489         return GLFW_TRUE;
490 
491     for (i = 0;  sonames[i];  i++)
492     {
493         _glfw.egl.handle = _glfw_dlopen(sonames[i]);
494         if (_glfw.egl.handle)
495             break;
496     }
497 
498     if (!_glfw.egl.handle)
499     {
500         _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Library not found");
501         return GLFW_FALSE;
502     }
503 
504     _glfw.egl.prefix = (strncmp(sonames[i], "lib", 3) == 0);
505 
506     _glfw.egl.GetConfigAttrib = cast(PFN_eglGetConfigAttrib)
507         _glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib");
508     _glfw.egl.GetConfigs = cast(PFN_eglGetConfigs)
509         _glfw_dlsym(_glfw.egl.handle, "eglGetConfigs");
510     _glfw.egl.GetDisplay = cast(PFN_eglGetDisplay)
511         _glfw_dlsym(_glfw.egl.handle, "eglGetDisplay");
512     _glfw.egl.GetError = cast(PFN_eglGetError)
513         _glfw_dlsym(_glfw.egl.handle, "eglGetError");
514     _glfw.egl.Initialize = cast(PFN_eglInitialize)
515         _glfw_dlsym(_glfw.egl.handle, "eglInitialize");
516     _glfw.egl.Terminate = cast(PFN_eglTerminate)
517         _glfw_dlsym(_glfw.egl.handle, "eglTerminate");
518     _glfw.egl.BindAPI = cast(PFN_eglBindAPI)
519         _glfw_dlsym(_glfw.egl.handle, "eglBindAPI");
520     _glfw.egl.CreateContext = cast(PFN_eglCreateContext)
521         _glfw_dlsym(_glfw.egl.handle, "eglCreateContext");
522     _glfw.egl.DestroySurface = cast(PFN_eglDestroySurface)
523         _glfw_dlsym(_glfw.egl.handle, "eglDestroySurface");
524     _glfw.egl.DestroyContext = cast(PFN_eglDestroyContext)
525         _glfw_dlsym(_glfw.egl.handle, "eglDestroyContext");
526     _glfw.egl.CreateWindowSurface = cast(PFN_eglCreateWindowSurface)
527         _glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface");
528     _glfw.egl.MakeCurrent = cast(PFN_eglMakeCurrent)
529         _glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent");
530     _glfw.egl.SwapBuffers = cast(PFN_eglSwapBuffers)
531         _glfw_dlsym(_glfw.egl.handle, "eglSwapBuffers");
532     _glfw.egl.SwapInterval = cast(PFN_eglSwapInterval)
533         _glfw_dlsym(_glfw.egl.handle, "eglSwapInterval");
534     _glfw.egl.QueryString = cast(PFN_eglQueryString)
535         _glfw_dlsym(_glfw.egl.handle, "eglQueryString");
536     _glfw.egl.GetProcAddress = cast(PFN_eglGetProcAddress)
537         _glfw_dlsym(_glfw.egl.handle, "eglGetProcAddress");
538 
539     if (!_glfw.egl.GetConfigAttrib ||
540         !_glfw.egl.GetConfigs ||
541         !_glfw.egl.GetDisplay ||
542         !_glfw.egl.GetError ||
543         !_glfw.egl.Initialize ||
544         !_glfw.egl.Terminate ||
545         !_glfw.egl.BindAPI ||
546         !_glfw.egl.CreateContext ||
547         !_glfw.egl.DestroySurface ||
548         !_glfw.egl.DestroyContext ||
549         !_glfw.egl.CreateWindowSurface ||
550         !_glfw.egl.MakeCurrent ||
551         !_glfw.egl.SwapBuffers ||
552         !_glfw.egl.SwapInterval ||
553         !_glfw.egl.QueryString ||
554         !_glfw.egl.GetProcAddress)
555     {
556         _glfwInputError(GLFW_PLATFORM_ERROR,
557                         "EGL: Failed to load required entry points");
558 
559         _glfwTerminateEGL();
560         return GLFW_FALSE;
561     }
562 
563     _glfw.egl.display = _glfw.egl.GetDisplay(mixin(_GLFW_EGL_NATIVE_DISPLAY));
564     if (_glfw.egl.display == EGL_NO_DISPLAY)
565     {
566         _glfwInputError(GLFW_API_UNAVAILABLE,
567                         "EGL: Failed to get EGL display: %s",
568                         getEGLErrorString(_glfw.egl.GetError()));
569 
570         _glfwTerminateEGL();
571         return GLFW_FALSE;
572     }
573 
574     if (!_glfw.egl.Initialize(_glfw.egl.display, &_glfw.egl.major, &_glfw.egl.minor))
575     {
576         _glfwInputError(GLFW_API_UNAVAILABLE,
577                         "EGL: Failed to initialize EGL: %s",
578                         getEGLErrorString(_glfw.egl.GetError()));
579 
580         _glfwTerminateEGL();
581         return GLFW_FALSE;
582     }
583 
584     _glfw.egl.KHR_create_context =
585         extensionSupportedEGL("EGL_KHR_create_context");
586     _glfw.egl.KHR_create_context_no_error =
587         extensionSupportedEGL("EGL_KHR_create_context_no_error");
588     _glfw.egl.KHR_gl_colorspace =
589         extensionSupportedEGL("EGL_KHR_gl_colorspace");
590     _glfw.egl.KHR_get_all_proc_addresses =
591         extensionSupportedEGL("EGL_KHR_get_all_proc_addresses");
592     _glfw.egl.KHR_context_flush_control =
593         extensionSupportedEGL("EGL_KHR_context_flush_control");
594 
595     return GLFW_TRUE;
596 }
597 
598 // Terminate EGL
599 //
600 void _glfwTerminateEGL() {
601     if (_glfw.egl.display)
602     {
603         _glfw.egl.Terminate(_glfw.egl.display);
604         _glfw.egl.display = EGL_NO_DISPLAY;
605     }
606 
607     if (_glfw.egl.handle)
608     {
609         _glfw_dlclose(_glfw.egl.handle);
610         _glfw.egl.handle = null;
611     }
612 }
613 
614 
615 // Create the OpenGL or OpenGL ES context
616 //
617 GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, const(_GLFWctxconfig)* ctxconfig, const(_GLFWfbconfig)* fbconfig) {
618     EGLint[40] attribs;
619     int index = 0;
620     void setAttrib(EGLint a, EGLint v) {
621         assert((cast(size_t) index + 1) < attribs.length);
622         attribs[index++] = a;
623         attribs[index++] = v;
624     }
625     EGLConfig config;
626     EGLContext share = null;
627 
628     if (!_glfw.egl.display)
629     {
630         _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: API not available");
631         return GLFW_FALSE;
632     }
633 
634     if (ctxconfig.share)
635         share = cast(void*) ctxconfig.share.context.egl.handle;
636 
637     if (!chooseEGLConfig(ctxconfig, fbconfig, &config))
638     {
639         _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
640                         "EGL: Failed to find a suitable EGLConfig");
641         return GLFW_FALSE;
642     }
643 
644     if (ctxconfig.client == GLFW_OPENGL_ES_API)
645     {
646         if (!_glfw.egl.BindAPI(EGL_OPENGL_ES_API))
647         {
648             _glfwInputError(GLFW_API_UNAVAILABLE,
649                             "EGL: Failed to bind OpenGL ES: %s",
650                             getEGLErrorString(_glfw.egl.GetError()));
651             return GLFW_FALSE;
652         }
653     }
654     else
655     {
656         if (!_glfw.egl.BindAPI(EGL_OPENGL_API))
657         {
658             _glfwInputError(GLFW_API_UNAVAILABLE,
659                             "EGL: Failed to bind OpenGL: %s",
660                             getEGLErrorString(_glfw.egl.GetError()));
661             return GLFW_FALSE;
662         }
663     }
664 
665     if (_glfw.egl.KHR_create_context)
666     {
667         int mask = 0;int flags = 0;
668 
669         if (ctxconfig.client == GLFW_OPENGL_API)
670         {
671             if (ctxconfig.forward)
672                 flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
673 
674             if (ctxconfig.profile == GLFW_OPENGL_CORE_PROFILE)
675                 mask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
676             else if (ctxconfig.profile == GLFW_OPENGL_COMPAT_PROFILE)
677                 mask |= EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
678         }
679 
680         if (ctxconfig.debug_)
681             flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
682 
683         if (ctxconfig.robustness)
684         {
685             if (ctxconfig.robustness == GLFW_NO_RESET_NOTIFICATION)
686             {
687                 setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
688                           EGL_NO_RESET_NOTIFICATION_KHR);
689             }
690             else if (ctxconfig.robustness == GLFW_LOSE_CONTEXT_ON_RESET)
691             {
692                 setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
693                           EGL_LOSE_CONTEXT_ON_RESET_KHR);
694             }
695 
696             flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
697         }
698 
699         if (ctxconfig.noerror)
700         {
701             if (_glfw.egl.KHR_create_context_no_error)
702                 setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);
703         }
704 
705         if (ctxconfig.major != 1 || ctxconfig.minor != 0)
706         {
707             setAttrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig.major);
708             setAttrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig.minor);
709         }
710 
711         if (mask)
712             setAttrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
713 
714         if (flags)
715             setAttrib(EGL_CONTEXT_FLAGS_KHR, flags);
716     }
717     else
718     {
719         if (ctxconfig.client == GLFW_OPENGL_ES_API)
720             setAttrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig.major);
721     }
722 
723     if (_glfw.egl.KHR_context_flush_control)
724     {
725         if (ctxconfig.release == GLFW_RELEASE_BEHAVIOR_NONE)
726         {
727             setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
728                       EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR);
729         }
730         else if (ctxconfig.release == GLFW_RELEASE_BEHAVIOR_FLUSH)
731         {
732             setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
733                       EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR);
734         }
735     }
736 
737     setAttrib(EGL_NONE, EGL_NONE);
738 
739     window.context.egl.handle = _glfw.egl.CreateContext(_glfw.egl.display,
740                                                   config, share, attribs.ptr);
741 
742     if (window.context.egl.handle == EGL_NO_CONTEXT)
743     {
744         _glfwInputError(GLFW_VERSION_UNAVAILABLE,
745                         "EGL: Failed to create context: %s",
746                         getEGLErrorString(_glfw.egl.GetError()));
747         return GLFW_FALSE;
748     }
749 
750     // Set up attributes for surface creation
751     {
752         index = 0;
753 
754         if (fbconfig.sRGB)
755         {
756             if (_glfw.egl.KHR_gl_colorspace)
757                 setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
758         }
759 
760         setAttrib(EGL_NONE, EGL_NONE);
761     }
762 
763     window.context.egl.surface =
764         _glfw.egl.CreateWindowSurface(_glfw.egl.display,
765                                config,
766                                mixin(_GLFW_EGL_NATIVE_WINDOW),
767                                attribs.ptr);
768     if (window.context.egl.surface == EGL_NO_SURFACE)
769     {
770         _glfwInputError(GLFW_PLATFORM_ERROR,
771                         "EGL: Failed to create window surface: %s",
772                         getEGLErrorString(_glfw.egl.GetError()));
773         return GLFW_FALSE;
774     }
775 
776     window.context.egl.config = config;
777 
778     // Load the appropriate client library
779     if (!_glfw.egl.KHR_get_all_proc_addresses)
780     {
781         int i;
782         const(char*)* sonames;
783 
784         version(_GLFW_WIN32) {
785             static immutable char*[3] es1sonames = ["GLESv1_CM.dll","libGLES_CM.dll", null];
786         } else version(_GLFW_COCOA) {
787             static immutable char*[2] es1sonames = ["libGLESv1_CM.dylib", null];
788         } else {
789             static immutable char*[3] es1sonames = ["libGLESv1_CM.so.1","libGLES_CM.so.1", null];
790         }
791 
792         version(_GLFW_WIN32) {
793             static immutable char*[3] es2sonames = ["GLESv2.dll","libGLESv2.dll",null];
794         } else version(_GLFW_COCOA) {
795             static immutable char*[2] es2sonames = ["libGLESv2.dylib",null];
796         } else version(Cygwin) {
797             static immutable char*[2] es2sonames = ["libGLESv2-2.so",null];
798         } else {
799             static immutable char*[2] es2sonames = ["libGLESv2.so.2",null];
800         }
801 
802         version(_GLFW_WIN32) {
803             static immutable char*[1] glsonames = [null];
804         } else version(_GLFW_COCOA) {
805             static immutable char*[1] glsonames = [null];
806         } else {
807             static immutable char*[2] glsonames = ["libGL.so.1",null];
808         }
809 
810         if (ctxconfig.client == GLFW_OPENGL_ES_API)
811         {
812             if (ctxconfig.major == 1)
813                 sonames = es1sonames.ptr;
814             else
815                 sonames = es2sonames.ptr;
816         }
817         else
818             sonames = glsonames.ptr;
819 
820         for (i = 0;  sonames[i];  i++)
821         {
822             // HACK: Match presence of lib prefix to increase chance of finding
823             //       a matching pair in the jungle that is Win32 EGL/GLES
824             if (_glfw.egl.prefix != (strncmp(sonames[i], "lib", 3) == 0))
825                 continue;
826 
827             window.context.egl.client = _glfw_dlopen(sonames[i]);
828             if (window.context.egl.client)
829                 break;
830         }
831 
832         if (!window.context.egl.client)
833         {
834             _glfwInputError(GLFW_API_UNAVAILABLE,
835                             "EGL: Failed to load client library");
836             return GLFW_FALSE;
837         }
838     }
839 
840     window.context.makeCurrent = &makeContextCurrentEGL;
841     window.context.swapBuffers = &swapBuffersEGL;
842     window.context.swapInterval = &swapIntervalEGL;
843     window.context.extensionSupported = &extensionSupportedEGL;
844     window.context.getProcAddress = &getProcAddressEGL;
845     window.context.destroy = &destroyContextEGL;
846 
847     return GLFW_TRUE;
848 }
849 
850 // Returns the Visual and depth of the chosen EGLConfig
851 //
852 version (_GLFW_X11) {
853 GLFWbool _glfwChooseVisualEGL(
854     const(_GLFWwndconfig)* wndconfig, const(_GLFWctxconfig)* ctxconfig,
855     const(_GLFWfbconfig)* fbconfig, Visual** visual, int* depth
856 ) {
857     XVisualInfo* result;
858     XVisualInfo desired;
859     EGLConfig native;
860     EGLint visualID = 0;EGLint count = 0;
861     const(int) vimask = VisualScreenMask | VisualIDMask;
862 
863     if (!chooseEGLConfig(ctxconfig, fbconfig, &native))
864     {
865         _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
866                         "EGL: Failed to find a suitable EGLConfig");
867         return GLFW_FALSE;
868     }
869 
870     _glfw.egl.GetConfigAttrib(_glfw.egl.display, native,
871                        EGL_NATIVE_VISUAL_ID, &visualID);
872 
873     desired.screen = _glfw.x11.screen;
874     desired.visualid = visualID;
875 
876     result = XGetVisualInfo(_glfw.x11.display, vimask, &desired, &count);
877     if (!result)
878     {
879         _glfwInputError(GLFW_PLATFORM_ERROR,
880                         "EGL: Failed to retrieve Visual for EGLConfig");
881         return GLFW_FALSE;
882     }
883 
884     *visual = result.visual;
885     *depth = result.depth;
886 
887     XFree(result);
888     return GLFW_TRUE;
889 }
890 } // _GLFW_X11
891 
892 
893 //////////////////////////////////////////////////////////////////////////
894 //////                        GLFW native API                       //////
895 //////////////////////////////////////////////////////////////////////////
896 
897 EGLDisplay glfwGetEGLDisplay() {
898     mixin(_GLFW_REQUIRE_INIT_OR_RETURN!("EGL_NO_DISPLAY"));
899     return _glfw.egl.display;
900 }
901 
902 EGLContext glfwGetEGLContext(GLFWwindow* handle) {
903     _GLFWwindow* window = cast(_GLFWwindow*) handle;
904     mixin(_GLFW_REQUIRE_INIT_OR_RETURN!("EGL_NO_CONTEXT"));
905 
906     if (window.context.client == GLFW_NO_API)
907     {
908         _glfwInputError(GLFW_NO_WINDOW_CONTEXT, null);
909         return EGL_NO_CONTEXT;
910     }
911 
912     return window.context.egl.handle;
913 }
914 
915 EGLSurface glfwGetEGLSurface(GLFWwindow* handle) {
916     _GLFWwindow* window = cast(_GLFWwindow*) handle;
917     mixin(_GLFW_REQUIRE_INIT_OR_RETURN!("EGL_NO_SURFACE"));
918 
919     if (window.context.client == GLFW_NO_API)
920     {
921         _glfwInputError(GLFW_NO_WINDOW_CONTEXT, null);
922         return EGL_NO_SURFACE;
923     }
924 
925     return window.context.egl.surface;
926 }