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 //
getEGLErrorString(EGLint error)40 static 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 //
getEGLConfigAttrib(EGLConfig config,int attrib)81 static 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 //
chooseEGLConfig(const _GLFWctxconfig * ctxconfig,const _GLFWfbconfig * desired,EGLConfig * result)90 static 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
makeContextCurrentEGL(_GLFWwindow * window)192 static 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
swapBuffersEGL(_GLFWwindow * window)224 static 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
swapIntervalEGL(int interval)236 static void swapIntervalEGL(int interval)
237 {
238 eglSwapInterval(_glfw.egl.display, interval);
239 }
240
extensionSupportedEGL(const char * extension)241 static 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
getProcAddressEGL(const char * procname)253 static 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
destroyContextEGL(_GLFWwindow * window)268 static 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 //
_glfwInitEGL(void)303 GLFWbool _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 //
_glfwTerminateEGL(void)435 void _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 //
_glfwCreateContextEGL(_GLFWwindow * window,const _GLFWctxconfig * ctxconfig,const _GLFWfbconfig * fbconfig)459 GLFWbool _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 index = 0;
592
593 if (fbconfig->sRGB)
594 {
595 if (_glfw.egl.KHR_gl_colorspace)
596 setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
597 }
598
599 setAttrib(EGL_NONE, EGL_NONE);
600
601 window->context.egl.surface =
602 eglCreateWindowSurface(_glfw.egl.display,
603 config,
604 _GLFW_EGL_NATIVE_WINDOW,
605 attribs);
606 if (window->context.egl.surface == EGL_NO_SURFACE)
607 {
608 _glfwInputError(GLFW_PLATFORM_ERROR,
609 "EGL: Failed to create window surface: %s",
610 getEGLErrorString(eglGetError()));
611 return GLFW_FALSE;
612 }
613
614 window->context.egl.config = config;
615
616 // Load the appropriate client library
617 if (!_glfw.egl.KHR_get_all_proc_addresses)
618 {
619 int i;
620 const char** sonames;
621 const char* es1sonames[] =
622 {
623 #if defined(_GLFW_GLESV1_LIBRARY)
624 _GLFW_GLESV1_LIBRARY,
625 #elif defined(_GLFW_WIN32)
626 "GLESv1_CM.dll",
627 "libGLES_CM.dll",
628 #elif defined(_GLFW_COCOA)
629 "libGLESv1_CM.dylib",
630 #else
631 "libGLESv1_CM.so.1",
632 "libGLES_CM.so.1",
633 #endif
634 NULL
635 };
636 const char* es2sonames[] =
637 {
638 #if defined(_GLFW_GLESV2_LIBRARY)
639 _GLFW_GLESV2_LIBRARY,
640 #elif defined(_GLFW_WIN32)
641 "GLESv2.dll",
642 "libGLESv2.dll",
643 #elif defined(_GLFW_COCOA)
644 "libGLESv2.dylib",
645 #elif defined(__CYGWIN__)
646 "libGLESv2-2.so",
647 #else
648 "libGLESv2.so.2",
649 #endif
650 NULL
651 };
652 const char* glsonames[] =
653 {
654 #if defined(_GLFW_OPENGL_LIBRARY)
655 _GLFW_OPENGL_LIBRARY,
656 #elif defined(_GLFW_WIN32)
657 #elif defined(_GLFW_COCOA)
658 #else
659 "libGL.so.1",
660 #endif
661 NULL
662 };
663
664 if (ctxconfig->client == GLFW_OPENGL_ES_API)
665 {
666 if (ctxconfig->major == 1)
667 sonames = es1sonames;
668 else
669 sonames = es2sonames;
670 }
671 else
672 sonames = glsonames;
673
674 for (i = 0; sonames[i]; i++)
675 {
676 // HACK: Match presence of lib prefix to increase chance of finding
677 // a matching pair in the jungle that is Win32 EGL/GLES
678 if (_glfw.egl.prefix != (strncmp(sonames[i], "lib", 3) == 0))
679 continue;
680
681 window->context.egl.client = _glfw_dlopen(sonames[i]);
682 if (window->context.egl.client)
683 break;
684 }
685
686 if (!window->context.egl.client)
687 {
688 _glfwInputError(GLFW_API_UNAVAILABLE,
689 "EGL: Failed to load client library");
690 return GLFW_FALSE;
691 }
692 }
693
694 window->context.makeCurrent = makeContextCurrentEGL;
695 window->context.swapBuffers = swapBuffersEGL;
696 window->context.swapInterval = swapIntervalEGL;
697 window->context.extensionSupported = extensionSupportedEGL;
698 window->context.getProcAddress = getProcAddressEGL;
699 window->context.destroy = destroyContextEGL;
700
701 return GLFW_TRUE;
702 }
703
704 #undef setAttrib
705
706 // Returns the Visual and depth of the chosen EGLConfig
707 //
708 #if defined(_GLFW_X11)
_glfwChooseVisualEGL(const _GLFWwndconfig * wndconfig,const _GLFWctxconfig * ctxconfig,const _GLFWfbconfig * fbconfig,Visual ** visual,int * depth)709 GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
710 const _GLFWctxconfig* ctxconfig,
711 const _GLFWfbconfig* fbconfig,
712 Visual** visual, int* depth)
713 {
714 XVisualInfo* result;
715 XVisualInfo desired;
716 EGLConfig native;
717 EGLint visualID = 0, count = 0;
718 const long vimask = VisualScreenMask | VisualIDMask;
719
720 if (!chooseEGLConfig(ctxconfig, fbconfig, &native))
721 {
722 _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
723 "EGL: Failed to find a suitable EGLConfig");
724 return GLFW_FALSE;
725 }
726
727 eglGetConfigAttrib(_glfw.egl.display, native,
728 EGL_NATIVE_VISUAL_ID, &visualID);
729
730 desired.screen = _glfw.x11.screen;
731 desired.visualid = visualID;
732
733 result = XGetVisualInfo(_glfw.x11.display, vimask, &desired, &count);
734 if (!result)
735 {
736 _glfwInputError(GLFW_PLATFORM_ERROR,
737 "EGL: Failed to retrieve Visual for EGLConfig");
738 return GLFW_FALSE;
739 }
740
741 *visual = result->visual;
742 *depth = result->depth;
743
744 XFree(result);
745 return GLFW_TRUE;
746 }
747 #endif // _GLFW_X11
748
749
750 //////////////////////////////////////////////////////////////////////////
751 ////// GLFW native API //////
752 //////////////////////////////////////////////////////////////////////////
753
glfwGetEGLDisplay(void)754 GLFWAPI EGLDisplay glfwGetEGLDisplay(void)
755 {
756 _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_DISPLAY);
757 return _glfw.egl.display;
758 }
759
glfwGetEGLContext(GLFWwindow * handle)760 GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* handle)
761 {
762 _GLFWwindow* window = (_GLFWwindow*) handle;
763 _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT);
764
765 if (window->context.client == GLFW_NO_API)
766 {
767 _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
768 return EGL_NO_CONTEXT;
769 }
770
771 return window->context.egl.handle;
772 }
773
glfwGetEGLSurface(GLFWwindow * handle)774 GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* handle)
775 {
776 _GLFWwindow* window = (_GLFWwindow*) handle;
777 _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE);
778
779 if (window->context.client == GLFW_NO_API)
780 {
781 _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
782 return EGL_NO_SURFACE;
783 }
784
785 return window->context.egl.surface;
786 }
787
788