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