• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //========================================================================
2 // GLFW 3.2 EGL - 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 <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <assert.h>
34 
35 
36 // Return a description of the specified EGL error
37 //
getEGLErrorString(EGLint error)38 static const char* getEGLErrorString(EGLint error)
39 {
40     switch (error)
41     {
42         case EGL_SUCCESS:
43             return "Success";
44         case EGL_NOT_INITIALIZED:
45             return "EGL is not or could not be initialized";
46         case EGL_BAD_ACCESS:
47             return "EGL cannot access a requested resource";
48         case EGL_BAD_ALLOC:
49             return "EGL failed to allocate resources for the requested operation";
50         case EGL_BAD_ATTRIBUTE:
51             return "An unrecognized attribute or attribute value was passed in the attribute list";
52         case EGL_BAD_CONTEXT:
53             return "An EGLContext argument does not name a valid EGL rendering context";
54         case EGL_BAD_CONFIG:
55             return "An EGLConfig argument does not name a valid EGL frame buffer configuration";
56         case EGL_BAD_CURRENT_SURFACE:
57             return "The current surface of the calling thread is a window, pixel buffer or pixmap that is no longer valid";
58         case EGL_BAD_DISPLAY:
59             return "An EGLDisplay argument does not name a valid EGL display connection";
60         case EGL_BAD_SURFACE:
61             return "An EGLSurface argument does not name a valid surface configured for GL rendering";
62         case EGL_BAD_MATCH:
63             return "Arguments are inconsistent";
64         case EGL_BAD_PARAMETER:
65             return "One or more argument values are invalid";
66         case EGL_BAD_NATIVE_PIXMAP:
67             return "A NativePixmapType argument does not refer to a valid native pixmap";
68         case EGL_BAD_NATIVE_WINDOW:
69             return "A NativeWindowType argument does not refer to a valid native window";
70         case EGL_CONTEXT_LOST:
71             return "The application must destroy all contexts and reinitialise";
72         default:
73             return "ERROR: UNKNOWN EGL ERROR";
74     }
75 }
76 
77 // Returns the specified attribute of the specified EGLConfig
78 //
getEGLConfigAttrib(EGLConfig config,int attrib)79 static int getEGLConfigAttrib(EGLConfig config, int attrib)
80 {
81     int value;
82     eglGetConfigAttrib(_glfw.egl.display, config, attrib, &value);
83     return value;
84 }
85 
86 // Return the EGLConfig most closely matching the specified hints
87 //
chooseEGLConfig(const _GLFWctxconfig * ctxconfig,const _GLFWfbconfig * desired,EGLConfig * result)88 static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
89                                 const _GLFWfbconfig* desired,
90                                 EGLConfig* result)
91 {
92     EGLConfig* nativeConfigs;
93     _GLFWfbconfig* usableConfigs;
94     const _GLFWfbconfig* closest;
95     int i, nativeCount, usableCount;
96 
97     eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount);
98     if (!nativeCount)
99     {
100         _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: No EGLConfigs returned");
101         return GLFW_FALSE;
102     }
103 
104     nativeConfigs = calloc(nativeCount, sizeof(EGLConfig));
105     eglGetConfigs(_glfw.egl.display, nativeConfigs, nativeCount, &nativeCount);
106 
107     usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
108     usableCount = 0;
109 
110     for (i = 0;  i < nativeCount;  i++)
111     {
112         const EGLConfig n = nativeConfigs[i];
113         _GLFWfbconfig* u = usableConfigs + usableCount;
114 
115         // Only consider RGB(A) EGLConfigs
116         if (!(getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) & EGL_RGB_BUFFER))
117             continue;
118 
119         // Only consider window EGLConfigs
120         if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))
121             continue;
122 
123 #if defined(_GLFW_X11)
124         // Only consider EGLConfigs with associated Visuals
125         if (!getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID))
126             continue;
127 #endif // _GLFW_X11
128 
129         if (ctxconfig->client == GLFW_OPENGL_ES_API)
130         {
131             if (ctxconfig->major == 1)
132             {
133                 if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT))
134                     continue;
135             }
136             else
137             {
138                 if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT))
139                     continue;
140             }
141         }
142         else if (ctxconfig->client == GLFW_OPENGL_API)
143         {
144             if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT))
145                 continue;
146         }
147 
148         u->redBits = getEGLConfigAttrib(n, EGL_RED_SIZE);
149         u->greenBits = getEGLConfigAttrib(n, EGL_GREEN_SIZE);
150         u->blueBits = getEGLConfigAttrib(n, EGL_BLUE_SIZE);
151 
152         u->alphaBits = getEGLConfigAttrib(n, EGL_ALPHA_SIZE);
153         u->depthBits = getEGLConfigAttrib(n, EGL_DEPTH_SIZE);
154         u->stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE);
155 
156         u->samples = getEGLConfigAttrib(n, EGL_SAMPLES);
157         u->doublebuffer = GLFW_TRUE;
158 
159         u->handle = (uintptr_t) n;
160         usableCount++;
161     }
162 
163     closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
164     if (closest)
165         *result = (EGLConfig) closest->handle;
166 
167     free(nativeConfigs);
168     free(usableConfigs);
169 
170     return closest != NULL;
171 }
172 
makeContextCurrentEGL(_GLFWwindow * window)173 static void makeContextCurrentEGL(_GLFWwindow* window)
174 {
175     if (window)
176     {
177         if (!eglMakeCurrent(_glfw.egl.display,
178                             window->context.egl.surface,
179                             window->context.egl.surface,
180                             window->context.egl.handle))
181         {
182             _glfwInputError(GLFW_PLATFORM_ERROR,
183                             "EGL: Failed to make context current: %s",
184                             getEGLErrorString(eglGetError()));
185             return;
186         }
187     }
188     else
189     {
190         if (!eglMakeCurrent(_glfw.egl.display,
191                             EGL_NO_SURFACE,
192                             EGL_NO_SURFACE,
193                             EGL_NO_CONTEXT))
194         {
195             _glfwInputError(GLFW_PLATFORM_ERROR,
196                             "EGL: Failed to clear current context: %s",
197                             getEGLErrorString(eglGetError()));
198             return;
199         }
200     }
201 
202     _glfwPlatformSetCurrentContext(window);
203 }
204 
swapBuffersEGL(_GLFWwindow * window)205 static void swapBuffersEGL(_GLFWwindow* window)
206 {
207     if (window != _glfwPlatformGetCurrentContext())
208     {
209         _glfwInputError(GLFW_PLATFORM_ERROR,
210                         "EGL: The context must be current on the calling thread when swapping buffers");
211         return;
212     }
213 
214     eglSwapBuffers(_glfw.egl.display, window->context.egl.surface);
215 }
216 
swapIntervalEGL(int interval)217 static void swapIntervalEGL(int interval)
218 {
219     eglSwapInterval(_glfw.egl.display, interval);
220 }
221 
extensionSupportedEGL(const char * extension)222 static int extensionSupportedEGL(const char* extension)
223 {
224     const char* extensions = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS);
225     if (extensions)
226     {
227         if (_glfwStringInExtensionString(extension, extensions))
228             return GLFW_TRUE;
229     }
230 
231     return GLFW_FALSE;
232 }
233 
getProcAddressEGL(const char * procname)234 static GLFWglproc getProcAddressEGL(const char* procname)
235 {
236     _GLFWwindow* window = _glfwPlatformGetCurrentContext();
237 
238     if (window->context.egl.client)
239     {
240         GLFWglproc proc = (GLFWglproc) _glfw_dlsym(window->context.egl.client,
241                                                    procname);
242         if (proc)
243             return proc;
244     }
245 
246     return eglGetProcAddress(procname);
247 }
248 
destroyContextEGL(_GLFWwindow * window)249 static void destroyContextEGL(_GLFWwindow* window)
250 {
251 #if defined(_GLFW_X11)
252     // NOTE: Do not unload libGL.so.1 while the X11 display is still open,
253     //       as it will make XCloseDisplay segfault
254     if (window->context.client != GLFW_OPENGL_API)
255 #endif // _GLFW_X11
256     {
257         if (window->context.egl.client)
258         {
259             _glfw_dlclose(window->context.egl.client);
260             window->context.egl.client = NULL;
261         }
262     }
263 
264     if (window->context.egl.surface)
265     {
266         eglDestroySurface(_glfw.egl.display, window->context.egl.surface);
267         window->context.egl.surface = EGL_NO_SURFACE;
268     }
269 
270     if (window->context.egl.handle)
271     {
272         eglDestroyContext(_glfw.egl.display, window->context.egl.handle);
273         window->context.egl.handle = EGL_NO_CONTEXT;
274     }
275 }
276 
277 
278 //////////////////////////////////////////////////////////////////////////
279 //////                       GLFW internal API                      //////
280 //////////////////////////////////////////////////////////////////////////
281 
282 // Initialize EGL
283 //
_glfwInitEGL(void)284 GLFWbool _glfwInitEGL(void)
285 {
286     int i;
287     const char* sonames[] =
288     {
289 #if defined(_GLFW_WIN32)
290         "libEGL.dll",
291         "EGL.dll",
292 #elif defined(_GLFW_COCOA)
293         "libEGL.dylib",
294 #else
295         "libEGL.so.1",
296 #endif
297         NULL
298     };
299 
300     if (_glfw.egl.handle)
301         return GLFW_TRUE;
302 
303     for (i = 0;  sonames[i];  i++)
304     {
305         _glfw.egl.handle = _glfw_dlopen(sonames[i]);
306         if (_glfw.egl.handle)
307             break;
308     }
309 
310     if (!_glfw.egl.handle)
311     {
312         _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Library not found");
313         return GLFW_FALSE;
314     }
315 
316     _glfw.egl.prefix = (strncmp(sonames[i], "lib", 3) == 0);
317 
318     _glfw.egl.GetConfigAttrib = (PFNEGLGETCONFIGATTRIBPROC)
319         _glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib");
320     _glfw.egl.GetConfigs = (PFNEGLGETCONFIGSPROC)
321         _glfw_dlsym(_glfw.egl.handle, "eglGetConfigs");
322     _glfw.egl.GetDisplay = (PFNEGLGETDISPLAYPROC)
323         _glfw_dlsym(_glfw.egl.handle, "eglGetDisplay");
324     _glfw.egl.GetError = (PFNEGLGETERRORPROC)
325         _glfw_dlsym(_glfw.egl.handle, "eglGetError");
326     _glfw.egl.Initialize = (PFNEGLINITIALIZEPROC)
327         _glfw_dlsym(_glfw.egl.handle, "eglInitialize");
328     _glfw.egl.Terminate = (PFNEGLTERMINATEPROC)
329         _glfw_dlsym(_glfw.egl.handle, "eglTerminate");
330     _glfw.egl.BindAPI = (PFNEGLBINDAPIPROC)
331         _glfw_dlsym(_glfw.egl.handle, "eglBindAPI");
332     _glfw.egl.CreateContext = (PFNEGLCREATECONTEXTPROC)
333         _glfw_dlsym(_glfw.egl.handle, "eglCreateContext");
334     _glfw.egl.DestroySurface = (PFNEGLDESTROYSURFACEPROC)
335         _glfw_dlsym(_glfw.egl.handle, "eglDestroySurface");
336     _glfw.egl.DestroyContext = (PFNEGLDESTROYCONTEXTPROC)
337         _glfw_dlsym(_glfw.egl.handle, "eglDestroyContext");
338     _glfw.egl.CreateWindowSurface = (PFNEGLCREATEWINDOWSURFACEPROC)
339         _glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface");
340     _glfw.egl.MakeCurrent = (PFNEGLMAKECURRENTPROC)
341         _glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent");
342     _glfw.egl.SwapBuffers = (PFNEGLSWAPBUFFERSPROC)
343         _glfw_dlsym(_glfw.egl.handle, "eglSwapBuffers");
344     _glfw.egl.SwapInterval = (PFNEGLSWAPINTERVALPROC)
345         _glfw_dlsym(_glfw.egl.handle, "eglSwapInterval");
346     _glfw.egl.QueryString = (PFNEGLQUERYSTRINGPROC)
347         _glfw_dlsym(_glfw.egl.handle, "eglQueryString");
348     _glfw.egl.GetProcAddress = (PFNEGLGETPROCADDRESSPROC)
349         _glfw_dlsym(_glfw.egl.handle, "eglGetProcAddress");
350 
351     if (!_glfw.egl.GetConfigAttrib ||
352         !_glfw.egl.GetConfigs ||
353         !_glfw.egl.GetDisplay ||
354         !_glfw.egl.GetError ||
355         !_glfw.egl.Initialize ||
356         !_glfw.egl.Terminate ||
357         !_glfw.egl.BindAPI ||
358         !_glfw.egl.CreateContext ||
359         !_glfw.egl.DestroySurface ||
360         !_glfw.egl.DestroyContext ||
361         !_glfw.egl.CreateWindowSurface ||
362         !_glfw.egl.MakeCurrent ||
363         !_glfw.egl.SwapBuffers ||
364         !_glfw.egl.SwapInterval ||
365         !_glfw.egl.QueryString ||
366         !_glfw.egl.GetProcAddress)
367     {
368         _glfwInputError(GLFW_PLATFORM_ERROR,
369                         "EGL: Failed to load required entry points");
370 
371         _glfwTerminateEGL();
372         return GLFW_FALSE;
373     }
374 
375     _glfw.egl.display = eglGetDisplay(_GLFW_EGL_NATIVE_DISPLAY);
376     if (_glfw.egl.display == EGL_NO_DISPLAY)
377     {
378         _glfwInputError(GLFW_API_UNAVAILABLE,
379                         "EGL: Failed to get EGL display: %s",
380                         getEGLErrorString(eglGetError()));
381 
382         _glfwTerminateEGL();
383         return GLFW_FALSE;
384     }
385 
386     if (!eglInitialize(_glfw.egl.display, &_glfw.egl.major, &_glfw.egl.minor))
387     {
388         _glfwInputError(GLFW_API_UNAVAILABLE,
389                         "EGL: Failed to initialize EGL: %s",
390                         getEGLErrorString(eglGetError()));
391 
392         _glfwTerminateEGL();
393         return GLFW_FALSE;
394     }
395 
396     _glfw.egl.KHR_create_context =
397         extensionSupportedEGL("EGL_KHR_create_context");
398     _glfw.egl.KHR_create_context_no_error =
399         extensionSupportedEGL("EGL_KHR_create_context_no_error");
400     _glfw.egl.KHR_gl_colorspace =
401         extensionSupportedEGL("EGL_KHR_gl_colorspace");
402 
403     return GLFW_TRUE;
404 }
405 
406 // Terminate EGL
407 //
_glfwTerminateEGL(void)408 void _glfwTerminateEGL(void)
409 {
410     if (_glfw.egl.display)
411     {
412         eglTerminate(_glfw.egl.display);
413         _glfw.egl.display = EGL_NO_DISPLAY;
414     }
415 
416     if (_glfw.egl.handle)
417     {
418         _glfw_dlclose(_glfw.egl.handle);
419         _glfw.egl.handle = NULL;
420     }
421 }
422 
423 #define setEGLattrib(attribName, attribValue) \
424 { \
425     attribs[index++] = attribName; \
426     attribs[index++] = attribValue; \
427     assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
428 }
429 
430 // Create the OpenGL or OpenGL ES context
431 //
_glfwCreateContextEGL(_GLFWwindow * window,const _GLFWctxconfig * ctxconfig,const _GLFWfbconfig * fbconfig)432 GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
433                                const _GLFWctxconfig* ctxconfig,
434                                const _GLFWfbconfig* fbconfig)
435 {
436     EGLint attribs[40];
437     EGLConfig config;
438     EGLContext share = NULL;
439 
440     if (!_glfw.egl.display)
441     {
442         _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: API not available");
443         return GLFW_FALSE;
444     }
445 
446     if (ctxconfig->share)
447         share = ctxconfig->share->context.egl.handle;
448 
449     if (!chooseEGLConfig(ctxconfig, fbconfig, &config))
450     {
451         _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
452                         "EGL: Failed to find a suitable EGLConfig");
453         return GLFW_FALSE;
454     }
455 
456     if (ctxconfig->client == GLFW_OPENGL_ES_API)
457     {
458         if (!eglBindAPI(EGL_OPENGL_ES_API))
459         {
460             _glfwInputError(GLFW_API_UNAVAILABLE,
461                             "EGL: Failed to bind OpenGL ES: %s",
462                             getEGLErrorString(eglGetError()));
463             return GLFW_FALSE;
464         }
465     }
466     else
467     {
468         if (!eglBindAPI(EGL_OPENGL_API))
469         {
470             _glfwInputError(GLFW_API_UNAVAILABLE,
471                             "EGL: Failed to bind OpenGL: %s",
472                             getEGLErrorString(eglGetError()));
473             return GLFW_FALSE;
474         }
475     }
476 
477     if (_glfw.egl.KHR_create_context)
478     {
479         int index = 0, mask = 0, flags = 0;
480 
481         if (ctxconfig->client == GLFW_OPENGL_API)
482         {
483             if (ctxconfig->forward)
484                 flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
485 
486             if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
487                 mask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
488             else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
489                 mask |= EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
490 
491             if (_glfw.egl.KHR_create_context_no_error)
492             {
493                 if (ctxconfig->noerror)
494                     flags |= EGL_CONTEXT_OPENGL_NO_ERROR_KHR;
495             }
496         }
497 
498         if (ctxconfig->debug)
499             flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
500 
501         if (ctxconfig->robustness)
502         {
503             if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
504             {
505                 setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
506                              EGL_NO_RESET_NOTIFICATION_KHR);
507             }
508             else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
509             {
510                 setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
511                              EGL_LOSE_CONTEXT_ON_RESET_KHR);
512             }
513 
514             flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
515         }
516 
517         if (ctxconfig->major != 1 || ctxconfig->minor != 0)
518         {
519             setEGLattrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
520             setEGLattrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
521         }
522 
523         if (mask)
524             setEGLattrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
525 
526         if (flags)
527             setEGLattrib(EGL_CONTEXT_FLAGS_KHR, flags);
528 
529         setEGLattrib(EGL_NONE, EGL_NONE);
530     }
531     else
532     {
533         int index = 0;
534 
535         if (ctxconfig->client == GLFW_OPENGL_ES_API)
536             setEGLattrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
537 
538         setEGLattrib(EGL_NONE, EGL_NONE);
539     }
540 
541     // Context release behaviors (GL_KHR_context_flush_control) are not yet
542     // supported on EGL but are not a hard constraint, so ignore and continue
543 
544     window->context.egl.handle = eglCreateContext(_glfw.egl.display,
545                                                   config, share, attribs);
546 
547     if (window->context.egl.handle == EGL_NO_CONTEXT)
548     {
549         _glfwInputError(GLFW_VERSION_UNAVAILABLE,
550                         "EGL: Failed to create context: %s",
551                         getEGLErrorString(eglGetError()));
552         return GLFW_FALSE;
553     }
554 
555     // Set up attributes for surface creation
556     {
557         int index = 0;
558 
559         if (fbconfig->sRGB)
560         {
561             if (_glfw.egl.KHR_gl_colorspace)
562             {
563                 setEGLattrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
564             }
565         }
566 
567         setEGLattrib(EGL_NONE, EGL_NONE);
568     }
569 
570     window->context.egl.surface =
571         eglCreateWindowSurface(_glfw.egl.display,
572                                config,
573                                _GLFW_EGL_NATIVE_WINDOW,
574                                attribs);
575     if (window->context.egl.surface == EGL_NO_SURFACE)
576     {
577         _glfwInputError(GLFW_PLATFORM_ERROR,
578                         "EGL: Failed to create window surface: %s",
579                         getEGLErrorString(eglGetError()));
580         return GLFW_FALSE;
581     }
582 
583     window->context.egl.config = config;
584 
585     // Load the appropriate client library
586     {
587         int i;
588         const char** sonames;
589         const char* es1sonames[] =
590         {
591 #if defined(_GLFW_WIN32)
592             "GLESv1_CM.dll",
593             "libGLES_CM.dll",
594 #elif defined(_GLFW_COCOA)
595             "libGLESv1_CM.dylib",
596 #else
597             "libGLESv1_CM.so.1",
598             "libGLES_CM.so.1",
599 #endif
600             NULL
601         };
602         const char* es2sonames[] =
603         {
604 #if defined(_GLFW_WIN32)
605             "GLESv2.dll",
606             "libGLESv2.dll",
607 #elif defined(_GLFW_COCOA)
608             "libGLESv2.dylib",
609 #else
610             "libGLESv2.so.2",
611 #endif
612             NULL
613         };
614         const char* glsonames[] =
615         {
616 #if defined(_GLFW_WIN32)
617 #elif defined(_GLFW_COCOA)
618 #else
619             "libGL.so.1",
620 #endif
621             NULL
622         };
623 
624         if (ctxconfig->client == GLFW_OPENGL_ES_API)
625         {
626             if (ctxconfig->major == 1)
627                 sonames = es1sonames;
628             else
629                 sonames = es2sonames;
630         }
631         else
632             sonames = glsonames;
633 
634         for (i = 0;  sonames[i];  i++)
635         {
636             // HACK: Match presence of lib prefix to increase chance of finding
637             //       a matching pair in the jungle that is Win32 EGL/GLES
638             if (_glfw.egl.prefix != (strncmp(sonames[i], "lib", 3) == 0))
639                 continue;
640 
641             window->context.egl.client = _glfw_dlopen(sonames[i]);
642             if (window->context.egl.client)
643                 break;
644         }
645 
646         if (!window->context.egl.client)
647         {
648             _glfwInputError(GLFW_API_UNAVAILABLE,
649                             "EGL: Failed to load client library");
650             return GLFW_FALSE;
651         }
652     }
653 
654     window->context.makeCurrent = makeContextCurrentEGL;
655     window->context.swapBuffers = swapBuffersEGL;
656     window->context.swapInterval = swapIntervalEGL;
657     window->context.extensionSupported = extensionSupportedEGL;
658     window->context.getProcAddress = getProcAddressEGL;
659     window->context.destroy = destroyContextEGL;
660 
661     return GLFW_TRUE;
662 }
663 
664 #undef setEGLattrib
665 
666 // Returns the Visual and depth of the chosen EGLConfig
667 //
668 #if defined(_GLFW_X11)
_glfwChooseVisualEGL(const _GLFWctxconfig * ctxconfig,const _GLFWfbconfig * fbconfig,Visual ** visual,int * depth)669 GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig,
670                               const _GLFWfbconfig* fbconfig,
671                               Visual** visual, int* depth)
672 {
673     XVisualInfo* result;
674     XVisualInfo desired;
675     EGLConfig native;
676     EGLint visualID = 0, count = 0;
677     const long vimask = VisualScreenMask | VisualIDMask;
678 
679     if (!chooseEGLConfig(ctxconfig, fbconfig, &native))
680     {
681         _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
682                         "EGL: Failed to find a suitable EGLConfig");
683         return GLFW_FALSE;
684     }
685 
686     eglGetConfigAttrib(_glfw.egl.display, native,
687                        EGL_NATIVE_VISUAL_ID, &visualID);
688 
689     desired.screen = _glfw.x11.screen;
690     desired.visualid = visualID;
691 
692     result = XGetVisualInfo(_glfw.x11.display, vimask, &desired, &count);
693     if (!result)
694     {
695         _glfwInputError(GLFW_PLATFORM_ERROR,
696                         "EGL: Failed to retrieve Visual for EGLConfig");
697         return GLFW_FALSE;
698     }
699 
700     *visual = result->visual;
701     *depth = result->depth;
702 
703     XFree(result);
704     return GLFW_TRUE;
705 }
706 #endif // _GLFW_X11
707 
708 
709 //////////////////////////////////////////////////////////////////////////
710 //////                        GLFW native API                       //////
711 //////////////////////////////////////////////////////////////////////////
712 
glfwGetEGLDisplay(void)713 GLFWAPI EGLDisplay glfwGetEGLDisplay(void)
714 {
715     _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_DISPLAY);
716     return _glfw.egl.display;
717 }
718 
glfwGetEGLContext(GLFWwindow * handle)719 GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* handle)
720 {
721     _GLFWwindow* window = (_GLFWwindow*) handle;
722     _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT);
723 
724     if (window->context.client == GLFW_NO_API)
725     {
726         _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
727         return EGL_NO_CONTEXT;
728     }
729 
730     return window->context.egl.handle;
731 }
732 
glfwGetEGLSurface(GLFWwindow * handle)733 GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* handle)
734 {
735     _GLFWwindow* window = (_GLFWwindow*) handle;
736     _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE);
737 
738     if (window->context.client == GLFW_NO_API)
739     {
740         _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
741         return EGL_NO_SURFACE;
742     }
743 
744     return window->context.egl.surface;
745 }
746 
747