egl_context.cc (23759B)
1 //======================================================================== 2 // GLFW 3.3 EGL - www.glfw.org 3 //------------------------------------------------------------------------ 4 // Copyright (c) 2002-2006 Marcus Geelnard 5 // Copyright (c) 2006-2016 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 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 // 38 static 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 // 79 static 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 // 88 static 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 173 static 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 _glfwPlatformSetTls(&_glfw.contextSlot, window); 203 } 204 205 static void swapBuffersEGL(_GLFWwindow* window) 206 { 207 if (window != _glfwPlatformGetTls(&_glfw.contextSlot)) 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 217 static void swapIntervalEGL(int interval) 218 { 219 eglSwapInterval(_glfw.egl.display, interval); 220 } 221 222 static 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 234 static GLFWglproc getProcAddressEGL(const char* procname) 235 { 236 _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot); 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 249 static 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 // 284 GLFWbool _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 #elif defined(__CYGWIN__) 295 "libEGL-1.so", 296 #else 297 "libEGL.so.1", 298 #endif 299 NULL 300 }; 301 302 if (_glfw.egl.handle) 303 return GLFW_TRUE; 304 305 for (i = 0; sonames[i]; i++) 306 { 307 _glfw.egl.handle = _glfw_dlopen(sonames[i]); 308 if (_glfw.egl.handle) 309 break; 310 } 311 312 if (!_glfw.egl.handle) 313 { 314 _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Library not found"); 315 return GLFW_FALSE; 316 } 317 318 _glfw.egl.prefix = (strncmp(sonames[i], "lib", 3) == 0); 319 320 _glfw.egl.GetConfigAttrib = (PFN_eglGetConfigAttrib) 321 _glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib"); 322 _glfw.egl.GetConfigs = (PFN_eglGetConfigs) 323 _glfw_dlsym(_glfw.egl.handle, "eglGetConfigs"); 324 _glfw.egl.GetDisplay = (PFN_eglGetDisplay) 325 _glfw_dlsym(_glfw.egl.handle, "eglGetDisplay"); 326 _glfw.egl.GetError = (PFN_eglGetError) 327 _glfw_dlsym(_glfw.egl.handle, "eglGetError"); 328 _glfw.egl.Initialize = (PFN_eglInitialize) 329 _glfw_dlsym(_glfw.egl.handle, "eglInitialize"); 330 _glfw.egl.Terminate = (PFN_eglTerminate) 331 _glfw_dlsym(_glfw.egl.handle, "eglTerminate"); 332 _glfw.egl.BindAPI = (PFN_eglBindAPI) 333 _glfw_dlsym(_glfw.egl.handle, "eglBindAPI"); 334 _glfw.egl.CreateContext = (PFN_eglCreateContext) 335 _glfw_dlsym(_glfw.egl.handle, "eglCreateContext"); 336 _glfw.egl.DestroySurface = (PFN_eglDestroySurface) 337 _glfw_dlsym(_glfw.egl.handle, "eglDestroySurface"); 338 _glfw.egl.DestroyContext = (PFN_eglDestroyContext) 339 _glfw_dlsym(_glfw.egl.handle, "eglDestroyContext"); 340 _glfw.egl.CreateWindowSurface = (PFN_eglCreateWindowSurface) 341 _glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface"); 342 _glfw.egl.MakeCurrent = (PFN_eglMakeCurrent) 343 _glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent"); 344 _glfw.egl.SwapBuffers = (PFN_eglSwapBuffers) 345 _glfw_dlsym(_glfw.egl.handle, "eglSwapBuffers"); 346 _glfw.egl.SwapInterval = (PFN_eglSwapInterval) 347 _glfw_dlsym(_glfw.egl.handle, "eglSwapInterval"); 348 _glfw.egl.QueryString = (PFN_eglQueryString) 349 _glfw_dlsym(_glfw.egl.handle, "eglQueryString"); 350 _glfw.egl.GetProcAddress = (PFN_eglGetProcAddress) 351 _glfw_dlsym(_glfw.egl.handle, "eglGetProcAddress"); 352 353 if (!_glfw.egl.GetConfigAttrib || 354 !_glfw.egl.GetConfigs || 355 !_glfw.egl.GetDisplay || 356 !_glfw.egl.GetError || 357 !_glfw.egl.Initialize || 358 !_glfw.egl.Terminate || 359 !_glfw.egl.BindAPI || 360 !_glfw.egl.CreateContext || 361 !_glfw.egl.DestroySurface || 362 !_glfw.egl.DestroyContext || 363 !_glfw.egl.CreateWindowSurface || 364 !_glfw.egl.MakeCurrent || 365 !_glfw.egl.SwapBuffers || 366 !_glfw.egl.SwapInterval || 367 !_glfw.egl.QueryString || 368 !_glfw.egl.GetProcAddress) 369 { 370 _glfwInputError(GLFW_PLATFORM_ERROR, 371 "EGL: Failed to load required entry points"); 372 373 _glfwTerminateEGL(); 374 return GLFW_FALSE; 375 } 376 377 _glfw.egl.display = eglGetDisplay(_GLFW_EGL_NATIVE_DISPLAY); 378 if (_glfw.egl.display == EGL_NO_DISPLAY) 379 { 380 _glfwInputError(GLFW_API_UNAVAILABLE, 381 "EGL: Failed to get EGL display: %s", 382 getEGLErrorString(eglGetError())); 383 384 _glfwTerminateEGL(); 385 return GLFW_FALSE; 386 } 387 388 if (!eglInitialize(_glfw.egl.display, &_glfw.egl.major, &_glfw.egl.minor)) 389 { 390 _glfwInputError(GLFW_API_UNAVAILABLE, 391 "EGL: Failed to initialize EGL: %s", 392 getEGLErrorString(eglGetError())); 393 394 _glfwTerminateEGL(); 395 return GLFW_FALSE; 396 } 397 398 _glfw.egl.KHR_create_context = 399 extensionSupportedEGL("EGL_KHR_create_context"); 400 _glfw.egl.KHR_create_context_no_error = 401 extensionSupportedEGL("EGL_KHR_create_context_no_error"); 402 _glfw.egl.KHR_gl_colorspace = 403 extensionSupportedEGL("EGL_KHR_gl_colorspace"); 404 _glfw.egl.KHR_get_all_proc_addresses = 405 extensionSupportedEGL("EGL_KHR_get_all_proc_addresses"); 406 _glfw.egl.KHR_context_flush_control = 407 extensionSupportedEGL("EGL_KHR_context_flush_control"); 408 409 return GLFW_TRUE; 410 } 411 412 // Terminate EGL 413 // 414 void _glfwTerminateEGL(void) 415 { 416 if (_glfw.egl.display) 417 { 418 eglTerminate(_glfw.egl.display); 419 _glfw.egl.display = EGL_NO_DISPLAY; 420 } 421 422 if (_glfw.egl.handle) 423 { 424 _glfw_dlclose(_glfw.egl.handle); 425 _glfw.egl.handle = NULL; 426 } 427 } 428 429 #define setAttrib(a, v) \ 430 { \ 431 assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \ 432 attribs[index++] = a; \ 433 attribs[index++] = v; \ 434 } 435 436 // Create the OpenGL or OpenGL ES context 437 // 438 GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, 439 const _GLFWctxconfig* ctxconfig, 440 const _GLFWfbconfig* fbconfig) 441 { 442 EGLint attribs[40]; 443 EGLConfig config; 444 EGLContext share = NULL; 445 int index = 0; 446 447 if (!_glfw.egl.display) 448 { 449 _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: API not available"); 450 return GLFW_FALSE; 451 } 452 453 if (ctxconfig->share) 454 share = ctxconfig->share->context.egl.handle; 455 456 if (!chooseEGLConfig(ctxconfig, fbconfig, &config)) 457 { 458 _glfwInputError(GLFW_FORMAT_UNAVAILABLE, 459 "EGL: Failed to find a suitable EGLConfig"); 460 return GLFW_FALSE; 461 } 462 463 if (ctxconfig->client == GLFW_OPENGL_ES_API) 464 { 465 if (!eglBindAPI(EGL_OPENGL_ES_API)) 466 { 467 _glfwInputError(GLFW_API_UNAVAILABLE, 468 "EGL: Failed to bind OpenGL ES: %s", 469 getEGLErrorString(eglGetError())); 470 return GLFW_FALSE; 471 } 472 } 473 else 474 { 475 if (!eglBindAPI(EGL_OPENGL_API)) 476 { 477 _glfwInputError(GLFW_API_UNAVAILABLE, 478 "EGL: Failed to bind OpenGL: %s", 479 getEGLErrorString(eglGetError())); 480 return GLFW_FALSE; 481 } 482 } 483 484 if (_glfw.egl.KHR_create_context) 485 { 486 int mask = 0, flags = 0; 487 488 if (ctxconfig->client == GLFW_OPENGL_API) 489 { 490 if (ctxconfig->forward) 491 flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; 492 493 if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE) 494 mask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; 495 else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE) 496 mask |= EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; 497 } 498 499 if (ctxconfig->debug) 500 flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR; 501 502 if (ctxconfig->robustness) 503 { 504 if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION) 505 { 506 setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, 507 EGL_NO_RESET_NOTIFICATION_KHR); 508 } 509 else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET) 510 { 511 setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, 512 EGL_LOSE_CONTEXT_ON_RESET_KHR); 513 } 514 515 flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR; 516 } 517 518 if (ctxconfig->noerror) 519 { 520 if (_glfw.egl.KHR_create_context_no_error) 521 setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE); 522 } 523 524 if (ctxconfig->major != 1 || ctxconfig->minor != 0) 525 { 526 setAttrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major); 527 setAttrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor); 528 } 529 530 if (mask) 531 setAttrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask); 532 533 if (flags) 534 setAttrib(EGL_CONTEXT_FLAGS_KHR, flags); 535 } 536 else 537 { 538 if (ctxconfig->client == GLFW_OPENGL_ES_API) 539 setAttrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major); 540 } 541 542 if (_glfw.egl.KHR_context_flush_control) 543 { 544 if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE) 545 { 546 setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR, 547 EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR); 548 } 549 else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH) 550 { 551 setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR, 552 EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR); 553 } 554 } 555 556 setAttrib(EGL_NONE, EGL_NONE); 557 558 window->context.egl.handle = eglCreateContext(_glfw.egl.display, 559 config, share, attribs); 560 561 if (window->context.egl.handle == EGL_NO_CONTEXT) 562 { 563 _glfwInputError(GLFW_VERSION_UNAVAILABLE, 564 "EGL: Failed to create context: %s", 565 getEGLErrorString(eglGetError())); 566 return GLFW_FALSE; 567 } 568 569 // Set up attributes for surface creation 570 { 571 int index = 0; 572 573 if (fbconfig->sRGB) 574 { 575 if (_glfw.egl.KHR_gl_colorspace) 576 setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR); 577 } 578 579 setAttrib(EGL_NONE, EGL_NONE); 580 } 581 582 window->context.egl.surface = 583 eglCreateWindowSurface(_glfw.egl.display, 584 config, 585 _GLFW_EGL_NATIVE_WINDOW, 586 attribs); 587 if (window->context.egl.surface == EGL_NO_SURFACE) 588 { 589 _glfwInputError(GLFW_PLATFORM_ERROR, 590 "EGL: Failed to create window surface: %s", 591 getEGLErrorString(eglGetError())); 592 return GLFW_FALSE; 593 } 594 595 window->context.egl.config = config; 596 597 // Load the appropriate client library 598 if (!_glfw.egl.KHR_get_all_proc_addresses) 599 { 600 int i; 601 const char** sonames; 602 const char* es1sonames[] = 603 { 604 #if defined(_GLFW_WIN32) 605 "GLESv1_CM.dll", 606 "libGLES_CM.dll", 607 #elif defined(_GLFW_COCOA) 608 "libGLESv1_CM.dylib", 609 #else 610 "libGLESv1_CM.so.1", 611 "libGLES_CM.so.1", 612 #endif 613 NULL 614 }; 615 const char* es2sonames[] = 616 { 617 #if defined(_GLFW_WIN32) 618 "GLESv2.dll", 619 "libGLESv2.dll", 620 #elif defined(_GLFW_COCOA) 621 "libGLESv2.dylib", 622 #elif defined(__CYGWIN__) 623 "libGLESv2-2.so", 624 #else 625 "libGLESv2.so.2", 626 #endif 627 NULL 628 }; 629 const char* glsonames[] = 630 { 631 #if defined(_GLFW_WIN32) 632 #elif defined(_GLFW_COCOA) 633 #else 634 "libGL.so.1", 635 #endif 636 NULL 637 }; 638 639 if (ctxconfig->client == GLFW_OPENGL_ES_API) 640 { 641 if (ctxconfig->major == 1) 642 sonames = es1sonames; 643 else 644 sonames = es2sonames; 645 } 646 else 647 sonames = glsonames; 648 649 for (i = 0; sonames[i]; i++) 650 { 651 // HACK: Match presence of lib prefix to increase chance of finding 652 // a matching pair in the jungle that is Win32 EGL/GLES 653 if (_glfw.egl.prefix != (strncmp(sonames[i], "lib", 3) == 0)) 654 continue; 655 656 window->context.egl.client = _glfw_dlopen(sonames[i]); 657 if (window->context.egl.client) 658 break; 659 } 660 661 if (!window->context.egl.client) 662 { 663 _glfwInputError(GLFW_API_UNAVAILABLE, 664 "EGL: Failed to load client library"); 665 return GLFW_FALSE; 666 } 667 } 668 669 window->context.makeCurrent = makeContextCurrentEGL; 670 window->context.swapBuffers = swapBuffersEGL; 671 window->context.swapInterval = swapIntervalEGL; 672 window->context.extensionSupported = extensionSupportedEGL; 673 window->context.getProcAddress = getProcAddressEGL; 674 window->context.destroy = destroyContextEGL; 675 676 return GLFW_TRUE; 677 } 678 679 #undef setAttrib 680 681 // Returns the Visual and depth of the chosen EGLConfig 682 // 683 #if defined(_GLFW_X11) 684 GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig, 685 const _GLFWfbconfig* fbconfig, 686 Visual** visual, int* depth) 687 { 688 XVisualInfo* result; 689 XVisualInfo desired; 690 EGLConfig native; 691 EGLint visualID = 0, count = 0; 692 const long vimask = VisualScreenMask | VisualIDMask; 693 694 if (!chooseEGLConfig(ctxconfig, fbconfig, &native)) 695 { 696 _glfwInputError(GLFW_FORMAT_UNAVAILABLE, 697 "EGL: Failed to find a suitable EGLConfig"); 698 return GLFW_FALSE; 699 } 700 701 eglGetConfigAttrib(_glfw.egl.display, native, 702 EGL_NATIVE_VISUAL_ID, &visualID); 703 704 desired.screen = _glfw.x11.screen; 705 desired.visualid = visualID; 706 707 result = XGetVisualInfo(_glfw.x11.display, vimask, &desired, &count); 708 if (!result) 709 { 710 _glfwInputError(GLFW_PLATFORM_ERROR, 711 "EGL: Failed to retrieve Visual for EGLConfig"); 712 return GLFW_FALSE; 713 } 714 715 *visual = result->visual; 716 *depth = result->depth; 717 718 XFree(result); 719 return GLFW_TRUE; 720 } 721 #endif // _GLFW_X11 722 723 724 ////////////////////////////////////////////////////////////////////////// 725 ////// GLFW native API ////// 726 ////////////////////////////////////////////////////////////////////////// 727 728 GLFWAPI EGLDisplay glfwGetEGLDisplay(void) 729 { 730 _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_DISPLAY); 731 return _glfw.egl.display; 732 } 733 734 GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* handle) 735 { 736 _GLFWwindow* window = (_GLFWwindow*) handle; 737 _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT); 738 739 if (window->context.client == GLFW_NO_API) 740 { 741 _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); 742 return EGL_NO_CONTEXT; 743 } 744 745 return window->context.egl.handle; 746 } 747 748 GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* handle) 749 { 750 _GLFWwindow* window = (_GLFWwindow*) handle; 751 _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE); 752 753 if (window->context.client == GLFW_NO_API) 754 { 755 _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); 756 return EGL_NO_SURFACE; 757 } 758 759 return window->context.egl.surface; 760 } 761