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