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