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//
38static 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//
79static 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//
88static 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
173static 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
205static 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
217static void swapIntervalEGL(int interval)
218{
219 eglSwapInterval(_glfw.egl.display, interval);
220}
221
222static 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
234static 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
249static 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//
284GLFWbool _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//
408void _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//
432GLFWbool _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)
669GLFWbool _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
713GLFWAPI EGLDisplay glfwGetEGLDisplay(void)
714{
715 _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_DISPLAY);
716 return _glfw.egl.display;
717}
718
719GLFWAPI 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
733GLFWAPI 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