1 /* 2 ** Copyright 2007, The Android Open Source Project 3 ** 4 ** Licensed under the Apache License, Version 2.0 (the "License"); 5 ** you may not use this file except in compliance with the License. 6 ** You may obtain a copy of the License at 7 ** 8 ** http://www.apache.org/licenses/LICENSE-2.0 9 ** 10 ** Unless required by applicable law or agreed to in writing, software 11 ** distributed under the License is distributed on an "AS IS" BASIS, 12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 ** See the License for the specific language governing permissions and 14 ** limitations under the License. 15 */ 16 17 #define ATRACE_TAG ATRACE_TAG_GRAPHICS 18 19 #include <dlfcn.h> 20 #include <ctype.h> 21 #include <stdlib.h> 22 #include <string.h> 23 24 #include <hardware/gralloc.h> 25 #include <system/window.h> 26 27 #include <EGL/egl.h> 28 #include <EGL/eglext.h> 29 30 #include <cutils/log.h> 31 #include <cutils/atomic.h> 32 #include <cutils/compiler.h> 33 #include <cutils/properties.h> 34 #include <cutils/memory.h> 35 36 #include <utils/KeyedVector.h> 37 #include <utils/SortedVector.h> 38 #include <utils/String8.h> 39 #include <utils/Trace.h> 40 41 #include "../egl_impl.h" 42 #include "../glestrace.h" 43 #include "../hooks.h" 44 45 #include "egl_display.h" 46 #include "egl_object.h" 47 #include "egl_tls.h" 48 #include "egldefs.h" 49 50 using namespace android; 51 52 // This extension has not been ratified yet, so can't be shipped. 53 // Implementation is incomplete and untested. 54 #define ENABLE_EGL_KHR_GL_COLORSPACE 0 55 56 // ---------------------------------------------------------------------------- 57 58 namespace android { 59 60 struct extention_map_t { 61 const char* name; 62 __eglMustCastToProperFunctionPointerType address; 63 }; 64 65 /* 66 * This is the list of EGL extensions exposed to applications. 67 * 68 * Some of them (gBuiltinExtensionString) are implemented entirely in this EGL 69 * wrapper and are always available. 70 * 71 * The rest (gExtensionString) depend on support in the EGL driver, and are 72 * only available if the driver supports them. However, some of these must be 73 * supported because they are used by the Android system itself; these are 74 * listd as mandatory below and are required by the CDD. The system *assumes* 75 * the mandatory extensions are present and may not function properly if some 76 * are missing. 77 * 78 * NOTE: Both strings MUST have a single space as the last character. 79 */ 80 extern char const * const gBuiltinExtensionString = 81 "EGL_KHR_get_all_proc_addresses " 82 "EGL_ANDROID_presentation_time " 83 ; 84 extern char const * const gExtensionString = 85 "EGL_KHR_image " // mandatory 86 "EGL_KHR_image_base " // mandatory 87 "EGL_KHR_image_pixmap " 88 "EGL_KHR_lock_surface " 89 #if (ENABLE_EGL_KHR_GL_COLORSPACE != 0) 90 "EGL_KHR_gl_colorspace " 91 #endif 92 "EGL_KHR_gl_texture_2D_image " 93 "EGL_KHR_gl_texture_cubemap_image " 94 "EGL_KHR_gl_renderbuffer_image " 95 "EGL_KHR_reusable_sync " 96 "EGL_KHR_fence_sync " 97 "EGL_KHR_create_context " 98 "EGL_EXT_create_context_robustness " 99 "EGL_NV_system_time " 100 "EGL_ANDROID_image_native_buffer " // mandatory 101 "EGL_KHR_wait_sync " // strongly recommended 102 "EGL_ANDROID_recordable " // mandatory 103 ; 104 105 // extensions not exposed to applications but used by the ANDROID system 106 // "EGL_ANDROID_blob_cache " // strongly recommended 107 // "EGL_IMG_hibernate_process " // optional 108 // "EGL_ANDROID_native_fence_sync " // strongly recommended 109 // "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1 110 // "EGL_ANDROID_image_crop " // optional 111 112 /* 113 * EGL Extensions entry-points exposed to 3rd party applications 114 * (keep in sync with gExtensionString above) 115 * 116 */ 117 static const extention_map_t sExtensionMap[] = { 118 // EGL_KHR_lock_surface 119 { "eglLockSurfaceKHR", 120 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR }, 121 { "eglUnlockSurfaceKHR", 122 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR }, 123 124 // EGL_KHR_image, EGL_KHR_image_base 125 { "eglCreateImageKHR", 126 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, 127 { "eglDestroyImageKHR", 128 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, 129 130 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync 131 { "eglCreateSyncKHR", 132 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR }, 133 { "eglDestroySyncKHR", 134 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR }, 135 { "eglClientWaitSyncKHR", 136 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR }, 137 { "eglSignalSyncKHR", 138 (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR }, 139 { "eglGetSyncAttribKHR", 140 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR }, 141 142 // EGL_NV_system_time 143 { "eglGetSystemTimeFrequencyNV", 144 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV }, 145 { "eglGetSystemTimeNV", 146 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV }, 147 148 // EGL_KHR_wait_sync 149 { "eglWaitSyncKHR", 150 (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR }, 151 152 // EGL_ANDROID_presentation_time 153 { "eglPresentationTimeANDROID", 154 (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID }, 155 }; 156 157 /* 158 * These extensions entry-points should not be exposed to applications. 159 * They're used internally by the Android EGL layer. 160 */ 161 #define FILTER_EXTENSIONS(procname) \ 162 (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \ 163 !strcmp((procname), "eglHibernateProcessIMG") || \ 164 !strcmp((procname), "eglAwakenProcessIMG") || \ 165 !strcmp((procname), "eglDupNativeFenceFDANDROID")) 166 167 168 169 // accesses protected by sExtensionMapMutex 170 static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap; 171 static int sGLExtentionSlot = 0; 172 static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER; 173 174 static void(*findProcAddress(const char* name, 175 const extention_map_t* map, size_t n))() { 176 for (uint32_t i=0 ; i<n ; i++) { 177 if (!strcmp(name, map[i].name)) { 178 return map[i].address; 179 } 180 } 181 return NULL; 182 } 183 184 // ---------------------------------------------------------------------------- 185 186 extern void setGLHooksThreadSpecific(gl_hooks_t const *value); 187 extern EGLBoolean egl_init_drivers(); 188 extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS]; 189 extern int getEGLDebugLevel(); 190 extern void setEGLDebugLevel(int level); 191 extern gl_hooks_t gHooksTrace; 192 193 } // namespace android; 194 195 196 // ---------------------------------------------------------------------------- 197 198 static inline void clearError() { egl_tls_t::clearError(); } 199 static inline EGLContext getContext() { return egl_tls_t::getContext(); } 200 201 // ---------------------------------------------------------------------------- 202 203 EGLDisplay eglGetDisplay(EGLNativeDisplayType display) 204 { 205 clearError(); 206 207 uintptr_t index = reinterpret_cast<uintptr_t>(display); 208 if (index >= NUM_DISPLAYS) { 209 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 210 } 211 212 if (egl_init_drivers() == EGL_FALSE) { 213 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 214 } 215 216 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display); 217 return dpy; 218 } 219 220 // ---------------------------------------------------------------------------- 221 // Initialization 222 // ---------------------------------------------------------------------------- 223 224 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) 225 { 226 clearError(); 227 228 egl_display_ptr dp = get_display(dpy); 229 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 230 231 EGLBoolean res = dp->initialize(major, minor); 232 233 return res; 234 } 235 236 EGLBoolean eglTerminate(EGLDisplay dpy) 237 { 238 // NOTE: don't unload the drivers b/c some APIs can be called 239 // after eglTerminate() has been called. eglTerminate() only 240 // terminates an EGLDisplay, not a EGL itself. 241 242 clearError(); 243 244 egl_display_ptr dp = get_display(dpy); 245 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 246 247 EGLBoolean res = dp->terminate(); 248 249 return res; 250 } 251 252 // ---------------------------------------------------------------------------- 253 // configuration 254 // ---------------------------------------------------------------------------- 255 256 EGLBoolean eglGetConfigs( EGLDisplay dpy, 257 EGLConfig *configs, 258 EGLint config_size, EGLint *num_config) 259 { 260 clearError(); 261 262 const egl_display_ptr dp = validate_display(dpy); 263 if (!dp) return EGL_FALSE; 264 265 if (num_config==0) { 266 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 267 } 268 269 EGLBoolean res = EGL_FALSE; 270 *num_config = 0; 271 272 egl_connection_t* const cnx = &gEGLImpl; 273 if (cnx->dso) { 274 res = cnx->egl.eglGetConfigs( 275 dp->disp.dpy, configs, config_size, num_config); 276 } 277 278 return res; 279 } 280 281 EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, 282 EGLConfig *configs, EGLint config_size, 283 EGLint *num_config) 284 { 285 clearError(); 286 287 const egl_display_ptr dp = validate_display(dpy); 288 if (!dp) return EGL_FALSE; 289 290 if (num_config==0) { 291 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 292 } 293 294 EGLBoolean res = EGL_FALSE; 295 *num_config = 0; 296 297 egl_connection_t* const cnx = &gEGLImpl; 298 if (cnx->dso) { 299 if (attrib_list) { 300 char value[PROPERTY_VALUE_MAX]; 301 property_get("debug.egl.force_msaa", value, "false"); 302 303 if (!strcmp(value, "true")) { 304 size_t attribCount = 0; 305 EGLint attrib = attrib_list[0]; 306 307 // Only enable MSAA if the context is OpenGL ES 2.0 and 308 // if no caveat is requested 309 const EGLint *attribRendererable = NULL; 310 const EGLint *attribCaveat = NULL; 311 312 // Count the number of attributes and look for 313 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT 314 while (attrib != EGL_NONE) { 315 attrib = attrib_list[attribCount]; 316 switch (attrib) { 317 case EGL_RENDERABLE_TYPE: 318 attribRendererable = &attrib_list[attribCount]; 319 break; 320 case EGL_CONFIG_CAVEAT: 321 attribCaveat = &attrib_list[attribCount]; 322 break; 323 } 324 attribCount++; 325 } 326 327 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT && 328 (!attribCaveat || attribCaveat[1] != EGL_NONE)) { 329 330 // Insert 2 extra attributes to force-enable MSAA 4x 331 EGLint aaAttribs[attribCount + 4]; 332 aaAttribs[0] = EGL_SAMPLE_BUFFERS; 333 aaAttribs[1] = 1; 334 aaAttribs[2] = EGL_SAMPLES; 335 aaAttribs[3] = 4; 336 337 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint)); 338 339 EGLint numConfigAA; 340 EGLBoolean resAA = cnx->egl.eglChooseConfig( 341 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA); 342 343 if (resAA == EGL_TRUE && numConfigAA > 0) { 344 ALOGD("Enabling MSAA 4x"); 345 *num_config = numConfigAA; 346 return resAA; 347 } 348 } 349 } 350 } 351 352 res = cnx->egl.eglChooseConfig( 353 dp->disp.dpy, attrib_list, configs, config_size, num_config); 354 } 355 return res; 356 } 357 358 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, 359 EGLint attribute, EGLint *value) 360 { 361 clearError(); 362 363 egl_connection_t* cnx = NULL; 364 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 365 if (!dp) return EGL_FALSE; 366 367 return cnx->egl.eglGetConfigAttrib( 368 dp->disp.dpy, config, attribute, value); 369 } 370 371 // ---------------------------------------------------------------------------- 372 // surfaces 373 // ---------------------------------------------------------------------------- 374 375 // The EGL_KHR_gl_colorspace spec hasn't been ratified yet, so these haven't 376 // been added to the Khronos egl.h. 377 #define EGL_GL_COLORSPACE_KHR EGL_VG_COLORSPACE 378 #define EGL_GL_COLORSPACE_SRGB_KHR EGL_VG_COLORSPACE_sRGB 379 #define EGL_GL_COLORSPACE_LINEAR_KHR EGL_VG_COLORSPACE_LINEAR 380 381 // Turn linear formats into corresponding sRGB formats when colorspace is 382 // EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear 383 // formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where 384 // the modification isn't possible, the original format is returned. 385 static int modifyFormatColorspace(int fmt, EGLint colorspace) { 386 if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) { 387 switch (fmt) { 388 case HAL_PIXEL_FORMAT_sRGB_A_8888: return HAL_PIXEL_FORMAT_RGBA_8888; 389 case HAL_PIXEL_FORMAT_sRGB_X_8888: return HAL_PIXEL_FORMAT_RGBX_8888; 390 } 391 } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) { 392 switch (fmt) { 393 case HAL_PIXEL_FORMAT_RGBA_8888: return HAL_PIXEL_FORMAT_sRGB_A_8888; 394 case HAL_PIXEL_FORMAT_RGBX_8888: return HAL_PIXEL_FORMAT_sRGB_X_8888; 395 } 396 } 397 return fmt; 398 } 399 400 EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, 401 NativeWindowType window, 402 const EGLint *attrib_list) 403 { 404 clearError(); 405 406 egl_connection_t* cnx = NULL; 407 egl_display_ptr dp = validate_display_connection(dpy, cnx); 408 if (dp) { 409 EGLDisplay iDpy = dp->disp.dpy; 410 411 int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL); 412 if (result != OK) { 413 ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) " 414 "failed (%#x) (already connected to another API?)", 415 window, result); 416 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); 417 } 418 419 // Set the native window's buffers format to match what this config requests. 420 // Whether to use sRGB gamma is not part of the EGLconfig, but is part 421 // of our native format. So if sRGB gamma is requested, we have to 422 // modify the EGLconfig's format before setting the native window's 423 // format. 424 #if WORKAROUND_BUG_10194508 425 #warning "WORKAROUND_10194508 enabled" 426 EGLint format; 427 if (!cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_NATIVE_VISUAL_ID, 428 &format)) { 429 ALOGE("eglGetConfigAttrib(EGL_NATIVE_VISUAL_ID) failed: %#x", 430 eglGetError()); 431 format = 0; 432 } 433 if (attrib_list) { 434 for (const EGLint* attr = attrib_list; *attr != EGL_NONE; 435 attr += 2) { 436 if (*attr == EGL_GL_COLORSPACE_KHR && 437 dp->haveExtension("EGL_KHR_gl_colorspace")) { 438 if (ENABLE_EGL_KHR_GL_COLORSPACE) { 439 format = modifyFormatColorspace(format, *(attr+1)); 440 } else { 441 // Normally we'd pass through unhandled attributes to 442 // the driver. But in case the driver implements this 443 // extension but we're disabling it, we want to prevent 444 // it getting through -- support will be broken without 445 // our help. 446 ALOGE("sRGB window surfaces not supported"); 447 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); 448 } 449 } 450 } 451 } 452 #else 453 // by default, just pick RGBA_8888 454 EGLint format = HAL_PIXEL_FORMAT_RGBA_8888; 455 456 EGLint a = 0; 457 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a); 458 if (a > 0) { 459 // alpha-channel requested, there's really only one suitable format 460 format = HAL_PIXEL_FORMAT_RGBA_8888; 461 } else { 462 EGLint r, g, b; 463 r = g = b = 0; 464 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE, &r); 465 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g); 466 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE, &b); 467 EGLint colorDepth = r + g + b; 468 if (colorDepth <= 16) { 469 format = HAL_PIXEL_FORMAT_RGB_565; 470 } else { 471 format = HAL_PIXEL_FORMAT_RGBX_8888; 472 } 473 } 474 475 // now select a corresponding sRGB format if needed 476 if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) { 477 for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) { 478 if (*attr == EGL_GL_COLORSPACE_KHR) { 479 if (ENABLE_EGL_KHR_GL_COLORSPACE) { 480 format = modifyFormatColorspace(format, *(attr+1)); 481 } else { 482 // Normally we'd pass through unhandled attributes to 483 // the driver. But in case the driver implements this 484 // extension but we're disabling it, we want to prevent 485 // it getting through -- support will be broken without 486 // our help. 487 ALOGE("sRGB window surfaces not supported"); 488 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); 489 } 490 } 491 } 492 } 493 #endif 494 if (format != 0) { 495 int err = native_window_set_buffers_format(window, format); 496 if (err != 0) { 497 ALOGE("error setting native window pixel format: %s (%d)", 498 strerror(-err), err); 499 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 500 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 501 } 502 } 503 504 // the EGL spec requires that a new EGLSurface default to swap interval 505 // 1, so explicitly set that on the window here. 506 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window); 507 anw->setSwapInterval(anw, 1); 508 509 EGLSurface surface = cnx->egl.eglCreateWindowSurface( 510 iDpy, config, window, attrib_list); 511 if (surface != EGL_NO_SURFACE) { 512 egl_surface_t* s = new egl_surface_t(dp.get(), config, window, 513 surface, cnx); 514 return s; 515 } 516 517 // EGLSurface creation failed 518 native_window_set_buffers_format(window, 0); 519 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 520 } 521 return EGL_NO_SURFACE; 522 } 523 524 EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, 525 NativePixmapType pixmap, 526 const EGLint *attrib_list) 527 { 528 clearError(); 529 530 egl_connection_t* cnx = NULL; 531 egl_display_ptr dp = validate_display_connection(dpy, cnx); 532 if (dp) { 533 EGLSurface surface = cnx->egl.eglCreatePixmapSurface( 534 dp->disp.dpy, config, pixmap, attrib_list); 535 if (surface != EGL_NO_SURFACE) { 536 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, 537 surface, cnx); 538 return s; 539 } 540 } 541 return EGL_NO_SURFACE; 542 } 543 544 EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, 545 const EGLint *attrib_list) 546 { 547 clearError(); 548 549 egl_connection_t* cnx = NULL; 550 egl_display_ptr dp = validate_display_connection(dpy, cnx); 551 if (dp) { 552 EGLSurface surface = cnx->egl.eglCreatePbufferSurface( 553 dp->disp.dpy, config, attrib_list); 554 if (surface != EGL_NO_SURFACE) { 555 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, 556 surface, cnx); 557 return s; 558 } 559 } 560 return EGL_NO_SURFACE; 561 } 562 563 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) 564 { 565 clearError(); 566 567 const egl_display_ptr dp = validate_display(dpy); 568 if (!dp) return EGL_FALSE; 569 570 SurfaceRef _s(dp.get(), surface); 571 if (!_s.get()) 572 return setError(EGL_BAD_SURFACE, EGL_FALSE); 573 574 egl_surface_t * const s = get_surface(surface); 575 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface); 576 if (result == EGL_TRUE) { 577 _s.terminate(); 578 } 579 return result; 580 } 581 582 EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface, 583 EGLint attribute, EGLint *value) 584 { 585 clearError(); 586 587 const egl_display_ptr dp = validate_display(dpy); 588 if (!dp) return EGL_FALSE; 589 590 SurfaceRef _s(dp.get(), surface); 591 if (!_s.get()) 592 return setError(EGL_BAD_SURFACE, EGL_FALSE); 593 594 egl_surface_t const * const s = get_surface(surface); 595 return s->cnx->egl.eglQuerySurface( 596 dp->disp.dpy, s->surface, attribute, value); 597 } 598 599 void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) { 600 ATRACE_CALL(); 601 clearError(); 602 603 const egl_display_ptr dp = validate_display(dpy); 604 if (!dp) { 605 return; 606 } 607 608 SurfaceRef _s(dp.get(), surface); 609 if (!_s.get()) { 610 setError(EGL_BAD_SURFACE, EGL_FALSE); 611 return; 612 } 613 } 614 615 // ---------------------------------------------------------------------------- 616 // Contexts 617 // ---------------------------------------------------------------------------- 618 619 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, 620 EGLContext share_list, const EGLint *attrib_list) 621 { 622 clearError(); 623 624 egl_connection_t* cnx = NULL; 625 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 626 if (dp) { 627 if (share_list != EGL_NO_CONTEXT) { 628 if (!ContextRef(dp.get(), share_list).get()) { 629 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT); 630 } 631 egl_context_t* const c = get_context(share_list); 632 share_list = c->context; 633 } 634 EGLContext context = cnx->egl.eglCreateContext( 635 dp->disp.dpy, config, share_list, attrib_list); 636 if (context != EGL_NO_CONTEXT) { 637 // figure out if it's a GLESv1 or GLESv2 638 int version = 0; 639 if (attrib_list) { 640 while (*attrib_list != EGL_NONE) { 641 GLint attr = *attrib_list++; 642 GLint value = *attrib_list++; 643 if (attr == EGL_CONTEXT_CLIENT_VERSION) { 644 if (value == 1) { 645 version = egl_connection_t::GLESv1_INDEX; 646 } else if (value == 2 || value == 3) { 647 version = egl_connection_t::GLESv2_INDEX; 648 } 649 } 650 }; 651 } 652 egl_context_t* c = new egl_context_t(dpy, context, config, cnx, 653 version); 654 #if EGL_TRACE 655 if (getEGLDebugLevel() > 0) 656 GLTrace_eglCreateContext(version, c); 657 #endif 658 return c; 659 } 660 } 661 return EGL_NO_CONTEXT; 662 } 663 664 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) 665 { 666 clearError(); 667 668 const egl_display_ptr dp = validate_display(dpy); 669 if (!dp) 670 return EGL_FALSE; 671 672 ContextRef _c(dp.get(), ctx); 673 if (!_c.get()) 674 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 675 676 egl_context_t * const c = get_context(ctx); 677 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context); 678 if (result == EGL_TRUE) { 679 _c.terminate(); 680 } 681 return result; 682 } 683 684 EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, 685 EGLSurface read, EGLContext ctx) 686 { 687 clearError(); 688 689 egl_display_ptr dp = validate_display(dpy); 690 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 691 692 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not 693 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is 694 // a valid but uninitialized display. 695 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) || 696 (draw != EGL_NO_SURFACE) ) { 697 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE); 698 } 699 700 // get a reference to the object passed in 701 ContextRef _c(dp.get(), ctx); 702 SurfaceRef _d(dp.get(), draw); 703 SurfaceRef _r(dp.get(), read); 704 705 // validate the context (if not EGL_NO_CONTEXT) 706 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) { 707 // EGL_NO_CONTEXT is valid 708 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 709 } 710 711 // these are the underlying implementation's object 712 EGLContext impl_ctx = EGL_NO_CONTEXT; 713 EGLSurface impl_draw = EGL_NO_SURFACE; 714 EGLSurface impl_read = EGL_NO_SURFACE; 715 716 // these are our objects structs passed in 717 egl_context_t * c = NULL; 718 egl_surface_t const * d = NULL; 719 egl_surface_t const * r = NULL; 720 721 // these are the current objects structs 722 egl_context_t * cur_c = get_context(getContext()); 723 724 if (ctx != EGL_NO_CONTEXT) { 725 c = get_context(ctx); 726 impl_ctx = c->context; 727 } else { 728 // no context given, use the implementation of the current context 729 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) { 730 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT); 731 return setError(EGL_BAD_MATCH, EGL_FALSE); 732 } 733 if (cur_c == NULL) { 734 // no current context 735 // not an error, there is just no current context. 736 return EGL_TRUE; 737 } 738 } 739 740 // retrieve the underlying implementation's draw EGLSurface 741 if (draw != EGL_NO_SURFACE) { 742 if (!_d.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 743 d = get_surface(draw); 744 impl_draw = d->surface; 745 } 746 747 // retrieve the underlying implementation's read EGLSurface 748 if (read != EGL_NO_SURFACE) { 749 if (!_r.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 750 r = get_surface(read); 751 impl_read = r->surface; 752 } 753 754 755 EGLBoolean result = dp->makeCurrent(c, cur_c, 756 draw, read, ctx, 757 impl_draw, impl_read, impl_ctx); 758 759 if (result == EGL_TRUE) { 760 if (c) { 761 setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 762 egl_tls_t::setContext(ctx); 763 #if EGL_TRACE 764 if (getEGLDebugLevel() > 0) 765 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx); 766 #endif 767 _c.acquire(); 768 _r.acquire(); 769 _d.acquire(); 770 } else { 771 setGLHooksThreadSpecific(&gHooksNoContext); 772 egl_tls_t::setContext(EGL_NO_CONTEXT); 773 } 774 } else { 775 // this will ALOGE the error 776 egl_connection_t* const cnx = &gEGLImpl; 777 result = setError(cnx->egl.eglGetError(), EGL_FALSE); 778 } 779 return result; 780 } 781 782 783 EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, 784 EGLint attribute, EGLint *value) 785 { 786 clearError(); 787 788 const egl_display_ptr dp = validate_display(dpy); 789 if (!dp) return EGL_FALSE; 790 791 ContextRef _c(dp.get(), ctx); 792 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 793 794 egl_context_t * const c = get_context(ctx); 795 return c->cnx->egl.eglQueryContext( 796 dp->disp.dpy, c->context, attribute, value); 797 798 } 799 800 EGLContext eglGetCurrentContext(void) 801 { 802 // could be called before eglInitialize(), but we wouldn't have a context 803 // then, and this function would correctly return EGL_NO_CONTEXT. 804 805 clearError(); 806 807 EGLContext ctx = getContext(); 808 return ctx; 809 } 810 811 EGLSurface eglGetCurrentSurface(EGLint readdraw) 812 { 813 // could be called before eglInitialize(), but we wouldn't have a context 814 // then, and this function would correctly return EGL_NO_SURFACE. 815 816 clearError(); 817 818 EGLContext ctx = getContext(); 819 if (ctx) { 820 egl_context_t const * const c = get_context(ctx); 821 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 822 switch (readdraw) { 823 case EGL_READ: return c->read; 824 case EGL_DRAW: return c->draw; 825 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 826 } 827 } 828 return EGL_NO_SURFACE; 829 } 830 831 EGLDisplay eglGetCurrentDisplay(void) 832 { 833 // could be called before eglInitialize(), but we wouldn't have a context 834 // then, and this function would correctly return EGL_NO_DISPLAY. 835 836 clearError(); 837 838 EGLContext ctx = getContext(); 839 if (ctx) { 840 egl_context_t const * const c = get_context(ctx); 841 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 842 return c->dpy; 843 } 844 return EGL_NO_DISPLAY; 845 } 846 847 EGLBoolean eglWaitGL(void) 848 { 849 clearError(); 850 851 egl_connection_t* const cnx = &gEGLImpl; 852 if (!cnx->dso) 853 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 854 855 return cnx->egl.eglWaitGL(); 856 } 857 858 EGLBoolean eglWaitNative(EGLint engine) 859 { 860 clearError(); 861 862 egl_connection_t* const cnx = &gEGLImpl; 863 if (!cnx->dso) 864 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 865 866 return cnx->egl.eglWaitNative(engine); 867 } 868 869 EGLint eglGetError(void) 870 { 871 EGLint err = EGL_SUCCESS; 872 egl_connection_t* const cnx = &gEGLImpl; 873 if (cnx->dso) { 874 err = cnx->egl.eglGetError(); 875 } 876 if (err == EGL_SUCCESS) { 877 err = egl_tls_t::getError(); 878 } 879 return err; 880 } 881 882 static __eglMustCastToProperFunctionPointerType findBuiltinWrapper( 883 const char* procname) { 884 const egl_connection_t* cnx = &gEGLImpl; 885 void* proc = NULL; 886 887 proc = dlsym(cnx->libEgl, procname); 888 if (proc) return (__eglMustCastToProperFunctionPointerType)proc; 889 890 proc = dlsym(cnx->libGles2, procname); 891 if (proc) return (__eglMustCastToProperFunctionPointerType)proc; 892 893 proc = dlsym(cnx->libGles1, procname); 894 if (proc) return (__eglMustCastToProperFunctionPointerType)proc; 895 896 return NULL; 897 } 898 899 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) 900 { 901 // eglGetProcAddress() could be the very first function called 902 // in which case we must make sure we've initialized ourselves, this 903 // happens the first time egl_get_display() is called. 904 905 clearError(); 906 907 if (egl_init_drivers() == EGL_FALSE) { 908 setError(EGL_BAD_PARAMETER, NULL); 909 return NULL; 910 } 911 912 if (FILTER_EXTENSIONS(procname)) { 913 return NULL; 914 } 915 916 __eglMustCastToProperFunctionPointerType addr; 917 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap)); 918 if (addr) return addr; 919 920 addr = findBuiltinWrapper(procname); 921 if (addr) return addr; 922 923 // this protects accesses to sGLExtentionMap and sGLExtentionSlot 924 pthread_mutex_lock(&sExtensionMapMutex); 925 926 /* 927 * Since eglGetProcAddress() is not associated to anything, it needs 928 * to return a function pointer that "works" regardless of what 929 * the current context is. 930 * 931 * For this reason, we return a "forwarder", a small stub that takes 932 * care of calling the function associated with the context 933 * currently bound. 934 * 935 * We first look for extensions we've already resolved, if we're seeing 936 * this extension for the first time, we go through all our 937 * implementations and call eglGetProcAddress() and record the 938 * result in the appropriate implementation hooks and return the 939 * address of the forwarder corresponding to that hook set. 940 * 941 */ 942 943 const String8 name(procname); 944 addr = sGLExtentionMap.valueFor(name); 945 const int slot = sGLExtentionSlot; 946 947 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS, 948 "no more slots for eglGetProcAddress(\"%s\")", 949 procname); 950 951 #if EGL_TRACE 952 gl_hooks_t *debugHooks = GLTrace_getGLHooks(); 953 #endif 954 955 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) { 956 bool found = false; 957 958 egl_connection_t* const cnx = &gEGLImpl; 959 if (cnx->dso && cnx->egl.eglGetProcAddress) { 960 // Extensions are independent of the bound context 961 addr = 962 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] = 963 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] = 964 #if EGL_TRACE 965 debugHooks->ext.extensions[slot] = 966 gHooksTrace.ext.extensions[slot] = 967 #endif 968 cnx->egl.eglGetProcAddress(procname); 969 if (addr) found = true; 970 } 971 972 if (found) { 973 addr = gExtensionForwarders[slot]; 974 sGLExtentionMap.add(name, addr); 975 sGLExtentionSlot++; 976 } 977 } 978 979 pthread_mutex_unlock(&sExtensionMapMutex); 980 return addr; 981 } 982 983 class FrameCompletionThread : public Thread { 984 public: 985 986 static void queueSync(EGLSyncKHR sync) { 987 static sp<FrameCompletionThread> thread(new FrameCompletionThread); 988 static bool running = false; 989 if (!running) { 990 thread->run("GPUFrameCompletion"); 991 running = true; 992 } 993 { 994 Mutex::Autolock lock(thread->mMutex); 995 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d", 996 thread->mFramesQueued).string()); 997 thread->mQueue.push_back(sync); 998 thread->mCondition.signal(); 999 thread->mFramesQueued++; 1000 ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size()); 1001 } 1002 } 1003 1004 private: 1005 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {} 1006 1007 virtual bool threadLoop() { 1008 EGLSyncKHR sync; 1009 uint32_t frameNum; 1010 { 1011 Mutex::Autolock lock(mMutex); 1012 while (mQueue.isEmpty()) { 1013 mCondition.wait(mMutex); 1014 } 1015 sync = mQueue[0]; 1016 frameNum = mFramesCompleted; 1017 } 1018 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); 1019 { 1020 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d", 1021 frameNum).string()); 1022 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR); 1023 if (result == EGL_FALSE) { 1024 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError()); 1025 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { 1026 ALOGE("FrameCompletion: timeout waiting for fence"); 1027 } 1028 eglDestroySyncKHR(dpy, sync); 1029 } 1030 { 1031 Mutex::Autolock lock(mMutex); 1032 mQueue.removeAt(0); 1033 mFramesCompleted++; 1034 ATRACE_INT("GPU Frames Outstanding", mQueue.size()); 1035 } 1036 return true; 1037 } 1038 1039 uint32_t mFramesQueued; 1040 uint32_t mFramesCompleted; 1041 Vector<EGLSyncKHR> mQueue; 1042 Condition mCondition; 1043 Mutex mMutex; 1044 }; 1045 1046 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) 1047 { 1048 ATRACE_CALL(); 1049 clearError(); 1050 1051 const egl_display_ptr dp = validate_display(dpy); 1052 if (!dp) return EGL_FALSE; 1053 1054 SurfaceRef _s(dp.get(), draw); 1055 if (!_s.get()) 1056 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1057 1058 #if EGL_TRACE 1059 gl_hooks_t const *trace_hooks = getGLTraceThreadSpecific(); 1060 if (getEGLDebugLevel() > 0) { 1061 if (trace_hooks == NULL) { 1062 if (GLTrace_start() < 0) { 1063 ALOGE("Disabling Tracer for OpenGL ES"); 1064 setEGLDebugLevel(0); 1065 } else { 1066 // switch over to the trace version of hooks 1067 EGLContext ctx = egl_tls_t::getContext(); 1068 egl_context_t * const c = get_context(ctx); 1069 if (c) { 1070 setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 1071 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx); 1072 } 1073 } 1074 } 1075 1076 GLTrace_eglSwapBuffers(dpy, draw); 1077 } else if (trace_hooks != NULL) { 1078 // tracing is now disabled, so switch back to the non trace version 1079 EGLContext ctx = egl_tls_t::getContext(); 1080 egl_context_t * const c = get_context(ctx); 1081 if (c) setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 1082 GLTrace_stop(); 1083 } 1084 #endif 1085 1086 egl_surface_t const * const s = get_surface(draw); 1087 1088 if (CC_UNLIKELY(dp->traceGpuCompletion)) { 1089 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL); 1090 if (sync != EGL_NO_SYNC_KHR) { 1091 FrameCompletionThread::queueSync(sync); 1092 } 1093 } 1094 1095 if (CC_UNLIKELY(dp->finishOnSwap)) { 1096 uint32_t pixel; 1097 egl_context_t * const c = get_context( egl_tls_t::getContext() ); 1098 if (c) { 1099 // glReadPixels() ensures that the frame is complete 1100 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1, 1101 GL_RGBA,GL_UNSIGNED_BYTE,&pixel); 1102 } 1103 } 1104 1105 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface); 1106 } 1107 1108 EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, 1109 NativePixmapType target) 1110 { 1111 clearError(); 1112 1113 const egl_display_ptr dp = validate_display(dpy); 1114 if (!dp) return EGL_FALSE; 1115 1116 SurfaceRef _s(dp.get(), surface); 1117 if (!_s.get()) 1118 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1119 1120 egl_surface_t const * const s = get_surface(surface); 1121 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target); 1122 } 1123 1124 const char* eglQueryString(EGLDisplay dpy, EGLint name) 1125 { 1126 clearError(); 1127 1128 const egl_display_ptr dp = validate_display(dpy); 1129 if (!dp) return (const char *) NULL; 1130 1131 switch (name) { 1132 case EGL_VENDOR: 1133 return dp->getVendorString(); 1134 case EGL_VERSION: 1135 return dp->getVersionString(); 1136 case EGL_EXTENSIONS: 1137 return dp->getExtensionString(); 1138 case EGL_CLIENT_APIS: 1139 return dp->getClientApiString(); 1140 } 1141 return setError(EGL_BAD_PARAMETER, (const char *)0); 1142 } 1143 1144 EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name) 1145 { 1146 clearError(); 1147 1148 const egl_display_ptr dp = validate_display(dpy); 1149 if (!dp) return (const char *) NULL; 1150 1151 switch (name) { 1152 case EGL_VENDOR: 1153 return dp->disp.queryString.vendor; 1154 case EGL_VERSION: 1155 return dp->disp.queryString.version; 1156 case EGL_EXTENSIONS: 1157 return dp->disp.queryString.extensions; 1158 case EGL_CLIENT_APIS: 1159 return dp->disp.queryString.clientApi; 1160 } 1161 return setError(EGL_BAD_PARAMETER, (const char *)0); 1162 } 1163 1164 // ---------------------------------------------------------------------------- 1165 // EGL 1.1 1166 // ---------------------------------------------------------------------------- 1167 1168 EGLBoolean eglSurfaceAttrib( 1169 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 1170 { 1171 clearError(); 1172 1173 const egl_display_ptr dp = validate_display(dpy); 1174 if (!dp) return EGL_FALSE; 1175 1176 SurfaceRef _s(dp.get(), surface); 1177 if (!_s.get()) 1178 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1179 1180 egl_surface_t const * const s = get_surface(surface); 1181 if (s->cnx->egl.eglSurfaceAttrib) { 1182 return s->cnx->egl.eglSurfaceAttrib( 1183 dp->disp.dpy, s->surface, attribute, value); 1184 } 1185 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1186 } 1187 1188 EGLBoolean eglBindTexImage( 1189 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1190 { 1191 clearError(); 1192 1193 const egl_display_ptr dp = validate_display(dpy); 1194 if (!dp) return EGL_FALSE; 1195 1196 SurfaceRef _s(dp.get(), surface); 1197 if (!_s.get()) 1198 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1199 1200 egl_surface_t const * const s = get_surface(surface); 1201 if (s->cnx->egl.eglBindTexImage) { 1202 return s->cnx->egl.eglBindTexImage( 1203 dp->disp.dpy, s->surface, buffer); 1204 } 1205 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1206 } 1207 1208 EGLBoolean eglReleaseTexImage( 1209 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1210 { 1211 clearError(); 1212 1213 const egl_display_ptr dp = validate_display(dpy); 1214 if (!dp) return EGL_FALSE; 1215 1216 SurfaceRef _s(dp.get(), surface); 1217 if (!_s.get()) 1218 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1219 1220 egl_surface_t const * const s = get_surface(surface); 1221 if (s->cnx->egl.eglReleaseTexImage) { 1222 return s->cnx->egl.eglReleaseTexImage( 1223 dp->disp.dpy, s->surface, buffer); 1224 } 1225 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1226 } 1227 1228 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 1229 { 1230 clearError(); 1231 1232 const egl_display_ptr dp = validate_display(dpy); 1233 if (!dp) return EGL_FALSE; 1234 1235 EGLBoolean res = EGL_TRUE; 1236 egl_connection_t* const cnx = &gEGLImpl; 1237 if (cnx->dso && cnx->egl.eglSwapInterval) { 1238 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval); 1239 } 1240 1241 return res; 1242 } 1243 1244 1245 // ---------------------------------------------------------------------------- 1246 // EGL 1.2 1247 // ---------------------------------------------------------------------------- 1248 1249 EGLBoolean eglWaitClient(void) 1250 { 1251 clearError(); 1252 1253 egl_connection_t* const cnx = &gEGLImpl; 1254 if (!cnx->dso) 1255 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1256 1257 EGLBoolean res; 1258 if (cnx->egl.eglWaitClient) { 1259 res = cnx->egl.eglWaitClient(); 1260 } else { 1261 res = cnx->egl.eglWaitGL(); 1262 } 1263 return res; 1264 } 1265 1266 EGLBoolean eglBindAPI(EGLenum api) 1267 { 1268 clearError(); 1269 1270 if (egl_init_drivers() == EGL_FALSE) { 1271 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1272 } 1273 1274 // bind this API on all EGLs 1275 EGLBoolean res = EGL_TRUE; 1276 egl_connection_t* const cnx = &gEGLImpl; 1277 if (cnx->dso && cnx->egl.eglBindAPI) { 1278 res = cnx->egl.eglBindAPI(api); 1279 } 1280 return res; 1281 } 1282 1283 EGLenum eglQueryAPI(void) 1284 { 1285 clearError(); 1286 1287 if (egl_init_drivers() == EGL_FALSE) { 1288 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1289 } 1290 1291 egl_connection_t* const cnx = &gEGLImpl; 1292 if (cnx->dso && cnx->egl.eglQueryAPI) { 1293 return cnx->egl.eglQueryAPI(); 1294 } 1295 1296 // or, it can only be OpenGL ES 1297 return EGL_OPENGL_ES_API; 1298 } 1299 1300 EGLBoolean eglReleaseThread(void) 1301 { 1302 clearError(); 1303 1304 #if EGL_TRACE 1305 if (getEGLDebugLevel() > 0) 1306 GLTrace_eglReleaseThread(); 1307 #endif 1308 1309 // If there is context bound to the thread, release it 1310 egl_display_t::loseCurrent(get_context(getContext())); 1311 1312 egl_connection_t* const cnx = &gEGLImpl; 1313 if (cnx->dso && cnx->egl.eglReleaseThread) { 1314 cnx->egl.eglReleaseThread(); 1315 } 1316 egl_tls_t::clearTLS(); 1317 return EGL_TRUE; 1318 } 1319 1320 EGLSurface eglCreatePbufferFromClientBuffer( 1321 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 1322 EGLConfig config, const EGLint *attrib_list) 1323 { 1324 clearError(); 1325 1326 egl_connection_t* cnx = NULL; 1327 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 1328 if (!dp) return EGL_FALSE; 1329 if (cnx->egl.eglCreatePbufferFromClientBuffer) { 1330 return cnx->egl.eglCreatePbufferFromClientBuffer( 1331 dp->disp.dpy, buftype, buffer, config, attrib_list); 1332 } 1333 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); 1334 } 1335 1336 // ---------------------------------------------------------------------------- 1337 // EGL_EGLEXT_VERSION 3 1338 // ---------------------------------------------------------------------------- 1339 1340 EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, 1341 const EGLint *attrib_list) 1342 { 1343 clearError(); 1344 1345 const egl_display_ptr dp = validate_display(dpy); 1346 if (!dp) return EGL_FALSE; 1347 1348 SurfaceRef _s(dp.get(), surface); 1349 if (!_s.get()) 1350 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1351 1352 egl_surface_t const * const s = get_surface(surface); 1353 if (s->cnx->egl.eglLockSurfaceKHR) { 1354 return s->cnx->egl.eglLockSurfaceKHR( 1355 dp->disp.dpy, s->surface, attrib_list); 1356 } 1357 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1358 } 1359 1360 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) 1361 { 1362 clearError(); 1363 1364 const egl_display_ptr dp = validate_display(dpy); 1365 if (!dp) return EGL_FALSE; 1366 1367 SurfaceRef _s(dp.get(), surface); 1368 if (!_s.get()) 1369 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1370 1371 egl_surface_t const * const s = get_surface(surface); 1372 if (s->cnx->egl.eglUnlockSurfaceKHR) { 1373 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface); 1374 } 1375 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1376 } 1377 1378 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1379 EGLClientBuffer buffer, const EGLint *attrib_list) 1380 { 1381 clearError(); 1382 1383 const egl_display_ptr dp = validate_display(dpy); 1384 if (!dp) return EGL_NO_IMAGE_KHR; 1385 1386 ContextRef _c(dp.get(), ctx); 1387 egl_context_t * const c = _c.get(); 1388 1389 EGLImageKHR result = EGL_NO_IMAGE_KHR; 1390 egl_connection_t* const cnx = &gEGLImpl; 1391 if (cnx->dso && cnx->egl.eglCreateImageKHR) { 1392 result = cnx->egl.eglCreateImageKHR( 1393 dp->disp.dpy, 1394 c ? c->context : EGL_NO_CONTEXT, 1395 target, buffer, attrib_list); 1396 } 1397 return result; 1398 } 1399 1400 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 1401 { 1402 clearError(); 1403 1404 const egl_display_ptr dp = validate_display(dpy); 1405 if (!dp) return EGL_FALSE; 1406 1407 EGLBoolean result = EGL_FALSE; 1408 egl_connection_t* const cnx = &gEGLImpl; 1409 if (cnx->dso && cnx->egl.eglDestroyImageKHR) { 1410 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img); 1411 } 1412 return result; 1413 } 1414 1415 // ---------------------------------------------------------------------------- 1416 // EGL_EGLEXT_VERSION 5 1417 // ---------------------------------------------------------------------------- 1418 1419 1420 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) 1421 { 1422 clearError(); 1423 1424 const egl_display_ptr dp = validate_display(dpy); 1425 if (!dp) return EGL_NO_SYNC_KHR; 1426 1427 EGLSyncKHR result = EGL_NO_SYNC_KHR; 1428 egl_connection_t* const cnx = &gEGLImpl; 1429 if (cnx->dso && cnx->egl.eglCreateSyncKHR) { 1430 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list); 1431 } 1432 return result; 1433 } 1434 1435 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) 1436 { 1437 clearError(); 1438 1439 const egl_display_ptr dp = validate_display(dpy); 1440 if (!dp) return EGL_FALSE; 1441 1442 EGLBoolean result = EGL_FALSE; 1443 egl_connection_t* const cnx = &gEGLImpl; 1444 if (cnx->dso && cnx->egl.eglDestroySyncKHR) { 1445 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync); 1446 } 1447 return result; 1448 } 1449 1450 EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) { 1451 clearError(); 1452 1453 const egl_display_ptr dp = validate_display(dpy); 1454 if (!dp) return EGL_FALSE; 1455 1456 EGLBoolean result = EGL_FALSE; 1457 egl_connection_t* const cnx = &gEGLImpl; 1458 if (cnx->dso && cnx->egl.eglSignalSyncKHR) { 1459 result = cnx->egl.eglSignalSyncKHR( 1460 dp->disp.dpy, sync, mode); 1461 } 1462 return result; 1463 } 1464 1465 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, 1466 EGLint flags, EGLTimeKHR timeout) 1467 { 1468 clearError(); 1469 1470 const egl_display_ptr dp = validate_display(dpy); 1471 if (!dp) return EGL_FALSE; 1472 1473 EGLBoolean result = EGL_FALSE; 1474 egl_connection_t* const cnx = &gEGLImpl; 1475 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) { 1476 result = cnx->egl.eglClientWaitSyncKHR( 1477 dp->disp.dpy, sync, flags, timeout); 1478 } 1479 return result; 1480 } 1481 1482 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, 1483 EGLint attribute, EGLint *value) 1484 { 1485 clearError(); 1486 1487 const egl_display_ptr dp = validate_display(dpy); 1488 if (!dp) return EGL_FALSE; 1489 1490 EGLBoolean result = EGL_FALSE; 1491 egl_connection_t* const cnx = &gEGLImpl; 1492 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) { 1493 result = cnx->egl.eglGetSyncAttribKHR( 1494 dp->disp.dpy, sync, attribute, value); 1495 } 1496 return result; 1497 } 1498 1499 // ---------------------------------------------------------------------------- 1500 // EGL_EGLEXT_VERSION 15 1501 // ---------------------------------------------------------------------------- 1502 1503 EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) { 1504 clearError(); 1505 const egl_display_ptr dp = validate_display(dpy); 1506 if (!dp) return EGL_FALSE; 1507 EGLint result = EGL_FALSE; 1508 egl_connection_t* const cnx = &gEGLImpl; 1509 if (cnx->dso && cnx->egl.eglWaitSyncKHR) { 1510 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags); 1511 } 1512 return result; 1513 } 1514 1515 // ---------------------------------------------------------------------------- 1516 // ANDROID extensions 1517 // ---------------------------------------------------------------------------- 1518 1519 EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync) 1520 { 1521 clearError(); 1522 1523 const egl_display_ptr dp = validate_display(dpy); 1524 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID; 1525 1526 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID; 1527 egl_connection_t* const cnx = &gEGLImpl; 1528 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) { 1529 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync); 1530 } 1531 return result; 1532 } 1533 1534 EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface, 1535 EGLnsecsANDROID time) 1536 { 1537 clearError(); 1538 1539 const egl_display_ptr dp = validate_display(dpy); 1540 if (!dp) { 1541 return EGL_FALSE; 1542 } 1543 1544 SurfaceRef _s(dp.get(), surface); 1545 if (!_s.get()) { 1546 setError(EGL_BAD_SURFACE, EGL_FALSE); 1547 return EGL_FALSE; 1548 } 1549 1550 egl_surface_t const * const s = get_surface(surface); 1551 native_window_set_buffers_timestamp(s->win.get(), time); 1552 1553 return EGL_TRUE; 1554 } 1555 1556 // ---------------------------------------------------------------------------- 1557 // NVIDIA extensions 1558 // ---------------------------------------------------------------------------- 1559 EGLuint64NV eglGetSystemTimeFrequencyNV() 1560 { 1561 clearError(); 1562 1563 if (egl_init_drivers() == EGL_FALSE) { 1564 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1565 } 1566 1567 EGLuint64NV ret = 0; 1568 egl_connection_t* const cnx = &gEGLImpl; 1569 1570 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) { 1571 return cnx->egl.eglGetSystemTimeFrequencyNV(); 1572 } 1573 1574 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1575 } 1576 1577 EGLuint64NV eglGetSystemTimeNV() 1578 { 1579 clearError(); 1580 1581 if (egl_init_drivers() == EGL_FALSE) { 1582 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1583 } 1584 1585 EGLuint64NV ret = 0; 1586 egl_connection_t* const cnx = &gEGLImpl; 1587 1588 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) { 1589 return cnx->egl.eglGetSystemTimeNV(); 1590 } 1591 1592 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1593 } 1594