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