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