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 <ctype.h> 20 #include <dlfcn.h> 21 #include <stdlib.h> 22 #include <string.h> 23 24 #include <hardware/gralloc1.h> 25 26 #include <EGL/egl.h> 27 #include <EGL/eglext.h> 28 29 #include <android/hardware_buffer.h> 30 #include <private/android/AHardwareBufferHelpers.h> 31 32 #include <cutils/compiler.h> 33 #include <cutils/properties.h> 34 #include <log/log.h> 35 36 #include <condition_variable> 37 #include <deque> 38 #include <mutex> 39 #include <unordered_map> 40 #include <string> 41 #include <thread> 42 43 #include "../egl_impl.h" 44 45 #include "egl_display.h" 46 #include "egl_object.h" 47 #include "egl_tls.h" 48 #include "egl_trace.h" 49 50 using namespace android; 51 52 // ---------------------------------------------------------------------------- 53 54 namespace android { 55 56 using nsecs_t = int64_t; 57 58 struct extention_map_t { 59 const char* name; 60 __eglMustCastToProperFunctionPointerType address; 61 }; 62 63 /* 64 * This is the list of EGL extensions exposed to applications. 65 * 66 * Some of them (gBuiltinExtensionString) are implemented entirely in this EGL 67 * wrapper and are always available. 68 * 69 * The rest (gExtensionString) depend on support in the EGL driver, and are 70 * only available if the driver supports them. However, some of these must be 71 * supported because they are used by the Android system itself; these are 72 * listed as mandatory below and are required by the CDD. The system *assumes* 73 * the mandatory extensions are present and may not function properly if some 74 * are missing. 75 * 76 * NOTE: Both strings MUST have a single space as the last character. 77 */ 78 79 extern char const * const gBuiltinExtensionString; 80 extern char const * const gExtensionString; 81 82 // clang-format off 83 char const * const gBuiltinExtensionString = 84 "EGL_KHR_get_all_proc_addresses " 85 "EGL_ANDROID_presentation_time " 86 "EGL_KHR_swap_buffers_with_damage " 87 "EGL_ANDROID_get_native_client_buffer " 88 "EGL_ANDROID_front_buffer_auto_refresh " 89 "EGL_ANDROID_get_frame_timestamps " 90 ; 91 92 char const * const gExtensionString = 93 "EGL_KHR_image " // mandatory 94 "EGL_KHR_image_base " // mandatory 95 "EGL_KHR_image_pixmap " 96 "EGL_KHR_lock_surface " 97 "EGL_KHR_gl_colorspace " 98 "EGL_KHR_gl_texture_2D_image " 99 "EGL_KHR_gl_texture_3D_image " 100 "EGL_KHR_gl_texture_cubemap_image " 101 "EGL_KHR_gl_renderbuffer_image " 102 "EGL_KHR_reusable_sync " 103 "EGL_KHR_fence_sync " 104 "EGL_KHR_create_context " 105 "EGL_KHR_config_attribs " 106 "EGL_KHR_surfaceless_context " 107 "EGL_KHR_stream " 108 "EGL_KHR_stream_fifo " 109 "EGL_KHR_stream_producer_eglsurface " 110 "EGL_KHR_stream_consumer_gltexture " 111 "EGL_KHR_stream_cross_process_fd " 112 "EGL_EXT_create_context_robustness " 113 "EGL_NV_system_time " 114 "EGL_ANDROID_image_native_buffer " // mandatory 115 "EGL_KHR_wait_sync " // strongly recommended 116 "EGL_ANDROID_recordable " // mandatory 117 "EGL_KHR_partial_update " // strongly recommended 118 "EGL_EXT_pixel_format_float " 119 "EGL_EXT_buffer_age " // strongly recommended with partial_update 120 "EGL_KHR_create_context_no_error " 121 "EGL_KHR_mutable_render_buffer " 122 "EGL_EXT_yuv_surface " 123 "EGL_EXT_protected_content " 124 "EGL_IMG_context_priority " 125 "EGL_KHR_no_config_context " 126 ; 127 // clang-format on 128 129 // extensions not exposed to applications but used by the ANDROID system 130 // "EGL_ANDROID_blob_cache " // strongly recommended 131 // "EGL_IMG_hibernate_process " // optional 132 // "EGL_ANDROID_native_fence_sync " // strongly recommended 133 // "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1 134 // "EGL_ANDROID_image_crop " // optional 135 136 /* 137 * EGL Extensions entry-points exposed to 3rd party applications 138 * (keep in sync with gExtensionString above) 139 * 140 */ 141 static const extention_map_t sExtensionMap[] = { 142 // EGL_KHR_lock_surface 143 { "eglLockSurfaceKHR", 144 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR }, 145 { "eglUnlockSurfaceKHR", 146 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR }, 147 148 // EGL_KHR_image, EGL_KHR_image_base 149 { "eglCreateImageKHR", 150 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, 151 { "eglDestroyImageKHR", 152 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, 153 154 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync 155 { "eglCreateSyncKHR", 156 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR }, 157 { "eglDestroySyncKHR", 158 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR }, 159 { "eglClientWaitSyncKHR", 160 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR }, 161 { "eglSignalSyncKHR", 162 (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR }, 163 { "eglGetSyncAttribKHR", 164 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR }, 165 166 // EGL_NV_system_time 167 { "eglGetSystemTimeFrequencyNV", 168 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV }, 169 { "eglGetSystemTimeNV", 170 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV }, 171 172 // EGL_KHR_wait_sync 173 { "eglWaitSyncKHR", 174 (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR }, 175 176 // EGL_ANDROID_presentation_time 177 { "eglPresentationTimeANDROID", 178 (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID }, 179 180 // EGL_KHR_swap_buffers_with_damage 181 { "eglSwapBuffersWithDamageKHR", 182 (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR }, 183 184 // EGL_ANDROID_get_native_client_buffer 185 { "eglGetNativeClientBufferANDROID", 186 (__eglMustCastToProperFunctionPointerType)&eglGetNativeClientBufferANDROID }, 187 188 // EGL_KHR_partial_update 189 { "eglSetDamageRegionKHR", 190 (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR }, 191 192 { "eglCreateStreamKHR", 193 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamKHR }, 194 { "eglDestroyStreamKHR", 195 (__eglMustCastToProperFunctionPointerType)&eglDestroyStreamKHR }, 196 { "eglStreamAttribKHR", 197 (__eglMustCastToProperFunctionPointerType)&eglStreamAttribKHR }, 198 { "eglQueryStreamKHR", 199 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamKHR }, 200 { "eglQueryStreamu64KHR", 201 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamu64KHR }, 202 { "eglQueryStreamTimeKHR", 203 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamTimeKHR }, 204 { "eglCreateStreamProducerSurfaceKHR", 205 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamProducerSurfaceKHR }, 206 { "eglStreamConsumerGLTextureExternalKHR", 207 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerGLTextureExternalKHR }, 208 { "eglStreamConsumerAcquireKHR", 209 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerAcquireKHR }, 210 { "eglStreamConsumerReleaseKHR", 211 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerReleaseKHR }, 212 { "eglGetStreamFileDescriptorKHR", 213 (__eglMustCastToProperFunctionPointerType)&eglGetStreamFileDescriptorKHR }, 214 { "eglCreateStreamFromFileDescriptorKHR", 215 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR }, 216 217 // EGL_ANDROID_get_frame_timestamps 218 { "eglGetNextFrameIdANDROID", 219 (__eglMustCastToProperFunctionPointerType)&eglGetNextFrameIdANDROID }, 220 { "eglGetCompositorTimingANDROID", 221 (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingANDROID }, 222 { "eglGetCompositorTimingSupportedANDROID", 223 (__eglMustCastToProperFunctionPointerType)&eglGetCompositorTimingSupportedANDROID }, 224 { "eglGetFrameTimestampsANDROID", 225 (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampsANDROID }, 226 { "eglGetFrameTimestampSupportedANDROID", 227 (__eglMustCastToProperFunctionPointerType)&eglGetFrameTimestampSupportedANDROID }, 228 229 // EGL_ANDROID_native_fence_sync 230 { "eglDupNativeFenceFDANDROID", 231 (__eglMustCastToProperFunctionPointerType)&eglDupNativeFenceFDANDROID }, 232 }; 233 234 /* 235 * These extensions entry-points should not be exposed to applications. 236 * They're used internally by the Android EGL layer. 237 */ 238 #define FILTER_EXTENSIONS(procname) \ 239 (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \ 240 !strcmp((procname), "eglHibernateProcessIMG") || \ 241 !strcmp((procname), "eglAwakenProcessIMG")) 242 243 244 245 // accesses protected by sExtensionMapMutex 246 static std::unordered_map<std::string, __eglMustCastToProperFunctionPointerType> sGLExtentionMap; 247 248 static int sGLExtentionSlot = 0; 249 static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER; 250 251 static void(*findProcAddress(const char* name, 252 const extention_map_t* map, size_t n))() { 253 for (uint32_t i=0 ; i<n ; i++) { 254 if (!strcmp(name, map[i].name)) { 255 return map[i].address; 256 } 257 } 258 return NULL; 259 } 260 261 // ---------------------------------------------------------------------------- 262 263 extern void setGLHooksThreadSpecific(gl_hooks_t const *value); 264 extern EGLBoolean egl_init_drivers(); 265 extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS]; 266 extern gl_hooks_t gHooksTrace; 267 268 } // namespace android; 269 270 271 // ---------------------------------------------------------------------------- 272 273 static inline void clearError() { egl_tls_t::clearError(); } 274 static inline EGLContext getContext() { return egl_tls_t::getContext(); } 275 276 // ---------------------------------------------------------------------------- 277 278 EGLDisplay eglGetDisplay(EGLNativeDisplayType display) 279 { 280 ATRACE_CALL(); 281 clearError(); 282 283 uintptr_t index = reinterpret_cast<uintptr_t>(display); 284 if (index >= NUM_DISPLAYS) { 285 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 286 } 287 288 if (egl_init_drivers() == EGL_FALSE) { 289 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 290 } 291 292 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display); 293 return dpy; 294 } 295 296 // ---------------------------------------------------------------------------- 297 // Initialization 298 // ---------------------------------------------------------------------------- 299 300 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) 301 { 302 clearError(); 303 304 egl_display_ptr dp = get_display(dpy); 305 if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); 306 307 EGLBoolean res = dp->initialize(major, minor); 308 309 return res; 310 } 311 312 EGLBoolean eglTerminate(EGLDisplay dpy) 313 { 314 // NOTE: don't unload the drivers b/c some APIs can be called 315 // after eglTerminate() has been called. eglTerminate() only 316 // terminates an EGLDisplay, not a EGL itself. 317 318 clearError(); 319 320 egl_display_ptr dp = get_display(dpy); 321 if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); 322 323 EGLBoolean res = dp->terminate(); 324 325 return res; 326 } 327 328 // ---------------------------------------------------------------------------- 329 // configuration 330 // ---------------------------------------------------------------------------- 331 332 EGLBoolean eglGetConfigs( EGLDisplay dpy, 333 EGLConfig *configs, 334 EGLint config_size, EGLint *num_config) 335 { 336 clearError(); 337 338 const egl_display_ptr dp = validate_display(dpy); 339 if (!dp) return EGL_FALSE; 340 341 if (num_config==0) { 342 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE); 343 } 344 345 EGLBoolean res = EGL_FALSE; 346 *num_config = 0; 347 348 egl_connection_t* const cnx = &gEGLImpl; 349 if (cnx->dso) { 350 res = cnx->egl.eglGetConfigs( 351 dp->disp.dpy, configs, config_size, num_config); 352 } 353 354 return res; 355 } 356 357 EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, 358 EGLConfig *configs, EGLint config_size, 359 EGLint *num_config) 360 { 361 clearError(); 362 363 const egl_display_ptr dp = validate_display(dpy); 364 if (!dp) return EGL_FALSE; 365 366 if (num_config==0) { 367 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE); 368 } 369 370 EGLBoolean res = EGL_FALSE; 371 *num_config = 0; 372 373 egl_connection_t* const cnx = &gEGLImpl; 374 if (cnx->dso) { 375 if (attrib_list) { 376 char value[PROPERTY_VALUE_MAX]; 377 property_get("debug.egl.force_msaa", value, "false"); 378 379 if (!strcmp(value, "true")) { 380 size_t attribCount = 0; 381 EGLint attrib = attrib_list[0]; 382 383 // Only enable MSAA if the context is OpenGL ES 2.0 and 384 // if no caveat is requested 385 const EGLint *attribRendererable = NULL; 386 const EGLint *attribCaveat = NULL; 387 388 // Count the number of attributes and look for 389 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT 390 while (attrib != EGL_NONE) { 391 attrib = attrib_list[attribCount]; 392 switch (attrib) { 393 case EGL_RENDERABLE_TYPE: 394 attribRendererable = &attrib_list[attribCount]; 395 break; 396 case EGL_CONFIG_CAVEAT: 397 attribCaveat = &attrib_list[attribCount]; 398 break; 399 default: 400 break; 401 } 402 attribCount++; 403 } 404 405 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT && 406 (!attribCaveat || attribCaveat[1] != EGL_NONE)) { 407 408 // Insert 2 extra attributes to force-enable MSAA 4x 409 EGLint aaAttribs[attribCount + 4]; 410 aaAttribs[0] = EGL_SAMPLE_BUFFERS; 411 aaAttribs[1] = 1; 412 aaAttribs[2] = EGL_SAMPLES; 413 aaAttribs[3] = 4; 414 415 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint)); 416 417 EGLint numConfigAA; 418 EGLBoolean resAA = cnx->egl.eglChooseConfig( 419 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA); 420 421 if (resAA == EGL_TRUE && numConfigAA > 0) { 422 ALOGD("Enabling MSAA 4x"); 423 *num_config = numConfigAA; 424 return resAA; 425 } 426 } 427 } 428 } 429 430 res = cnx->egl.eglChooseConfig( 431 dp->disp.dpy, attrib_list, configs, config_size, num_config); 432 } 433 return res; 434 } 435 436 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, 437 EGLint attribute, EGLint *value) 438 { 439 clearError(); 440 441 egl_connection_t* cnx = NULL; 442 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 443 if (!dp) return EGL_FALSE; 444 445 return cnx->egl.eglGetConfigAttrib( 446 dp->disp.dpy, config, attribute, value); 447 } 448 449 // ---------------------------------------------------------------------------- 450 // surfaces 451 // ---------------------------------------------------------------------------- 452 453 // Turn linear formats into corresponding sRGB formats when colorspace is 454 // EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear 455 // formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where 456 // the modification isn't possible, the original dataSpace is returned. 457 static android_dataspace modifyBufferDataspace(android_dataspace dataSpace, 458 EGLint colorspace) { 459 if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) { 460 return HAL_DATASPACE_SRGB_LINEAR; 461 } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) { 462 return HAL_DATASPACE_SRGB; 463 } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_EXT) { 464 return HAL_DATASPACE_DISPLAY_P3; 465 } else if (colorspace == EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT) { 466 return HAL_DATASPACE_DISPLAY_P3_LINEAR; 467 } else if (colorspace == EGL_GL_COLORSPACE_SCRGB_EXT) { 468 return HAL_DATASPACE_V0_SCRGB; 469 } else if (colorspace == EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT) { 470 return HAL_DATASPACE_V0_SCRGB_LINEAR; 471 } 472 return dataSpace; 473 } 474 475 // Return true if we stripped any EGL_GL_COLORSPACE_KHR attributes. 476 static EGLBoolean stripColorSpaceAttribute(egl_display_ptr dp, const EGLint* attrib_list, 477 EGLint format, 478 std::vector<EGLint>& stripped_attrib_list) { 479 std::vector<EGLint> allowedColorSpaces; 480 switch (format) { 481 case HAL_PIXEL_FORMAT_RGBA_8888: 482 case HAL_PIXEL_FORMAT_RGB_565: 483 // driver okay with linear & sRGB for 8888, but can't handle 484 // Display-P3 or other spaces. 485 allowedColorSpaces.push_back(EGL_GL_COLORSPACE_SRGB_KHR); 486 allowedColorSpaces.push_back(EGL_GL_COLORSPACE_LINEAR_KHR); 487 break; 488 489 case HAL_PIXEL_FORMAT_RGBA_FP16: 490 case HAL_PIXEL_FORMAT_RGBA_1010102: 491 default: 492 // driver does not want to see colorspace attributes for 1010102 or fp16. 493 // Future: if driver supports XXXX extension, we can pass down that colorspace 494 break; 495 } 496 497 bool stripped = false; 498 if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) { 499 for (const EGLint* attr = attrib_list; attr[0] != EGL_NONE; attr += 2) { 500 if (attr[0] == EGL_GL_COLORSPACE_KHR) { 501 EGLint colorSpace = attr[1]; 502 bool found = false; 503 // Verify that color space is allowed 504 for (auto it : allowedColorSpaces) { 505 if (colorSpace == it) { 506 found = true; 507 } 508 } 509 if (!found) { 510 stripped = true; 511 } else { 512 stripped_attrib_list.push_back(attr[0]); 513 stripped_attrib_list.push_back(attr[1]); 514 } 515 } else { 516 stripped_attrib_list.push_back(attr[0]); 517 stripped_attrib_list.push_back(attr[1]); 518 } 519 } 520 } 521 if (stripped) { 522 stripped_attrib_list.push_back(EGL_NONE); 523 stripped_attrib_list.push_back(EGL_NONE); 524 } 525 return stripped; 526 } 527 528 static EGLBoolean getColorSpaceAttribute(egl_display_ptr dp, NativeWindowType window, 529 const EGLint* attrib_list, EGLint& colorSpace, 530 android_dataspace& dataSpace) { 531 colorSpace = EGL_GL_COLORSPACE_LINEAR_KHR; 532 dataSpace = HAL_DATASPACE_UNKNOWN; 533 534 if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) { 535 for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) { 536 if (*attr == EGL_GL_COLORSPACE_KHR) { 537 colorSpace = attr[1]; 538 bool found = false; 539 bool verify = true; 540 // Verify that color space is allowed 541 if (colorSpace == EGL_GL_COLORSPACE_SRGB_KHR || 542 colorSpace == EGL_GL_COLORSPACE_LINEAR_KHR) { 543 // SRGB and LINEAR are always supported when EGL_KHR_gl_colorspace 544 // is available, so no need to verify. 545 found = true; 546 verify = false; 547 } else if (colorSpace == EGL_EXT_gl_colorspace_bt2020_linear && 548 dp->haveExtension("EGL_EXT_gl_colorspace_bt2020_linear")) { 549 found = true; 550 } else if (colorSpace == EGL_EXT_gl_colorspace_bt2020_pq && 551 dp->haveExtension("EGL_EXT_gl_colorspace_bt2020_pq")) { 552 found = true; 553 } else if (colorSpace == EGL_GL_COLORSPACE_SCRGB_EXT && 554 dp->haveExtension("EGL_EXT_gl_colorspace_scrgb")) { 555 found = true; 556 } else if (colorSpace == EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT && 557 dp->haveExtension("EGL_EXT_gl_colorspace_scrgb_linear")) { 558 found = true; 559 } else if (colorSpace == EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT && 560 dp->haveExtension("EGL_EXT_gl_colorspace_display_p3_linear")) { 561 found = true; 562 } else if (colorSpace == EGL_GL_COLORSPACE_DISPLAY_P3_EXT && 563 dp->haveExtension("EGL_EXT_gl_colorspace_display_p3")) { 564 found = true; 565 } 566 if (!found) { 567 return false; 568 } 569 if (verify && window) { 570 bool wide_color_support = true; 571 // Ordinarily we'd put a call to native_window_get_wide_color_support 572 // at the beginning of the function so that we'll have the 573 // result when needed elsewhere in the function. 574 // However, because eglCreateWindowSurface is called by SurfaceFlinger and 575 // SurfaceFlinger is required to answer the call below we would 576 // end up in a deadlock situation. By moving the call to only happen 577 // if the application has specifically asked for wide-color we avoid 578 // the deadlock with SurfaceFlinger since it will not ask for a 579 // wide-color surface. 580 int err = native_window_get_wide_color_support(window, &wide_color_support); 581 582 if (err) { 583 ALOGE("getColorSpaceAttribute: invalid window (win=%p) " 584 "failed (%#x) (already connected to another API?)", 585 window, err); 586 return false; 587 } 588 if (!wide_color_support) { 589 // Application has asked for a wide-color colorspace but 590 // wide-color support isn't available on the display the window is on. 591 return false; 592 } 593 } 594 // Only change the dataSpace from default if the application 595 // has explicitly set the color space with a EGL_GL_COLORSPACE_KHR attribute. 596 dataSpace = modifyBufferDataspace(dataSpace, colorSpace); 597 } 598 } 599 } 600 return true; 601 } 602 603 static EGLBoolean getColorSpaceAttribute(egl_display_ptr dp, const EGLint* attrib_list, 604 EGLint& colorSpace, android_dataspace& dataSpace) { 605 return getColorSpaceAttribute(dp, NULL, attrib_list, colorSpace, dataSpace); 606 } 607 608 void getNativePixelFormat(EGLDisplay dpy, egl_connection_t* cnx, EGLConfig config, EGLint& format) { 609 // Set the native window's buffers format to match what this config requests. 610 // Whether to use sRGB gamma is not part of the EGLconfig, but is part 611 // of our native format. So if sRGB gamma is requested, we have to 612 // modify the EGLconfig's format before setting the native window's 613 // format. 614 615 EGLint componentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT; 616 cnx->egl.eglGetConfigAttrib(dpy, config, EGL_COLOR_COMPONENT_TYPE_EXT, &componentType); 617 618 EGLint a = 0; 619 EGLint r, g, b; 620 r = g = b = 0; 621 cnx->egl.eglGetConfigAttrib(dpy, config, EGL_RED_SIZE, &r); 622 cnx->egl.eglGetConfigAttrib(dpy, config, EGL_GREEN_SIZE, &g); 623 cnx->egl.eglGetConfigAttrib(dpy, config, EGL_BLUE_SIZE, &b); 624 cnx->egl.eglGetConfigAttrib(dpy, config, EGL_ALPHA_SIZE, &a); 625 EGLint colorDepth = r + g + b; 626 627 // Today, the driver only understands sRGB and linear on 888X 628 // formats. Strip other colorspaces from the attribute list and 629 // only use them to set the dataspace via 630 // native_window_set_buffers_dataspace 631 // if pixel format is RGBX 8888 632 // TBD: Can test for future extensions that indicate that driver 633 // handles requested color space and we can let it through. 634 // allow SRGB and LINEAR. All others need to be stripped. 635 // else if 565, 4444 636 // TBD: Can we assume these are supported if 8888 is? 637 // else if FP16 or 1010102 638 // strip colorspace from attribs. 639 // endif 640 if (a == 0) { 641 if (colorDepth <= 16) { 642 format = HAL_PIXEL_FORMAT_RGB_565; 643 } else { 644 if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) { 645 if (colorDepth > 24) { 646 format = HAL_PIXEL_FORMAT_RGBA_1010102; 647 } else { 648 format = HAL_PIXEL_FORMAT_RGBX_8888; 649 } 650 } else { 651 format = HAL_PIXEL_FORMAT_RGBA_FP16; 652 } 653 } 654 } else { 655 if (componentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT) { 656 if (colorDepth > 24) { 657 format = HAL_PIXEL_FORMAT_RGBA_1010102; 658 } else { 659 format = HAL_PIXEL_FORMAT_RGBA_8888; 660 } 661 } else { 662 format = HAL_PIXEL_FORMAT_RGBA_FP16; 663 } 664 } 665 } 666 667 EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, 668 NativeWindowType window, 669 const EGLint *attrib_list) 670 { 671 clearError(); 672 673 egl_connection_t* cnx = NULL; 674 egl_display_ptr dp = validate_display_connection(dpy, cnx); 675 if (dp) { 676 EGLDisplay iDpy = dp->disp.dpy; 677 678 if (!window) { 679 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 680 } 681 682 int value = 0; 683 window->query(window, NATIVE_WINDOW_IS_VALID, &value); 684 if (!value) { 685 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 686 } 687 688 int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL); 689 if (result < 0) { 690 ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) " 691 "failed (%#x) (already connected to another API?)", 692 window, result); 693 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); 694 } 695 696 EGLint format; 697 getNativePixelFormat(iDpy, cnx, config, format); 698 699 // now select correct colorspace and dataspace based on user's attribute list 700 EGLint colorSpace; 701 android_dataspace dataSpace; 702 if (!getColorSpaceAttribute(dp, window, attrib_list, colorSpace, dataSpace)) { 703 ALOGE("error invalid colorspace: %d", colorSpace); 704 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); 705 } 706 707 std::vector<EGLint> strippedAttribList; 708 if (stripColorSpaceAttribute(dp, attrib_list, format, strippedAttribList)) { 709 // Had to modify the attribute list due to use of color space. 710 // Use modified list from here on. 711 attrib_list = strippedAttribList.data(); 712 } 713 714 if (format != 0) { 715 int err = native_window_set_buffers_format(window, format); 716 if (err != 0) { 717 ALOGE("error setting native window pixel format: %s (%d)", 718 strerror(-err), err); 719 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 720 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 721 } 722 } 723 724 if (dataSpace != 0) { 725 int err = native_window_set_buffers_data_space(window, dataSpace); 726 if (err != 0) { 727 ALOGE("error setting native window pixel dataSpace: %s (%d)", 728 strerror(-err), err); 729 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 730 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 731 } 732 } 733 734 // the EGL spec requires that a new EGLSurface default to swap interval 735 // 1, so explicitly set that on the window here. 736 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window); 737 anw->setSwapInterval(anw, 1); 738 739 EGLSurface surface = cnx->egl.eglCreateWindowSurface( 740 iDpy, config, window, attrib_list); 741 if (surface != EGL_NO_SURFACE) { 742 egl_surface_t* s = 743 new egl_surface_t(dp.get(), config, window, surface, colorSpace, cnx); 744 return s; 745 } 746 747 // EGLSurface creation failed 748 native_window_set_buffers_format(window, 0); 749 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 750 } 751 return EGL_NO_SURFACE; 752 } 753 754 EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, 755 NativePixmapType pixmap, 756 const EGLint *attrib_list) 757 { 758 clearError(); 759 760 egl_connection_t* cnx = NULL; 761 egl_display_ptr dp = validate_display_connection(dpy, cnx); 762 EGLint colorSpace; 763 android_dataspace dataSpace; 764 if (dp) { 765 // now select a corresponding sRGB format if needed 766 if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) { 767 ALOGE("error invalid colorspace: %d", colorSpace); 768 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); 769 } 770 771 EGLSurface surface = cnx->egl.eglCreatePixmapSurface( 772 dp->disp.dpy, config, pixmap, attrib_list); 773 if (surface != EGL_NO_SURFACE) { 774 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface, colorSpace, cnx); 775 return s; 776 } 777 } 778 return EGL_NO_SURFACE; 779 } 780 781 EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, 782 const EGLint *attrib_list) 783 { 784 clearError(); 785 786 egl_connection_t* cnx = NULL; 787 egl_display_ptr dp = validate_display_connection(dpy, cnx); 788 if (dp) { 789 EGLDisplay iDpy = dp->disp.dpy; 790 EGLint format; 791 getNativePixelFormat(iDpy, cnx, config, format); 792 793 // now select correct colorspace and dataspace based on user's attribute list 794 EGLint colorSpace; 795 android_dataspace dataSpace; 796 if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) { 797 ALOGE("error invalid colorspace: %d", colorSpace); 798 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); 799 } 800 801 // Pbuffers are not displayed so we don't need to store the 802 // colorspace. We do need to filter out color spaces the 803 // driver doesn't know how to process. 804 std::vector<EGLint> strippedAttribList; 805 if (stripColorSpaceAttribute(dp, attrib_list, format, strippedAttribList)) { 806 // Had to modify the attribute list due to use of color space. 807 // Use modified list from here on. 808 attrib_list = strippedAttribList.data(); 809 } 810 811 EGLSurface surface = cnx->egl.eglCreatePbufferSurface( 812 dp->disp.dpy, config, attrib_list); 813 if (surface != EGL_NO_SURFACE) { 814 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface, colorSpace, cnx); 815 return s; 816 } 817 } 818 return EGL_NO_SURFACE; 819 } 820 821 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) 822 { 823 clearError(); 824 825 const egl_display_ptr dp = validate_display(dpy); 826 if (!dp) return EGL_FALSE; 827 828 SurfaceRef _s(dp.get(), surface); 829 if (!_s.get()) 830 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 831 832 egl_surface_t * const s = get_surface(surface); 833 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface); 834 if (result == EGL_TRUE) { 835 _s.terminate(); 836 } 837 return result; 838 } 839 840 EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface, 841 EGLint attribute, EGLint *value) 842 { 843 clearError(); 844 845 const egl_display_ptr dp = validate_display(dpy); 846 if (!dp) return EGL_FALSE; 847 848 SurfaceRef _s(dp.get(), surface); 849 if (!_s.get()) 850 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 851 852 egl_surface_t const * const s = get_surface(surface); 853 if (attribute == EGL_GL_COLORSPACE_KHR) { 854 *value = s->getColorSpace(); 855 return EGL_TRUE; 856 } 857 return s->cnx->egl.eglQuerySurface( 858 dp->disp.dpy, s->surface, attribute, value); 859 } 860 861 void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) { 862 ATRACE_CALL(); 863 clearError(); 864 865 const egl_display_ptr dp = validate_display(dpy); 866 if (!dp) { 867 return; 868 } 869 870 SurfaceRef _s(dp.get(), surface); 871 if (!_s.get()) { 872 setError(EGL_BAD_SURFACE, EGL_FALSE); 873 } 874 } 875 876 // ---------------------------------------------------------------------------- 877 // Contexts 878 // ---------------------------------------------------------------------------- 879 880 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, 881 EGLContext share_list, const EGLint *attrib_list) 882 { 883 clearError(); 884 885 egl_connection_t* cnx = NULL; 886 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 887 if (dp) { 888 if (share_list != EGL_NO_CONTEXT) { 889 if (!ContextRef(dp.get(), share_list).get()) { 890 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT); 891 } 892 egl_context_t* const c = get_context(share_list); 893 share_list = c->context; 894 } 895 EGLContext context = cnx->egl.eglCreateContext( 896 dp->disp.dpy, config, share_list, attrib_list); 897 if (context != EGL_NO_CONTEXT) { 898 // figure out if it's a GLESv1 or GLESv2 899 int version = 0; 900 if (attrib_list) { 901 while (*attrib_list != EGL_NONE) { 902 GLint attr = *attrib_list++; 903 GLint value = *attrib_list++; 904 if (attr == EGL_CONTEXT_CLIENT_VERSION) { 905 if (value == 1) { 906 version = egl_connection_t::GLESv1_INDEX; 907 } else if (value == 2 || value == 3) { 908 version = egl_connection_t::GLESv2_INDEX; 909 } 910 } 911 }; 912 } 913 egl_context_t* c = new egl_context_t(dpy, context, config, cnx, 914 version); 915 return c; 916 } 917 } 918 return EGL_NO_CONTEXT; 919 } 920 921 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) 922 { 923 clearError(); 924 925 const egl_display_ptr dp = validate_display(dpy); 926 if (!dp) 927 return EGL_FALSE; 928 929 ContextRef _c(dp.get(), ctx); 930 if (!_c.get()) 931 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE); 932 933 egl_context_t * const c = get_context(ctx); 934 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context); 935 if (result == EGL_TRUE) { 936 _c.terminate(); 937 } 938 return result; 939 } 940 941 EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, 942 EGLSurface read, EGLContext ctx) 943 { 944 clearError(); 945 946 egl_display_ptr dp = validate_display(dpy); 947 if (!dp) return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); 948 949 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not 950 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is 951 // a valid but uninitialized display. 952 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) || 953 (draw != EGL_NO_SURFACE) ) { 954 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE); 955 } 956 957 // get a reference to the object passed in 958 ContextRef _c(dp.get(), ctx); 959 SurfaceRef _d(dp.get(), draw); 960 SurfaceRef _r(dp.get(), read); 961 962 // validate the context (if not EGL_NO_CONTEXT) 963 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) { 964 // EGL_NO_CONTEXT is valid 965 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE); 966 } 967 968 // these are the underlying implementation's object 969 EGLContext impl_ctx = EGL_NO_CONTEXT; 970 EGLSurface impl_draw = EGL_NO_SURFACE; 971 EGLSurface impl_read = EGL_NO_SURFACE; 972 973 // these are our objects structs passed in 974 egl_context_t * c = NULL; 975 egl_surface_t const * d = NULL; 976 egl_surface_t const * r = NULL; 977 978 // these are the current objects structs 979 egl_context_t * cur_c = get_context(getContext()); 980 981 if (ctx != EGL_NO_CONTEXT) { 982 c = get_context(ctx); 983 impl_ctx = c->context; 984 } else { 985 // no context given, use the implementation of the current context 986 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) { 987 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT); 988 return setError(EGL_BAD_MATCH, (EGLBoolean)EGL_FALSE); 989 } 990 if (cur_c == NULL) { 991 // no current context 992 // not an error, there is just no current context. 993 return EGL_TRUE; 994 } 995 } 996 997 // retrieve the underlying implementation's draw EGLSurface 998 if (draw != EGL_NO_SURFACE) { 999 if (!_d.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 1000 d = get_surface(draw); 1001 impl_draw = d->surface; 1002 } 1003 1004 // retrieve the underlying implementation's read EGLSurface 1005 if (read != EGL_NO_SURFACE) { 1006 if (!_r.get()) return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 1007 r = get_surface(read); 1008 impl_read = r->surface; 1009 } 1010 1011 1012 EGLBoolean result = dp->makeCurrent(c, cur_c, 1013 draw, read, ctx, 1014 impl_draw, impl_read, impl_ctx); 1015 1016 if (result == EGL_TRUE) { 1017 if (c) { 1018 setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 1019 egl_tls_t::setContext(ctx); 1020 _c.acquire(); 1021 _r.acquire(); 1022 _d.acquire(); 1023 } else { 1024 setGLHooksThreadSpecific(&gHooksNoContext); 1025 egl_tls_t::setContext(EGL_NO_CONTEXT); 1026 } 1027 } else { 1028 1029 if (cur_c != NULL) { 1030 // Force return to current context for drivers that cannot handle errors 1031 EGLBoolean restore_result = EGL_FALSE; 1032 // get a reference to the old current objects 1033 ContextRef _c2(dp.get(), cur_c); 1034 SurfaceRef _d2(dp.get(), cur_c->draw); 1035 SurfaceRef _r2(dp.get(), cur_c->read); 1036 1037 c = cur_c; 1038 impl_ctx = c->context; 1039 impl_draw = EGL_NO_SURFACE; 1040 if (cur_c->draw != EGL_NO_SURFACE) { 1041 d = get_surface(cur_c->draw); 1042 impl_draw = d->surface; 1043 } 1044 impl_read = EGL_NO_SURFACE; 1045 if (cur_c->read != EGL_NO_SURFACE) { 1046 r = get_surface(cur_c->read); 1047 impl_read = r->surface; 1048 } 1049 restore_result = dp->makeCurrent(c, cur_c, 1050 cur_c->draw, cur_c->read, cur_c->context, 1051 impl_draw, impl_read, impl_ctx); 1052 if (restore_result == EGL_TRUE) { 1053 _c2.acquire(); 1054 _r2.acquire(); 1055 _d2.acquire(); 1056 } else { 1057 ALOGE("Could not restore original EGL context"); 1058 } 1059 } 1060 // this will ALOGE the error 1061 egl_connection_t* const cnx = &gEGLImpl; 1062 result = setError(cnx->egl.eglGetError(), (EGLBoolean)EGL_FALSE); 1063 } 1064 return result; 1065 } 1066 1067 1068 EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, 1069 EGLint attribute, EGLint *value) 1070 { 1071 clearError(); 1072 1073 const egl_display_ptr dp = validate_display(dpy); 1074 if (!dp) return EGL_FALSE; 1075 1076 ContextRef _c(dp.get(), ctx); 1077 if (!_c.get()) return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE); 1078 1079 egl_context_t * const c = get_context(ctx); 1080 return c->cnx->egl.eglQueryContext( 1081 dp->disp.dpy, c->context, attribute, value); 1082 1083 } 1084 1085 EGLContext eglGetCurrentContext(void) 1086 { 1087 // could be called before eglInitialize(), but we wouldn't have a context 1088 // then, and this function would correctly return EGL_NO_CONTEXT. 1089 1090 clearError(); 1091 1092 EGLContext ctx = getContext(); 1093 return ctx; 1094 } 1095 1096 EGLSurface eglGetCurrentSurface(EGLint readdraw) 1097 { 1098 // could be called before eglInitialize(), but we wouldn't have a context 1099 // then, and this function would correctly return EGL_NO_SURFACE. 1100 1101 clearError(); 1102 1103 EGLContext ctx = getContext(); 1104 if (ctx) { 1105 egl_context_t const * const c = get_context(ctx); 1106 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 1107 switch (readdraw) { 1108 case EGL_READ: return c->read; 1109 case EGL_DRAW: return c->draw; 1110 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 1111 } 1112 } 1113 return EGL_NO_SURFACE; 1114 } 1115 1116 EGLDisplay eglGetCurrentDisplay(void) 1117 { 1118 // could be called before eglInitialize(), but we wouldn't have a context 1119 // then, and this function would correctly return EGL_NO_DISPLAY. 1120 1121 clearError(); 1122 1123 EGLContext ctx = getContext(); 1124 if (ctx) { 1125 egl_context_t const * const c = get_context(ctx); 1126 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 1127 return c->dpy; 1128 } 1129 return EGL_NO_DISPLAY; 1130 } 1131 1132 EGLBoolean eglWaitGL(void) 1133 { 1134 clearError(); 1135 1136 egl_connection_t* const cnx = &gEGLImpl; 1137 if (!cnx->dso) 1138 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE); 1139 1140 return cnx->egl.eglWaitGL(); 1141 } 1142 1143 EGLBoolean eglWaitNative(EGLint engine) 1144 { 1145 clearError(); 1146 1147 egl_connection_t* const cnx = &gEGLImpl; 1148 if (!cnx->dso) 1149 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE); 1150 1151 return cnx->egl.eglWaitNative(engine); 1152 } 1153 1154 EGLint eglGetError(void) 1155 { 1156 EGLint err = EGL_SUCCESS; 1157 egl_connection_t* const cnx = &gEGLImpl; 1158 if (cnx->dso) { 1159 err = cnx->egl.eglGetError(); 1160 } 1161 if (err == EGL_SUCCESS) { 1162 err = egl_tls_t::getError(); 1163 } 1164 return err; 1165 } 1166 1167 static __eglMustCastToProperFunctionPointerType findBuiltinWrapper( 1168 const char* procname) { 1169 const egl_connection_t* cnx = &gEGLImpl; 1170 void* proc = NULL; 1171 1172 proc = dlsym(cnx->libEgl, procname); 1173 if (proc) return (__eglMustCastToProperFunctionPointerType)proc; 1174 1175 proc = dlsym(cnx->libGles2, procname); 1176 if (proc) return (__eglMustCastToProperFunctionPointerType)proc; 1177 1178 proc = dlsym(cnx->libGles1, procname); 1179 if (proc) return (__eglMustCastToProperFunctionPointerType)proc; 1180 1181 return NULL; 1182 } 1183 1184 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) 1185 { 1186 // eglGetProcAddress() could be the very first function called 1187 // in which case we must make sure we've initialized ourselves, this 1188 // happens the first time egl_get_display() is called. 1189 1190 clearError(); 1191 1192 if (egl_init_drivers() == EGL_FALSE) { 1193 setError(EGL_BAD_PARAMETER, NULL); 1194 return NULL; 1195 } 1196 1197 if (FILTER_EXTENSIONS(procname)) { 1198 return NULL; 1199 } 1200 1201 __eglMustCastToProperFunctionPointerType addr; 1202 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap)); 1203 if (addr) return addr; 1204 1205 addr = findBuiltinWrapper(procname); 1206 if (addr) return addr; 1207 1208 // this protects accesses to sGLExtentionMap and sGLExtentionSlot 1209 pthread_mutex_lock(&sExtensionMapMutex); 1210 1211 /* 1212 * Since eglGetProcAddress() is not associated to anything, it needs 1213 * to return a function pointer that "works" regardless of what 1214 * the current context is. 1215 * 1216 * For this reason, we return a "forwarder", a small stub that takes 1217 * care of calling the function associated with the context 1218 * currently bound. 1219 * 1220 * We first look for extensions we've already resolved, if we're seeing 1221 * this extension for the first time, we go through all our 1222 * implementations and call eglGetProcAddress() and record the 1223 * result in the appropriate implementation hooks and return the 1224 * address of the forwarder corresponding to that hook set. 1225 * 1226 */ 1227 1228 const std::string name(procname); 1229 1230 auto& extentionMap = sGLExtentionMap; 1231 auto pos = extentionMap.find(name); 1232 addr = (pos != extentionMap.end()) ? pos->second : nullptr; 1233 const int slot = sGLExtentionSlot; 1234 1235 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS, 1236 "no more slots for eglGetProcAddress(\"%s\")", 1237 procname); 1238 1239 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) { 1240 bool found = false; 1241 1242 egl_connection_t* const cnx = &gEGLImpl; 1243 if (cnx->dso && cnx->egl.eglGetProcAddress) { 1244 // Extensions are independent of the bound context 1245 addr = 1246 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] = 1247 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] = 1248 cnx->egl.eglGetProcAddress(procname); 1249 if (addr) found = true; 1250 } 1251 1252 if (found) { 1253 addr = gExtensionForwarders[slot]; 1254 extentionMap[name] = addr; 1255 sGLExtentionSlot++; 1256 } 1257 } 1258 1259 pthread_mutex_unlock(&sExtensionMapMutex); 1260 return addr; 1261 } 1262 1263 class FrameCompletionThread { 1264 public: 1265 1266 static void queueSync(EGLSyncKHR sync) { 1267 static FrameCompletionThread thread; 1268 1269 char name[64]; 1270 1271 std::lock_guard<std::mutex> lock(thread.mMutex); 1272 snprintf(name, sizeof(name), "kicked off frame %u", (unsigned int)thread.mFramesQueued); 1273 ATRACE_NAME(name); 1274 1275 thread.mQueue.push_back(sync); 1276 thread.mCondition.notify_one(); 1277 thread.mFramesQueued++; 1278 ATRACE_INT("GPU Frames Outstanding", int32_t(thread.mQueue.size())); 1279 } 1280 1281 private: 1282 1283 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) { 1284 std::thread thread(&FrameCompletionThread::loop, this); 1285 thread.detach(); 1286 } 1287 1288 #pragma clang diagnostic push 1289 #pragma clang diagnostic ignored "-Wmissing-noreturn" 1290 void loop() { 1291 while (true) { 1292 threadLoop(); 1293 } 1294 } 1295 #pragma clang diagnostic pop 1296 1297 void threadLoop() { 1298 EGLSyncKHR sync; 1299 uint32_t frameNum; 1300 { 1301 std::unique_lock<std::mutex> lock(mMutex); 1302 while (mQueue.empty()) { 1303 mCondition.wait(lock); 1304 } 1305 sync = mQueue[0]; 1306 frameNum = mFramesCompleted; 1307 } 1308 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); 1309 { 1310 char name[64]; 1311 snprintf(name, sizeof(name), "waiting for frame %u", (unsigned int)frameNum); 1312 ATRACE_NAME(name); 1313 1314 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR); 1315 if (result == EGL_FALSE) { 1316 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError()); 1317 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { 1318 ALOGE("FrameCompletion: timeout waiting for fence"); 1319 } 1320 eglDestroySyncKHR(dpy, sync); 1321 } 1322 { 1323 std::lock_guard<std::mutex> lock(mMutex); 1324 mQueue.pop_front(); 1325 mFramesCompleted++; 1326 ATRACE_INT("GPU Frames Outstanding", int32_t(mQueue.size())); 1327 } 1328 } 1329 1330 uint32_t mFramesQueued; 1331 uint32_t mFramesCompleted; 1332 std::deque<EGLSyncKHR> mQueue; 1333 std::condition_variable mCondition; 1334 std::mutex mMutex; 1335 }; 1336 1337 EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw, 1338 EGLint *rects, EGLint n_rects) 1339 { 1340 ATRACE_CALL(); 1341 clearError(); 1342 1343 const egl_display_ptr dp = validate_display(dpy); 1344 if (!dp) return EGL_FALSE; 1345 1346 SurfaceRef _s(dp.get(), draw); 1347 if (!_s.get()) 1348 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 1349 1350 egl_surface_t const * const s = get_surface(draw); 1351 1352 if (CC_UNLIKELY(dp->traceGpuCompletion)) { 1353 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL); 1354 if (sync != EGL_NO_SYNC_KHR) { 1355 FrameCompletionThread::queueSync(sync); 1356 } 1357 } 1358 1359 if (CC_UNLIKELY(dp->finishOnSwap)) { 1360 uint32_t pixel; 1361 egl_context_t * const c = get_context( egl_tls_t::getContext() ); 1362 if (c) { 1363 // glReadPixels() ensures that the frame is complete 1364 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1, 1365 GL_RGBA,GL_UNSIGNED_BYTE,&pixel); 1366 } 1367 } 1368 1369 if (n_rects == 0) { 1370 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface); 1371 } 1372 1373 std::vector<android_native_rect_t> androidRects((size_t)n_rects); 1374 for (int r = 0; r < n_rects; ++r) { 1375 int offset = r * 4; 1376 int x = rects[offset]; 1377 int y = rects[offset + 1]; 1378 int width = rects[offset + 2]; 1379 int height = rects[offset + 3]; 1380 android_native_rect_t androidRect; 1381 androidRect.left = x; 1382 androidRect.top = y + height; 1383 androidRect.right = x + width; 1384 androidRect.bottom = y; 1385 androidRects.push_back(androidRect); 1386 } 1387 native_window_set_surface_damage(s->getNativeWindow(), androidRects.data(), androidRects.size()); 1388 1389 if (s->cnx->egl.eglSwapBuffersWithDamageKHR) { 1390 return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface, 1391 rects, n_rects); 1392 } else { 1393 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface); 1394 } 1395 } 1396 1397 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) 1398 { 1399 return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0); 1400 } 1401 1402 EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, 1403 NativePixmapType target) 1404 { 1405 clearError(); 1406 1407 const egl_display_ptr dp = validate_display(dpy); 1408 if (!dp) return EGL_FALSE; 1409 1410 SurfaceRef _s(dp.get(), surface); 1411 if (!_s.get()) 1412 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 1413 1414 egl_surface_t const * const s = get_surface(surface); 1415 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target); 1416 } 1417 1418 const char* eglQueryString(EGLDisplay dpy, EGLint name) 1419 { 1420 clearError(); 1421 1422 // Generate an error quietly when client extensions (as defined by 1423 // EGL_EXT_client_extensions) are queried. We do not want to rely on 1424 // validate_display to generate the error as validate_display would log 1425 // the error, which can be misleading. 1426 // 1427 // If we want to support EGL_EXT_client_extensions later, we can return 1428 // the client extension string here instead. 1429 if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) 1430 return setErrorQuiet(EGL_BAD_DISPLAY, (const char*)0); 1431 1432 const egl_display_ptr dp = validate_display(dpy); 1433 if (!dp) return (const char *) NULL; 1434 1435 switch (name) { 1436 case EGL_VENDOR: 1437 return dp->getVendorString(); 1438 case EGL_VERSION: 1439 return dp->getVersionString(); 1440 case EGL_EXTENSIONS: 1441 return dp->getExtensionString(); 1442 case EGL_CLIENT_APIS: 1443 return dp->getClientApiString(); 1444 default: 1445 break; 1446 } 1447 return setError(EGL_BAD_PARAMETER, (const char *)0); 1448 } 1449 1450 extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name) 1451 { 1452 clearError(); 1453 1454 const egl_display_ptr dp = validate_display(dpy); 1455 if (!dp) return (const char *) NULL; 1456 1457 switch (name) { 1458 case EGL_VENDOR: 1459 return dp->disp.queryString.vendor; 1460 case EGL_VERSION: 1461 return dp->disp.queryString.version; 1462 case EGL_EXTENSIONS: 1463 return dp->disp.queryString.extensions; 1464 case EGL_CLIENT_APIS: 1465 return dp->disp.queryString.clientApi; 1466 default: 1467 break; 1468 } 1469 return setError(EGL_BAD_PARAMETER, (const char *)0); 1470 } 1471 1472 // ---------------------------------------------------------------------------- 1473 // EGL 1.1 1474 // ---------------------------------------------------------------------------- 1475 1476 EGLBoolean eglSurfaceAttrib( 1477 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 1478 { 1479 clearError(); 1480 1481 const egl_display_ptr dp = validate_display(dpy); 1482 if (!dp) return EGL_FALSE; 1483 1484 SurfaceRef _s(dp.get(), surface); 1485 if (!_s.get()) 1486 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 1487 1488 egl_surface_t * const s = get_surface(surface); 1489 1490 if (attribute == EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID) { 1491 if (!s->getNativeWindow()) { 1492 setError(EGL_BAD_SURFACE, EGL_FALSE); 1493 } 1494 int err = native_window_set_auto_refresh(s->getNativeWindow(), value != 0); 1495 return (err == 0) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 1496 } 1497 1498 if (attribute == EGL_TIMESTAMPS_ANDROID) { 1499 if (!s->getNativeWindow()) { 1500 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 1501 } 1502 int err = native_window_enable_frame_timestamps(s->getNativeWindow(), value != 0); 1503 return (err == 0) ? EGL_TRUE : setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 1504 } 1505 1506 if (s->cnx->egl.eglSurfaceAttrib) { 1507 return s->cnx->egl.eglSurfaceAttrib( 1508 dp->disp.dpy, s->surface, attribute, value); 1509 } 1510 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 1511 } 1512 1513 EGLBoolean eglBindTexImage( 1514 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1515 { 1516 clearError(); 1517 1518 const egl_display_ptr dp = validate_display(dpy); 1519 if (!dp) return EGL_FALSE; 1520 1521 SurfaceRef _s(dp.get(), surface); 1522 if (!_s.get()) 1523 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 1524 1525 egl_surface_t const * const s = get_surface(surface); 1526 if (s->cnx->egl.eglBindTexImage) { 1527 return s->cnx->egl.eglBindTexImage( 1528 dp->disp.dpy, s->surface, buffer); 1529 } 1530 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 1531 } 1532 1533 EGLBoolean eglReleaseTexImage( 1534 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1535 { 1536 clearError(); 1537 1538 const egl_display_ptr dp = validate_display(dpy); 1539 if (!dp) return EGL_FALSE; 1540 1541 SurfaceRef _s(dp.get(), surface); 1542 if (!_s.get()) 1543 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 1544 1545 egl_surface_t const * const s = get_surface(surface); 1546 if (s->cnx->egl.eglReleaseTexImage) { 1547 return s->cnx->egl.eglReleaseTexImage( 1548 dp->disp.dpy, s->surface, buffer); 1549 } 1550 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 1551 } 1552 1553 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 1554 { 1555 clearError(); 1556 1557 const egl_display_ptr dp = validate_display(dpy); 1558 if (!dp) return EGL_FALSE; 1559 1560 EGLBoolean res = EGL_TRUE; 1561 egl_connection_t* const cnx = &gEGLImpl; 1562 if (cnx->dso && cnx->egl.eglSwapInterval) { 1563 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval); 1564 } 1565 1566 return res; 1567 } 1568 1569 1570 // ---------------------------------------------------------------------------- 1571 // EGL 1.2 1572 // ---------------------------------------------------------------------------- 1573 1574 EGLBoolean eglWaitClient(void) 1575 { 1576 clearError(); 1577 1578 egl_connection_t* const cnx = &gEGLImpl; 1579 if (!cnx->dso) 1580 return setError(EGL_BAD_CONTEXT, (EGLBoolean)EGL_FALSE); 1581 1582 EGLBoolean res; 1583 if (cnx->egl.eglWaitClient) { 1584 res = cnx->egl.eglWaitClient(); 1585 } else { 1586 res = cnx->egl.eglWaitGL(); 1587 } 1588 return res; 1589 } 1590 1591 EGLBoolean eglBindAPI(EGLenum api) 1592 { 1593 clearError(); 1594 1595 if (egl_init_drivers() == EGL_FALSE) { 1596 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE); 1597 } 1598 1599 // bind this API on all EGLs 1600 EGLBoolean res = EGL_TRUE; 1601 egl_connection_t* const cnx = &gEGLImpl; 1602 if (cnx->dso && cnx->egl.eglBindAPI) { 1603 res = cnx->egl.eglBindAPI(api); 1604 } 1605 return res; 1606 } 1607 1608 EGLenum eglQueryAPI(void) 1609 { 1610 clearError(); 1611 1612 if (egl_init_drivers() == EGL_FALSE) { 1613 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE); 1614 } 1615 1616 egl_connection_t* const cnx = &gEGLImpl; 1617 if (cnx->dso && cnx->egl.eglQueryAPI) { 1618 return cnx->egl.eglQueryAPI(); 1619 } 1620 1621 // or, it can only be OpenGL ES 1622 return EGL_OPENGL_ES_API; 1623 } 1624 1625 EGLBoolean eglReleaseThread(void) 1626 { 1627 clearError(); 1628 1629 egl_connection_t* const cnx = &gEGLImpl; 1630 if (cnx->dso && cnx->egl.eglReleaseThread) { 1631 cnx->egl.eglReleaseThread(); 1632 } 1633 1634 // If there is context bound to the thread, release it 1635 egl_display_t::loseCurrent(get_context(getContext())); 1636 1637 egl_tls_t::clearTLS(); 1638 return EGL_TRUE; 1639 } 1640 1641 EGLSurface eglCreatePbufferFromClientBuffer( 1642 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 1643 EGLConfig config, const EGLint *attrib_list) 1644 { 1645 clearError(); 1646 1647 egl_connection_t* cnx = NULL; 1648 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 1649 if (!dp) return EGL_FALSE; 1650 if (cnx->egl.eglCreatePbufferFromClientBuffer) { 1651 return cnx->egl.eglCreatePbufferFromClientBuffer( 1652 dp->disp.dpy, buftype, buffer, config, attrib_list); 1653 } 1654 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); 1655 } 1656 1657 // ---------------------------------------------------------------------------- 1658 // EGL_EGLEXT_VERSION 3 1659 // ---------------------------------------------------------------------------- 1660 1661 EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, 1662 const EGLint *attrib_list) 1663 { 1664 clearError(); 1665 1666 const egl_display_ptr dp = validate_display(dpy); 1667 if (!dp) return EGL_FALSE; 1668 1669 SurfaceRef _s(dp.get(), surface); 1670 if (!_s.get()) 1671 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 1672 1673 egl_surface_t const * const s = get_surface(surface); 1674 if (s->cnx->egl.eglLockSurfaceKHR) { 1675 return s->cnx->egl.eglLockSurfaceKHR( 1676 dp->disp.dpy, s->surface, attrib_list); 1677 } 1678 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); 1679 } 1680 1681 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) 1682 { 1683 clearError(); 1684 1685 const egl_display_ptr dp = validate_display(dpy); 1686 if (!dp) return EGL_FALSE; 1687 1688 SurfaceRef _s(dp.get(), surface); 1689 if (!_s.get()) 1690 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 1691 1692 egl_surface_t const * const s = get_surface(surface); 1693 if (s->cnx->egl.eglUnlockSurfaceKHR) { 1694 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface); 1695 } 1696 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); 1697 } 1698 1699 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1700 EGLClientBuffer buffer, const EGLint *attrib_list) 1701 { 1702 clearError(); 1703 1704 const egl_display_ptr dp = validate_display(dpy); 1705 if (!dp) return EGL_NO_IMAGE_KHR; 1706 1707 ContextRef _c(dp.get(), ctx); 1708 egl_context_t * const c = _c.get(); 1709 1710 EGLImageKHR result = EGL_NO_IMAGE_KHR; 1711 egl_connection_t* const cnx = &gEGLImpl; 1712 if (cnx->dso && cnx->egl.eglCreateImageKHR) { 1713 result = cnx->egl.eglCreateImageKHR( 1714 dp->disp.dpy, 1715 c ? c->context : EGL_NO_CONTEXT, 1716 target, buffer, attrib_list); 1717 } 1718 return result; 1719 } 1720 1721 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 1722 { 1723 clearError(); 1724 1725 const egl_display_ptr dp = validate_display(dpy); 1726 if (!dp) return EGL_FALSE; 1727 1728 EGLBoolean result = EGL_FALSE; 1729 egl_connection_t* const cnx = &gEGLImpl; 1730 if (cnx->dso && cnx->egl.eglDestroyImageKHR) { 1731 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img); 1732 } 1733 return result; 1734 } 1735 1736 // ---------------------------------------------------------------------------- 1737 // EGL_EGLEXT_VERSION 5 1738 // ---------------------------------------------------------------------------- 1739 1740 1741 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) 1742 { 1743 clearError(); 1744 1745 const egl_display_ptr dp = validate_display(dpy); 1746 if (!dp) return EGL_NO_SYNC_KHR; 1747 1748 EGLSyncKHR result = EGL_NO_SYNC_KHR; 1749 egl_connection_t* const cnx = &gEGLImpl; 1750 if (cnx->dso && cnx->egl.eglCreateSyncKHR) { 1751 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list); 1752 } 1753 return result; 1754 } 1755 1756 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) 1757 { 1758 clearError(); 1759 1760 const egl_display_ptr dp = validate_display(dpy); 1761 if (!dp) return EGL_FALSE; 1762 1763 EGLBoolean result = EGL_FALSE; 1764 egl_connection_t* const cnx = &gEGLImpl; 1765 if (cnx->dso && cnx->egl.eglDestroySyncKHR) { 1766 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync); 1767 } 1768 return result; 1769 } 1770 1771 EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) { 1772 clearError(); 1773 1774 const egl_display_ptr dp = validate_display(dpy); 1775 if (!dp) return EGL_FALSE; 1776 1777 EGLBoolean result = EGL_FALSE; 1778 egl_connection_t* const cnx = &gEGLImpl; 1779 if (cnx->dso && cnx->egl.eglSignalSyncKHR) { 1780 result = cnx->egl.eglSignalSyncKHR( 1781 dp->disp.dpy, sync, mode); 1782 } 1783 return result; 1784 } 1785 1786 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, 1787 EGLint flags, EGLTimeKHR timeout) 1788 { 1789 clearError(); 1790 1791 const egl_display_ptr dp = validate_display(dpy); 1792 if (!dp) return EGL_FALSE; 1793 1794 EGLint result = EGL_FALSE; 1795 egl_connection_t* const cnx = &gEGLImpl; 1796 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) { 1797 result = cnx->egl.eglClientWaitSyncKHR( 1798 dp->disp.dpy, sync, flags, timeout); 1799 } 1800 return result; 1801 } 1802 1803 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, 1804 EGLint attribute, EGLint *value) 1805 { 1806 clearError(); 1807 1808 const egl_display_ptr dp = validate_display(dpy); 1809 if (!dp) return EGL_FALSE; 1810 1811 EGLBoolean result = EGL_FALSE; 1812 egl_connection_t* const cnx = &gEGLImpl; 1813 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) { 1814 result = cnx->egl.eglGetSyncAttribKHR( 1815 dp->disp.dpy, sync, attribute, value); 1816 } 1817 return result; 1818 } 1819 1820 EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list) 1821 { 1822 clearError(); 1823 1824 const egl_display_ptr dp = validate_display(dpy); 1825 if (!dp) return EGL_NO_STREAM_KHR; 1826 1827 EGLStreamKHR result = EGL_NO_STREAM_KHR; 1828 egl_connection_t* const cnx = &gEGLImpl; 1829 if (cnx->dso && cnx->egl.eglCreateStreamKHR) { 1830 result = cnx->egl.eglCreateStreamKHR( 1831 dp->disp.dpy, attrib_list); 1832 } 1833 return result; 1834 } 1835 1836 EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream) 1837 { 1838 clearError(); 1839 1840 const egl_display_ptr dp = validate_display(dpy); 1841 if (!dp) return EGL_FALSE; 1842 1843 EGLBoolean result = EGL_FALSE; 1844 egl_connection_t* const cnx = &gEGLImpl; 1845 if (cnx->dso && cnx->egl.eglDestroyStreamKHR) { 1846 result = cnx->egl.eglDestroyStreamKHR( 1847 dp->disp.dpy, stream); 1848 } 1849 return result; 1850 } 1851 1852 EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream, 1853 EGLenum attribute, EGLint value) 1854 { 1855 clearError(); 1856 1857 const egl_display_ptr dp = validate_display(dpy); 1858 if (!dp) return EGL_FALSE; 1859 1860 EGLBoolean result = EGL_FALSE; 1861 egl_connection_t* const cnx = &gEGLImpl; 1862 if (cnx->dso && cnx->egl.eglStreamAttribKHR) { 1863 result = cnx->egl.eglStreamAttribKHR( 1864 dp->disp.dpy, stream, attribute, value); 1865 } 1866 return result; 1867 } 1868 1869 EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream, 1870 EGLenum attribute, EGLint *value) 1871 { 1872 clearError(); 1873 1874 const egl_display_ptr dp = validate_display(dpy); 1875 if (!dp) return EGL_FALSE; 1876 1877 EGLBoolean result = EGL_FALSE; 1878 egl_connection_t* const cnx = &gEGLImpl; 1879 if (cnx->dso && cnx->egl.eglQueryStreamKHR) { 1880 result = cnx->egl.eglQueryStreamKHR( 1881 dp->disp.dpy, stream, attribute, value); 1882 } 1883 return result; 1884 } 1885 1886 EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream, 1887 EGLenum attribute, EGLuint64KHR *value) 1888 { 1889 clearError(); 1890 1891 const egl_display_ptr dp = validate_display(dpy); 1892 if (!dp) return EGL_FALSE; 1893 1894 EGLBoolean result = EGL_FALSE; 1895 egl_connection_t* const cnx = &gEGLImpl; 1896 if (cnx->dso && cnx->egl.eglQueryStreamu64KHR) { 1897 result = cnx->egl.eglQueryStreamu64KHR( 1898 dp->disp.dpy, stream, attribute, value); 1899 } 1900 return result; 1901 } 1902 1903 EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream, 1904 EGLenum attribute, EGLTimeKHR *value) 1905 { 1906 clearError(); 1907 1908 const egl_display_ptr dp = validate_display(dpy); 1909 if (!dp) return EGL_FALSE; 1910 1911 EGLBoolean result = EGL_FALSE; 1912 egl_connection_t* const cnx = &gEGLImpl; 1913 if (cnx->dso && cnx->egl.eglQueryStreamTimeKHR) { 1914 result = cnx->egl.eglQueryStreamTimeKHR( 1915 dp->disp.dpy, stream, attribute, value); 1916 } 1917 return result; 1918 } 1919 1920 EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config, 1921 EGLStreamKHR stream, const EGLint *attrib_list) 1922 { 1923 clearError(); 1924 1925 egl_display_ptr dp = validate_display(dpy); 1926 if (!dp) return EGL_NO_SURFACE; 1927 1928 EGLint colorSpace = EGL_GL_COLORSPACE_LINEAR_KHR; 1929 android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN; 1930 // TODO: Probably need to update EGL_KHR_stream_producer_eglsurface to 1931 // indicate support for EGL_GL_COLORSPACE_KHR. 1932 // now select a corresponding sRGB format if needed 1933 if (!getColorSpaceAttribute(dp, attrib_list, colorSpace, dataSpace)) { 1934 ALOGE("error invalid colorspace: %d", colorSpace); 1935 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); 1936 } 1937 1938 egl_connection_t* const cnx = &gEGLImpl; 1939 if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) { 1940 EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR( 1941 dp->disp.dpy, config, stream, attrib_list); 1942 if (surface != EGL_NO_SURFACE) { 1943 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, surface, colorSpace, cnx); 1944 return s; 1945 } 1946 } 1947 return EGL_NO_SURFACE; 1948 } 1949 1950 EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy, 1951 EGLStreamKHR stream) 1952 { 1953 clearError(); 1954 1955 const egl_display_ptr dp = validate_display(dpy); 1956 if (!dp) return EGL_FALSE; 1957 1958 EGLBoolean result = EGL_FALSE; 1959 egl_connection_t* const cnx = &gEGLImpl; 1960 if (cnx->dso && cnx->egl.eglStreamConsumerGLTextureExternalKHR) { 1961 result = cnx->egl.eglStreamConsumerGLTextureExternalKHR( 1962 dp->disp.dpy, stream); 1963 } 1964 return result; 1965 } 1966 1967 EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy, 1968 EGLStreamKHR stream) 1969 { 1970 clearError(); 1971 1972 const egl_display_ptr dp = validate_display(dpy); 1973 if (!dp) return EGL_FALSE; 1974 1975 EGLBoolean result = EGL_FALSE; 1976 egl_connection_t* const cnx = &gEGLImpl; 1977 if (cnx->dso && cnx->egl.eglStreamConsumerAcquireKHR) { 1978 result = cnx->egl.eglStreamConsumerAcquireKHR( 1979 dp->disp.dpy, stream); 1980 } 1981 return result; 1982 } 1983 1984 EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy, 1985 EGLStreamKHR stream) 1986 { 1987 clearError(); 1988 1989 const egl_display_ptr dp = validate_display(dpy); 1990 if (!dp) return EGL_FALSE; 1991 1992 EGLBoolean result = EGL_FALSE; 1993 egl_connection_t* const cnx = &gEGLImpl; 1994 if (cnx->dso && cnx->egl.eglStreamConsumerReleaseKHR) { 1995 result = cnx->egl.eglStreamConsumerReleaseKHR( 1996 dp->disp.dpy, stream); 1997 } 1998 return result; 1999 } 2000 2001 EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR( 2002 EGLDisplay dpy, EGLStreamKHR stream) 2003 { 2004 clearError(); 2005 2006 const egl_display_ptr dp = validate_display(dpy); 2007 if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR; 2008 2009 EGLNativeFileDescriptorKHR result = EGL_NO_FILE_DESCRIPTOR_KHR; 2010 egl_connection_t* const cnx = &gEGLImpl; 2011 if (cnx->dso && cnx->egl.eglGetStreamFileDescriptorKHR) { 2012 result = cnx->egl.eglGetStreamFileDescriptorKHR( 2013 dp->disp.dpy, stream); 2014 } 2015 return result; 2016 } 2017 2018 EGLStreamKHR eglCreateStreamFromFileDescriptorKHR( 2019 EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor) 2020 { 2021 clearError(); 2022 2023 const egl_display_ptr dp = validate_display(dpy); 2024 if (!dp) return EGL_NO_STREAM_KHR; 2025 2026 EGLStreamKHR result = EGL_NO_STREAM_KHR; 2027 egl_connection_t* const cnx = &gEGLImpl; 2028 if (cnx->dso && cnx->egl.eglCreateStreamFromFileDescriptorKHR) { 2029 result = cnx->egl.eglCreateStreamFromFileDescriptorKHR( 2030 dp->disp.dpy, file_descriptor); 2031 } 2032 return result; 2033 } 2034 2035 // ---------------------------------------------------------------------------- 2036 // EGL_EGLEXT_VERSION 15 2037 // ---------------------------------------------------------------------------- 2038 2039 EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) { 2040 clearError(); 2041 const egl_display_ptr dp = validate_display(dpy); 2042 if (!dp) return EGL_FALSE; 2043 EGLint result = EGL_FALSE; 2044 egl_connection_t* const cnx = &gEGLImpl; 2045 if (cnx->dso && cnx->egl.eglWaitSyncKHR) { 2046 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags); 2047 } 2048 return result; 2049 } 2050 2051 // ---------------------------------------------------------------------------- 2052 // ANDROID extensions 2053 // ---------------------------------------------------------------------------- 2054 2055 EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync) 2056 { 2057 clearError(); 2058 2059 const egl_display_ptr dp = validate_display(dpy); 2060 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID; 2061 2062 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID; 2063 egl_connection_t* const cnx = &gEGLImpl; 2064 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) { 2065 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync); 2066 } 2067 return result; 2068 } 2069 2070 EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface, 2071 EGLnsecsANDROID time) 2072 { 2073 clearError(); 2074 2075 const egl_display_ptr dp = validate_display(dpy); 2076 if (!dp) { 2077 return EGL_FALSE; 2078 } 2079 2080 SurfaceRef _s(dp.get(), surface); 2081 if (!_s.get()) { 2082 setError(EGL_BAD_SURFACE, EGL_FALSE); 2083 return EGL_FALSE; 2084 } 2085 2086 egl_surface_t const * const s = get_surface(surface); 2087 native_window_set_buffers_timestamp(s->getNativeWindow(), time); 2088 2089 return EGL_TRUE; 2090 } 2091 2092 EGLClientBuffer eglGetNativeClientBufferANDROID(const AHardwareBuffer *buffer) { 2093 clearError(); 2094 // AHardwareBuffer_to_ANativeWindowBuffer is a platform-only symbol and thus 2095 // this function cannot be implemented when this libEGL is built for 2096 // vendors. 2097 #ifndef __ANDROID_VNDK__ 2098 if (!buffer) return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0); 2099 return const_cast<ANativeWindowBuffer *>(AHardwareBuffer_to_ANativeWindowBuffer(buffer)); 2100 #else 2101 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0); 2102 #endif 2103 } 2104 2105 // ---------------------------------------------------------------------------- 2106 // NVIDIA extensions 2107 // ---------------------------------------------------------------------------- 2108 EGLuint64NV eglGetSystemTimeFrequencyNV() 2109 { 2110 clearError(); 2111 2112 if (egl_init_drivers() == EGL_FALSE) { 2113 return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE); 2114 } 2115 2116 EGLuint64NV ret = 0; 2117 egl_connection_t* const cnx = &gEGLImpl; 2118 2119 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) { 2120 return cnx->egl.eglGetSystemTimeFrequencyNV(); 2121 } 2122 2123 return setErrorQuiet(EGL_BAD_DISPLAY, (EGLuint64NV)0); 2124 } 2125 2126 EGLuint64NV eglGetSystemTimeNV() 2127 { 2128 clearError(); 2129 2130 if (egl_init_drivers() == EGL_FALSE) { 2131 return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE); 2132 } 2133 2134 EGLuint64NV ret = 0; 2135 egl_connection_t* const cnx = &gEGLImpl; 2136 2137 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) { 2138 return cnx->egl.eglGetSystemTimeNV(); 2139 } 2140 2141 return setErrorQuiet(EGL_BAD_DISPLAY, (EGLuint64NV)0); 2142 } 2143 2144 // ---------------------------------------------------------------------------- 2145 // Partial update extension 2146 // ---------------------------------------------------------------------------- 2147 EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface, 2148 EGLint *rects, EGLint n_rects) 2149 { 2150 clearError(); 2151 2152 const egl_display_ptr dp = validate_display(dpy); 2153 if (!dp) { 2154 setError(EGL_BAD_DISPLAY, EGL_FALSE); 2155 return EGL_FALSE; 2156 } 2157 2158 SurfaceRef _s(dp.get(), surface); 2159 if (!_s.get()) { 2160 setError(EGL_BAD_SURFACE, EGL_FALSE); 2161 return EGL_FALSE; 2162 } 2163 2164 egl_surface_t const * const s = get_surface(surface); 2165 if (s->cnx->egl.eglSetDamageRegionKHR) { 2166 return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface, 2167 rects, n_rects); 2168 } 2169 2170 return EGL_FALSE; 2171 } 2172 2173 EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface, 2174 EGLuint64KHR *frameId) { 2175 clearError(); 2176 2177 const egl_display_ptr dp = validate_display(dpy); 2178 if (!dp) { 2179 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); 2180 } 2181 2182 SurfaceRef _s(dp.get(), surface); 2183 if (!_s.get()) { 2184 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 2185 } 2186 2187 egl_surface_t const * const s = get_surface(surface); 2188 2189 if (!s->getNativeWindow()) { 2190 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 2191 } 2192 2193 uint64_t nextFrameId = 0; 2194 int ret = native_window_get_next_frame_id(s->getNativeWindow(), &nextFrameId); 2195 2196 if (ret != 0) { 2197 // This should not happen. Return an error that is not in the spec 2198 // so it's obvious something is very wrong. 2199 ALOGE("eglGetNextFrameId: Unexpected error."); 2200 return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE); 2201 } 2202 2203 *frameId = nextFrameId; 2204 return EGL_TRUE; 2205 } 2206 2207 EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, EGLSurface surface, 2208 EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values) 2209 { 2210 clearError(); 2211 2212 const egl_display_ptr dp = validate_display(dpy); 2213 if (!dp) { 2214 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); 2215 } 2216 2217 SurfaceRef _s(dp.get(), surface); 2218 if (!_s.get()) { 2219 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 2220 } 2221 2222 egl_surface_t const * const s = get_surface(surface); 2223 2224 if (!s->getNativeWindow()) { 2225 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 2226 } 2227 2228 nsecs_t* compositeDeadline = nullptr; 2229 nsecs_t* compositeInterval = nullptr; 2230 nsecs_t* compositeToPresentLatency = nullptr; 2231 2232 for (int i = 0; i < numTimestamps; i++) { 2233 switch (names[i]) { 2234 case EGL_COMPOSITE_DEADLINE_ANDROID: 2235 compositeDeadline = &values[i]; 2236 break; 2237 case EGL_COMPOSITE_INTERVAL_ANDROID: 2238 compositeInterval = &values[i]; 2239 break; 2240 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID: 2241 compositeToPresentLatency = &values[i]; 2242 break; 2243 default: 2244 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE); 2245 } 2246 } 2247 2248 int ret = native_window_get_compositor_timing(s->getNativeWindow(), 2249 compositeDeadline, compositeInterval, compositeToPresentLatency); 2250 2251 switch (ret) { 2252 case 0: 2253 return EGL_TRUE; 2254 case -ENOSYS: 2255 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 2256 default: 2257 // This should not happen. Return an error that is not in the spec 2258 // so it's obvious something is very wrong. 2259 ALOGE("eglGetCompositorTiming: Unexpected error."); 2260 return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE); 2261 } 2262 } 2263 2264 EGLBoolean eglGetCompositorTimingSupportedANDROID( 2265 EGLDisplay dpy, EGLSurface surface, EGLint name) 2266 { 2267 clearError(); 2268 2269 const egl_display_ptr dp = validate_display(dpy); 2270 if (!dp) { 2271 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); 2272 } 2273 2274 SurfaceRef _s(dp.get(), surface); 2275 if (!_s.get()) { 2276 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 2277 } 2278 2279 egl_surface_t const * const s = get_surface(surface); 2280 2281 ANativeWindow* window = s->getNativeWindow(); 2282 if (!window) { 2283 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 2284 } 2285 2286 switch (name) { 2287 case EGL_COMPOSITE_DEADLINE_ANDROID: 2288 case EGL_COMPOSITE_INTERVAL_ANDROID: 2289 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID: 2290 return EGL_TRUE; 2291 default: 2292 return EGL_FALSE; 2293 } 2294 } 2295 2296 EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, 2297 EGLuint64KHR frameId, EGLint numTimestamps, const EGLint *timestamps, 2298 EGLnsecsANDROID *values) 2299 { 2300 clearError(); 2301 2302 const egl_display_ptr dp = validate_display(dpy); 2303 if (!dp) { 2304 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); 2305 } 2306 2307 SurfaceRef _s(dp.get(), surface); 2308 if (!_s.get()) { 2309 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 2310 } 2311 2312 egl_surface_t const * const s = get_surface(surface); 2313 2314 if (!s->getNativeWindow()) { 2315 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 2316 } 2317 2318 nsecs_t* requestedPresentTime = nullptr; 2319 nsecs_t* acquireTime = nullptr; 2320 nsecs_t* latchTime = nullptr; 2321 nsecs_t* firstRefreshStartTime = nullptr; 2322 nsecs_t* gpuCompositionDoneTime = nullptr; 2323 nsecs_t* lastRefreshStartTime = nullptr; 2324 nsecs_t* displayPresentTime = nullptr; 2325 nsecs_t* dequeueReadyTime = nullptr; 2326 nsecs_t* releaseTime = nullptr; 2327 2328 for (int i = 0; i < numTimestamps; i++) { 2329 switch (timestamps[i]) { 2330 case EGL_REQUESTED_PRESENT_TIME_ANDROID: 2331 requestedPresentTime = &values[i]; 2332 break; 2333 case EGL_RENDERING_COMPLETE_TIME_ANDROID: 2334 acquireTime = &values[i]; 2335 break; 2336 case EGL_COMPOSITION_LATCH_TIME_ANDROID: 2337 latchTime = &values[i]; 2338 break; 2339 case EGL_FIRST_COMPOSITION_START_TIME_ANDROID: 2340 firstRefreshStartTime = &values[i]; 2341 break; 2342 case EGL_LAST_COMPOSITION_START_TIME_ANDROID: 2343 lastRefreshStartTime = &values[i]; 2344 break; 2345 case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID: 2346 gpuCompositionDoneTime = &values[i]; 2347 break; 2348 case EGL_DISPLAY_PRESENT_TIME_ANDROID: 2349 displayPresentTime = &values[i]; 2350 break; 2351 case EGL_DEQUEUE_READY_TIME_ANDROID: 2352 dequeueReadyTime = &values[i]; 2353 break; 2354 case EGL_READS_DONE_TIME_ANDROID: 2355 releaseTime = &values[i]; 2356 break; 2357 default: 2358 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE); 2359 } 2360 } 2361 2362 int ret = native_window_get_frame_timestamps(s->getNativeWindow(), frameId, 2363 requestedPresentTime, acquireTime, latchTime, firstRefreshStartTime, 2364 lastRefreshStartTime, gpuCompositionDoneTime, displayPresentTime, 2365 dequeueReadyTime, releaseTime); 2366 2367 switch (ret) { 2368 case 0: 2369 return EGL_TRUE; 2370 case -ENOENT: 2371 return setError(EGL_BAD_ACCESS, (EGLBoolean)EGL_FALSE); 2372 case -ENOSYS: 2373 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 2374 case -EINVAL: 2375 return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE); 2376 default: 2377 // This should not happen. Return an error that is not in the spec 2378 // so it's obvious something is very wrong. 2379 ALOGE("eglGetFrameTimestamps: Unexpected error."); 2380 return setError(EGL_NOT_INITIALIZED, (EGLBoolean)EGL_FALSE); 2381 } 2382 } 2383 2384 EGLBoolean eglGetFrameTimestampSupportedANDROID( 2385 EGLDisplay dpy, EGLSurface surface, EGLint timestamp) 2386 { 2387 clearError(); 2388 2389 const egl_display_ptr dp = validate_display(dpy); 2390 if (!dp) { 2391 return setError(EGL_BAD_DISPLAY, (EGLBoolean)EGL_FALSE); 2392 } 2393 2394 SurfaceRef _s(dp.get(), surface); 2395 if (!_s.get()) { 2396 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 2397 } 2398 2399 egl_surface_t const * const s = get_surface(surface); 2400 2401 ANativeWindow* window = s->getNativeWindow(); 2402 if (!window) { 2403 return setError(EGL_BAD_SURFACE, (EGLBoolean)EGL_FALSE); 2404 } 2405 2406 switch (timestamp) { 2407 case EGL_COMPOSITE_DEADLINE_ANDROID: 2408 case EGL_COMPOSITE_INTERVAL_ANDROID: 2409 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID: 2410 case EGL_REQUESTED_PRESENT_TIME_ANDROID: 2411 case EGL_RENDERING_COMPLETE_TIME_ANDROID: 2412 case EGL_COMPOSITION_LATCH_TIME_ANDROID: 2413 case EGL_FIRST_COMPOSITION_START_TIME_ANDROID: 2414 case EGL_LAST_COMPOSITION_START_TIME_ANDROID: 2415 case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID: 2416 case EGL_DEQUEUE_READY_TIME_ANDROID: 2417 case EGL_READS_DONE_TIME_ANDROID: 2418 return EGL_TRUE; 2419 case EGL_DISPLAY_PRESENT_TIME_ANDROID: { 2420 int value = 0; 2421 window->query(window, 2422 NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &value); 2423 return value == 0 ? EGL_FALSE : EGL_TRUE; 2424 } 2425 default: 2426 return EGL_FALSE; 2427 } 2428 } 2429