eglApi.cpp revision da22e6bf36a2a83efef83bd723714ea6af30f540
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 <ctype.h> 20#include <stdlib.h> 21#include <string.h> 22 23#include <hardware/gralloc.h> 24#include <system/window.h> 25 26#include <EGL/egl.h> 27#include <EGL/eglext.h> 28 29#include <cutils/log.h> 30#include <cutils/atomic.h> 31#include <cutils/compiler.h> 32#include <cutils/properties.h> 33#include <cutils/memory.h> 34 35#include <utils/KeyedVector.h> 36#include <utils/SortedVector.h> 37#include <utils/String8.h> 38#include <utils/Trace.h> 39 40#include "../egl_impl.h" 41#include "../glestrace.h" 42#include "../hooks.h" 43 44#include "egl_display.h" 45#include "egl_object.h" 46#include "egl_tls.h" 47#include "egldefs.h" 48 49using namespace android; 50 51// ---------------------------------------------------------------------------- 52 53namespace android { 54 55struct extention_map_t { 56 const char* name; 57 __eglMustCastToProperFunctionPointerType address; 58}; 59 60/* 61 * This is the list of EGL extensions exposed to applications, 62 * some of them are mandatory because used by the ANDROID system. 63 * 64 * Mandatory extensions are required per the CDD and not explicitly 65 * checked during EGL initialization. the system *assumes* these extensions 66 * are present. the system may not function properly if some mandatory 67 * extensions are missing. 68 * 69 * NOTE: gExtensionString MUST have a single space as the last character. 70 */ 71extern char const * const gExtensionString = 72 "EGL_KHR_image " // mandatory 73 "EGL_KHR_image_base " // mandatory 74 "EGL_KHR_image_pixmap " 75 "EGL_KHR_lock_surface " 76 "EGL_KHR_gl_texture_2D_image " 77 "EGL_KHR_gl_texture_cubemap_image " 78 "EGL_KHR_gl_renderbuffer_image " 79 "EGL_KHR_reusable_sync " 80 "EGL_KHR_fence_sync " 81 "EGL_KHR_create_context " 82 "EGL_EXT_create_context_robustness " 83 "EGL_NV_system_time " 84 "EGL_ANDROID_image_native_buffer " // mandatory 85 "EGL_KHR_wait_sync " // strongly recommended 86 "EGL_ANDROID_presentation_time " 87 ; 88 89// extensions not exposed to applications but used by the ANDROID system 90// "EGL_ANDROID_blob_cache " // strongly recommended 91// "EGL_IMG_hibernate_process " // optional 92// "EGL_ANDROID_native_fence_sync " // strongly recommended 93// "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1 94// "EGL_ANDROID_recordable " // mandatory 95 96 97/* 98 * EGL Extensions entry-points exposed to 3rd party applications 99 * (keep in sync with gExtensionString above) 100 * 101 */ 102static const extention_map_t sExtensionMap[] = { 103 // EGL_KHR_lock_surface 104 { "eglLockSurfaceKHR", 105 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR }, 106 { "eglUnlockSurfaceKHR", 107 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR }, 108 109 // EGL_KHR_image, EGL_KHR_image_base 110 { "eglCreateImageKHR", 111 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, 112 { "eglDestroyImageKHR", 113 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, 114 115 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync 116 { "eglCreateSyncKHR", 117 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR }, 118 { "eglDestroySyncKHR", 119 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR }, 120 { "eglClientWaitSyncKHR", 121 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR }, 122 { "eglSignalSyncKHR", 123 (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR }, 124 { "eglGetSyncAttribKHR", 125 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR }, 126 127 // EGL_NV_system_time 128 { "eglGetSystemTimeFrequencyNV", 129 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV }, 130 { "eglGetSystemTimeNV", 131 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV }, 132 133 // EGL_KHR_wait_sync 134 { "eglWaitSyncKHR", 135 (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR }, 136 137 // EGL_ANDROID_presentation_time 138 { "eglPresentationTimeANDROID", 139 (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID }, 140}; 141 142/* 143 * These extensions entry-points should not be exposed to applications. 144 * They're used internally by the Android EGL layer. 145 */ 146#define FILTER_EXTENSIONS(procname) \ 147 (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \ 148 !strcmp((procname), "eglHibernateProcessIMG") || \ 149 !strcmp((procname), "eglAwakenProcessIMG") || \ 150 !strcmp((procname), "eglDupNativeFenceFDANDROID")) 151 152 153 154// accesses protected by sExtensionMapMutex 155static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap; 156static int sGLExtentionSlot = 0; 157static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER; 158 159static void(*findProcAddress(const char* name, 160 const extention_map_t* map, size_t n))() { 161 for (uint32_t i=0 ; i<n ; i++) { 162 if (!strcmp(name, map[i].name)) { 163 return map[i].address; 164 } 165 } 166 return NULL; 167} 168 169// ---------------------------------------------------------------------------- 170 171extern void setGLHooksThreadSpecific(gl_hooks_t const *value); 172extern EGLBoolean egl_init_drivers(); 173extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS]; 174extern int getEGLDebugLevel(); 175extern void setEGLDebugLevel(int level); 176extern gl_hooks_t gHooksTrace; 177 178} // namespace android; 179 180 181// ---------------------------------------------------------------------------- 182 183static inline void clearError() { egl_tls_t::clearError(); } 184static inline EGLContext getContext() { return egl_tls_t::getContext(); } 185 186// ---------------------------------------------------------------------------- 187 188EGLDisplay eglGetDisplay(EGLNativeDisplayType display) 189{ 190 clearError(); 191 192 uint32_t index = uint32_t(display); 193 if (index >= NUM_DISPLAYS) { 194 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 195 } 196 197 if (egl_init_drivers() == EGL_FALSE) { 198 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 199 } 200 201 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display); 202 return dpy; 203} 204 205// ---------------------------------------------------------------------------- 206// Initialization 207// ---------------------------------------------------------------------------- 208 209EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) 210{ 211 clearError(); 212 213 egl_display_ptr dp = get_display(dpy); 214 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 215 216 EGLBoolean res = dp->initialize(major, minor); 217 218 return res; 219} 220 221EGLBoolean eglTerminate(EGLDisplay dpy) 222{ 223 // NOTE: don't unload the drivers b/c some APIs can be called 224 // after eglTerminate() has been called. eglTerminate() only 225 // terminates an EGLDisplay, not a EGL itself. 226 227 clearError(); 228 229 egl_display_ptr dp = get_display(dpy); 230 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 231 232 EGLBoolean res = dp->terminate(); 233 234 return res; 235} 236 237// ---------------------------------------------------------------------------- 238// configuration 239// ---------------------------------------------------------------------------- 240 241EGLBoolean eglGetConfigs( EGLDisplay dpy, 242 EGLConfig *configs, 243 EGLint config_size, EGLint *num_config) 244{ 245 clearError(); 246 247 const egl_display_ptr dp = validate_display(dpy); 248 if (!dp) return EGL_FALSE; 249 250 if (num_config==0) { 251 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 252 } 253 254 EGLBoolean res = EGL_FALSE; 255 *num_config = 0; 256 257 egl_connection_t* const cnx = &gEGLImpl; 258 if (cnx->dso) { 259 res = cnx->egl.eglGetConfigs( 260 dp->disp.dpy, configs, config_size, num_config); 261 } 262 263 return res; 264} 265 266EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, 267 EGLConfig *configs, EGLint config_size, 268 EGLint *num_config) 269{ 270 clearError(); 271 272 const egl_display_ptr dp = validate_display(dpy); 273 if (!dp) return EGL_FALSE; 274 275 if (num_config==0) { 276 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 277 } 278 279 EGLBoolean res = EGL_FALSE; 280 *num_config = 0; 281 282 egl_connection_t* const cnx = &gEGLImpl; 283 if (cnx->dso) { 284 if (attrib_list) { 285 char value[PROPERTY_VALUE_MAX]; 286 property_get("debug.egl.force_msaa", value, "false"); 287 288 if (!strcmp(value, "true")) { 289 size_t attribCount = 0; 290 EGLint attrib = attrib_list[0]; 291 292 // Only enable MSAA if the context is OpenGL ES 2.0 and 293 // if no caveat is requested 294 const EGLint *attribRendererable = NULL; 295 const EGLint *attribCaveat = NULL; 296 297 // Count the number of attributes and look for 298 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT 299 while (attrib != EGL_NONE) { 300 attrib = attrib_list[attribCount]; 301 switch (attrib) { 302 case EGL_RENDERABLE_TYPE: 303 attribRendererable = &attrib_list[attribCount]; 304 break; 305 case EGL_CONFIG_CAVEAT: 306 attribCaveat = &attrib_list[attribCount]; 307 break; 308 } 309 attribCount++; 310 } 311 312 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT && 313 (!attribCaveat || attribCaveat[1] != EGL_NONE)) { 314 315 // Insert 2 extra attributes to force-enable MSAA 4x 316 EGLint aaAttribs[attribCount + 4]; 317 aaAttribs[0] = EGL_SAMPLE_BUFFERS; 318 aaAttribs[1] = 1; 319 aaAttribs[2] = EGL_SAMPLES; 320 aaAttribs[3] = 4; 321 322 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint)); 323 324 EGLint numConfigAA; 325 EGLBoolean resAA = cnx->egl.eglChooseConfig( 326 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA); 327 328 if (resAA == EGL_TRUE && numConfigAA > 0) { 329 ALOGD("Enabling MSAA 4x"); 330 *num_config = numConfigAA; 331 return resAA; 332 } 333 } 334 } 335 } 336 337 res = cnx->egl.eglChooseConfig( 338 dp->disp.dpy, attrib_list, configs, config_size, num_config); 339 } 340 return res; 341} 342 343EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, 344 EGLint attribute, EGLint *value) 345{ 346 clearError(); 347 348 egl_connection_t* cnx = NULL; 349 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 350 if (!dp) return EGL_FALSE; 351 352 return cnx->egl.eglGetConfigAttrib( 353 dp->disp.dpy, config, attribute, value); 354} 355 356// ---------------------------------------------------------------------------- 357// surfaces 358// ---------------------------------------------------------------------------- 359 360EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, 361 NativeWindowType window, 362 const EGLint *attrib_list) 363{ 364 clearError(); 365 366 egl_connection_t* cnx = NULL; 367 egl_display_ptr dp = validate_display_connection(dpy, cnx); 368 if (dp) { 369 EGLDisplay iDpy = dp->disp.dpy; 370 EGLint format; 371 372 if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != OK) { 373 ALOGE("EGLNativeWindowType %p already connected to another API", 374 window); 375 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 376 } 377 378 // set the native window's buffers format to match this config 379 if (cnx->egl.eglGetConfigAttrib(iDpy, 380 config, EGL_NATIVE_VISUAL_ID, &format)) { 381 if (format != 0) { 382 int err = native_window_set_buffers_format(window, format); 383 if (err != 0) { 384 ALOGE("error setting native window pixel format: %s (%d)", 385 strerror(-err), err); 386 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 387 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 388 } 389 } 390 } 391 392 // the EGL spec requires that a new EGLSurface default to swap interval 393 // 1, so explicitly set that on the window here. 394 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window); 395 anw->setSwapInterval(anw, 1); 396 397 EGLSurface surface = cnx->egl.eglCreateWindowSurface( 398 iDpy, config, window, attrib_list); 399 if (surface != EGL_NO_SURFACE) { 400 egl_surface_t* s = new egl_surface_t(dp.get(), config, window, 401 surface, cnx); 402 return s; 403 } 404 405 // EGLSurface creation failed 406 native_window_set_buffers_format(window, 0); 407 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 408 } 409 return EGL_NO_SURFACE; 410} 411 412EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, 413 NativePixmapType pixmap, 414 const EGLint *attrib_list) 415{ 416 clearError(); 417 418 egl_connection_t* cnx = NULL; 419 egl_display_ptr dp = validate_display_connection(dpy, cnx); 420 if (dp) { 421 EGLSurface surface = cnx->egl.eglCreatePixmapSurface( 422 dp->disp.dpy, config, pixmap, attrib_list); 423 if (surface != EGL_NO_SURFACE) { 424 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, 425 surface, cnx); 426 return s; 427 } 428 } 429 return EGL_NO_SURFACE; 430} 431 432EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, 433 const EGLint *attrib_list) 434{ 435 clearError(); 436 437 egl_connection_t* cnx = NULL; 438 egl_display_ptr dp = validate_display_connection(dpy, cnx); 439 if (dp) { 440 EGLSurface surface = cnx->egl.eglCreatePbufferSurface( 441 dp->disp.dpy, config, attrib_list); 442 if (surface != EGL_NO_SURFACE) { 443 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, 444 surface, cnx); 445 return s; 446 } 447 } 448 return EGL_NO_SURFACE; 449} 450 451EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) 452{ 453 clearError(); 454 455 const egl_display_ptr dp = validate_display(dpy); 456 if (!dp) return EGL_FALSE; 457 458 SurfaceRef _s(dp.get(), surface); 459 if (!_s.get()) 460 return setError(EGL_BAD_SURFACE, EGL_FALSE); 461 462 egl_surface_t * const s = get_surface(surface); 463 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface); 464 if (result == EGL_TRUE) { 465 _s.terminate(); 466 } 467 return result; 468} 469 470EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface, 471 EGLint attribute, EGLint *value) 472{ 473 clearError(); 474 475 const egl_display_ptr dp = validate_display(dpy); 476 if (!dp) return EGL_FALSE; 477 478 SurfaceRef _s(dp.get(), surface); 479 if (!_s.get()) 480 return setError(EGL_BAD_SURFACE, EGL_FALSE); 481 482 egl_surface_t const * const s = get_surface(surface); 483 return s->cnx->egl.eglQuerySurface( 484 dp->disp.dpy, s->surface, attribute, value); 485} 486 487void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) { 488 ATRACE_CALL(); 489 clearError(); 490 491 const egl_display_ptr dp = validate_display(dpy); 492 if (!dp) { 493 return; 494 } 495 496 SurfaceRef _s(dp.get(), surface); 497 if (!_s.get()) { 498 setError(EGL_BAD_SURFACE, EGL_FALSE); 499 return; 500 } 501 502 int64_t timestamp = systemTime(SYSTEM_TIME_MONOTONIC); 503 504 egl_surface_t const * const s = get_surface(surface); 505 native_window_set_buffers_timestamp(s->win.get(), timestamp); 506} 507 508// ---------------------------------------------------------------------------- 509// Contexts 510// ---------------------------------------------------------------------------- 511 512EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, 513 EGLContext share_list, const EGLint *attrib_list) 514{ 515 clearError(); 516 517 egl_connection_t* cnx = NULL; 518 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 519 if (dp) { 520 if (share_list != EGL_NO_CONTEXT) { 521 if (!ContextRef(dp.get(), share_list).get()) { 522 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT); 523 } 524 egl_context_t* const c = get_context(share_list); 525 share_list = c->context; 526 } 527 EGLContext context = cnx->egl.eglCreateContext( 528 dp->disp.dpy, config, share_list, attrib_list); 529 if (context != EGL_NO_CONTEXT) { 530 // figure out if it's a GLESv1 or GLESv2 531 int version = 0; 532 if (attrib_list) { 533 while (*attrib_list != EGL_NONE) { 534 GLint attr = *attrib_list++; 535 GLint value = *attrib_list++; 536 if (attr == EGL_CONTEXT_CLIENT_VERSION) { 537 if (value == 1) { 538 version = egl_connection_t::GLESv1_INDEX; 539 } else if (value == 2 || value == 3) { 540 version = egl_connection_t::GLESv2_INDEX; 541 } 542 } 543 }; 544 } 545 egl_context_t* c = new egl_context_t(dpy, context, config, cnx, 546 version); 547#if EGL_TRACE 548 if (getEGLDebugLevel() > 0) 549 GLTrace_eglCreateContext(version, c); 550#endif 551 return c; 552 } else { 553 EGLint error = eglGetError(); 554 ALOGE_IF(error == EGL_SUCCESS, 555 "eglCreateContext(%p, %p, %p, %p) returned EGL_NO_CONTEXT " 556 "but no EGL error!", 557 dpy, config, share_list, attrib_list); 558 } 559 } 560 return EGL_NO_CONTEXT; 561} 562 563EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) 564{ 565 clearError(); 566 567 const egl_display_ptr dp = validate_display(dpy); 568 if (!dp) 569 return EGL_FALSE; 570 571 ContextRef _c(dp.get(), ctx); 572 if (!_c.get()) 573 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 574 575 egl_context_t * const c = get_context(ctx); 576 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context); 577 if (result == EGL_TRUE) { 578 _c.terminate(); 579 } 580 return result; 581} 582 583EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, 584 EGLSurface read, EGLContext ctx) 585{ 586 clearError(); 587 588 egl_display_ptr dp = validate_display(dpy); 589 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 590 591 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not 592 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is 593 // a valid but uninitialized display. 594 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) || 595 (draw != EGL_NO_SURFACE) ) { 596 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE); 597 } 598 599 // get a reference to the object passed in 600 ContextRef _c(dp.get(), ctx); 601 SurfaceRef _d(dp.get(), draw); 602 SurfaceRef _r(dp.get(), read); 603 604 // validate the context (if not EGL_NO_CONTEXT) 605 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) { 606 // EGL_NO_CONTEXT is valid 607 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 608 } 609 610 // these are the underlying implementation's object 611 EGLContext impl_ctx = EGL_NO_CONTEXT; 612 EGLSurface impl_draw = EGL_NO_SURFACE; 613 EGLSurface impl_read = EGL_NO_SURFACE; 614 615 // these are our objects structs passed in 616 egl_context_t * c = NULL; 617 egl_surface_t const * d = NULL; 618 egl_surface_t const * r = NULL; 619 620 // these are the current objects structs 621 egl_context_t * cur_c = get_context(getContext()); 622 623 if (ctx != EGL_NO_CONTEXT) { 624 c = get_context(ctx); 625 impl_ctx = c->context; 626 } else { 627 // no context given, use the implementation of the current context 628 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) { 629 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT); 630 return setError(EGL_BAD_MATCH, EGL_FALSE); 631 } 632 if (cur_c == NULL) { 633 // no current context 634 // not an error, there is just no current context. 635 return EGL_TRUE; 636 } 637 } 638 639 // retrieve the underlying implementation's draw EGLSurface 640 if (draw != EGL_NO_SURFACE) { 641 if (!_d.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 642 d = get_surface(draw); 643 impl_draw = d->surface; 644 } 645 646 // retrieve the underlying implementation's read EGLSurface 647 if (read != EGL_NO_SURFACE) { 648 if (!_r.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 649 r = get_surface(read); 650 impl_read = r->surface; 651 } 652 653 654 EGLBoolean result = dp->makeCurrent(c, cur_c, 655 draw, read, ctx, 656 impl_draw, impl_read, impl_ctx); 657 658 if (result == EGL_TRUE) { 659 if (c) { 660 setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 661 egl_tls_t::setContext(ctx); 662#if EGL_TRACE 663 if (getEGLDebugLevel() > 0) 664 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx); 665#endif 666 _c.acquire(); 667 _r.acquire(); 668 _d.acquire(); 669 } else { 670 setGLHooksThreadSpecific(&gHooksNoContext); 671 egl_tls_t::setContext(EGL_NO_CONTEXT); 672 } 673 } else { 674 // this will ALOGE the error 675 result = setError(c->cnx->egl.eglGetError(), EGL_FALSE); 676 } 677 return result; 678} 679 680 681EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, 682 EGLint attribute, EGLint *value) 683{ 684 clearError(); 685 686 const egl_display_ptr dp = validate_display(dpy); 687 if (!dp) return EGL_FALSE; 688 689 ContextRef _c(dp.get(), ctx); 690 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 691 692 egl_context_t * const c = get_context(ctx); 693 return c->cnx->egl.eglQueryContext( 694 dp->disp.dpy, c->context, attribute, value); 695 696} 697 698EGLContext eglGetCurrentContext(void) 699{ 700 // could be called before eglInitialize(), but we wouldn't have a context 701 // then, and this function would correctly return EGL_NO_CONTEXT. 702 703 clearError(); 704 705 EGLContext ctx = getContext(); 706 return ctx; 707} 708 709EGLSurface eglGetCurrentSurface(EGLint readdraw) 710{ 711 // could be called before eglInitialize(), but we wouldn't have a context 712 // then, and this function would correctly return EGL_NO_SURFACE. 713 714 clearError(); 715 716 EGLContext ctx = getContext(); 717 if (ctx) { 718 egl_context_t const * const c = get_context(ctx); 719 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 720 switch (readdraw) { 721 case EGL_READ: return c->read; 722 case EGL_DRAW: return c->draw; 723 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 724 } 725 } 726 return EGL_NO_SURFACE; 727} 728 729EGLDisplay eglGetCurrentDisplay(void) 730{ 731 // could be called before eglInitialize(), but we wouldn't have a context 732 // then, and this function would correctly return EGL_NO_DISPLAY. 733 734 clearError(); 735 736 EGLContext ctx = getContext(); 737 if (ctx) { 738 egl_context_t const * const c = get_context(ctx); 739 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 740 return c->dpy; 741 } 742 return EGL_NO_DISPLAY; 743} 744 745EGLBoolean eglWaitGL(void) 746{ 747 clearError(); 748 749 egl_connection_t* const cnx = &gEGLImpl; 750 if (!cnx->dso) 751 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 752 753 return cnx->egl.eglWaitGL(); 754} 755 756EGLBoolean eglWaitNative(EGLint engine) 757{ 758 clearError(); 759 760 egl_connection_t* const cnx = &gEGLImpl; 761 if (!cnx->dso) 762 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 763 764 return cnx->egl.eglWaitNative(engine); 765} 766 767EGLint eglGetError(void) 768{ 769 EGLint err = EGL_SUCCESS; 770 egl_connection_t* const cnx = &gEGLImpl; 771 if (cnx->dso) { 772 err = cnx->egl.eglGetError(); 773 } 774 if (err == EGL_SUCCESS) { 775 err = egl_tls_t::getError(); 776 } 777 return err; 778} 779 780__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) 781{ 782 // eglGetProcAddress() could be the very first function called 783 // in which case we must make sure we've initialized ourselves, this 784 // happens the first time egl_get_display() is called. 785 786 clearError(); 787 788 if (egl_init_drivers() == EGL_FALSE) { 789 setError(EGL_BAD_PARAMETER, NULL); 790 return NULL; 791 } 792 793 if (FILTER_EXTENSIONS(procname)) { 794 return NULL; 795 } 796 797 __eglMustCastToProperFunctionPointerType addr; 798 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap)); 799 if (addr) return addr; 800 801 802 // this protects accesses to sGLExtentionMap and sGLExtentionSlot 803 pthread_mutex_lock(&sExtensionMapMutex); 804 805 /* 806 * Since eglGetProcAddress() is not associated to anything, it needs 807 * to return a function pointer that "works" regardless of what 808 * the current context is. 809 * 810 * For this reason, we return a "forwarder", a small stub that takes 811 * care of calling the function associated with the context 812 * currently bound. 813 * 814 * We first look for extensions we've already resolved, if we're seeing 815 * this extension for the first time, we go through all our 816 * implementations and call eglGetProcAddress() and record the 817 * result in the appropriate implementation hooks and return the 818 * address of the forwarder corresponding to that hook set. 819 * 820 */ 821 822 const String8 name(procname); 823 addr = sGLExtentionMap.valueFor(name); 824 const int slot = sGLExtentionSlot; 825 826 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS, 827 "no more slots for eglGetProcAddress(\"%s\")", 828 procname); 829 830#if EGL_TRACE 831 gl_hooks_t *debugHooks = GLTrace_getGLHooks(); 832#endif 833 834 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) { 835 bool found = false; 836 837 egl_connection_t* const cnx = &gEGLImpl; 838 if (cnx->dso && cnx->egl.eglGetProcAddress) { 839 // Extensions are independent of the bound context 840 addr = 841 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] = 842 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] = 843#if EGL_TRACE 844 debugHooks->ext.extensions[slot] = 845 gHooksTrace.ext.extensions[slot] = 846#endif 847 cnx->egl.eglGetProcAddress(procname); 848 if (addr) found = true; 849 } 850 851 if (found) { 852#if USE_FAST_TLS_KEY 853 addr = gExtensionForwarders[slot]; 854#endif 855 sGLExtentionMap.add(name, addr); 856 sGLExtentionSlot++; 857 } 858 } 859 860 pthread_mutex_unlock(&sExtensionMapMutex); 861 return addr; 862} 863 864class FrameCompletionThread : public Thread { 865public: 866 867 static void queueSync(EGLSyncKHR sync) { 868 static sp<FrameCompletionThread> thread(new FrameCompletionThread); 869 static bool running = false; 870 if (!running) { 871 thread->run("GPUFrameCompletion"); 872 running = true; 873 } 874 { 875 Mutex::Autolock lock(thread->mMutex); 876 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d", 877 thread->mFramesQueued).string()); 878 thread->mQueue.push_back(sync); 879 thread->mCondition.signal(); 880 thread->mFramesQueued++; 881 ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size()); 882 } 883 } 884 885private: 886 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {} 887 888 virtual bool threadLoop() { 889 EGLSyncKHR sync; 890 uint32_t frameNum; 891 { 892 Mutex::Autolock lock(mMutex); 893 while (mQueue.isEmpty()) { 894 mCondition.wait(mMutex); 895 } 896 sync = mQueue[0]; 897 frameNum = mFramesCompleted; 898 } 899 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); 900 { 901 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d", 902 frameNum).string()); 903 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR); 904 if (result == EGL_FALSE) { 905 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError()); 906 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { 907 ALOGE("FrameCompletion: timeout waiting for fence"); 908 } 909 eglDestroySyncKHR(dpy, sync); 910 } 911 { 912 Mutex::Autolock lock(mMutex); 913 mQueue.removeAt(0); 914 mFramesCompleted++; 915 ATRACE_INT("GPU Frames Outstanding", mQueue.size()); 916 } 917 return true; 918 } 919 920 uint32_t mFramesQueued; 921 uint32_t mFramesCompleted; 922 Vector<EGLSyncKHR> mQueue; 923 Condition mCondition; 924 Mutex mMutex; 925}; 926 927EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) 928{ 929 ATRACE_CALL(); 930 clearError(); 931 932 const egl_display_ptr dp = validate_display(dpy); 933 if (!dp) return EGL_FALSE; 934 935 SurfaceRef _s(dp.get(), draw); 936 if (!_s.get()) 937 return setError(EGL_BAD_SURFACE, EGL_FALSE); 938 939#if EGL_TRACE 940 gl_hooks_t const *trace_hooks = getGLTraceThreadSpecific(); 941 if (getEGLDebugLevel() > 0) { 942 if (trace_hooks == NULL) { 943 if (GLTrace_start() < 0) { 944 ALOGE("Disabling Tracer for OpenGL ES"); 945 setEGLDebugLevel(0); 946 } else { 947 // switch over to the trace version of hooks 948 EGLContext ctx = egl_tls_t::getContext(); 949 egl_context_t * const c = get_context(ctx); 950 if (c) { 951 setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 952 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx); 953 } 954 } 955 } 956 957 GLTrace_eglSwapBuffers(dpy, draw); 958 } else if (trace_hooks != NULL) { 959 // tracing is now disabled, so switch back to the non trace version 960 EGLContext ctx = egl_tls_t::getContext(); 961 egl_context_t * const c = get_context(ctx); 962 if (c) setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 963 GLTrace_stop(); 964 } 965#endif 966 967 egl_surface_t const * const s = get_surface(draw); 968 969 if (CC_UNLIKELY(dp->traceGpuCompletion)) { 970 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL); 971 if (sync != EGL_NO_SYNC_KHR) { 972 FrameCompletionThread::queueSync(sync); 973 } 974 } 975 976 if (CC_UNLIKELY(dp->finishOnSwap)) { 977 uint32_t pixel; 978 egl_context_t * const c = get_context( egl_tls_t::getContext() ); 979 if (c) { 980 // glReadPixels() ensures that the frame is complete 981 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1, 982 GL_RGBA,GL_UNSIGNED_BYTE,&pixel); 983 } 984 } 985 986 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface); 987} 988 989EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, 990 NativePixmapType target) 991{ 992 clearError(); 993 994 const egl_display_ptr dp = validate_display(dpy); 995 if (!dp) return EGL_FALSE; 996 997 SurfaceRef _s(dp.get(), surface); 998 if (!_s.get()) 999 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1000 1001 egl_surface_t const * const s = get_surface(surface); 1002 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target); 1003} 1004 1005const char* eglQueryString(EGLDisplay dpy, EGLint name) 1006{ 1007 clearError(); 1008 1009 const egl_display_ptr dp = validate_display(dpy); 1010 if (!dp) return (const char *) NULL; 1011 1012 switch (name) { 1013 case EGL_VENDOR: 1014 return dp->getVendorString(); 1015 case EGL_VERSION: 1016 return dp->getVersionString(); 1017 case EGL_EXTENSIONS: 1018 return dp->getExtensionString(); 1019 case EGL_CLIENT_APIS: 1020 return dp->getClientApiString(); 1021 } 1022 return setError(EGL_BAD_PARAMETER, (const char *)0); 1023} 1024 1025EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name) 1026{ 1027 clearError(); 1028 1029 const egl_display_ptr dp = validate_display(dpy); 1030 if (!dp) return (const char *) NULL; 1031 1032 switch (name) { 1033 case EGL_VENDOR: 1034 return dp->disp.queryString.vendor; 1035 case EGL_VERSION: 1036 return dp->disp.queryString.version; 1037 case EGL_EXTENSIONS: 1038 return dp->disp.queryString.extensions; 1039 case EGL_CLIENT_APIS: 1040 return dp->disp.queryString.clientApi; 1041 } 1042 return setError(EGL_BAD_PARAMETER, (const char *)0); 1043} 1044 1045// ---------------------------------------------------------------------------- 1046// EGL 1.1 1047// ---------------------------------------------------------------------------- 1048 1049EGLBoolean eglSurfaceAttrib( 1050 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 1051{ 1052 clearError(); 1053 1054 const egl_display_ptr dp = validate_display(dpy); 1055 if (!dp) return EGL_FALSE; 1056 1057 SurfaceRef _s(dp.get(), surface); 1058 if (!_s.get()) 1059 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1060 1061 egl_surface_t const * const s = get_surface(surface); 1062 if (s->cnx->egl.eglSurfaceAttrib) { 1063 return s->cnx->egl.eglSurfaceAttrib( 1064 dp->disp.dpy, s->surface, attribute, value); 1065 } 1066 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1067} 1068 1069EGLBoolean eglBindTexImage( 1070 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1071{ 1072 clearError(); 1073 1074 const egl_display_ptr dp = validate_display(dpy); 1075 if (!dp) return EGL_FALSE; 1076 1077 SurfaceRef _s(dp.get(), surface); 1078 if (!_s.get()) 1079 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1080 1081 egl_surface_t const * const s = get_surface(surface); 1082 if (s->cnx->egl.eglBindTexImage) { 1083 return s->cnx->egl.eglBindTexImage( 1084 dp->disp.dpy, s->surface, buffer); 1085 } 1086 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1087} 1088 1089EGLBoolean eglReleaseTexImage( 1090 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1091{ 1092 clearError(); 1093 1094 const egl_display_ptr dp = validate_display(dpy); 1095 if (!dp) return EGL_FALSE; 1096 1097 SurfaceRef _s(dp.get(), surface); 1098 if (!_s.get()) 1099 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1100 1101 egl_surface_t const * const s = get_surface(surface); 1102 if (s->cnx->egl.eglReleaseTexImage) { 1103 return s->cnx->egl.eglReleaseTexImage( 1104 dp->disp.dpy, s->surface, buffer); 1105 } 1106 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1107} 1108 1109EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 1110{ 1111 clearError(); 1112 1113 const egl_display_ptr dp = validate_display(dpy); 1114 if (!dp) return EGL_FALSE; 1115 1116 EGLBoolean res = EGL_TRUE; 1117 egl_connection_t* const cnx = &gEGLImpl; 1118 if (cnx->dso && cnx->egl.eglSwapInterval) { 1119 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval); 1120 } 1121 1122 return res; 1123} 1124 1125 1126// ---------------------------------------------------------------------------- 1127// EGL 1.2 1128// ---------------------------------------------------------------------------- 1129 1130EGLBoolean eglWaitClient(void) 1131{ 1132 clearError(); 1133 1134 egl_connection_t* const cnx = &gEGLImpl; 1135 if (!cnx->dso) 1136 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1137 1138 EGLBoolean res; 1139 if (cnx->egl.eglWaitClient) { 1140 res = cnx->egl.eglWaitClient(); 1141 } else { 1142 res = cnx->egl.eglWaitGL(); 1143 } 1144 return res; 1145} 1146 1147EGLBoolean eglBindAPI(EGLenum api) 1148{ 1149 clearError(); 1150 1151 if (egl_init_drivers() == EGL_FALSE) { 1152 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1153 } 1154 1155 // bind this API on all EGLs 1156 EGLBoolean res = EGL_TRUE; 1157 egl_connection_t* const cnx = &gEGLImpl; 1158 if (cnx->dso && cnx->egl.eglBindAPI) { 1159 res = cnx->egl.eglBindAPI(api); 1160 } 1161 return res; 1162} 1163 1164EGLenum eglQueryAPI(void) 1165{ 1166 clearError(); 1167 1168 if (egl_init_drivers() == EGL_FALSE) { 1169 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1170 } 1171 1172 egl_connection_t* const cnx = &gEGLImpl; 1173 if (cnx->dso && cnx->egl.eglQueryAPI) { 1174 return cnx->egl.eglQueryAPI(); 1175 } 1176 1177 // or, it can only be OpenGL ES 1178 return EGL_OPENGL_ES_API; 1179} 1180 1181EGLBoolean eglReleaseThread(void) 1182{ 1183 clearError(); 1184 1185#if EGL_TRACE 1186 if (getEGLDebugLevel() > 0) 1187 GLTrace_eglReleaseThread(); 1188#endif 1189 1190 // If there is context bound to the thread, release it 1191 egl_display_t::loseCurrent(get_context(getContext())); 1192 1193 egl_connection_t* const cnx = &gEGLImpl; 1194 if (cnx->dso && cnx->egl.eglReleaseThread) { 1195 cnx->egl.eglReleaseThread(); 1196 } 1197 egl_tls_t::clearTLS(); 1198 return EGL_TRUE; 1199} 1200 1201EGLSurface eglCreatePbufferFromClientBuffer( 1202 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 1203 EGLConfig config, const EGLint *attrib_list) 1204{ 1205 clearError(); 1206 1207 egl_connection_t* cnx = NULL; 1208 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 1209 if (!dp) return EGL_FALSE; 1210 if (cnx->egl.eglCreatePbufferFromClientBuffer) { 1211 return cnx->egl.eglCreatePbufferFromClientBuffer( 1212 dp->disp.dpy, buftype, buffer, config, attrib_list); 1213 } 1214 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); 1215} 1216 1217// ---------------------------------------------------------------------------- 1218// EGL_EGLEXT_VERSION 3 1219// ---------------------------------------------------------------------------- 1220 1221EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, 1222 const EGLint *attrib_list) 1223{ 1224 clearError(); 1225 1226 const egl_display_ptr dp = validate_display(dpy); 1227 if (!dp) return EGL_FALSE; 1228 1229 SurfaceRef _s(dp.get(), surface); 1230 if (!_s.get()) 1231 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1232 1233 egl_surface_t const * const s = get_surface(surface); 1234 if (s->cnx->egl.eglLockSurfaceKHR) { 1235 return s->cnx->egl.eglLockSurfaceKHR( 1236 dp->disp.dpy, s->surface, attrib_list); 1237 } 1238 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1239} 1240 1241EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) 1242{ 1243 clearError(); 1244 1245 const egl_display_ptr dp = validate_display(dpy); 1246 if (!dp) return EGL_FALSE; 1247 1248 SurfaceRef _s(dp.get(), surface); 1249 if (!_s.get()) 1250 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1251 1252 egl_surface_t const * const s = get_surface(surface); 1253 if (s->cnx->egl.eglUnlockSurfaceKHR) { 1254 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface); 1255 } 1256 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1257} 1258 1259EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1260 EGLClientBuffer buffer, const EGLint *attrib_list) 1261{ 1262 clearError(); 1263 1264 const egl_display_ptr dp = validate_display(dpy); 1265 if (!dp) return EGL_NO_IMAGE_KHR; 1266 1267 ContextRef _c(dp.get(), ctx); 1268 egl_context_t * const c = _c.get(); 1269 1270 EGLImageKHR result = EGL_NO_IMAGE_KHR; 1271 egl_connection_t* const cnx = &gEGLImpl; 1272 if (cnx->dso && cnx->egl.eglCreateImageKHR) { 1273 result = cnx->egl.eglCreateImageKHR( 1274 dp->disp.dpy, 1275 c ? c->context : EGL_NO_CONTEXT, 1276 target, buffer, attrib_list); 1277 } 1278 return result; 1279} 1280 1281EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 1282{ 1283 clearError(); 1284 1285 const egl_display_ptr dp = validate_display(dpy); 1286 if (!dp) return EGL_FALSE; 1287 1288 EGLBoolean result = EGL_FALSE; 1289 egl_connection_t* const cnx = &gEGLImpl; 1290 if (cnx->dso && cnx->egl.eglDestroyImageKHR) { 1291 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img); 1292 } 1293 return result; 1294} 1295 1296// ---------------------------------------------------------------------------- 1297// EGL_EGLEXT_VERSION 5 1298// ---------------------------------------------------------------------------- 1299 1300 1301EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) 1302{ 1303 clearError(); 1304 1305 const egl_display_ptr dp = validate_display(dpy); 1306 if (!dp) return EGL_NO_SYNC_KHR; 1307 1308 EGLSyncKHR result = EGL_NO_SYNC_KHR; 1309 egl_connection_t* const cnx = &gEGLImpl; 1310 if (cnx->dso && cnx->egl.eglCreateSyncKHR) { 1311 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list); 1312 } 1313 return result; 1314} 1315 1316EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) 1317{ 1318 clearError(); 1319 1320 const egl_display_ptr dp = validate_display(dpy); 1321 if (!dp) return EGL_FALSE; 1322 1323 EGLBoolean result = EGL_FALSE; 1324 egl_connection_t* const cnx = &gEGLImpl; 1325 if (cnx->dso && cnx->egl.eglDestroySyncKHR) { 1326 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync); 1327 } 1328 return result; 1329} 1330 1331EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) { 1332 clearError(); 1333 1334 const egl_display_ptr dp = validate_display(dpy); 1335 if (!dp) return EGL_FALSE; 1336 1337 EGLBoolean result = EGL_FALSE; 1338 egl_connection_t* const cnx = &gEGLImpl; 1339 if (cnx->dso && cnx->egl.eglSignalSyncKHR) { 1340 result = cnx->egl.eglSignalSyncKHR( 1341 dp->disp.dpy, sync, mode); 1342 } 1343 return result; 1344} 1345 1346EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, 1347 EGLint flags, EGLTimeKHR timeout) 1348{ 1349 clearError(); 1350 1351 const egl_display_ptr dp = validate_display(dpy); 1352 if (!dp) return EGL_FALSE; 1353 1354 EGLBoolean result = EGL_FALSE; 1355 egl_connection_t* const cnx = &gEGLImpl; 1356 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) { 1357 result = cnx->egl.eglClientWaitSyncKHR( 1358 dp->disp.dpy, sync, flags, timeout); 1359 } 1360 return result; 1361} 1362 1363EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, 1364 EGLint attribute, EGLint *value) 1365{ 1366 clearError(); 1367 1368 const egl_display_ptr dp = validate_display(dpy); 1369 if (!dp) return EGL_FALSE; 1370 1371 EGLBoolean result = EGL_FALSE; 1372 egl_connection_t* const cnx = &gEGLImpl; 1373 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) { 1374 result = cnx->egl.eglGetSyncAttribKHR( 1375 dp->disp.dpy, sync, attribute, value); 1376 } 1377 return result; 1378} 1379 1380// ---------------------------------------------------------------------------- 1381// EGL_EGLEXT_VERSION 15 1382// ---------------------------------------------------------------------------- 1383 1384EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) { 1385 clearError(); 1386 const egl_display_ptr dp = validate_display(dpy); 1387 if (!dp) return EGL_FALSE; 1388 EGLint result = EGL_FALSE; 1389 egl_connection_t* const cnx = &gEGLImpl; 1390 if (cnx->dso && cnx->egl.eglWaitSyncKHR) { 1391 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags); 1392 } 1393 return result; 1394} 1395 1396// ---------------------------------------------------------------------------- 1397// ANDROID extensions 1398// ---------------------------------------------------------------------------- 1399 1400EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync) 1401{ 1402 clearError(); 1403 1404 const egl_display_ptr dp = validate_display(dpy); 1405 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID; 1406 1407 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID; 1408 egl_connection_t* const cnx = &gEGLImpl; 1409 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) { 1410 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync); 1411 } 1412 return result; 1413} 1414 1415EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface, 1416 EGLnsecsANDROID time) 1417{ 1418 clearError(); 1419 1420 const egl_display_ptr dp = validate_display(dpy); 1421 if (!dp) { 1422 return EGL_FALSE; 1423 } 1424 1425 SurfaceRef _s(dp.get(), surface); 1426 if (!_s.get()) { 1427 setError(EGL_BAD_SURFACE, EGL_FALSE); 1428 return EGL_FALSE; 1429 } 1430 1431 egl_surface_t const * const s = get_surface(surface); 1432 native_window_set_buffers_timestamp(s->win.get(), time); 1433 1434 return EGL_TRUE; 1435} 1436 1437// ---------------------------------------------------------------------------- 1438// NVIDIA extensions 1439// ---------------------------------------------------------------------------- 1440EGLuint64NV eglGetSystemTimeFrequencyNV() 1441{ 1442 clearError(); 1443 1444 if (egl_init_drivers() == EGL_FALSE) { 1445 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1446 } 1447 1448 EGLuint64NV ret = 0; 1449 egl_connection_t* const cnx = &gEGLImpl; 1450 1451 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) { 1452 return cnx->egl.eglGetSystemTimeFrequencyNV(); 1453 } 1454 1455 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1456} 1457 1458EGLuint64NV eglGetSystemTimeNV() 1459{ 1460 clearError(); 1461 1462 if (egl_init_drivers() == EGL_FALSE) { 1463 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1464 } 1465 1466 EGLuint64NV ret = 0; 1467 egl_connection_t* const cnx = &gEGLImpl; 1468 1469 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) { 1470 return cnx->egl.eglGetSystemTimeNV(); 1471 } 1472 1473 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1474} 1475