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