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