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