eglApi.cpp revision 500407a2c07ced40c36e7356574a47bcec9c2fd9
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 res = cnx->egl.eglChooseConfig( 208 dp->disp.dpy, attrib_list, configs, config_size, num_config); 209 } 210 return res; 211} 212 213EGLBoolean 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 230EGLSurface 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 282EGLSurface 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 302EGLSurface 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 321EGLBoolean 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 340EGLBoolean 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 357void 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 382EGLContext 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 } else { 420 EGLint error = eglGetError(); 421 ALOGE_IF(error == EGL_SUCCESS, 422 "eglCreateContext(%p, %p, %p, %p) returned EGL_NO_CONTEXT " 423 "but no EGL error!", 424 dpy, config, share_list, attrib_list); 425 } 426 } 427 return EGL_NO_CONTEXT; 428} 429 430EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) 431{ 432 clearError(); 433 434 const egl_display_ptr dp = validate_display(dpy); 435 if (!dp) 436 return EGL_FALSE; 437 438 ContextRef _c(dp.get(), ctx); 439 if (!_c.get()) 440 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 441 442 egl_context_t * const c = get_context(ctx); 443 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context); 444 if (result == EGL_TRUE) { 445 _c.terminate(); 446 } 447 return result; 448} 449 450EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, 451 EGLSurface read, EGLContext ctx) 452{ 453 clearError(); 454 455 egl_display_ptr dp = validate_display(dpy); 456 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 457 458 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not 459 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is 460 // a valid but uninitialized display. 461 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) || 462 (draw != EGL_NO_SURFACE) ) { 463 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE); 464 } 465 466 // get a reference to the object passed in 467 ContextRef _c(dp.get(), ctx); 468 SurfaceRef _d(dp.get(), draw); 469 SurfaceRef _r(dp.get(), read); 470 471 // validate the context (if not EGL_NO_CONTEXT) 472 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) { 473 // EGL_NO_CONTEXT is valid 474 return EGL_FALSE; 475 } 476 477 // these are the underlying implementation's object 478 EGLContext impl_ctx = EGL_NO_CONTEXT; 479 EGLSurface impl_draw = EGL_NO_SURFACE; 480 EGLSurface impl_read = EGL_NO_SURFACE; 481 482 // these are our objects structs passed in 483 egl_context_t * c = NULL; 484 egl_surface_t const * d = NULL; 485 egl_surface_t const * r = NULL; 486 487 // these are the current objects structs 488 egl_context_t * cur_c = get_context(getContext()); 489 490 if (ctx != EGL_NO_CONTEXT) { 491 c = get_context(ctx); 492 impl_ctx = c->context; 493 } else { 494 // no context given, use the implementation of the current context 495 if (cur_c == NULL) { 496 // no current context 497 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) { 498 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT); 499 return setError(EGL_BAD_MATCH, EGL_FALSE); 500 } 501 // not an error, there is just no current context. 502 return EGL_TRUE; 503 } 504 } 505 506 // retrieve the underlying implementation's draw EGLSurface 507 if (draw != EGL_NO_SURFACE) { 508 d = get_surface(draw); 509 impl_draw = d->surface; 510 } 511 512 // retrieve the underlying implementation's read EGLSurface 513 if (read != EGL_NO_SURFACE) { 514 r = get_surface(read); 515 impl_read = r->surface; 516 } 517 518 519 EGLBoolean result = dp->makeCurrent(c, cur_c, 520 draw, read, ctx, 521 impl_draw, impl_read, impl_ctx); 522 523 if (result == EGL_TRUE) { 524 if (c) { 525 setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 526 egl_tls_t::setContext(ctx); 527#if EGL_TRACE 528 if (gEGLDebugLevel > 0) 529 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx); 530#endif 531 _c.acquire(); 532 _r.acquire(); 533 _d.acquire(); 534 } else { 535 setGLHooksThreadSpecific(&gHooksNoContext); 536 egl_tls_t::setContext(EGL_NO_CONTEXT); 537 } 538 } else { 539 // this will ALOGE the error 540 result = setError(c->cnx->egl.eglGetError(), EGL_FALSE); 541 } 542 return result; 543} 544 545 546EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, 547 EGLint attribute, EGLint *value) 548{ 549 clearError(); 550 551 const egl_display_ptr dp = validate_display(dpy); 552 if (!dp) return EGL_FALSE; 553 554 ContextRef _c(dp.get(), ctx); 555 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 556 557 egl_context_t * const c = get_context(ctx); 558 return c->cnx->egl.eglQueryContext( 559 dp->disp.dpy, c->context, attribute, value); 560 561} 562 563EGLContext eglGetCurrentContext(void) 564{ 565 // could be called before eglInitialize(), but we wouldn't have a context 566 // then, and this function would correctly return EGL_NO_CONTEXT. 567 568 clearError(); 569 570 EGLContext ctx = getContext(); 571 return ctx; 572} 573 574EGLSurface eglGetCurrentSurface(EGLint readdraw) 575{ 576 // could be called before eglInitialize(), but we wouldn't have a context 577 // then, and this function would correctly return EGL_NO_SURFACE. 578 579 clearError(); 580 581 EGLContext ctx = getContext(); 582 if (ctx) { 583 egl_context_t const * const c = get_context(ctx); 584 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 585 switch (readdraw) { 586 case EGL_READ: return c->read; 587 case EGL_DRAW: return c->draw; 588 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 589 } 590 } 591 return EGL_NO_SURFACE; 592} 593 594EGLDisplay eglGetCurrentDisplay(void) 595{ 596 // could be called before eglInitialize(), but we wouldn't have a context 597 // then, and this function would correctly return EGL_NO_DISPLAY. 598 599 clearError(); 600 601 EGLContext ctx = getContext(); 602 if (ctx) { 603 egl_context_t const * const c = get_context(ctx); 604 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 605 return c->dpy; 606 } 607 return EGL_NO_DISPLAY; 608} 609 610EGLBoolean eglWaitGL(void) 611{ 612 clearError(); 613 614 egl_connection_t* const cnx = &gEGLImpl; 615 if (!cnx->dso) 616 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 617 618 return cnx->egl.eglWaitGL(); 619} 620 621EGLBoolean eglWaitNative(EGLint engine) 622{ 623 clearError(); 624 625 egl_connection_t* const cnx = &gEGLImpl; 626 if (!cnx->dso) 627 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 628 629 return cnx->egl.eglWaitNative(engine); 630} 631 632EGLint eglGetError(void) 633{ 634 EGLint err = EGL_SUCCESS; 635 egl_connection_t* const cnx = &gEGLImpl; 636 if (cnx->dso) { 637 err = cnx->egl.eglGetError(); 638 } 639 if (err == EGL_SUCCESS) { 640 err = egl_tls_t::getError(); 641 } 642 return err; 643} 644 645__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) 646{ 647 // eglGetProcAddress() could be the very first function called 648 // in which case we must make sure we've initialized ourselves, this 649 // happens the first time egl_get_display() is called. 650 651 clearError(); 652 653 if (egl_init_drivers() == EGL_FALSE) { 654 setError(EGL_BAD_PARAMETER, NULL); 655 return NULL; 656 } 657 658 // These extensions should not be exposed to applications. They're used 659 // internally by the Android EGL layer. 660 if (!strcmp(procname, "eglSetBlobCacheFuncsANDROID") || 661 !strcmp(procname, "eglDupNativeFenceFDANDROID") || 662 !strcmp(procname, "eglWaitSyncANDROID") || 663 !strcmp(procname, "eglHibernateProcessIMG") || 664 !strcmp(procname, "eglAwakenProcessIMG")) { 665 return NULL; 666 } 667 668 __eglMustCastToProperFunctionPointerType addr; 669 addr = findProcAddress(procname, sExtentionMap, NELEM(sExtentionMap)); 670 if (addr) return addr; 671 672 673 // this protects accesses to sGLExtentionMap and sGLExtentionSlot 674 pthread_mutex_lock(&sExtensionMapMutex); 675 676 /* 677 * Since eglGetProcAddress() is not associated to anything, it needs 678 * to return a function pointer that "works" regardless of what 679 * the current context is. 680 * 681 * For this reason, we return a "forwarder", a small stub that takes 682 * care of calling the function associated with the context 683 * currently bound. 684 * 685 * We first look for extensions we've already resolved, if we're seeing 686 * this extension for the first time, we go through all our 687 * implementations and call eglGetProcAddress() and record the 688 * result in the appropriate implementation hooks and return the 689 * address of the forwarder corresponding to that hook set. 690 * 691 */ 692 693 const String8 name(procname); 694 addr = sGLExtentionMap.valueFor(name); 695 const int slot = sGLExtentionSlot; 696 697 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS, 698 "no more slots for eglGetProcAddress(\"%s\")", 699 procname); 700 701#if EGL_TRACE 702 gl_hooks_t *debugHooks = GLTrace_getGLHooks(); 703#endif 704 705 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) { 706 bool found = false; 707 708 egl_connection_t* const cnx = &gEGLImpl; 709 if (cnx->dso && cnx->egl.eglGetProcAddress) { 710 found = true; 711 // Extensions are independent of the bound context 712 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] = 713 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] = 714#if EGL_TRACE 715 debugHooks->ext.extensions[slot] = 716 gHooksTrace.ext.extensions[slot] = 717#endif 718 cnx->egl.eglGetProcAddress(procname); 719 } 720 721 if (found) { 722 addr = gExtensionForwarders[slot]; 723 sGLExtentionMap.add(name, addr); 724 sGLExtentionSlot++; 725 } 726 } 727 728 pthread_mutex_unlock(&sExtensionMapMutex); 729 return addr; 730} 731 732class FrameCompletionThread : public Thread { 733public: 734 735 static void queueSync(EGLSyncKHR sync) { 736 static sp<FrameCompletionThread> thread(new FrameCompletionThread); 737 static bool running = false; 738 if (!running) { 739 thread->run("GPUFrameCompletion"); 740 running = true; 741 } 742 { 743 Mutex::Autolock lock(thread->mMutex); 744 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d", 745 thread->mFramesQueued).string()); 746 thread->mQueue.push_back(sync); 747 thread->mCondition.signal(); 748 thread->mFramesQueued++; 749 ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size()); 750 } 751 } 752 753private: 754 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {} 755 756 virtual bool threadLoop() { 757 EGLSyncKHR sync; 758 uint32_t frameNum; 759 { 760 Mutex::Autolock lock(mMutex); 761 while (mQueue.isEmpty()) { 762 mCondition.wait(mMutex); 763 } 764 sync = mQueue[0]; 765 frameNum = mFramesCompleted; 766 } 767 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); 768 { 769 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d", 770 frameNum).string()); 771 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR); 772 if (result == EGL_FALSE) { 773 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError()); 774 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { 775 ALOGE("FrameCompletion: timeout waiting for fence"); 776 } 777 eglDestroySyncKHR(dpy, sync); 778 } 779 { 780 Mutex::Autolock lock(mMutex); 781 mQueue.removeAt(0); 782 mFramesCompleted++; 783 ATRACE_INT("GPU Frames Outstanding", mQueue.size()); 784 } 785 return true; 786 } 787 788 uint32_t mFramesQueued; 789 uint32_t mFramesCompleted; 790 Vector<EGLSyncKHR> mQueue; 791 Condition mCondition; 792 Mutex mMutex; 793}; 794 795EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) 796{ 797 ATRACE_CALL(); 798 clearError(); 799 800 const egl_display_ptr dp = validate_display(dpy); 801 if (!dp) return EGL_FALSE; 802 803 SurfaceRef _s(dp.get(), draw); 804 if (!_s.get()) 805 return setError(EGL_BAD_SURFACE, EGL_FALSE); 806 807#if EGL_TRACE 808 if (gEGLDebugLevel > 0) 809 GLTrace_eglSwapBuffers(dpy, draw); 810#endif 811 812 egl_surface_t const * const s = get_surface(draw); 813 814 if (CC_UNLIKELY(dp->finishOnSwap)) { 815 uint32_t pixel; 816 egl_context_t * const c = get_context( egl_tls_t::getContext() ); 817 if (c) { 818 // glReadPixels() ensures that the frame is complete 819 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1, 820 GL_RGBA,GL_UNSIGNED_BYTE,&pixel); 821 } 822 } 823 824 EGLBoolean result = s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface); 825 826 if (CC_UNLIKELY(dp->traceGpuCompletion)) { 827 EGLSyncKHR sync = EGL_NO_SYNC_KHR; 828 { 829 sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL); 830 } 831 if (sync != EGL_NO_SYNC_KHR) { 832 FrameCompletionThread::queueSync(sync); 833 } 834 } 835 836 return result; 837} 838 839EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, 840 NativePixmapType target) 841{ 842 clearError(); 843 844 const egl_display_ptr dp = validate_display(dpy); 845 if (!dp) return EGL_FALSE; 846 847 SurfaceRef _s(dp.get(), surface); 848 if (!_s.get()) 849 return setError(EGL_BAD_SURFACE, EGL_FALSE); 850 851 egl_surface_t const * const s = get_surface(surface); 852 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target); 853} 854 855const char* eglQueryString(EGLDisplay dpy, EGLint name) 856{ 857 clearError(); 858 859 const egl_display_ptr dp = validate_display(dpy); 860 if (!dp) return (const char *) NULL; 861 862 switch (name) { 863 case EGL_VENDOR: 864 return dp->getVendorString(); 865 case EGL_VERSION: 866 return dp->getVersionString(); 867 case EGL_EXTENSIONS: 868 return dp->getExtensionString(); 869 case EGL_CLIENT_APIS: 870 return dp->getClientApiString(); 871 case EGL_VERSION_HW_ANDROID: 872 return dp->disp.queryString.version; 873 } 874 return setError(EGL_BAD_PARAMETER, (const char *)0); 875} 876 877 878// ---------------------------------------------------------------------------- 879// EGL 1.1 880// ---------------------------------------------------------------------------- 881 882EGLBoolean eglSurfaceAttrib( 883 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 884{ 885 clearError(); 886 887 const egl_display_ptr dp = validate_display(dpy); 888 if (!dp) return EGL_FALSE; 889 890 SurfaceRef _s(dp.get(), surface); 891 if (!_s.get()) 892 return setError(EGL_BAD_SURFACE, EGL_FALSE); 893 894 egl_surface_t const * const s = get_surface(surface); 895 if (s->cnx->egl.eglSurfaceAttrib) { 896 return s->cnx->egl.eglSurfaceAttrib( 897 dp->disp.dpy, s->surface, attribute, value); 898 } 899 return setError(EGL_BAD_SURFACE, EGL_FALSE); 900} 901 902EGLBoolean eglBindTexImage( 903 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 904{ 905 clearError(); 906 907 const egl_display_ptr dp = validate_display(dpy); 908 if (!dp) return EGL_FALSE; 909 910 SurfaceRef _s(dp.get(), surface); 911 if (!_s.get()) 912 return setError(EGL_BAD_SURFACE, EGL_FALSE); 913 914 egl_surface_t const * const s = get_surface(surface); 915 if (s->cnx->egl.eglBindTexImage) { 916 return s->cnx->egl.eglBindTexImage( 917 dp->disp.dpy, s->surface, buffer); 918 } 919 return setError(EGL_BAD_SURFACE, EGL_FALSE); 920} 921 922EGLBoolean eglReleaseTexImage( 923 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 924{ 925 clearError(); 926 927 const egl_display_ptr dp = validate_display(dpy); 928 if (!dp) return EGL_FALSE; 929 930 SurfaceRef _s(dp.get(), surface); 931 if (!_s.get()) 932 return setError(EGL_BAD_SURFACE, EGL_FALSE); 933 934 egl_surface_t const * const s = get_surface(surface); 935 if (s->cnx->egl.eglReleaseTexImage) { 936 return s->cnx->egl.eglReleaseTexImage( 937 dp->disp.dpy, s->surface, buffer); 938 } 939 return setError(EGL_BAD_SURFACE, EGL_FALSE); 940} 941 942EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 943{ 944 clearError(); 945 946 const egl_display_ptr dp = validate_display(dpy); 947 if (!dp) return EGL_FALSE; 948 949 EGLBoolean res = EGL_TRUE; 950 egl_connection_t* const cnx = &gEGLImpl; 951 if (cnx->dso && cnx->egl.eglSwapInterval) { 952 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval); 953 } 954 955 return res; 956} 957 958 959// ---------------------------------------------------------------------------- 960// EGL 1.2 961// ---------------------------------------------------------------------------- 962 963EGLBoolean eglWaitClient(void) 964{ 965 clearError(); 966 967 egl_connection_t* const cnx = &gEGLImpl; 968 if (!cnx->dso) 969 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 970 971 EGLBoolean res; 972 if (cnx->egl.eglWaitClient) { 973 res = cnx->egl.eglWaitClient(); 974 } else { 975 res = cnx->egl.eglWaitGL(); 976 } 977 return res; 978} 979 980EGLBoolean eglBindAPI(EGLenum api) 981{ 982 clearError(); 983 984 if (egl_init_drivers() == EGL_FALSE) { 985 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 986 } 987 988 // bind this API on all EGLs 989 EGLBoolean res = EGL_TRUE; 990 egl_connection_t* const cnx = &gEGLImpl; 991 if (cnx->dso && cnx->egl.eglBindAPI) { 992 res = cnx->egl.eglBindAPI(api); 993 } 994 return res; 995} 996 997EGLenum eglQueryAPI(void) 998{ 999 clearError(); 1000 1001 if (egl_init_drivers() == EGL_FALSE) { 1002 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1003 } 1004 1005 egl_connection_t* const cnx = &gEGLImpl; 1006 if (cnx->dso && cnx->egl.eglQueryAPI) { 1007 return cnx->egl.eglQueryAPI(); 1008 } 1009 1010 // or, it can only be OpenGL ES 1011 return EGL_OPENGL_ES_API; 1012} 1013 1014EGLBoolean eglReleaseThread(void) 1015{ 1016 clearError(); 1017 1018 // If there is context bound to the thread, release it 1019 egl_display_t::loseCurrent(get_context(getContext())); 1020 1021 egl_connection_t* const cnx = &gEGLImpl; 1022 if (cnx->dso && cnx->egl.eglReleaseThread) { 1023 cnx->egl.eglReleaseThread(); 1024 } 1025 1026 egl_tls_t::clearTLS(); 1027#if EGL_TRACE 1028 if (gEGLDebugLevel > 0) 1029 GLTrace_eglReleaseThread(); 1030#endif 1031 return EGL_TRUE; 1032} 1033 1034EGLSurface eglCreatePbufferFromClientBuffer( 1035 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 1036 EGLConfig config, const EGLint *attrib_list) 1037{ 1038 clearError(); 1039 1040 egl_connection_t* cnx = NULL; 1041 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 1042 if (!dp) return EGL_FALSE; 1043 if (cnx->egl.eglCreatePbufferFromClientBuffer) { 1044 return cnx->egl.eglCreatePbufferFromClientBuffer( 1045 dp->disp.dpy, buftype, buffer, config, attrib_list); 1046 } 1047 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); 1048} 1049 1050// ---------------------------------------------------------------------------- 1051// EGL_EGLEXT_VERSION 3 1052// ---------------------------------------------------------------------------- 1053 1054EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, 1055 const EGLint *attrib_list) 1056{ 1057 clearError(); 1058 1059 const egl_display_ptr dp = validate_display(dpy); 1060 if (!dp) return EGL_FALSE; 1061 1062 SurfaceRef _s(dp.get(), surface); 1063 if (!_s.get()) 1064 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1065 1066 egl_surface_t const * const s = get_surface(surface); 1067 if (s->cnx->egl.eglLockSurfaceKHR) { 1068 return s->cnx->egl.eglLockSurfaceKHR( 1069 dp->disp.dpy, s->surface, attrib_list); 1070 } 1071 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1072} 1073 1074EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) 1075{ 1076 clearError(); 1077 1078 const egl_display_ptr dp = validate_display(dpy); 1079 if (!dp) return EGL_FALSE; 1080 1081 SurfaceRef _s(dp.get(), surface); 1082 if (!_s.get()) 1083 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1084 1085 egl_surface_t const * const s = get_surface(surface); 1086 if (s->cnx->egl.eglUnlockSurfaceKHR) { 1087 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface); 1088 } 1089 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1090} 1091 1092EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1093 EGLClientBuffer buffer, const EGLint *attrib_list) 1094{ 1095 clearError(); 1096 1097 const egl_display_ptr dp = validate_display(dpy); 1098 if (!dp) return EGL_NO_IMAGE_KHR; 1099 1100 ContextRef _c(dp.get(), ctx); 1101 egl_context_t * const c = _c.get(); 1102 1103 EGLImageKHR result = EGL_NO_IMAGE_KHR; 1104 egl_connection_t* const cnx = &gEGLImpl; 1105 if (cnx->dso && cnx->egl.eglCreateImageKHR) { 1106 result = cnx->egl.eglCreateImageKHR( 1107 dp->disp.dpy, 1108 c ? c->context : EGL_NO_CONTEXT, 1109 target, buffer, attrib_list); 1110 } 1111 return result; 1112} 1113 1114EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 1115{ 1116 clearError(); 1117 1118 const egl_display_ptr dp = validate_display(dpy); 1119 if (!dp) return EGL_FALSE; 1120 1121 egl_connection_t* const cnx = &gEGLImpl; 1122 if (cnx->dso && cnx->egl.eglDestroyImageKHR) { 1123 cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img); 1124 } 1125 return EGL_TRUE; 1126} 1127 1128// ---------------------------------------------------------------------------- 1129// EGL_EGLEXT_VERSION 5 1130// ---------------------------------------------------------------------------- 1131 1132 1133EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) 1134{ 1135 clearError(); 1136 1137 const egl_display_ptr dp = validate_display(dpy); 1138 if (!dp) return EGL_NO_SYNC_KHR; 1139 1140 EGLSyncKHR result = EGL_NO_SYNC_KHR; 1141 egl_connection_t* const cnx = &gEGLImpl; 1142 if (cnx->dso && cnx->egl.eglCreateSyncKHR) { 1143 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list); 1144 } 1145 return result; 1146} 1147 1148EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) 1149{ 1150 clearError(); 1151 1152 const egl_display_ptr dp = validate_display(dpy); 1153 if (!dp) return EGL_FALSE; 1154 1155 EGLBoolean result = EGL_FALSE; 1156 egl_connection_t* const cnx = &gEGLImpl; 1157 if (cnx->dso && cnx->egl.eglDestroySyncKHR) { 1158 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync); 1159 } 1160 return result; 1161} 1162 1163EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, 1164 EGLint flags, EGLTimeKHR timeout) 1165{ 1166 clearError(); 1167 1168 const egl_display_ptr dp = validate_display(dpy); 1169 if (!dp) return EGL_FALSE; 1170 1171 EGLBoolean result = EGL_FALSE; 1172 egl_connection_t* const cnx = &gEGLImpl; 1173 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) { 1174 result = cnx->egl.eglClientWaitSyncKHR( 1175 dp->disp.dpy, sync, flags, timeout); 1176 } 1177 return result; 1178} 1179 1180EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, 1181 EGLint attribute, EGLint *value) 1182{ 1183 clearError(); 1184 1185 const egl_display_ptr dp = validate_display(dpy); 1186 if (!dp) return EGL_FALSE; 1187 1188 EGLBoolean result = EGL_FALSE; 1189 egl_connection_t* const cnx = &gEGLImpl; 1190 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) { 1191 result = cnx->egl.eglGetSyncAttribKHR( 1192 dp->disp.dpy, sync, attribute, value); 1193 } 1194 return result; 1195} 1196 1197// ---------------------------------------------------------------------------- 1198// ANDROID extensions 1199// ---------------------------------------------------------------------------- 1200 1201EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync) 1202{ 1203 clearError(); 1204 1205 const egl_display_ptr dp = validate_display(dpy); 1206 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID; 1207 1208 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID; 1209 egl_connection_t* const cnx = &gEGLImpl; 1210 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) { 1211 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync); 1212 } 1213 return result; 1214} 1215 1216EGLint eglWaitSyncANDROID(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) 1217{ 1218 clearError(); 1219 1220 const egl_display_ptr dp = validate_display(dpy); 1221 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID; 1222 1223 EGLint result = EGL_FALSE; 1224 egl_connection_t* const cnx = &gEGLImpl; 1225 if (cnx->dso && cnx->egl.eglWaitSyncANDROID) { 1226 result = cnx->egl.eglWaitSyncANDROID(dp->disp.dpy, sync, flags); 1227 } 1228 return result; 1229} 1230 1231// ---------------------------------------------------------------------------- 1232// NVIDIA extensions 1233// ---------------------------------------------------------------------------- 1234EGLuint64NV eglGetSystemTimeFrequencyNV() 1235{ 1236 clearError(); 1237 1238 if (egl_init_drivers() == EGL_FALSE) { 1239 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1240 } 1241 1242 EGLuint64NV ret = 0; 1243 egl_connection_t* const cnx = &gEGLImpl; 1244 1245 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) { 1246 return cnx->egl.eglGetSystemTimeFrequencyNV(); 1247 } 1248 1249 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1250} 1251 1252EGLuint64NV eglGetSystemTimeNV() 1253{ 1254 clearError(); 1255 1256 if (egl_init_drivers() == EGL_FALSE) { 1257 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1258 } 1259 1260 EGLuint64NV ret = 0; 1261 egl_connection_t* const cnx = &gEGLImpl; 1262 1263 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) { 1264 return cnx->egl.eglGetSystemTimeNV(); 1265 } 1266 1267 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1268} 1269