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