eglApi.cpp revision 7db993a98b9239bd4e384cc4aa128262fe3cf52c
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 718EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) 719{ 720 ATRACE_CALL(); 721 clearError(); 722 723 egl_display_t const * const dp = validate_display(dpy); 724 if (!dp) return EGL_FALSE; 725 726 SurfaceRef _s(dp, draw); 727 if (!_s.get()) 728 return setError(EGL_BAD_SURFACE, EGL_FALSE); 729 730#if EGL_TRACE 731 if (gEGLDebugLevel > 0) 732 GLTrace_eglSwapBuffers(dpy, draw); 733#endif 734 735 egl_surface_t const * const s = get_surface(draw); 736 737 if (CC_UNLIKELY(dp->finishOnSwap)) { 738 uint32_t pixel; 739 egl_context_t * const c = get_context( egl_tls_t::getContext() ); 740 if (c) { 741 // glReadPixels() ensures that the frame is complete 742 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1, 743 GL_RGBA,GL_UNSIGNED_BYTE,&pixel); 744 } 745 } 746 747 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface); 748} 749 750EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, 751 NativePixmapType target) 752{ 753 clearError(); 754 755 egl_display_t const * const dp = validate_display(dpy); 756 if (!dp) return EGL_FALSE; 757 758 SurfaceRef _s(dp, surface); 759 if (!_s.get()) 760 return setError(EGL_BAD_SURFACE, EGL_FALSE); 761 762 egl_surface_t const * const s = get_surface(surface); 763 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target); 764} 765 766const char* eglQueryString(EGLDisplay dpy, EGLint name) 767{ 768 clearError(); 769 770 egl_display_t const * const dp = validate_display(dpy); 771 if (!dp) return (const char *) NULL; 772 773 switch (name) { 774 case EGL_VENDOR: 775 return dp->getVendorString(); 776 case EGL_VERSION: 777 return dp->getVersionString(); 778 case EGL_EXTENSIONS: 779 return dp->getExtensionString(); 780 case EGL_CLIENT_APIS: 781 return dp->getClientApiString(); 782 case EGL_VERSION_HW_ANDROID: 783 return dp->disp.queryString.version; 784 } 785 return setError(EGL_BAD_PARAMETER, (const char *)0); 786} 787 788 789// ---------------------------------------------------------------------------- 790// EGL 1.1 791// ---------------------------------------------------------------------------- 792 793EGLBoolean eglSurfaceAttrib( 794 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 795{ 796 clearError(); 797 798 egl_display_t const * const dp = validate_display(dpy); 799 if (!dp) return EGL_FALSE; 800 801 SurfaceRef _s(dp, surface); 802 if (!_s.get()) 803 return setError(EGL_BAD_SURFACE, EGL_FALSE); 804 805 egl_surface_t const * const s = get_surface(surface); 806 if (s->cnx->egl.eglSurfaceAttrib) { 807 return s->cnx->egl.eglSurfaceAttrib( 808 dp->disp.dpy, s->surface, attribute, value); 809 } 810 return setError(EGL_BAD_SURFACE, EGL_FALSE); 811} 812 813EGLBoolean eglBindTexImage( 814 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 815{ 816 clearError(); 817 818 egl_display_t const * const dp = validate_display(dpy); 819 if (!dp) return EGL_FALSE; 820 821 SurfaceRef _s(dp, surface); 822 if (!_s.get()) 823 return setError(EGL_BAD_SURFACE, EGL_FALSE); 824 825 egl_surface_t const * const s = get_surface(surface); 826 if (s->cnx->egl.eglBindTexImage) { 827 return s->cnx->egl.eglBindTexImage( 828 dp->disp.dpy, s->surface, buffer); 829 } 830 return setError(EGL_BAD_SURFACE, EGL_FALSE); 831} 832 833EGLBoolean eglReleaseTexImage( 834 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 835{ 836 clearError(); 837 838 egl_display_t const * const dp = validate_display(dpy); 839 if (!dp) return EGL_FALSE; 840 841 SurfaceRef _s(dp, surface); 842 if (!_s.get()) 843 return setError(EGL_BAD_SURFACE, EGL_FALSE); 844 845 egl_surface_t const * const s = get_surface(surface); 846 if (s->cnx->egl.eglReleaseTexImage) { 847 return s->cnx->egl.eglReleaseTexImage( 848 dp->disp.dpy, s->surface, buffer); 849 } 850 return setError(EGL_BAD_SURFACE, EGL_FALSE); 851} 852 853EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 854{ 855 clearError(); 856 857 egl_display_t const * const dp = validate_display(dpy); 858 if (!dp) return EGL_FALSE; 859 860 EGLBoolean res = EGL_TRUE; 861 egl_connection_t* const cnx = &gEGLImpl; 862 if (cnx->dso && cnx->egl.eglSwapInterval) { 863 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval); 864 } 865 866 return res; 867} 868 869 870// ---------------------------------------------------------------------------- 871// EGL 1.2 872// ---------------------------------------------------------------------------- 873 874EGLBoolean eglWaitClient(void) 875{ 876 clearError(); 877 878 egl_connection_t* const cnx = &gEGLImpl; 879 if (!cnx->dso) 880 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 881 882 EGLBoolean res; 883 if (cnx->egl.eglWaitClient) { 884 res = cnx->egl.eglWaitClient(); 885 } else { 886 res = cnx->egl.eglWaitGL(); 887 } 888 return res; 889} 890 891EGLBoolean eglBindAPI(EGLenum api) 892{ 893 clearError(); 894 895 if (egl_init_drivers() == EGL_FALSE) { 896 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 897 } 898 899 // bind this API on all EGLs 900 EGLBoolean res = EGL_TRUE; 901 egl_connection_t* const cnx = &gEGLImpl; 902 if (cnx->dso && cnx->egl.eglBindAPI) { 903 res = cnx->egl.eglBindAPI(api); 904 } 905 return res; 906} 907 908EGLenum eglQueryAPI(void) 909{ 910 clearError(); 911 912 if (egl_init_drivers() == EGL_FALSE) { 913 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 914 } 915 916 egl_connection_t* const cnx = &gEGLImpl; 917 if (cnx->dso && cnx->egl.eglQueryAPI) { 918 return cnx->egl.eglQueryAPI(); 919 } 920 921 // or, it can only be OpenGL ES 922 return EGL_OPENGL_ES_API; 923} 924 925EGLBoolean eglReleaseThread(void) 926{ 927 clearError(); 928 929 // If there is context bound to the thread, release it 930 egl_display_t::loseCurrent(get_context(getContext())); 931 932 egl_connection_t* const cnx = &gEGLImpl; 933 if (cnx->dso && cnx->egl.eglReleaseThread) { 934 cnx->egl.eglReleaseThread(); 935 } 936 937 egl_tls_t::clearTLS(); 938#if EGL_TRACE 939 if (gEGLDebugLevel > 0) 940 GLTrace_eglReleaseThread(); 941#endif 942 return EGL_TRUE; 943} 944 945EGLSurface eglCreatePbufferFromClientBuffer( 946 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 947 EGLConfig config, const EGLint *attrib_list) 948{ 949 clearError(); 950 951 egl_display_t const* dp = 0; 952 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 953 if (!cnx) return EGL_FALSE; 954 if (cnx->egl.eglCreatePbufferFromClientBuffer) { 955 return cnx->egl.eglCreatePbufferFromClientBuffer( 956 dp->disp.dpy, buftype, buffer, config, attrib_list); 957 } 958 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); 959} 960 961// ---------------------------------------------------------------------------- 962// EGL_EGLEXT_VERSION 3 963// ---------------------------------------------------------------------------- 964 965EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, 966 const EGLint *attrib_list) 967{ 968 clearError(); 969 970 egl_display_t const * const dp = validate_display(dpy); 971 if (!dp) return EGL_FALSE; 972 973 SurfaceRef _s(dp, surface); 974 if (!_s.get()) 975 return setError(EGL_BAD_SURFACE, EGL_FALSE); 976 977 egl_surface_t const * const s = get_surface(surface); 978 if (s->cnx->egl.eglLockSurfaceKHR) { 979 return s->cnx->egl.eglLockSurfaceKHR( 980 dp->disp.dpy, s->surface, attrib_list); 981 } 982 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 983} 984 985EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) 986{ 987 clearError(); 988 989 egl_display_t const * const dp = validate_display(dpy); 990 if (!dp) return EGL_FALSE; 991 992 SurfaceRef _s(dp, surface); 993 if (!_s.get()) 994 return setError(EGL_BAD_SURFACE, EGL_FALSE); 995 996 egl_surface_t const * const s = get_surface(surface); 997 if (s->cnx->egl.eglUnlockSurfaceKHR) { 998 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface); 999 } 1000 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1001} 1002 1003EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1004 EGLClientBuffer buffer, const EGLint *attrib_list) 1005{ 1006 clearError(); 1007 1008 egl_display_t const * const dp = validate_display(dpy); 1009 if (!dp) return EGL_NO_IMAGE_KHR; 1010 1011 ContextRef _c(dp, ctx); 1012 egl_context_t * const c = _c.get(); 1013 1014 EGLImageKHR result = EGL_NO_IMAGE_KHR; 1015 egl_connection_t* const cnx = &gEGLImpl; 1016 if (cnx->dso && cnx->egl.eglCreateImageKHR) { 1017 result = cnx->egl.eglCreateImageKHR( 1018 dp->disp.dpy, 1019 c ? c->context : EGL_NO_CONTEXT, 1020 target, buffer, attrib_list); 1021 } 1022 return result; 1023} 1024 1025EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 1026{ 1027 clearError(); 1028 1029 egl_display_t const * const dp = validate_display(dpy); 1030 if (!dp) return EGL_FALSE; 1031 1032 egl_connection_t* const cnx = &gEGLImpl; 1033 if (cnx->dso && cnx->egl.eglDestroyImageKHR) { 1034 cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img); 1035 } 1036 return EGL_TRUE; 1037} 1038 1039// ---------------------------------------------------------------------------- 1040// EGL_EGLEXT_VERSION 5 1041// ---------------------------------------------------------------------------- 1042 1043 1044EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) 1045{ 1046 clearError(); 1047 1048 egl_display_t const * const dp = validate_display(dpy); 1049 if (!dp) return EGL_NO_SYNC_KHR; 1050 1051 EGLSyncKHR result = EGL_NO_SYNC_KHR; 1052 egl_connection_t* const cnx = &gEGLImpl; 1053 if (cnx->dso && cnx->egl.eglCreateSyncKHR) { 1054 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list); 1055 } 1056 return result; 1057} 1058 1059EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) 1060{ 1061 clearError(); 1062 1063 egl_display_t const * const dp = validate_display(dpy); 1064 if (!dp) return EGL_FALSE; 1065 1066 EGLBoolean result = EGL_FALSE; 1067 egl_connection_t* const cnx = &gEGLImpl; 1068 if (cnx->dso && cnx->egl.eglDestroySyncKHR) { 1069 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync); 1070 } 1071 return result; 1072} 1073 1074EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, 1075 EGLint flags, EGLTimeKHR timeout) 1076{ 1077 clearError(); 1078 1079 egl_display_t const * const dp = validate_display(dpy); 1080 if (!dp) return EGL_FALSE; 1081 1082 EGLBoolean result = EGL_FALSE; 1083 egl_connection_t* const cnx = &gEGLImpl; 1084 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) { 1085 result = cnx->egl.eglClientWaitSyncKHR( 1086 dp->disp.dpy, sync, flags, timeout); 1087 } 1088 return result; 1089} 1090 1091EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, 1092 EGLint attribute, EGLint *value) 1093{ 1094 clearError(); 1095 1096 egl_display_t const * const dp = validate_display(dpy); 1097 if (!dp) return EGL_FALSE; 1098 1099 EGLBoolean result = EGL_FALSE; 1100 egl_connection_t* const cnx = &gEGLImpl; 1101 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) { 1102 result = cnx->egl.eglGetSyncAttribKHR( 1103 dp->disp.dpy, sync, attribute, value); 1104 } 1105 return result; 1106} 1107 1108// ---------------------------------------------------------------------------- 1109// ANDROID extensions 1110// ---------------------------------------------------------------------------- 1111 1112/* ANDROID extensions entry-point go here */ 1113 1114// ---------------------------------------------------------------------------- 1115// NVIDIA extensions 1116// ---------------------------------------------------------------------------- 1117EGLuint64NV eglGetSystemTimeFrequencyNV() 1118{ 1119 clearError(); 1120 1121 if (egl_init_drivers() == EGL_FALSE) { 1122 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1123 } 1124 1125 EGLuint64NV ret = 0; 1126 egl_connection_t* const cnx = &gEGLImpl; 1127 1128 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) { 1129 return cnx->egl.eglGetSystemTimeFrequencyNV(); 1130 } 1131 1132 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1133} 1134 1135EGLuint64NV eglGetSystemTimeNV() 1136{ 1137 clearError(); 1138 1139 if (egl_init_drivers() == EGL_FALSE) { 1140 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1141 } 1142 1143 EGLuint64NV ret = 0; 1144 egl_connection_t* const cnx = &gEGLImpl; 1145 1146 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) { 1147 return cnx->egl.eglGetSystemTimeNV(); 1148 } 1149 1150 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1151} 1152