eglApi.cpp revision 02b05da60a4669df44c9c0747ec262ec1862cf61
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 return (native_window_set_auto_refresh(s->win.get(), 1200 value ? true : false)) ? EGL_TRUE : EGL_FALSE; 1201 } 1202 1203 if (s->cnx->egl.eglSurfaceAttrib) { 1204 return s->cnx->egl.eglSurfaceAttrib( 1205 dp->disp.dpy, s->surface, attribute, value); 1206 } 1207 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1208} 1209 1210EGLBoolean eglBindTexImage( 1211 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1212{ 1213 clearError(); 1214 1215 const egl_display_ptr dp = validate_display(dpy); 1216 if (!dp) return EGL_FALSE; 1217 1218 SurfaceRef _s(dp.get(), surface); 1219 if (!_s.get()) 1220 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1221 1222 egl_surface_t const * const s = get_surface(surface); 1223 if (s->cnx->egl.eglBindTexImage) { 1224 return s->cnx->egl.eglBindTexImage( 1225 dp->disp.dpy, s->surface, buffer); 1226 } 1227 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1228} 1229 1230EGLBoolean eglReleaseTexImage( 1231 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1232{ 1233 clearError(); 1234 1235 const egl_display_ptr dp = validate_display(dpy); 1236 if (!dp) return EGL_FALSE; 1237 1238 SurfaceRef _s(dp.get(), surface); 1239 if (!_s.get()) 1240 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1241 1242 egl_surface_t const * const s = get_surface(surface); 1243 if (s->cnx->egl.eglReleaseTexImage) { 1244 return s->cnx->egl.eglReleaseTexImage( 1245 dp->disp.dpy, s->surface, buffer); 1246 } 1247 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1248} 1249 1250EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 1251{ 1252 clearError(); 1253 1254 const egl_display_ptr dp = validate_display(dpy); 1255 if (!dp) return EGL_FALSE; 1256 1257 EGLBoolean res = EGL_TRUE; 1258 egl_connection_t* const cnx = &gEGLImpl; 1259 if (cnx->dso && cnx->egl.eglSwapInterval) { 1260 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval); 1261 } 1262 1263 return res; 1264} 1265 1266 1267// ---------------------------------------------------------------------------- 1268// EGL 1.2 1269// ---------------------------------------------------------------------------- 1270 1271EGLBoolean eglWaitClient(void) 1272{ 1273 clearError(); 1274 1275 egl_connection_t* const cnx = &gEGLImpl; 1276 if (!cnx->dso) 1277 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1278 1279 EGLBoolean res; 1280 if (cnx->egl.eglWaitClient) { 1281 res = cnx->egl.eglWaitClient(); 1282 } else { 1283 res = cnx->egl.eglWaitGL(); 1284 } 1285 return res; 1286} 1287 1288EGLBoolean eglBindAPI(EGLenum api) 1289{ 1290 clearError(); 1291 1292 if (egl_init_drivers() == EGL_FALSE) { 1293 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1294 } 1295 1296 // bind this API on all EGLs 1297 EGLBoolean res = EGL_TRUE; 1298 egl_connection_t* const cnx = &gEGLImpl; 1299 if (cnx->dso && cnx->egl.eglBindAPI) { 1300 res = cnx->egl.eglBindAPI(api); 1301 } 1302 return res; 1303} 1304 1305EGLenum eglQueryAPI(void) 1306{ 1307 clearError(); 1308 1309 if (egl_init_drivers() == EGL_FALSE) { 1310 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1311 } 1312 1313 egl_connection_t* const cnx = &gEGLImpl; 1314 if (cnx->dso && cnx->egl.eglQueryAPI) { 1315 return cnx->egl.eglQueryAPI(); 1316 } 1317 1318 // or, it can only be OpenGL ES 1319 return EGL_OPENGL_ES_API; 1320} 1321 1322EGLBoolean eglReleaseThread(void) 1323{ 1324 clearError(); 1325 1326 // If there is context bound to the thread, release it 1327 egl_display_t::loseCurrent(get_context(getContext())); 1328 1329 egl_connection_t* const cnx = &gEGLImpl; 1330 if (cnx->dso && cnx->egl.eglReleaseThread) { 1331 cnx->egl.eglReleaseThread(); 1332 } 1333 egl_tls_t::clearTLS(); 1334 return EGL_TRUE; 1335} 1336 1337EGLSurface eglCreatePbufferFromClientBuffer( 1338 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 1339 EGLConfig config, const EGLint *attrib_list) 1340{ 1341 clearError(); 1342 1343 egl_connection_t* cnx = NULL; 1344 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 1345 if (!dp) return EGL_FALSE; 1346 if (cnx->egl.eglCreatePbufferFromClientBuffer) { 1347 return cnx->egl.eglCreatePbufferFromClientBuffer( 1348 dp->disp.dpy, buftype, buffer, config, attrib_list); 1349 } 1350 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); 1351} 1352 1353// ---------------------------------------------------------------------------- 1354// EGL_EGLEXT_VERSION 3 1355// ---------------------------------------------------------------------------- 1356 1357EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, 1358 const EGLint *attrib_list) 1359{ 1360 clearError(); 1361 1362 const egl_display_ptr dp = validate_display(dpy); 1363 if (!dp) return EGL_FALSE; 1364 1365 SurfaceRef _s(dp.get(), surface); 1366 if (!_s.get()) 1367 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1368 1369 egl_surface_t const * const s = get_surface(surface); 1370 if (s->cnx->egl.eglLockSurfaceKHR) { 1371 return s->cnx->egl.eglLockSurfaceKHR( 1372 dp->disp.dpy, s->surface, attrib_list); 1373 } 1374 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1375} 1376 1377EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) 1378{ 1379 clearError(); 1380 1381 const egl_display_ptr dp = validate_display(dpy); 1382 if (!dp) return EGL_FALSE; 1383 1384 SurfaceRef _s(dp.get(), surface); 1385 if (!_s.get()) 1386 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1387 1388 egl_surface_t const * const s = get_surface(surface); 1389 if (s->cnx->egl.eglUnlockSurfaceKHR) { 1390 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface); 1391 } 1392 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1393} 1394 1395EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1396 EGLClientBuffer buffer, const EGLint *attrib_list) 1397{ 1398 clearError(); 1399 1400 const egl_display_ptr dp = validate_display(dpy); 1401 if (!dp) return EGL_NO_IMAGE_KHR; 1402 1403 ContextRef _c(dp.get(), ctx); 1404 egl_context_t * const c = _c.get(); 1405 1406 EGLImageKHR result = EGL_NO_IMAGE_KHR; 1407 egl_connection_t* const cnx = &gEGLImpl; 1408 if (cnx->dso && cnx->egl.eglCreateImageKHR) { 1409 result = cnx->egl.eglCreateImageKHR( 1410 dp->disp.dpy, 1411 c ? c->context : EGL_NO_CONTEXT, 1412 target, buffer, attrib_list); 1413 } 1414 return result; 1415} 1416 1417EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 1418{ 1419 clearError(); 1420 1421 const egl_display_ptr dp = validate_display(dpy); 1422 if (!dp) return EGL_FALSE; 1423 1424 EGLBoolean result = EGL_FALSE; 1425 egl_connection_t* const cnx = &gEGLImpl; 1426 if (cnx->dso && cnx->egl.eglDestroyImageKHR) { 1427 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img); 1428 } 1429 return result; 1430} 1431 1432// ---------------------------------------------------------------------------- 1433// EGL_EGLEXT_VERSION 5 1434// ---------------------------------------------------------------------------- 1435 1436 1437EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) 1438{ 1439 clearError(); 1440 1441 const egl_display_ptr dp = validate_display(dpy); 1442 if (!dp) return EGL_NO_SYNC_KHR; 1443 1444 EGLSyncKHR result = EGL_NO_SYNC_KHR; 1445 egl_connection_t* const cnx = &gEGLImpl; 1446 if (cnx->dso && cnx->egl.eglCreateSyncKHR) { 1447 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list); 1448 } 1449 return result; 1450} 1451 1452EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) 1453{ 1454 clearError(); 1455 1456 const egl_display_ptr dp = validate_display(dpy); 1457 if (!dp) return EGL_FALSE; 1458 1459 EGLBoolean result = EGL_FALSE; 1460 egl_connection_t* const cnx = &gEGLImpl; 1461 if (cnx->dso && cnx->egl.eglDestroySyncKHR) { 1462 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync); 1463 } 1464 return result; 1465} 1466 1467EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) { 1468 clearError(); 1469 1470 const egl_display_ptr dp = validate_display(dpy); 1471 if (!dp) return EGL_FALSE; 1472 1473 EGLBoolean result = EGL_FALSE; 1474 egl_connection_t* const cnx = &gEGLImpl; 1475 if (cnx->dso && cnx->egl.eglSignalSyncKHR) { 1476 result = cnx->egl.eglSignalSyncKHR( 1477 dp->disp.dpy, sync, mode); 1478 } 1479 return result; 1480} 1481 1482EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, 1483 EGLint flags, EGLTimeKHR timeout) 1484{ 1485 clearError(); 1486 1487 const egl_display_ptr dp = validate_display(dpy); 1488 if (!dp) return EGL_FALSE; 1489 1490 EGLBoolean result = EGL_FALSE; 1491 egl_connection_t* const cnx = &gEGLImpl; 1492 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) { 1493 result = cnx->egl.eglClientWaitSyncKHR( 1494 dp->disp.dpy, sync, flags, timeout); 1495 } 1496 return result; 1497} 1498 1499EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, 1500 EGLint attribute, EGLint *value) 1501{ 1502 clearError(); 1503 1504 const egl_display_ptr dp = validate_display(dpy); 1505 if (!dp) return EGL_FALSE; 1506 1507 EGLBoolean result = EGL_FALSE; 1508 egl_connection_t* const cnx = &gEGLImpl; 1509 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) { 1510 result = cnx->egl.eglGetSyncAttribKHR( 1511 dp->disp.dpy, sync, attribute, value); 1512 } 1513 return result; 1514} 1515 1516EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list) 1517{ 1518 clearError(); 1519 1520 const egl_display_ptr dp = validate_display(dpy); 1521 if (!dp) return EGL_NO_STREAM_KHR; 1522 1523 EGLStreamKHR result = EGL_NO_STREAM_KHR; 1524 egl_connection_t* const cnx = &gEGLImpl; 1525 if (cnx->dso && cnx->egl.eglCreateStreamKHR) { 1526 result = cnx->egl.eglCreateStreamKHR( 1527 dp->disp.dpy, attrib_list); 1528 } 1529 return result; 1530} 1531 1532EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream) 1533{ 1534 clearError(); 1535 1536 const egl_display_ptr dp = validate_display(dpy); 1537 if (!dp) return EGL_FALSE; 1538 1539 EGLBoolean result = EGL_FALSE; 1540 egl_connection_t* const cnx = &gEGLImpl; 1541 if (cnx->dso && cnx->egl.eglDestroyStreamKHR) { 1542 result = cnx->egl.eglDestroyStreamKHR( 1543 dp->disp.dpy, stream); 1544 } 1545 return result; 1546} 1547 1548EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream, 1549 EGLenum attribute, EGLint value) 1550{ 1551 clearError(); 1552 1553 const egl_display_ptr dp = validate_display(dpy); 1554 if (!dp) return EGL_FALSE; 1555 1556 EGLBoolean result = EGL_FALSE; 1557 egl_connection_t* const cnx = &gEGLImpl; 1558 if (cnx->dso && cnx->egl.eglStreamAttribKHR) { 1559 result = cnx->egl.eglStreamAttribKHR( 1560 dp->disp.dpy, stream, attribute, value); 1561 } 1562 return result; 1563} 1564 1565EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream, 1566 EGLenum attribute, EGLint *value) 1567{ 1568 clearError(); 1569 1570 const egl_display_ptr dp = validate_display(dpy); 1571 if (!dp) return EGL_FALSE; 1572 1573 EGLBoolean result = EGL_FALSE; 1574 egl_connection_t* const cnx = &gEGLImpl; 1575 if (cnx->dso && cnx->egl.eglQueryStreamKHR) { 1576 result = cnx->egl.eglQueryStreamKHR( 1577 dp->disp.dpy, stream, attribute, value); 1578 } 1579 return result; 1580} 1581 1582EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream, 1583 EGLenum attribute, EGLuint64KHR *value) 1584{ 1585 clearError(); 1586 1587 const egl_display_ptr dp = validate_display(dpy); 1588 if (!dp) return EGL_FALSE; 1589 1590 EGLBoolean result = EGL_FALSE; 1591 egl_connection_t* const cnx = &gEGLImpl; 1592 if (cnx->dso && cnx->egl.eglQueryStreamu64KHR) { 1593 result = cnx->egl.eglQueryStreamu64KHR( 1594 dp->disp.dpy, stream, attribute, value); 1595 } 1596 return result; 1597} 1598 1599EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream, 1600 EGLenum attribute, EGLTimeKHR *value) 1601{ 1602 clearError(); 1603 1604 const egl_display_ptr dp = validate_display(dpy); 1605 if (!dp) return EGL_FALSE; 1606 1607 EGLBoolean result = EGL_FALSE; 1608 egl_connection_t* const cnx = &gEGLImpl; 1609 if (cnx->dso && cnx->egl.eglQueryStreamTimeKHR) { 1610 result = cnx->egl.eglQueryStreamTimeKHR( 1611 dp->disp.dpy, stream, attribute, value); 1612 } 1613 return result; 1614} 1615 1616EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config, 1617 EGLStreamKHR stream, const EGLint *attrib_list) 1618{ 1619 clearError(); 1620 1621 egl_display_ptr dp = validate_display(dpy); 1622 if (!dp) return EGL_NO_SURFACE; 1623 1624 egl_connection_t* const cnx = &gEGLImpl; 1625 if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) { 1626 EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR( 1627 dp->disp.dpy, config, stream, attrib_list); 1628 if (surface != EGL_NO_SURFACE) { 1629 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, 1630 surface, cnx); 1631 return s; 1632 } 1633 } 1634 return EGL_NO_SURFACE; 1635} 1636 1637EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy, 1638 EGLStreamKHR stream) 1639{ 1640 clearError(); 1641 1642 const egl_display_ptr dp = validate_display(dpy); 1643 if (!dp) return EGL_FALSE; 1644 1645 EGLBoolean result = EGL_FALSE; 1646 egl_connection_t* const cnx = &gEGLImpl; 1647 if (cnx->dso && cnx->egl.eglStreamConsumerGLTextureExternalKHR) { 1648 result = cnx->egl.eglStreamConsumerGLTextureExternalKHR( 1649 dp->disp.dpy, stream); 1650 } 1651 return result; 1652} 1653 1654EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy, 1655 EGLStreamKHR stream) 1656{ 1657 clearError(); 1658 1659 const egl_display_ptr dp = validate_display(dpy); 1660 if (!dp) return EGL_FALSE; 1661 1662 EGLBoolean result = EGL_FALSE; 1663 egl_connection_t* const cnx = &gEGLImpl; 1664 if (cnx->dso && cnx->egl.eglStreamConsumerAcquireKHR) { 1665 result = cnx->egl.eglStreamConsumerAcquireKHR( 1666 dp->disp.dpy, stream); 1667 } 1668 return result; 1669} 1670 1671EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy, 1672 EGLStreamKHR stream) 1673{ 1674 clearError(); 1675 1676 const egl_display_ptr dp = validate_display(dpy); 1677 if (!dp) return EGL_FALSE; 1678 1679 EGLBoolean result = EGL_FALSE; 1680 egl_connection_t* const cnx = &gEGLImpl; 1681 if (cnx->dso && cnx->egl.eglStreamConsumerReleaseKHR) { 1682 result = cnx->egl.eglStreamConsumerReleaseKHR( 1683 dp->disp.dpy, stream); 1684 } 1685 return result; 1686} 1687 1688EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR( 1689 EGLDisplay dpy, EGLStreamKHR stream) 1690{ 1691 clearError(); 1692 1693 const egl_display_ptr dp = validate_display(dpy); 1694 if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR; 1695 1696 EGLNativeFileDescriptorKHR result = EGL_NO_FILE_DESCRIPTOR_KHR; 1697 egl_connection_t* const cnx = &gEGLImpl; 1698 if (cnx->dso && cnx->egl.eglGetStreamFileDescriptorKHR) { 1699 result = cnx->egl.eglGetStreamFileDescriptorKHR( 1700 dp->disp.dpy, stream); 1701 } 1702 return result; 1703} 1704 1705EGLStreamKHR eglCreateStreamFromFileDescriptorKHR( 1706 EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor) 1707{ 1708 clearError(); 1709 1710 const egl_display_ptr dp = validate_display(dpy); 1711 if (!dp) return EGL_NO_STREAM_KHR; 1712 1713 EGLStreamKHR result = EGL_NO_STREAM_KHR; 1714 egl_connection_t* const cnx = &gEGLImpl; 1715 if (cnx->dso && cnx->egl.eglCreateStreamFromFileDescriptorKHR) { 1716 result = cnx->egl.eglCreateStreamFromFileDescriptorKHR( 1717 dp->disp.dpy, file_descriptor); 1718 } 1719 return result; 1720} 1721 1722// ---------------------------------------------------------------------------- 1723// EGL_EGLEXT_VERSION 15 1724// ---------------------------------------------------------------------------- 1725 1726EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) { 1727 clearError(); 1728 const egl_display_ptr dp = validate_display(dpy); 1729 if (!dp) return EGL_FALSE; 1730 EGLint result = EGL_FALSE; 1731 egl_connection_t* const cnx = &gEGLImpl; 1732 if (cnx->dso && cnx->egl.eglWaitSyncKHR) { 1733 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags); 1734 } 1735 return result; 1736} 1737 1738// ---------------------------------------------------------------------------- 1739// ANDROID extensions 1740// ---------------------------------------------------------------------------- 1741 1742EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync) 1743{ 1744 clearError(); 1745 1746 const egl_display_ptr dp = validate_display(dpy); 1747 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID; 1748 1749 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID; 1750 egl_connection_t* const cnx = &gEGLImpl; 1751 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) { 1752 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync); 1753 } 1754 return result; 1755} 1756 1757EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface, 1758 EGLnsecsANDROID time) 1759{ 1760 clearError(); 1761 1762 const egl_display_ptr dp = validate_display(dpy); 1763 if (!dp) { 1764 return EGL_FALSE; 1765 } 1766 1767 SurfaceRef _s(dp.get(), surface); 1768 if (!_s.get()) { 1769 setError(EGL_BAD_SURFACE, EGL_FALSE); 1770 return EGL_FALSE; 1771 } 1772 1773 egl_surface_t const * const s = get_surface(surface); 1774 native_window_set_buffers_timestamp(s->win.get(), time); 1775 1776 return EGL_TRUE; 1777} 1778 1779EGLClientBuffer eglCreateNativeClientBufferANDROID(const EGLint *attrib_list) 1780{ 1781 clearError(); 1782 1783 int usage = 0; 1784 uint32_t width = 0; 1785 uint32_t height = 0; 1786 uint32_t format = 0; 1787 uint32_t red_size = 0; 1788 uint32_t green_size = 0; 1789 uint32_t blue_size = 0; 1790 uint32_t alpha_size = 0; 1791 1792#define GET_POSITIVE_VALUE(case_name, target) \ 1793 case case_name: \ 1794 if (value > 0) { \ 1795 target = value; \ 1796 } else { \ 1797 return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0); \ 1798 } \ 1799 break 1800 1801 if (attrib_list) { 1802 while (*attrib_list != EGL_NONE) { 1803 GLint attr = *attrib_list++; 1804 GLint value = *attrib_list++; 1805 switch (attr) { 1806 GET_POSITIVE_VALUE(EGL_WIDTH, width); 1807 GET_POSITIVE_VALUE(EGL_HEIGHT, height); 1808 GET_POSITIVE_VALUE(EGL_RED_SIZE, red_size); 1809 GET_POSITIVE_VALUE(EGL_GREEN_SIZE, green_size); 1810 GET_POSITIVE_VALUE(EGL_BLUE_SIZE, blue_size); 1811 GET_POSITIVE_VALUE(EGL_ALPHA_SIZE, alpha_size); 1812 case EGL_NATIVE_BUFFER_USAGE_ANDROID: 1813 if (value & EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID) { 1814 usage |= GRALLOC_USAGE_PROTECTED; 1815 // If we are using QCOM then add in extra bits. This 1816 // should be removed before launch. These correspond to: 1817 // USAGE_PRIVATE_MM_HEAP | USAGE_PRIVATE_UNCACHED 1818 usage |= 0x82000000; 1819 } 1820 if (value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_ANDROID) { 1821 usage |= GRALLOC_USAGE_HW_RENDER; 1822 } 1823 if (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_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_ANDROID) && 1829 (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_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