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