eglApi.cpp revision f37864bc99576b851015f115613cc851a866dbf2
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 ; 121 122// extensions not exposed to applications but used by the ANDROID system 123// "EGL_ANDROID_blob_cache " // strongly recommended 124// "EGL_IMG_hibernate_process " // optional 125// "EGL_ANDROID_native_fence_sync " // strongly recommended 126// "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1 127// "EGL_ANDROID_image_crop " // optional 128 129/* 130 * EGL Extensions entry-points exposed to 3rd party applications 131 * (keep in sync with gExtensionString above) 132 * 133 */ 134static const extention_map_t sExtensionMap[] = { 135 // EGL_KHR_lock_surface 136 { "eglLockSurfaceKHR", 137 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR }, 138 { "eglUnlockSurfaceKHR", 139 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR }, 140 141 // EGL_KHR_image, EGL_KHR_image_base 142 { "eglCreateImageKHR", 143 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, 144 { "eglDestroyImageKHR", 145 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, 146 147 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync 148 { "eglCreateSyncKHR", 149 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR }, 150 { "eglDestroySyncKHR", 151 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR }, 152 { "eglClientWaitSyncKHR", 153 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR }, 154 { "eglSignalSyncKHR", 155 (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR }, 156 { "eglGetSyncAttribKHR", 157 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR }, 158 159 // EGL_NV_system_time 160 { "eglGetSystemTimeFrequencyNV", 161 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV }, 162 { "eglGetSystemTimeNV", 163 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV }, 164 165 // EGL_KHR_wait_sync 166 { "eglWaitSyncKHR", 167 (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR }, 168 169 // EGL_ANDROID_presentation_time 170 { "eglPresentationTimeANDROID", 171 (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID }, 172 173 // EGL_KHR_swap_buffers_with_damage 174 { "eglSwapBuffersWithDamageKHR", 175 (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR }, 176 177 // EGL_ANDROID_native_client_buffer 178 { "eglCreateNativeClientBufferANDROID", 179 (__eglMustCastToProperFunctionPointerType)&eglCreateNativeClientBufferANDROID }, 180 181 // EGL_KHR_partial_update 182 { "eglSetDamageRegionKHR", 183 (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR }, 184 185 { "eglCreateStreamKHR", 186 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamKHR }, 187 { "eglDestroyStreamKHR", 188 (__eglMustCastToProperFunctionPointerType)&eglDestroyStreamKHR }, 189 { "eglStreamAttribKHR", 190 (__eglMustCastToProperFunctionPointerType)&eglStreamAttribKHR }, 191 { "eglQueryStreamKHR", 192 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamKHR }, 193 { "eglQueryStreamu64KHR", 194 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamu64KHR }, 195 { "eglQueryStreamTimeKHR", 196 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamTimeKHR }, 197 { "eglCreateStreamProducerSurfaceKHR", 198 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamProducerSurfaceKHR }, 199 { "eglStreamConsumerGLTextureExternalKHR", 200 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerGLTextureExternalKHR }, 201 { "eglStreamConsumerAcquireKHR", 202 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerAcquireKHR }, 203 { "eglStreamConsumerReleaseKHR", 204 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerReleaseKHR }, 205 { "eglGetStreamFileDescriptorKHR", 206 (__eglMustCastToProperFunctionPointerType)&eglGetStreamFileDescriptorKHR }, 207 { "eglCreateStreamFromFileDescriptorKHR", 208 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR }, 209}; 210 211/* 212 * These extensions entry-points should not be exposed to applications. 213 * They're used internally by the Android EGL layer. 214 */ 215#define FILTER_EXTENSIONS(procname) \ 216 (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \ 217 !strcmp((procname), "eglHibernateProcessIMG") || \ 218 !strcmp((procname), "eglAwakenProcessIMG") || \ 219 !strcmp((procname), "eglDupNativeFenceFDANDROID")) 220 221 222 223// accesses protected by sExtensionMapMutex 224static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap; 225static int sGLExtentionSlot = 0; 226static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER; 227 228static void(*findProcAddress(const char* name, 229 const extention_map_t* map, size_t n))() { 230 for (uint32_t i=0 ; i<n ; i++) { 231 if (!strcmp(name, map[i].name)) { 232 return map[i].address; 233 } 234 } 235 return NULL; 236} 237 238// ---------------------------------------------------------------------------- 239 240extern void setGLHooksThreadSpecific(gl_hooks_t const *value); 241extern EGLBoolean egl_init_drivers(); 242extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS]; 243extern gl_hooks_t gHooksTrace; 244 245} // namespace android; 246 247 248// ---------------------------------------------------------------------------- 249 250static inline void clearError() { egl_tls_t::clearError(); } 251static inline EGLContext getContext() { return egl_tls_t::getContext(); } 252 253// ---------------------------------------------------------------------------- 254 255EGLDisplay eglGetDisplay(EGLNativeDisplayType display) 256{ 257 clearError(); 258 259 uintptr_t index = reinterpret_cast<uintptr_t>(display); 260 if (index >= NUM_DISPLAYS) { 261 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 262 } 263 264 if (egl_init_drivers() == EGL_FALSE) { 265 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 266 } 267 268 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display); 269 return dpy; 270} 271 272// ---------------------------------------------------------------------------- 273// Initialization 274// ---------------------------------------------------------------------------- 275 276EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) 277{ 278 clearError(); 279 280 egl_display_ptr dp = get_display(dpy); 281 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 282 283 EGLBoolean res = dp->initialize(major, minor); 284 285 return res; 286} 287 288EGLBoolean eglTerminate(EGLDisplay dpy) 289{ 290 // NOTE: don't unload the drivers b/c some APIs can be called 291 // after eglTerminate() has been called. eglTerminate() only 292 // terminates an EGLDisplay, not a EGL itself. 293 294 clearError(); 295 296 egl_display_ptr dp = get_display(dpy); 297 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 298 299 EGLBoolean res = dp->terminate(); 300 301 return res; 302} 303 304// ---------------------------------------------------------------------------- 305// configuration 306// ---------------------------------------------------------------------------- 307 308EGLBoolean eglGetConfigs( EGLDisplay dpy, 309 EGLConfig *configs, 310 EGLint config_size, EGLint *num_config) 311{ 312 clearError(); 313 314 const egl_display_ptr dp = validate_display(dpy); 315 if (!dp) return EGL_FALSE; 316 317 if (num_config==0) { 318 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 319 } 320 321 EGLBoolean res = EGL_FALSE; 322 *num_config = 0; 323 324 egl_connection_t* const cnx = &gEGLImpl; 325 if (cnx->dso) { 326 res = cnx->egl.eglGetConfigs( 327 dp->disp.dpy, configs, config_size, num_config); 328 } 329 330 return res; 331} 332 333EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, 334 EGLConfig *configs, EGLint config_size, 335 EGLint *num_config) 336{ 337 clearError(); 338 339 const egl_display_ptr dp = validate_display(dpy); 340 if (!dp) return EGL_FALSE; 341 342 if (num_config==0) { 343 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 344 } 345 346 EGLBoolean res = EGL_FALSE; 347 *num_config = 0; 348 349 egl_connection_t* const cnx = &gEGLImpl; 350 if (cnx->dso) { 351 if (attrib_list) { 352 char value[PROPERTY_VALUE_MAX]; 353 property_get("debug.egl.force_msaa", value, "false"); 354 355 if (!strcmp(value, "true")) { 356 size_t attribCount = 0; 357 EGLint attrib = attrib_list[0]; 358 359 // Only enable MSAA if the context is OpenGL ES 2.0 and 360 // if no caveat is requested 361 const EGLint *attribRendererable = NULL; 362 const EGLint *attribCaveat = NULL; 363 364 // Count the number of attributes and look for 365 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT 366 while (attrib != EGL_NONE) { 367 attrib = attrib_list[attribCount]; 368 switch (attrib) { 369 case EGL_RENDERABLE_TYPE: 370 attribRendererable = &attrib_list[attribCount]; 371 break; 372 case EGL_CONFIG_CAVEAT: 373 attribCaveat = &attrib_list[attribCount]; 374 break; 375 } 376 attribCount++; 377 } 378 379 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT && 380 (!attribCaveat || attribCaveat[1] != EGL_NONE)) { 381 382 // Insert 2 extra attributes to force-enable MSAA 4x 383 EGLint aaAttribs[attribCount + 4]; 384 aaAttribs[0] = EGL_SAMPLE_BUFFERS; 385 aaAttribs[1] = 1; 386 aaAttribs[2] = EGL_SAMPLES; 387 aaAttribs[3] = 4; 388 389 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint)); 390 391 EGLint numConfigAA; 392 EGLBoolean resAA = cnx->egl.eglChooseConfig( 393 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA); 394 395 if (resAA == EGL_TRUE && numConfigAA > 0) { 396 ALOGD("Enabling MSAA 4x"); 397 *num_config = numConfigAA; 398 return resAA; 399 } 400 } 401 } 402 } 403 404 res = cnx->egl.eglChooseConfig( 405 dp->disp.dpy, attrib_list, configs, config_size, num_config); 406 } 407 return res; 408} 409 410EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, 411 EGLint attribute, EGLint *value) 412{ 413 clearError(); 414 415 egl_connection_t* cnx = NULL; 416 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 417 if (!dp) return EGL_FALSE; 418 419 return cnx->egl.eglGetConfigAttrib( 420 dp->disp.dpy, config, attribute, value); 421} 422 423// ---------------------------------------------------------------------------- 424// surfaces 425// ---------------------------------------------------------------------------- 426 427// The EGL_KHR_gl_colorspace spec hasn't been ratified yet, so these haven't 428// been added to the Khronos egl.h. 429#define EGL_GL_COLORSPACE_KHR EGL_VG_COLORSPACE 430#define EGL_GL_COLORSPACE_SRGB_KHR EGL_VG_COLORSPACE_sRGB 431#define EGL_GL_COLORSPACE_LINEAR_KHR EGL_VG_COLORSPACE_LINEAR 432 433// Turn linear formats into corresponding sRGB formats when colorspace is 434// EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear 435// formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where 436// the modification isn't possible, the original dataSpace is returned. 437static android_dataspace modifyBufferDataspace( android_dataspace dataSpace, 438 EGLint colorspace) { 439 if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) { 440 return HAL_DATASPACE_SRGB_LINEAR; 441 } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) { 442 return HAL_DATASPACE_SRGB; 443 } 444 return dataSpace; 445} 446 447EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, 448 NativeWindowType window, 449 const EGLint *attrib_list) 450{ 451 clearError(); 452 453 egl_connection_t* cnx = NULL; 454 egl_display_ptr dp = validate_display_connection(dpy, cnx); 455 if (dp) { 456 EGLDisplay iDpy = dp->disp.dpy; 457 458 int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL); 459 if (result != OK) { 460 ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) " 461 "failed (%#x) (already connected to another API?)", 462 window, result); 463 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); 464 } 465 466 // Set the native window's buffers format to match what this config requests. 467 // Whether to use sRGB gamma is not part of the EGLconfig, but is part 468 // of our native format. So if sRGB gamma is requested, we have to 469 // modify the EGLconfig's format before setting the native window's 470 // format. 471 472 // by default, just pick RGBA_8888 473 EGLint format = HAL_PIXEL_FORMAT_RGBA_8888; 474 android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN; 475 476 EGLint a = 0; 477 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a); 478 if (a > 0) { 479 // alpha-channel requested, there's really only one suitable format 480 format = HAL_PIXEL_FORMAT_RGBA_8888; 481 } else { 482 EGLint r, g, b; 483 r = g = b = 0; 484 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE, &r); 485 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g); 486 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE, &b); 487 EGLint colorDepth = r + g + b; 488 if (colorDepth <= 16) { 489 format = HAL_PIXEL_FORMAT_RGB_565; 490 } else { 491 format = HAL_PIXEL_FORMAT_RGBX_8888; 492 } 493 } 494 495 // now select a corresponding sRGB format if needed 496 if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) { 497 for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) { 498 if (*attr == EGL_GL_COLORSPACE_KHR) { 499 if (ENABLE_EGL_KHR_GL_COLORSPACE) { 500 dataSpace = modifyBufferDataspace(dataSpace, *(attr+1)); 501 } else { 502 // Normally we'd pass through unhandled attributes to 503 // the driver. But in case the driver implements this 504 // extension but we're disabling it, we want to prevent 505 // it getting through -- support will be broken without 506 // our help. 507 ALOGE("sRGB window surfaces not supported"); 508 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); 509 } 510 } 511 } 512 } 513 514 if (format != 0) { 515 int err = native_window_set_buffers_format(window, format); 516 if (err != 0) { 517 ALOGE("error setting native window pixel format: %s (%d)", 518 strerror(-err), err); 519 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 520 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 521 } 522 } 523 524 if (dataSpace != 0) { 525 int err = native_window_set_buffers_data_space(window, dataSpace); 526 if (err != 0) { 527 ALOGE("error setting native window pixel dataSpace: %s (%d)", 528 strerror(-err), err); 529 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 530 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 531 } 532 } 533 534 // the EGL spec requires that a new EGLSurface default to swap interval 535 // 1, so explicitly set that on the window here. 536 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window); 537 anw->setSwapInterval(anw, 1); 538 539 EGLSurface surface = cnx->egl.eglCreateWindowSurface( 540 iDpy, config, window, attrib_list); 541 if (surface != EGL_NO_SURFACE) { 542 egl_surface_t* s = new egl_surface_t(dp.get(), config, window, 543 surface, cnx); 544 return s; 545 } 546 547 // EGLSurface creation failed 548 native_window_set_buffers_format(window, 0); 549 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 550 } 551 return EGL_NO_SURFACE; 552} 553 554EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, 555 NativePixmapType pixmap, 556 const EGLint *attrib_list) 557{ 558 clearError(); 559 560 egl_connection_t* cnx = NULL; 561 egl_display_ptr dp = validate_display_connection(dpy, cnx); 562 if (dp) { 563 EGLSurface surface = cnx->egl.eglCreatePixmapSurface( 564 dp->disp.dpy, config, pixmap, attrib_list); 565 if (surface != EGL_NO_SURFACE) { 566 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, 567 surface, cnx); 568 return s; 569 } 570 } 571 return EGL_NO_SURFACE; 572} 573 574EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, 575 const EGLint *attrib_list) 576{ 577 clearError(); 578 579 egl_connection_t* cnx = NULL; 580 egl_display_ptr dp = validate_display_connection(dpy, cnx); 581 if (dp) { 582 EGLSurface surface = cnx->egl.eglCreatePbufferSurface( 583 dp->disp.dpy, config, attrib_list); 584 if (surface != EGL_NO_SURFACE) { 585 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, 586 surface, cnx); 587 return s; 588 } 589 } 590 return EGL_NO_SURFACE; 591} 592 593EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) 594{ 595 clearError(); 596 597 const egl_display_ptr dp = validate_display(dpy); 598 if (!dp) return EGL_FALSE; 599 600 SurfaceRef _s(dp.get(), surface); 601 if (!_s.get()) 602 return setError(EGL_BAD_SURFACE, EGL_FALSE); 603 604 egl_surface_t * const s = get_surface(surface); 605 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface); 606 if (result == EGL_TRUE) { 607 _s.terminate(); 608 dp->removeSurface(surface); 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_POSITIVE_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_POSITIVE_VALUE(EGL_WIDTH, width); 1812 GET_POSITIVE_VALUE(EGL_HEIGHT, height); 1813 GET_POSITIVE_VALUE(EGL_RED_SIZE, red_size); 1814 GET_POSITIVE_VALUE(EGL_GREEN_SIZE, green_size); 1815 GET_POSITIVE_VALUE(EGL_BLUE_SIZE, blue_size); 1816 GET_POSITIVE_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_POSITIVE_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