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