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