eglApi.cpp revision 69d100762c7c26d8328f4bb61cfef026d3a69bbf
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 // Extensions are independent of the bound context 764 addr = 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 if (addr) found = true; 773 } 774 775 if (found) { 776#if USE_FAST_TLS_KEY 777 addr = gExtensionForwarders[slot]; 778#endif 779 sGLExtentionMap.add(name, addr); 780 sGLExtentionSlot++; 781 } 782 } 783 784 pthread_mutex_unlock(&sExtensionMapMutex); 785 return addr; 786} 787 788class FrameCompletionThread : public Thread { 789public: 790 791 static void queueSync(EGLSyncKHR sync) { 792 static sp<FrameCompletionThread> thread(new FrameCompletionThread); 793 static bool running = false; 794 if (!running) { 795 thread->run("GPUFrameCompletion"); 796 running = true; 797 } 798 { 799 Mutex::Autolock lock(thread->mMutex); 800 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d", 801 thread->mFramesQueued).string()); 802 thread->mQueue.push_back(sync); 803 thread->mCondition.signal(); 804 thread->mFramesQueued++; 805 ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size()); 806 } 807 } 808 809private: 810 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {} 811 812 virtual bool threadLoop() { 813 EGLSyncKHR sync; 814 uint32_t frameNum; 815 { 816 Mutex::Autolock lock(mMutex); 817 while (mQueue.isEmpty()) { 818 mCondition.wait(mMutex); 819 } 820 sync = mQueue[0]; 821 frameNum = mFramesCompleted; 822 } 823 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); 824 { 825 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d", 826 frameNum).string()); 827 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR); 828 if (result == EGL_FALSE) { 829 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError()); 830 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { 831 ALOGE("FrameCompletion: timeout waiting for fence"); 832 } 833 eglDestroySyncKHR(dpy, sync); 834 } 835 { 836 Mutex::Autolock lock(mMutex); 837 mQueue.removeAt(0); 838 mFramesCompleted++; 839 ATRACE_INT("GPU Frames Outstanding", mQueue.size()); 840 } 841 return true; 842 } 843 844 uint32_t mFramesQueued; 845 uint32_t mFramesCompleted; 846 Vector<EGLSyncKHR> mQueue; 847 Condition mCondition; 848 Mutex mMutex; 849}; 850 851EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) 852{ 853 ATRACE_CALL(); 854 clearError(); 855 856 const egl_display_ptr dp = validate_display(dpy); 857 if (!dp) return EGL_FALSE; 858 859 SurfaceRef _s(dp.get(), draw); 860 if (!_s.get()) 861 return setError(EGL_BAD_SURFACE, EGL_FALSE); 862 863#if EGL_TRACE 864 if (gEGLDebugLevel > 0) 865 GLTrace_eglSwapBuffers(dpy, draw); 866#endif 867 868 egl_surface_t const * const s = get_surface(draw); 869 870 if (CC_UNLIKELY(dp->finishOnSwap)) { 871 uint32_t pixel; 872 egl_context_t * const c = get_context( egl_tls_t::getContext() ); 873 if (c) { 874 // glReadPixels() ensures that the frame is complete 875 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1, 876 GL_RGBA,GL_UNSIGNED_BYTE,&pixel); 877 } 878 } 879 880 EGLBoolean result = s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface); 881 882 if (CC_UNLIKELY(dp->traceGpuCompletion)) { 883 EGLSyncKHR sync = EGL_NO_SYNC_KHR; 884 { 885 sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL); 886 } 887 if (sync != EGL_NO_SYNC_KHR) { 888 FrameCompletionThread::queueSync(sync); 889 } 890 } 891 892 return result; 893} 894 895EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, 896 NativePixmapType target) 897{ 898 clearError(); 899 900 const egl_display_ptr dp = validate_display(dpy); 901 if (!dp) return EGL_FALSE; 902 903 SurfaceRef _s(dp.get(), surface); 904 if (!_s.get()) 905 return setError(EGL_BAD_SURFACE, EGL_FALSE); 906 907 egl_surface_t const * const s = get_surface(surface); 908 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target); 909} 910 911const char* eglQueryString(EGLDisplay dpy, EGLint name) 912{ 913 clearError(); 914 915 const egl_display_ptr dp = validate_display(dpy); 916 if (!dp) return (const char *) NULL; 917 918 switch (name) { 919 case EGL_VENDOR: 920 return dp->getVendorString(); 921 case EGL_VERSION: 922 return dp->getVersionString(); 923 case EGL_EXTENSIONS: 924 return dp->getExtensionString(); 925 case EGL_CLIENT_APIS: 926 return dp->getClientApiString(); 927 case EGL_VERSION_HW_ANDROID: 928 return dp->disp.queryString.version; 929 } 930 return setError(EGL_BAD_PARAMETER, (const char *)0); 931} 932 933 934// ---------------------------------------------------------------------------- 935// EGL 1.1 936// ---------------------------------------------------------------------------- 937 938EGLBoolean eglSurfaceAttrib( 939 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 940{ 941 clearError(); 942 943 const egl_display_ptr dp = validate_display(dpy); 944 if (!dp) return EGL_FALSE; 945 946 SurfaceRef _s(dp.get(), surface); 947 if (!_s.get()) 948 return setError(EGL_BAD_SURFACE, EGL_FALSE); 949 950 egl_surface_t const * const s = get_surface(surface); 951 if (s->cnx->egl.eglSurfaceAttrib) { 952 return s->cnx->egl.eglSurfaceAttrib( 953 dp->disp.dpy, s->surface, attribute, value); 954 } 955 return setError(EGL_BAD_SURFACE, EGL_FALSE); 956} 957 958EGLBoolean eglBindTexImage( 959 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 960{ 961 clearError(); 962 963 const egl_display_ptr dp = validate_display(dpy); 964 if (!dp) return EGL_FALSE; 965 966 SurfaceRef _s(dp.get(), surface); 967 if (!_s.get()) 968 return setError(EGL_BAD_SURFACE, EGL_FALSE); 969 970 egl_surface_t const * const s = get_surface(surface); 971 if (s->cnx->egl.eglBindTexImage) { 972 return s->cnx->egl.eglBindTexImage( 973 dp->disp.dpy, s->surface, buffer); 974 } 975 return setError(EGL_BAD_SURFACE, EGL_FALSE); 976} 977 978EGLBoolean eglReleaseTexImage( 979 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 980{ 981 clearError(); 982 983 const egl_display_ptr dp = validate_display(dpy); 984 if (!dp) return EGL_FALSE; 985 986 SurfaceRef _s(dp.get(), surface); 987 if (!_s.get()) 988 return setError(EGL_BAD_SURFACE, EGL_FALSE); 989 990 egl_surface_t const * const s = get_surface(surface); 991 if (s->cnx->egl.eglReleaseTexImage) { 992 return s->cnx->egl.eglReleaseTexImage( 993 dp->disp.dpy, s->surface, buffer); 994 } 995 return setError(EGL_BAD_SURFACE, EGL_FALSE); 996} 997 998EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 999{ 1000 clearError(); 1001 1002 const egl_display_ptr dp = validate_display(dpy); 1003 if (!dp) return EGL_FALSE; 1004 1005 EGLBoolean res = EGL_TRUE; 1006 egl_connection_t* const cnx = &gEGLImpl; 1007 if (cnx->dso && cnx->egl.eglSwapInterval) { 1008 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval); 1009 } 1010 1011 return res; 1012} 1013 1014 1015// ---------------------------------------------------------------------------- 1016// EGL 1.2 1017// ---------------------------------------------------------------------------- 1018 1019EGLBoolean eglWaitClient(void) 1020{ 1021 clearError(); 1022 1023 egl_connection_t* const cnx = &gEGLImpl; 1024 if (!cnx->dso) 1025 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1026 1027 EGLBoolean res; 1028 if (cnx->egl.eglWaitClient) { 1029 res = cnx->egl.eglWaitClient(); 1030 } else { 1031 res = cnx->egl.eglWaitGL(); 1032 } 1033 return res; 1034} 1035 1036EGLBoolean eglBindAPI(EGLenum api) 1037{ 1038 clearError(); 1039 1040 if (egl_init_drivers() == EGL_FALSE) { 1041 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1042 } 1043 1044 // bind this API on all EGLs 1045 EGLBoolean res = EGL_TRUE; 1046 egl_connection_t* const cnx = &gEGLImpl; 1047 if (cnx->dso && cnx->egl.eglBindAPI) { 1048 res = cnx->egl.eglBindAPI(api); 1049 } 1050 return res; 1051} 1052 1053EGLenum eglQueryAPI(void) 1054{ 1055 clearError(); 1056 1057 if (egl_init_drivers() == EGL_FALSE) { 1058 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1059 } 1060 1061 egl_connection_t* const cnx = &gEGLImpl; 1062 if (cnx->dso && cnx->egl.eglQueryAPI) { 1063 return cnx->egl.eglQueryAPI(); 1064 } 1065 1066 // or, it can only be OpenGL ES 1067 return EGL_OPENGL_ES_API; 1068} 1069 1070EGLBoolean eglReleaseThread(void) 1071{ 1072 clearError(); 1073 1074 // If there is context bound to the thread, release it 1075 egl_display_t::loseCurrent(get_context(getContext())); 1076 1077 egl_connection_t* const cnx = &gEGLImpl; 1078 if (cnx->dso && cnx->egl.eglReleaseThread) { 1079 cnx->egl.eglReleaseThread(); 1080 } 1081 1082 egl_tls_t::clearTLS(); 1083#if EGL_TRACE 1084 if (gEGLDebugLevel > 0) 1085 GLTrace_eglReleaseThread(); 1086#endif 1087 return EGL_TRUE; 1088} 1089 1090EGLSurface eglCreatePbufferFromClientBuffer( 1091 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 1092 EGLConfig config, const EGLint *attrib_list) 1093{ 1094 clearError(); 1095 1096 egl_connection_t* cnx = NULL; 1097 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 1098 if (!dp) return EGL_FALSE; 1099 if (cnx->egl.eglCreatePbufferFromClientBuffer) { 1100 return cnx->egl.eglCreatePbufferFromClientBuffer( 1101 dp->disp.dpy, buftype, buffer, config, attrib_list); 1102 } 1103 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); 1104} 1105 1106// ---------------------------------------------------------------------------- 1107// EGL_EGLEXT_VERSION 3 1108// ---------------------------------------------------------------------------- 1109 1110EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, 1111 const EGLint *attrib_list) 1112{ 1113 clearError(); 1114 1115 const egl_display_ptr dp = validate_display(dpy); 1116 if (!dp) return EGL_FALSE; 1117 1118 SurfaceRef _s(dp.get(), surface); 1119 if (!_s.get()) 1120 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1121 1122 egl_surface_t const * const s = get_surface(surface); 1123 if (s->cnx->egl.eglLockSurfaceKHR) { 1124 return s->cnx->egl.eglLockSurfaceKHR( 1125 dp->disp.dpy, s->surface, attrib_list); 1126 } 1127 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1128} 1129 1130EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) 1131{ 1132 clearError(); 1133 1134 const egl_display_ptr dp = validate_display(dpy); 1135 if (!dp) return EGL_FALSE; 1136 1137 SurfaceRef _s(dp.get(), surface); 1138 if (!_s.get()) 1139 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1140 1141 egl_surface_t const * const s = get_surface(surface); 1142 if (s->cnx->egl.eglUnlockSurfaceKHR) { 1143 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface); 1144 } 1145 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1146} 1147 1148EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1149 EGLClientBuffer buffer, const EGLint *attrib_list) 1150{ 1151 clearError(); 1152 1153 const egl_display_ptr dp = validate_display(dpy); 1154 if (!dp) return EGL_NO_IMAGE_KHR; 1155 1156 ContextRef _c(dp.get(), ctx); 1157 egl_context_t * const c = _c.get(); 1158 1159 EGLImageKHR result = EGL_NO_IMAGE_KHR; 1160 egl_connection_t* const cnx = &gEGLImpl; 1161 if (cnx->dso && cnx->egl.eglCreateImageKHR) { 1162 result = cnx->egl.eglCreateImageKHR( 1163 dp->disp.dpy, 1164 c ? c->context : EGL_NO_CONTEXT, 1165 target, buffer, attrib_list); 1166 } 1167 return result; 1168} 1169 1170EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 1171{ 1172 clearError(); 1173 1174 const egl_display_ptr dp = validate_display(dpy); 1175 if (!dp) return EGL_FALSE; 1176 1177 EGLBoolean result = EGL_FALSE; 1178 egl_connection_t* const cnx = &gEGLImpl; 1179 if (cnx->dso && cnx->egl.eglDestroyImageKHR) { 1180 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img); 1181 } 1182 return result; 1183} 1184 1185// ---------------------------------------------------------------------------- 1186// EGL_EGLEXT_VERSION 5 1187// ---------------------------------------------------------------------------- 1188 1189 1190EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) 1191{ 1192 clearError(); 1193 1194 const egl_display_ptr dp = validate_display(dpy); 1195 if (!dp) return EGL_NO_SYNC_KHR; 1196 1197 EGLSyncKHR result = EGL_NO_SYNC_KHR; 1198 egl_connection_t* const cnx = &gEGLImpl; 1199 if (cnx->dso && cnx->egl.eglCreateSyncKHR) { 1200 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list); 1201 } 1202 return result; 1203} 1204 1205EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) 1206{ 1207 clearError(); 1208 1209 const egl_display_ptr dp = validate_display(dpy); 1210 if (!dp) return EGL_FALSE; 1211 1212 EGLBoolean result = EGL_FALSE; 1213 egl_connection_t* const cnx = &gEGLImpl; 1214 if (cnx->dso && cnx->egl.eglDestroySyncKHR) { 1215 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync); 1216 } 1217 return result; 1218} 1219 1220EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, 1221 EGLint flags, EGLTimeKHR timeout) 1222{ 1223 clearError(); 1224 1225 const egl_display_ptr dp = validate_display(dpy); 1226 if (!dp) return EGL_FALSE; 1227 1228 EGLBoolean result = EGL_FALSE; 1229 egl_connection_t* const cnx = &gEGLImpl; 1230 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) { 1231 result = cnx->egl.eglClientWaitSyncKHR( 1232 dp->disp.dpy, sync, flags, timeout); 1233 } 1234 return result; 1235} 1236 1237EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, 1238 EGLint attribute, EGLint *value) 1239{ 1240 clearError(); 1241 1242 const egl_display_ptr dp = validate_display(dpy); 1243 if (!dp) return EGL_FALSE; 1244 1245 EGLBoolean result = EGL_FALSE; 1246 egl_connection_t* const cnx = &gEGLImpl; 1247 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) { 1248 result = cnx->egl.eglGetSyncAttribKHR( 1249 dp->disp.dpy, sync, attribute, value); 1250 } 1251 return result; 1252} 1253 1254// ---------------------------------------------------------------------------- 1255// ANDROID extensions 1256// ---------------------------------------------------------------------------- 1257 1258EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync) 1259{ 1260 clearError(); 1261 1262 const egl_display_ptr dp = validate_display(dpy); 1263 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID; 1264 1265 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID; 1266 egl_connection_t* const cnx = &gEGLImpl; 1267 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) { 1268 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync); 1269 } 1270 return result; 1271} 1272 1273EGLint eglWaitSyncANDROID(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) 1274{ 1275 clearError(); 1276 1277 const egl_display_ptr dp = validate_display(dpy); 1278 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID; 1279 1280 EGLint result = EGL_FALSE; 1281 egl_connection_t* const cnx = &gEGLImpl; 1282 if (cnx->dso && cnx->egl.eglWaitSyncANDROID) { 1283 result = cnx->egl.eglWaitSyncANDROID(dp->disp.dpy, sync, flags); 1284 } 1285 return result; 1286} 1287 1288// ---------------------------------------------------------------------------- 1289// NVIDIA extensions 1290// ---------------------------------------------------------------------------- 1291EGLuint64NV eglGetSystemTimeFrequencyNV() 1292{ 1293 clearError(); 1294 1295 if (egl_init_drivers() == EGL_FALSE) { 1296 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1297 } 1298 1299 EGLuint64NV ret = 0; 1300 egl_connection_t* const cnx = &gEGLImpl; 1301 1302 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) { 1303 return cnx->egl.eglGetSystemTimeFrequencyNV(); 1304 } 1305 1306 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1307} 1308 1309EGLuint64NV eglGetSystemTimeNV() 1310{ 1311 clearError(); 1312 1313 if (egl_init_drivers() == EGL_FALSE) { 1314 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1315 } 1316 1317 EGLuint64NV ret = 0; 1318 egl_connection_t* const cnx = &gEGLImpl; 1319 1320 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) { 1321 return cnx->egl.eglGetSystemTimeNV(); 1322 } 1323 1324 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1325} 1326