egl_context.c (24775B)
1 //======================================================================== 2 // GLFW 3.4 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 // 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 // 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 // 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 = (EGLConfig*)calloc(nativeCount, sizeof(EGLConfig)); 107 eglGetConfigs(_glfw.egl.display, nativeConfigs, nativeCount, &nativeCount); 108 109 usableConfigs = (_GLFWfbconfig*)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 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 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 236 static void swapIntervalEGL(int interval) 237 { 238 eglSwapInterval(_glfw.egl.display, interval); 239 } 240 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 253 static GLFWglproc getProcAddressEGL(const char* procname) 254 { 255 _GLFWwindow* window = (_GLFWwindow*)_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 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 // 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 // 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 // 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 { 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) 711 GLFWbool _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 756 GLFWAPI EGLDisplay glfwGetEGLDisplay(void) 757 { 758 _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_DISPLAY); 759 return _glfw.egl.display; 760 } 761 762 GLFWAPI 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 776 GLFWAPI 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