eglApi.cpp revision 77a9b4a6bd21188e2744ae9dcd8092c6837bff7c
1/* 2 ** Copyright 2007, The Android Open Source Project 3 ** 4 ** Licensed under the Apache License, Version 2.0 (the "License"); 5 ** you may not use this file except in compliance with the License. 6 ** You may obtain a copy of the License at 7 ** 8 ** http://www.apache.org/licenses/LICENSE-2.0 9 ** 10 ** Unless required by applicable law or agreed to in writing, software 11 ** distributed under the License is distributed on an "AS IS" BASIS, 12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 ** See the License for the specific language governing permissions and 14 ** limitations under the License. 15 */ 16 17#define ATRACE_TAG ATRACE_TAG_GRAPHICS 18 19#include <ctype.h> 20#include <stdlib.h> 21#include <string.h> 22 23#include <hardware/gralloc.h> 24#include <system/window.h> 25 26#include <EGL/egl.h> 27#include <EGL/eglext.h> 28#include <GLES/gl.h> 29#include <GLES/glext.h> 30 31#include <cutils/log.h> 32#include <cutils/atomic.h> 33#include <cutils/compiler.h> 34#include <cutils/properties.h> 35#include <cutils/memory.h> 36 37#include <utils/KeyedVector.h> 38#include <utils/SortedVector.h> 39#include <utils/String8.h> 40#include <utils/Trace.h> 41 42#include "egl_impl.h" 43#include "egl_tls.h" 44#include "glestrace.h" 45#include "hooks.h" 46 47#include "egl_display.h" 48#include "egl_impl.h" 49#include "egl_object.h" 50#include "egl_tls.h" 51#include "egldefs.h" 52 53using namespace android; 54 55// ---------------------------------------------------------------------------- 56 57#define EGL_VERSION_HW_ANDROID 0x3143 58 59struct extention_map_t { 60 const char* name; 61 __eglMustCastToProperFunctionPointerType address; 62}; 63 64static const extention_map_t sExtentionMap[] = { 65 { "eglLockSurfaceKHR", 66 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR }, 67 { "eglUnlockSurfaceKHR", 68 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR }, 69 { "eglCreateImageKHR", 70 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, 71 { "eglDestroyImageKHR", 72 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, 73 { "eglGetSystemTimeFrequencyNV", 74 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV }, 75 { "eglGetSystemTimeNV", 76 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV }, 77}; 78 79// accesses protected by sExtensionMapMutex 80static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap; 81static int sGLExtentionSlot = 0; 82static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER; 83 84static void(*findProcAddress(const char* name, 85 const extention_map_t* map, size_t n))() { 86 for (uint32_t i=0 ; i<n ; i++) { 87 if (!strcmp(name, map[i].name)) { 88 return map[i].address; 89 } 90 } 91 return NULL; 92} 93 94// ---------------------------------------------------------------------------- 95 96namespace android { 97extern void setGLHooksThreadSpecific(gl_hooks_t const *value); 98extern EGLBoolean egl_init_drivers(); 99extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS]; 100extern int gEGLDebugLevel; 101extern gl_hooks_t gHooksTrace; 102} // namespace android; 103 104// ---------------------------------------------------------------------------- 105 106static inline void clearError() { egl_tls_t::clearError(); } 107static inline EGLContext getContext() { return egl_tls_t::getContext(); } 108 109// ---------------------------------------------------------------------------- 110 111EGLDisplay eglGetDisplay(EGLNativeDisplayType display) 112{ 113 clearError(); 114 115 uint32_t index = uint32_t(display); 116 if (index >= NUM_DISPLAYS) { 117 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 118 } 119 120 if (egl_init_drivers() == EGL_FALSE) { 121 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 122 } 123 124 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display); 125 return dpy; 126} 127 128// ---------------------------------------------------------------------------- 129// Initialization 130// ---------------------------------------------------------------------------- 131 132EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) 133{ 134 clearError(); 135 136 egl_display_ptr dp = get_display(dpy); 137 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 138 139 EGLBoolean res = dp->initialize(major, minor); 140 141 return res; 142} 143 144EGLBoolean eglTerminate(EGLDisplay dpy) 145{ 146 // NOTE: don't unload the drivers b/c some APIs can be called 147 // after eglTerminate() has been called. eglTerminate() only 148 // terminates an EGLDisplay, not a EGL itself. 149 150 clearError(); 151 152 egl_display_ptr dp = get_display(dpy); 153 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 154 155 EGLBoolean res = dp->terminate(); 156 157 return res; 158} 159 160// ---------------------------------------------------------------------------- 161// configuration 162// ---------------------------------------------------------------------------- 163 164EGLBoolean eglGetConfigs( EGLDisplay dpy, 165 EGLConfig *configs, 166 EGLint config_size, EGLint *num_config) 167{ 168 clearError(); 169 170 const egl_display_ptr dp = validate_display(dpy); 171 if (!dp) return EGL_FALSE; 172 173 if (num_config==0) { 174 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 175 } 176 177 EGLBoolean res = EGL_FALSE; 178 *num_config = 0; 179 180 egl_connection_t* const cnx = &gEGLImpl; 181 if (cnx->dso) { 182 res = cnx->egl.eglGetConfigs( 183 dp->disp.dpy, configs, config_size, num_config); 184 } 185 186 return res; 187} 188 189EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, 190 EGLConfig *configs, EGLint config_size, 191 EGLint *num_config) 192{ 193 clearError(); 194 195 const egl_display_ptr dp = validate_display(dpy); 196 if (!dp) return EGL_FALSE; 197 198 if (num_config==0) { 199 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 200 } 201 202 EGLBoolean res = EGL_FALSE; 203 *num_config = 0; 204 205 egl_connection_t* const cnx = &gEGLImpl; 206 if (cnx->dso) { 207 if (attrib_list) { 208 char value[PROPERTY_VALUE_MAX]; 209 property_get("debug.egl.force_msaa", value, "false"); 210 211 if (!strcmp(value, "true")) { 212 size_t attribCount = 0; 213 EGLint attrib = attrib_list[0]; 214 215 // Only enable MSAA if the context is OpenGL ES 2.0 and 216 // if no caveat is requested 217 const EGLint *attribRendererable = NULL; 218 const EGLint *attribCaveat = NULL; 219 220 // Count the number of attributes and look for 221 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT 222 while (attrib != EGL_NONE) { 223 attrib = attrib_list[attribCount]; 224 switch (attrib) { 225 case EGL_RENDERABLE_TYPE: 226 attribRendererable = &attrib_list[attribCount]; 227 break; 228 case EGL_CONFIG_CAVEAT: 229 attribCaveat = &attrib_list[attribCount]; 230 break; 231 } 232 attribCount++; 233 } 234 235 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT && 236 (!attribCaveat || attribCaveat[1] != EGL_NONE)) { 237 238 // Insert 2 extra attributes to force-enable MSAA 4x 239 EGLint aaAttribs[attribCount + 4]; 240 aaAttribs[0] = EGL_SAMPLE_BUFFERS; 241 aaAttribs[1] = 1; 242 aaAttribs[2] = EGL_SAMPLES; 243 aaAttribs[3] = 4; 244 245 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint)); 246 247 EGLint numConfigAA; 248 EGLBoolean resAA = cnx->egl.eglChooseConfig( 249 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA); 250 251 if (resAA == EGL_TRUE && numConfigAA > 0) { 252 ALOGD("Enabling MSAA 4x"); 253 *num_config = numConfigAA; 254 return resAA; 255 } 256 } 257 } 258 } 259 260 res = cnx->egl.eglChooseConfig( 261 dp->disp.dpy, attrib_list, configs, config_size, num_config); 262 } 263 return res; 264} 265 266EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, 267 EGLint attribute, EGLint *value) 268{ 269 clearError(); 270 271 egl_connection_t* cnx = NULL; 272 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 273 if (!dp) return EGL_FALSE; 274 275 return cnx->egl.eglGetConfigAttrib( 276 dp->disp.dpy, config, attribute, value); 277} 278 279// ---------------------------------------------------------------------------- 280// surfaces 281// ---------------------------------------------------------------------------- 282 283EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, 284 NativeWindowType window, 285 const EGLint *attrib_list) 286{ 287 clearError(); 288 289 egl_connection_t* cnx = NULL; 290 egl_display_ptr dp = validate_display_connection(dpy, cnx); 291 if (dp) { 292 EGLDisplay iDpy = dp->disp.dpy; 293 EGLint format; 294 295 if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != OK) { 296 ALOGE("EGLNativeWindowType %p already connected to another API", 297 window); 298 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); 299 } 300 301 // set the native window's buffers format to match this config 302 if (cnx->egl.eglGetConfigAttrib(iDpy, 303 config, EGL_NATIVE_VISUAL_ID, &format)) { 304 if (format != 0) { 305 int err = native_window_set_buffers_format(window, format); 306 if (err != 0) { 307 ALOGE("error setting native window pixel format: %s (%d)", 308 strerror(-err), err); 309 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 310 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 311 } 312 } 313 } 314 315 // the EGL spec requires that a new EGLSurface default to swap interval 316 // 1, so explicitly set that on the window here. 317 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window); 318 anw->setSwapInterval(anw, 1); 319 320 EGLSurface surface = cnx->egl.eglCreateWindowSurface( 321 iDpy, config, window, attrib_list); 322 if (surface != EGL_NO_SURFACE) { 323 egl_surface_t* s = new egl_surface_t(dp.get(), config, window, 324 surface, cnx); 325 return s; 326 } 327 328 // EGLSurface creation failed 329 native_window_set_buffers_format(window, 0); 330 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 331 } 332 return EGL_NO_SURFACE; 333} 334 335EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, 336 NativePixmapType pixmap, 337 const EGLint *attrib_list) 338{ 339 clearError(); 340 341 egl_connection_t* cnx = NULL; 342 egl_display_ptr dp = validate_display_connection(dpy, cnx); 343 if (dp) { 344 EGLSurface surface = cnx->egl.eglCreatePixmapSurface( 345 dp->disp.dpy, config, pixmap, attrib_list); 346 if (surface != EGL_NO_SURFACE) { 347 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, 348 surface, cnx); 349 return s; 350 } 351 } 352 return EGL_NO_SURFACE; 353} 354 355EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, 356 const EGLint *attrib_list) 357{ 358 clearError(); 359 360 egl_connection_t* cnx = NULL; 361 egl_display_ptr dp = validate_display_connection(dpy, cnx); 362 if (dp) { 363 EGLSurface surface = cnx->egl.eglCreatePbufferSurface( 364 dp->disp.dpy, config, attrib_list); 365 if (surface != EGL_NO_SURFACE) { 366 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, 367 surface, cnx); 368 return s; 369 } 370 } 371 return EGL_NO_SURFACE; 372} 373 374EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) 375{ 376 clearError(); 377 378 const egl_display_ptr dp = validate_display(dpy); 379 if (!dp) return EGL_FALSE; 380 381 SurfaceRef _s(dp.get(), surface); 382 if (!_s.get()) 383 return setError(EGL_BAD_SURFACE, EGL_FALSE); 384 385 egl_surface_t * const s = get_surface(surface); 386 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface); 387 if (result == EGL_TRUE) { 388 _s.terminate(); 389 } 390 return result; 391} 392 393EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface, 394 EGLint attribute, EGLint *value) 395{ 396 clearError(); 397 398 const egl_display_ptr dp = validate_display(dpy); 399 if (!dp) return EGL_FALSE; 400 401 SurfaceRef _s(dp.get(), surface); 402 if (!_s.get()) 403 return setError(EGL_BAD_SURFACE, EGL_FALSE); 404 405 egl_surface_t const * const s = get_surface(surface); 406 return s->cnx->egl.eglQuerySurface( 407 dp->disp.dpy, s->surface, attribute, value); 408} 409 410void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) { 411 ATRACE_CALL(); 412 clearError(); 413 414 const egl_display_ptr dp = validate_display(dpy); 415 if (!dp) { 416 return; 417 } 418 419 SurfaceRef _s(dp.get(), surface); 420 if (!_s.get()) { 421 setError(EGL_BAD_SURFACE, EGL_FALSE); 422 return; 423 } 424 425 int64_t timestamp = systemTime(SYSTEM_TIME_MONOTONIC); 426 427 egl_surface_t const * const s = get_surface(surface); 428 native_window_set_buffers_timestamp(s->win.get(), timestamp); 429} 430 431// ---------------------------------------------------------------------------- 432// Contexts 433// ---------------------------------------------------------------------------- 434 435EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, 436 EGLContext share_list, const EGLint *attrib_list) 437{ 438 clearError(); 439 440 egl_connection_t* cnx = NULL; 441 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 442 if (dp) { 443 if (share_list != EGL_NO_CONTEXT) { 444 if (!ContextRef(dp.get(), share_list).get()) { 445 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT); 446 } 447 egl_context_t* const c = get_context(share_list); 448 share_list = c->context; 449 } 450 EGLContext context = cnx->egl.eglCreateContext( 451 dp->disp.dpy, config, share_list, attrib_list); 452 if (context != EGL_NO_CONTEXT) { 453 // figure out if it's a GLESv1 or GLESv2 454 int version = 0; 455 if (attrib_list) { 456 while (*attrib_list != EGL_NONE) { 457 GLint attr = *attrib_list++; 458 GLint value = *attrib_list++; 459 if (attr == EGL_CONTEXT_CLIENT_VERSION) { 460 if (value == 1) { 461 version = egl_connection_t::GLESv1_INDEX; 462 } else if (value == 2) { 463 version = egl_connection_t::GLESv2_INDEX; 464 } 465 } 466 }; 467 } 468 egl_context_t* c = new egl_context_t(dpy, context, config, cnx, 469 version); 470#if EGL_TRACE 471 if (gEGLDebugLevel > 0) 472 GLTrace_eglCreateContext(version, c); 473#endif 474 return c; 475 } else { 476 EGLint error = eglGetError(); 477 ALOGE_IF(error == EGL_SUCCESS, 478 "eglCreateContext(%p, %p, %p, %p) returned EGL_NO_CONTEXT " 479 "but no EGL error!", 480 dpy, config, share_list, attrib_list); 481 } 482 } 483 return EGL_NO_CONTEXT; 484} 485 486EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) 487{ 488 clearError(); 489 490 const egl_display_ptr dp = validate_display(dpy); 491 if (!dp) 492 return EGL_FALSE; 493 494 ContextRef _c(dp.get(), ctx); 495 if (!_c.get()) 496 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 497 498 egl_context_t * const c = get_context(ctx); 499 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context); 500 if (result == EGL_TRUE) { 501 _c.terminate(); 502 } 503 return result; 504} 505 506EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, 507 EGLSurface read, EGLContext ctx) 508{ 509 clearError(); 510 511 egl_display_ptr dp = validate_display(dpy); 512 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 513 514 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not 515 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is 516 // a valid but uninitialized display. 517 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) || 518 (draw != EGL_NO_SURFACE) ) { 519 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE); 520 } 521 522 // get a reference to the object passed in 523 ContextRef _c(dp.get(), ctx); 524 SurfaceRef _d(dp.get(), draw); 525 SurfaceRef _r(dp.get(), read); 526 527 // validate the context (if not EGL_NO_CONTEXT) 528 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) { 529 // EGL_NO_CONTEXT is valid 530 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 531 } 532 533 // these are the underlying implementation's object 534 EGLContext impl_ctx = EGL_NO_CONTEXT; 535 EGLSurface impl_draw = EGL_NO_SURFACE; 536 EGLSurface impl_read = EGL_NO_SURFACE; 537 538 // these are our objects structs passed in 539 egl_context_t * c = NULL; 540 egl_surface_t const * d = NULL; 541 egl_surface_t const * r = NULL; 542 543 // these are the current objects structs 544 egl_context_t * cur_c = get_context(getContext()); 545 546 if (ctx != EGL_NO_CONTEXT) { 547 c = get_context(ctx); 548 impl_ctx = c->context; 549 } else { 550 // no context given, use the implementation of the current context 551 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) { 552 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT); 553 return setError(EGL_BAD_MATCH, EGL_FALSE); 554 } 555 if (cur_c == NULL) { 556 // no current context 557 // not an error, there is just no current context. 558 return EGL_TRUE; 559 } 560 } 561 562 // retrieve the underlying implementation's draw EGLSurface 563 if (draw != EGL_NO_SURFACE) { 564 if (!_d.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 565 d = get_surface(draw); 566 impl_draw = d->surface; 567 } 568 569 // retrieve the underlying implementation's read EGLSurface 570 if (read != EGL_NO_SURFACE) { 571 if (!_r.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 572 r = get_surface(read); 573 impl_read = r->surface; 574 } 575 576 577 EGLBoolean result = dp->makeCurrent(c, cur_c, 578 draw, read, ctx, 579 impl_draw, impl_read, impl_ctx); 580 581 if (result == EGL_TRUE) { 582 if (c) { 583 setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 584 egl_tls_t::setContext(ctx); 585#if EGL_TRACE 586 if (gEGLDebugLevel > 0) 587 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx); 588#endif 589 _c.acquire(); 590 _r.acquire(); 591 _d.acquire(); 592 } else { 593 setGLHooksThreadSpecific(&gHooksNoContext); 594 egl_tls_t::setContext(EGL_NO_CONTEXT); 595 } 596 } else { 597 // this will ALOGE the error 598 result = setError(c->cnx->egl.eglGetError(), EGL_FALSE); 599 } 600 return result; 601} 602 603 604EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, 605 EGLint attribute, EGLint *value) 606{ 607 clearError(); 608 609 const egl_display_ptr dp = validate_display(dpy); 610 if (!dp) return EGL_FALSE; 611 612 ContextRef _c(dp.get(), ctx); 613 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 614 615 egl_context_t * const c = get_context(ctx); 616 return c->cnx->egl.eglQueryContext( 617 dp->disp.dpy, c->context, attribute, value); 618 619} 620 621EGLContext eglGetCurrentContext(void) 622{ 623 // could be called before eglInitialize(), but we wouldn't have a context 624 // then, and this function would correctly return EGL_NO_CONTEXT. 625 626 clearError(); 627 628 EGLContext ctx = getContext(); 629 return ctx; 630} 631 632EGLSurface eglGetCurrentSurface(EGLint readdraw) 633{ 634 // could be called before eglInitialize(), but we wouldn't have a context 635 // then, and this function would correctly return EGL_NO_SURFACE. 636 637 clearError(); 638 639 EGLContext ctx = getContext(); 640 if (ctx) { 641 egl_context_t const * const c = get_context(ctx); 642 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 643 switch (readdraw) { 644 case EGL_READ: return c->read; 645 case EGL_DRAW: return c->draw; 646 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 647 } 648 } 649 return EGL_NO_SURFACE; 650} 651 652EGLDisplay eglGetCurrentDisplay(void) 653{ 654 // could be called before eglInitialize(), but we wouldn't have a context 655 // then, and this function would correctly return EGL_NO_DISPLAY. 656 657 clearError(); 658 659 EGLContext ctx = getContext(); 660 if (ctx) { 661 egl_context_t const * const c = get_context(ctx); 662 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 663 return c->dpy; 664 } 665 return EGL_NO_DISPLAY; 666} 667 668EGLBoolean eglWaitGL(void) 669{ 670 clearError(); 671 672 egl_connection_t* const cnx = &gEGLImpl; 673 if (!cnx->dso) 674 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 675 676 return cnx->egl.eglWaitGL(); 677} 678 679EGLBoolean eglWaitNative(EGLint engine) 680{ 681 clearError(); 682 683 egl_connection_t* const cnx = &gEGLImpl; 684 if (!cnx->dso) 685 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 686 687 return cnx->egl.eglWaitNative(engine); 688} 689 690EGLint eglGetError(void) 691{ 692 EGLint err = EGL_SUCCESS; 693 egl_connection_t* const cnx = &gEGLImpl; 694 if (cnx->dso) { 695 err = cnx->egl.eglGetError(); 696 } 697 if (err == EGL_SUCCESS) { 698 err = egl_tls_t::getError(); 699 } 700 return err; 701} 702 703__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) 704{ 705 // eglGetProcAddress() could be the very first function called 706 // in which case we must make sure we've initialized ourselves, this 707 // happens the first time egl_get_display() is called. 708 709 clearError(); 710 711 if (egl_init_drivers() == EGL_FALSE) { 712 setError(EGL_BAD_PARAMETER, NULL); 713 return NULL; 714 } 715 716 // These extensions should not be exposed to applications. They're used 717 // internally by the Android EGL layer. 718 if (!strcmp(procname, "eglSetBlobCacheFuncsANDROID") || 719 !strcmp(procname, "eglDupNativeFenceFDANDROID") || 720 !strcmp(procname, "eglWaitSyncANDROID") || 721 !strcmp(procname, "eglHibernateProcessIMG") || 722 !strcmp(procname, "eglAwakenProcessIMG")) { 723 return NULL; 724 } 725 726 __eglMustCastToProperFunctionPointerType addr; 727 addr = findProcAddress(procname, sExtentionMap, NELEM(sExtentionMap)); 728 if (addr) return addr; 729 730 731 // this protects accesses to sGLExtentionMap and sGLExtentionSlot 732 pthread_mutex_lock(&sExtensionMapMutex); 733 734 /* 735 * Since eglGetProcAddress() is not associated to anything, it needs 736 * to return a function pointer that "works" regardless of what 737 * the current context is. 738 * 739 * For this reason, we return a "forwarder", a small stub that takes 740 * care of calling the function associated with the context 741 * currently bound. 742 * 743 * We first look for extensions we've already resolved, if we're seeing 744 * this extension for the first time, we go through all our 745 * implementations and call eglGetProcAddress() and record the 746 * result in the appropriate implementation hooks and return the 747 * address of the forwarder corresponding to that hook set. 748 * 749 */ 750 751 const String8 name(procname); 752 addr = sGLExtentionMap.valueFor(name); 753 const int slot = sGLExtentionSlot; 754 755 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS, 756 "no more slots for eglGetProcAddress(\"%s\")", 757 procname); 758 759#if EGL_TRACE 760 gl_hooks_t *debugHooks = GLTrace_getGLHooks(); 761#endif 762 763 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) { 764 bool found = false; 765 766 egl_connection_t* const cnx = &gEGLImpl; 767 if (cnx->dso && cnx->egl.eglGetProcAddress) { 768 // Extensions are independent of the bound context 769 addr = 770 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] = 771 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] = 772#if EGL_TRACE 773 debugHooks->ext.extensions[slot] = 774 gHooksTrace.ext.extensions[slot] = 775#endif 776 cnx->egl.eglGetProcAddress(procname); 777 if (addr) found = true; 778 } 779 780 if (found) { 781#if USE_FAST_TLS_KEY 782 addr = gExtensionForwarders[slot]; 783#endif 784 sGLExtentionMap.add(name, addr); 785 sGLExtentionSlot++; 786 } 787 } 788 789 pthread_mutex_unlock(&sExtensionMapMutex); 790 return addr; 791} 792 793class FrameCompletionThread : public Thread { 794public: 795 796 static void queueSync(EGLSyncKHR sync) { 797 static sp<FrameCompletionThread> thread(new FrameCompletionThread); 798 static bool running = false; 799 if (!running) { 800 thread->run("GPUFrameCompletion"); 801 running = true; 802 } 803 { 804 Mutex::Autolock lock(thread->mMutex); 805 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d", 806 thread->mFramesQueued).string()); 807 thread->mQueue.push_back(sync); 808 thread->mCondition.signal(); 809 thread->mFramesQueued++; 810 ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size()); 811 } 812 } 813 814private: 815 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {} 816 817 virtual bool threadLoop() { 818 EGLSyncKHR sync; 819 uint32_t frameNum; 820 { 821 Mutex::Autolock lock(mMutex); 822 while (mQueue.isEmpty()) { 823 mCondition.wait(mMutex); 824 } 825 sync = mQueue[0]; 826 frameNum = mFramesCompleted; 827 } 828 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); 829 { 830 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d", 831 frameNum).string()); 832 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR); 833 if (result == EGL_FALSE) { 834 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError()); 835 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { 836 ALOGE("FrameCompletion: timeout waiting for fence"); 837 } 838 eglDestroySyncKHR(dpy, sync); 839 } 840 { 841 Mutex::Autolock lock(mMutex); 842 mQueue.removeAt(0); 843 mFramesCompleted++; 844 ATRACE_INT("GPU Frames Outstanding", mQueue.size()); 845 } 846 return true; 847 } 848 849 uint32_t mFramesQueued; 850 uint32_t mFramesCompleted; 851 Vector<EGLSyncKHR> mQueue; 852 Condition mCondition; 853 Mutex mMutex; 854}; 855 856EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) 857{ 858 ATRACE_CALL(); 859 clearError(); 860 861 const egl_display_ptr dp = validate_display(dpy); 862 if (!dp) return EGL_FALSE; 863 864 SurfaceRef _s(dp.get(), draw); 865 if (!_s.get()) 866 return setError(EGL_BAD_SURFACE, EGL_FALSE); 867 868#if EGL_TRACE 869 if (gEGLDebugLevel > 0) 870 GLTrace_eglSwapBuffers(dpy, draw); 871#endif 872 873 egl_surface_t const * const s = get_surface(draw); 874 875 if (CC_UNLIKELY(dp->finishOnSwap)) { 876 uint32_t pixel; 877 egl_context_t * const c = get_context( egl_tls_t::getContext() ); 878 if (c) { 879 // glReadPixels() ensures that the frame is complete 880 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1, 881 GL_RGBA,GL_UNSIGNED_BYTE,&pixel); 882 } 883 } 884 885 EGLBoolean result = s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface); 886 887 if (CC_UNLIKELY(dp->traceGpuCompletion)) { 888 EGLSyncKHR sync = EGL_NO_SYNC_KHR; 889 { 890 sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL); 891 } 892 if (sync != EGL_NO_SYNC_KHR) { 893 FrameCompletionThread::queueSync(sync); 894 } 895 } 896 897 return result; 898} 899 900EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, 901 NativePixmapType target) 902{ 903 clearError(); 904 905 const egl_display_ptr dp = validate_display(dpy); 906 if (!dp) return EGL_FALSE; 907 908 SurfaceRef _s(dp.get(), surface); 909 if (!_s.get()) 910 return setError(EGL_BAD_SURFACE, EGL_FALSE); 911 912 egl_surface_t const * const s = get_surface(surface); 913 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target); 914} 915 916const char* eglQueryString(EGLDisplay dpy, EGLint name) 917{ 918 clearError(); 919 920 const egl_display_ptr dp = validate_display(dpy); 921 if (!dp) return (const char *) NULL; 922 923 switch (name) { 924 case EGL_VENDOR: 925 return dp->getVendorString(); 926 case EGL_VERSION: 927 return dp->getVersionString(); 928 case EGL_EXTENSIONS: 929 return dp->getExtensionString(); 930 case EGL_CLIENT_APIS: 931 return dp->getClientApiString(); 932 case EGL_VERSION_HW_ANDROID: 933 return dp->disp.queryString.version; 934 } 935 return setError(EGL_BAD_PARAMETER, (const char *)0); 936} 937 938 939// ---------------------------------------------------------------------------- 940// EGL 1.1 941// ---------------------------------------------------------------------------- 942 943EGLBoolean eglSurfaceAttrib( 944 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 945{ 946 clearError(); 947 948 const egl_display_ptr dp = validate_display(dpy); 949 if (!dp) return EGL_FALSE; 950 951 SurfaceRef _s(dp.get(), surface); 952 if (!_s.get()) 953 return setError(EGL_BAD_SURFACE, EGL_FALSE); 954 955 egl_surface_t const * const s = get_surface(surface); 956 if (s->cnx->egl.eglSurfaceAttrib) { 957 return s->cnx->egl.eglSurfaceAttrib( 958 dp->disp.dpy, s->surface, attribute, value); 959 } 960 return setError(EGL_BAD_SURFACE, EGL_FALSE); 961} 962 963EGLBoolean eglBindTexImage( 964 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 965{ 966 clearError(); 967 968 const egl_display_ptr dp = validate_display(dpy); 969 if (!dp) return EGL_FALSE; 970 971 SurfaceRef _s(dp.get(), surface); 972 if (!_s.get()) 973 return setError(EGL_BAD_SURFACE, EGL_FALSE); 974 975 egl_surface_t const * const s = get_surface(surface); 976 if (s->cnx->egl.eglBindTexImage) { 977 return s->cnx->egl.eglBindTexImage( 978 dp->disp.dpy, s->surface, buffer); 979 } 980 return setError(EGL_BAD_SURFACE, EGL_FALSE); 981} 982 983EGLBoolean eglReleaseTexImage( 984 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 985{ 986 clearError(); 987 988 const egl_display_ptr dp = validate_display(dpy); 989 if (!dp) return EGL_FALSE; 990 991 SurfaceRef _s(dp.get(), surface); 992 if (!_s.get()) 993 return setError(EGL_BAD_SURFACE, EGL_FALSE); 994 995 egl_surface_t const * const s = get_surface(surface); 996 if (s->cnx->egl.eglReleaseTexImage) { 997 return s->cnx->egl.eglReleaseTexImage( 998 dp->disp.dpy, s->surface, buffer); 999 } 1000 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1001} 1002 1003EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 1004{ 1005 clearError(); 1006 1007 const egl_display_ptr dp = validate_display(dpy); 1008 if (!dp) return EGL_FALSE; 1009 1010 EGLBoolean res = EGL_TRUE; 1011 egl_connection_t* const cnx = &gEGLImpl; 1012 if (cnx->dso && cnx->egl.eglSwapInterval) { 1013 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval); 1014 } 1015 1016 return res; 1017} 1018 1019 1020// ---------------------------------------------------------------------------- 1021// EGL 1.2 1022// ---------------------------------------------------------------------------- 1023 1024EGLBoolean eglWaitClient(void) 1025{ 1026 clearError(); 1027 1028 egl_connection_t* const cnx = &gEGLImpl; 1029 if (!cnx->dso) 1030 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1031 1032 EGLBoolean res; 1033 if (cnx->egl.eglWaitClient) { 1034 res = cnx->egl.eglWaitClient(); 1035 } else { 1036 res = cnx->egl.eglWaitGL(); 1037 } 1038 return res; 1039} 1040 1041EGLBoolean eglBindAPI(EGLenum api) 1042{ 1043 clearError(); 1044 1045 if (egl_init_drivers() == EGL_FALSE) { 1046 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1047 } 1048 1049 // bind this API on all EGLs 1050 EGLBoolean res = EGL_TRUE; 1051 egl_connection_t* const cnx = &gEGLImpl; 1052 if (cnx->dso && cnx->egl.eglBindAPI) { 1053 res = cnx->egl.eglBindAPI(api); 1054 } 1055 return res; 1056} 1057 1058EGLenum eglQueryAPI(void) 1059{ 1060 clearError(); 1061 1062 if (egl_init_drivers() == EGL_FALSE) { 1063 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1064 } 1065 1066 egl_connection_t* const cnx = &gEGLImpl; 1067 if (cnx->dso && cnx->egl.eglQueryAPI) { 1068 return cnx->egl.eglQueryAPI(); 1069 } 1070 1071 // or, it can only be OpenGL ES 1072 return EGL_OPENGL_ES_API; 1073} 1074 1075EGLBoolean eglReleaseThread(void) 1076{ 1077 clearError(); 1078 1079 // If there is context bound to the thread, release it 1080 egl_display_t::loseCurrent(get_context(getContext())); 1081 1082 egl_connection_t* const cnx = &gEGLImpl; 1083 if (cnx->dso && cnx->egl.eglReleaseThread) { 1084 cnx->egl.eglReleaseThread(); 1085 } 1086 1087 egl_tls_t::clearTLS(); 1088#if EGL_TRACE 1089 if (gEGLDebugLevel > 0) 1090 GLTrace_eglReleaseThread(); 1091#endif 1092 return EGL_TRUE; 1093} 1094 1095EGLSurface eglCreatePbufferFromClientBuffer( 1096 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 1097 EGLConfig config, const EGLint *attrib_list) 1098{ 1099 clearError(); 1100 1101 egl_connection_t* cnx = NULL; 1102 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 1103 if (!dp) return EGL_FALSE; 1104 if (cnx->egl.eglCreatePbufferFromClientBuffer) { 1105 return cnx->egl.eglCreatePbufferFromClientBuffer( 1106 dp->disp.dpy, buftype, buffer, config, attrib_list); 1107 } 1108 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); 1109} 1110 1111// ---------------------------------------------------------------------------- 1112// EGL_EGLEXT_VERSION 3 1113// ---------------------------------------------------------------------------- 1114 1115EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, 1116 const EGLint *attrib_list) 1117{ 1118 clearError(); 1119 1120 const egl_display_ptr dp = validate_display(dpy); 1121 if (!dp) return EGL_FALSE; 1122 1123 SurfaceRef _s(dp.get(), surface); 1124 if (!_s.get()) 1125 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1126 1127 egl_surface_t const * const s = get_surface(surface); 1128 if (s->cnx->egl.eglLockSurfaceKHR) { 1129 return s->cnx->egl.eglLockSurfaceKHR( 1130 dp->disp.dpy, s->surface, attrib_list); 1131 } 1132 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1133} 1134 1135EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) 1136{ 1137 clearError(); 1138 1139 const egl_display_ptr dp = validate_display(dpy); 1140 if (!dp) return EGL_FALSE; 1141 1142 SurfaceRef _s(dp.get(), surface); 1143 if (!_s.get()) 1144 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1145 1146 egl_surface_t const * const s = get_surface(surface); 1147 if (s->cnx->egl.eglUnlockSurfaceKHR) { 1148 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface); 1149 } 1150 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1151} 1152 1153EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1154 EGLClientBuffer buffer, const EGLint *attrib_list) 1155{ 1156 clearError(); 1157 1158 const egl_display_ptr dp = validate_display(dpy); 1159 if (!dp) return EGL_NO_IMAGE_KHR; 1160 1161 ContextRef _c(dp.get(), ctx); 1162 egl_context_t * const c = _c.get(); 1163 1164 EGLImageKHR result = EGL_NO_IMAGE_KHR; 1165 egl_connection_t* const cnx = &gEGLImpl; 1166 if (cnx->dso && cnx->egl.eglCreateImageKHR) { 1167 result = cnx->egl.eglCreateImageKHR( 1168 dp->disp.dpy, 1169 c ? c->context : EGL_NO_CONTEXT, 1170 target, buffer, attrib_list); 1171 } 1172 return result; 1173} 1174 1175EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 1176{ 1177 clearError(); 1178 1179 const egl_display_ptr dp = validate_display(dpy); 1180 if (!dp) return EGL_FALSE; 1181 1182 EGLBoolean result = EGL_FALSE; 1183 egl_connection_t* const cnx = &gEGLImpl; 1184 if (cnx->dso && cnx->egl.eglDestroyImageKHR) { 1185 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img); 1186 } 1187 return result; 1188} 1189 1190// ---------------------------------------------------------------------------- 1191// EGL_EGLEXT_VERSION 5 1192// ---------------------------------------------------------------------------- 1193 1194 1195EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) 1196{ 1197 clearError(); 1198 1199 const egl_display_ptr dp = validate_display(dpy); 1200 if (!dp) return EGL_NO_SYNC_KHR; 1201 1202 EGLSyncKHR result = EGL_NO_SYNC_KHR; 1203 egl_connection_t* const cnx = &gEGLImpl; 1204 if (cnx->dso && cnx->egl.eglCreateSyncKHR) { 1205 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list); 1206 } 1207 return result; 1208} 1209 1210EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) 1211{ 1212 clearError(); 1213 1214 const egl_display_ptr dp = validate_display(dpy); 1215 if (!dp) return EGL_FALSE; 1216 1217 EGLBoolean result = EGL_FALSE; 1218 egl_connection_t* const cnx = &gEGLImpl; 1219 if (cnx->dso && cnx->egl.eglDestroySyncKHR) { 1220 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync); 1221 } 1222 return result; 1223} 1224 1225EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, 1226 EGLint flags, EGLTimeKHR timeout) 1227{ 1228 clearError(); 1229 1230 const egl_display_ptr dp = validate_display(dpy); 1231 if (!dp) return EGL_FALSE; 1232 1233 EGLBoolean result = EGL_FALSE; 1234 egl_connection_t* const cnx = &gEGLImpl; 1235 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) { 1236 result = cnx->egl.eglClientWaitSyncKHR( 1237 dp->disp.dpy, sync, flags, timeout); 1238 } 1239 return result; 1240} 1241 1242EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, 1243 EGLint attribute, EGLint *value) 1244{ 1245 clearError(); 1246 1247 const egl_display_ptr dp = validate_display(dpy); 1248 if (!dp) return EGL_FALSE; 1249 1250 EGLBoolean result = EGL_FALSE; 1251 egl_connection_t* const cnx = &gEGLImpl; 1252 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) { 1253 result = cnx->egl.eglGetSyncAttribKHR( 1254 dp->disp.dpy, sync, attribute, value); 1255 } 1256 return result; 1257} 1258 1259// ---------------------------------------------------------------------------- 1260// ANDROID extensions 1261// ---------------------------------------------------------------------------- 1262 1263EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync) 1264{ 1265 clearError(); 1266 1267 const egl_display_ptr dp = validate_display(dpy); 1268 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID; 1269 1270 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID; 1271 egl_connection_t* const cnx = &gEGLImpl; 1272 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) { 1273 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync); 1274 } 1275 return result; 1276} 1277 1278EGLint eglWaitSyncANDROID(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) 1279{ 1280 clearError(); 1281 1282 const egl_display_ptr dp = validate_display(dpy); 1283 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID; 1284 1285 EGLint result = EGL_FALSE; 1286 egl_connection_t* const cnx = &gEGLImpl; 1287 if (cnx->dso && cnx->egl.eglWaitSyncANDROID) { 1288 result = cnx->egl.eglWaitSyncANDROID(dp->disp.dpy, sync, flags); 1289 } 1290 return result; 1291} 1292 1293// ---------------------------------------------------------------------------- 1294// NVIDIA extensions 1295// ---------------------------------------------------------------------------- 1296EGLuint64NV eglGetSystemTimeFrequencyNV() 1297{ 1298 clearError(); 1299 1300 if (egl_init_drivers() == EGL_FALSE) { 1301 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1302 } 1303 1304 EGLuint64NV ret = 0; 1305 egl_connection_t* const cnx = &gEGLImpl; 1306 1307 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) { 1308 return cnx->egl.eglGetSystemTimeFrequencyNV(); 1309 } 1310 1311 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1312} 1313 1314EGLuint64NV eglGetSystemTimeNV() 1315{ 1316 clearError(); 1317 1318 if (egl_init_drivers() == EGL_FALSE) { 1319 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1320 } 1321 1322 EGLuint64NV ret = 0; 1323 egl_connection_t* const cnx = &gEGLImpl; 1324 1325 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) { 1326 return cnx->egl.eglGetSystemTimeNV(); 1327 } 1328 1329 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1330} 1331