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