egl.cpp revision 02dafb5068be31cc45af897a8bd1cae8f4724401
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#include <ctype.h> 18#include <stdlib.h> 19#include <string.h> 20#include <errno.h> 21#include <dlfcn.h> 22 23#include <sys/ioctl.h> 24 25#if HAVE_ANDROID_OS 26#include <linux/android_pmem.h> 27#endif 28 29#include <EGL/egl.h> 30#include <EGL/eglext.h> 31#include <GLES/gl.h> 32#include <GLES/glext.h> 33 34#include <cutils/log.h> 35#include <cutils/atomic.h> 36#include <cutils/properties.h> 37#include <cutils/memory.h> 38 39#include <utils/SortedVector.h> 40#include <utils/KeyedVector.h> 41#include <utils/String8.h> 42 43#include "hooks.h" 44#include "egl_impl.h" 45#include "Loader.h" 46 47#define setError(_e, _r) setErrorEtc(__FUNCTION__, __LINE__, _e, _r) 48 49// ---------------------------------------------------------------------------- 50namespace android { 51// ---------------------------------------------------------------------------- 52 53#define VERSION_MAJOR 1 54#define VERSION_MINOR 4 55static char const * const gVendorString = "Android"; 56static char const * const gVersionString = "1.4 Android META-EGL"; 57static char const * const gClientApiString = "OpenGL ES"; 58static char const * const gExtensionString = 59 "EGL_KHR_image " 60 "EGL_KHR_image_base " 61 "EGL_KHR_image_pixmap " 62 "EGL_ANDROID_image_native_buffer " 63 "EGL_ANDROID_swap_rectangle " 64 ; 65 66// ---------------------------------------------------------------------------- 67 68class egl_object_t { 69 static SortedVector<egl_object_t*> sObjects; 70 static Mutex sLock; 71 72 volatile int32_t terminated; 73 mutable volatile int32_t count; 74 75public: 76 egl_object_t() : terminated(0), count(1) { 77 Mutex::Autolock _l(sLock); 78 sObjects.add(this); 79 } 80 81 inline bool isAlive() const { return !terminated; } 82 83private: 84 bool get() { 85 Mutex::Autolock _l(sLock); 86 if (egl_object_t::sObjects.indexOf(this) >= 0) { 87 android_atomic_inc(&count); 88 return true; 89 } 90 return false; 91 } 92 93 bool put() { 94 Mutex::Autolock _l(sLock); 95 if (android_atomic_dec(&count) == 1) { 96 sObjects.remove(this); 97 return true; 98 } 99 return false; 100 } 101 102public: 103 template <typename N, typename T> 104 struct LocalRef { 105 N* ref; 106 LocalRef(T o) : ref(0) { 107 N* native = reinterpret_cast<N*>(o); 108 if (o && native->get()) { 109 ref = native; 110 } 111 } 112 ~LocalRef() { 113 if (ref && ref->put()) { 114 delete ref; 115 } 116 } 117 inline N* get() { 118 return ref; 119 } 120 void acquire() const { 121 if (ref) { 122 android_atomic_inc(&ref->count); 123 } 124 } 125 void release() const { 126 if (ref) { 127 int32_t c = android_atomic_dec(&ref->count); 128 // ref->count cannot be 1 prior atomic_dec because we have 129 // a reference, and if we have one, it means there was 130 // already one before us. 131 LOGE_IF(c==1, "refcount is now 0 in release()"); 132 } 133 } 134 void terminate() { 135 if (ref) { 136 ref->terminated = 1; 137 release(); 138 } 139 } 140 }; 141}; 142 143SortedVector<egl_object_t*> egl_object_t::sObjects; 144Mutex egl_object_t::sLock; 145 146 147struct egl_config_t { 148 egl_config_t() {} 149 egl_config_t(int impl, EGLConfig config) 150 : impl(impl), config(config), configId(0), implConfigId(0) { } 151 int impl; // the implementation this config is for 152 EGLConfig config; // the implementation's EGLConfig 153 EGLint configId; // our CONFIG_ID 154 EGLint implConfigId; // the implementation's CONFIG_ID 155 inline bool operator < (const egl_config_t& rhs) const { 156 if (impl < rhs.impl) return true; 157 if (impl > rhs.impl) return false; 158 return config < rhs.config; 159 } 160}; 161 162struct egl_display_t { 163 enum { NOT_INITIALIZED, INITIALIZED, TERMINATED }; 164 165 struct strings_t { 166 char const * vendor; 167 char const * version; 168 char const * clientApi; 169 char const * extensions; 170 }; 171 172 struct DisplayImpl { 173 DisplayImpl() : dpy(EGL_NO_DISPLAY), config(0), 174 state(NOT_INITIALIZED), numConfigs(0) { } 175 EGLDisplay dpy; 176 EGLConfig* config; 177 EGLint state; 178 EGLint numConfigs; 179 strings_t queryString; 180 }; 181 182 uint32_t magic; 183 DisplayImpl disp[IMPL_NUM_IMPLEMENTATIONS]; 184 EGLint numTotalConfigs; 185 egl_config_t* configs; 186 uint32_t refs; 187 Mutex lock; 188 189 egl_display_t() : magic('_dpy'), numTotalConfigs(0), configs(0) { } 190 ~egl_display_t() { magic = 0; } 191 inline bool isValid() const { return magic == '_dpy'; } 192 inline bool isAlive() const { return isValid(); } 193}; 194 195struct egl_surface_t : public egl_object_t 196{ 197 typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref; 198 199 egl_surface_t(EGLDisplay dpy, EGLSurface surface, EGLConfig config, 200 int impl, egl_connection_t const* cnx) 201 : dpy(dpy), surface(surface), config(config), impl(impl), cnx(cnx) { 202 } 203 ~egl_surface_t() { 204 } 205 EGLDisplay dpy; 206 EGLSurface surface; 207 EGLConfig config; 208 int impl; 209 egl_connection_t const* cnx; 210}; 211 212struct egl_context_t : public egl_object_t 213{ 214 typedef egl_object_t::LocalRef<egl_context_t, EGLContext> Ref; 215 216 egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config, 217 int impl, egl_connection_t const* cnx, int version) 218 : dpy(dpy), context(context), read(0), draw(0), impl(impl), cnx(cnx), 219 version(version) 220 { 221 } 222 EGLDisplay dpy; 223 EGLContext context; 224 EGLConfig config; 225 EGLSurface read; 226 EGLSurface draw; 227 int impl; 228 egl_connection_t const* cnx; 229 int version; 230}; 231 232struct egl_image_t : public egl_object_t 233{ 234 typedef egl_object_t::LocalRef<egl_image_t, EGLImageKHR> Ref; 235 236 egl_image_t(EGLDisplay dpy, EGLContext context) 237 : dpy(dpy), context(context) 238 { 239 memset(images, 0, sizeof(images)); 240 } 241 EGLDisplay dpy; 242 EGLContext context; 243 EGLImageKHR images[IMPL_NUM_IMPLEMENTATIONS]; 244}; 245 246typedef egl_surface_t::Ref SurfaceRef; 247typedef egl_context_t::Ref ContextRef; 248typedef egl_image_t::Ref ImageRef; 249 250struct tls_t 251{ 252 tls_t() : error(EGL_SUCCESS), ctx(0), logCallWithNoContext(EGL_TRUE) { } 253 EGLint error; 254 EGLContext ctx; 255 EGLBoolean logCallWithNoContext; 256}; 257 258 259// ---------------------------------------------------------------------------- 260 261static egl_connection_t gEGLImpl[IMPL_NUM_IMPLEMENTATIONS]; 262static egl_display_t gDisplay[NUM_DISPLAYS]; 263static pthread_mutex_t gThreadLocalStorageKeyMutex = PTHREAD_MUTEX_INITIALIZER; 264static pthread_key_t gEGLThreadLocalStorageKey = -1; 265 266// ---------------------------------------------------------------------------- 267 268EGLAPI gl_hooks_t gHooks[2][IMPL_NUM_IMPLEMENTATIONS]; 269EGLAPI gl_hooks_t gHooksNoContext; 270EGLAPI pthread_key_t gGLWrapperKey = -1; 271 272// ---------------------------------------------------------------------------- 273 274static __attribute__((noinline)) 275const char *egl_strerror(EGLint err) 276{ 277 switch (err){ 278 case EGL_SUCCESS: return "EGL_SUCCESS"; 279 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED"; 280 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS"; 281 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC"; 282 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE"; 283 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG"; 284 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT"; 285 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE"; 286 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY"; 287 case EGL_BAD_MATCH: return "EGL_BAD_MATCH"; 288 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP"; 289 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW"; 290 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER"; 291 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE"; 292 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST"; 293 default: return "UNKNOWN"; 294 } 295} 296 297static __attribute__((noinline)) 298void clearTLS() { 299 if (gEGLThreadLocalStorageKey != -1) { 300 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey); 301 if (tls) { 302 delete tls; 303 pthread_setspecific(gEGLThreadLocalStorageKey, 0); 304 } 305 } 306} 307 308static tls_t* getTLS() 309{ 310 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey); 311 if (tls == 0) { 312 tls = new tls_t; 313 pthread_setspecific(gEGLThreadLocalStorageKey, tls); 314 } 315 return tls; 316} 317 318template<typename T> 319static __attribute__((noinline)) 320T setErrorEtc(const char* caller, int line, EGLint error, T returnValue) { 321 if (gEGLThreadLocalStorageKey == -1) { 322 pthread_mutex_lock(&gThreadLocalStorageKeyMutex); 323 if (gEGLThreadLocalStorageKey == -1) 324 pthread_key_create(&gEGLThreadLocalStorageKey, NULL); 325 pthread_mutex_unlock(&gThreadLocalStorageKeyMutex); 326 } 327 tls_t* tls = getTLS(); 328 if (tls->error != error) { 329 LOGE("%s:%d error %x (%s)", caller, line, error, egl_strerror(error)); 330 tls->error = error; 331 } 332 return returnValue; 333} 334 335static __attribute__((noinline)) 336GLint getError() { 337 if (gEGLThreadLocalStorageKey == -1) 338 return EGL_SUCCESS; 339 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey); 340 if (!tls) return EGL_SUCCESS; 341 GLint error = tls->error; 342 tls->error = EGL_SUCCESS; 343 return error; 344} 345 346static __attribute__((noinline)) 347void setContext(EGLContext ctx) { 348 if (gEGLThreadLocalStorageKey == -1) { 349 pthread_mutex_lock(&gThreadLocalStorageKeyMutex); 350 if (gEGLThreadLocalStorageKey == -1) 351 pthread_key_create(&gEGLThreadLocalStorageKey, NULL); 352 pthread_mutex_unlock(&gThreadLocalStorageKeyMutex); 353 } 354 tls_t* tls = getTLS(); 355 tls->ctx = ctx; 356} 357 358static __attribute__((noinline)) 359EGLContext getContext() { 360 if (gEGLThreadLocalStorageKey == -1) 361 return EGL_NO_CONTEXT; 362 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey); 363 if (!tls) return EGL_NO_CONTEXT; 364 return tls->ctx; 365} 366 367/*****************************************************************************/ 368 369template<typename T> 370static __attribute__((noinline)) 371int binarySearch( 372 T const sortedArray[], int first, int last, T key) 373{ 374 while (first <= last) { 375 int mid = (first + last) / 2; 376 if (sortedArray[mid] < key) { 377 first = mid + 1; 378 } else if (key < sortedArray[mid]) { 379 last = mid - 1; 380 } else { 381 return mid; 382 } 383 } 384 return -1; 385} 386 387static int cmp_configs(const void* a, const void *b) 388{ 389 const egl_config_t& c0 = *(egl_config_t const *)a; 390 const egl_config_t& c1 = *(egl_config_t const *)b; 391 return c0<c1 ? -1 : (c1<c0 ? 1 : 0); 392} 393 394struct extention_map_t { 395 const char* name; 396 __eglMustCastToProperFunctionPointerType address; 397}; 398 399static const extention_map_t gExtentionMap[] = { 400 { "eglLockSurfaceKHR", 401 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR }, 402 { "eglUnlockSurfaceKHR", 403 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR }, 404 { "eglCreateImageKHR", 405 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, 406 { "eglDestroyImageKHR", 407 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, 408 { "eglSetSwapRectangleANDROID", 409 (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID }, 410}; 411 412extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS]; 413 414// accesses protected by gInitDriverMutex 415static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> gGLExtentionMap; 416static int gGLExtentionSlot = 0; 417 418static void(*findProcAddress(const char* name, 419 const extention_map_t* map, size_t n))() 420{ 421 for (uint32_t i=0 ; i<n ; i++) { 422 if (!strcmp(name, map[i].name)) { 423 return map[i].address; 424 } 425 } 426 return NULL; 427} 428 429// ---------------------------------------------------------------------------- 430 431static void gl_no_context() { 432 tls_t* tls = getTLS(); 433 if (tls->logCallWithNoContext == EGL_TRUE) { 434 tls->logCallWithNoContext = EGL_FALSE; 435 LOGE("call to OpenGL ES API with no current context " 436 "(logged once per thread)"); 437 } 438} 439 440static void early_egl_init(void) 441{ 442#if !USE_FAST_TLS_KEY 443 pthread_key_create(&gGLWrapperKey, NULL); 444#endif 445 uint32_t addr = (uint32_t)((void*)gl_no_context); 446 android_memset32( 447 (uint32_t*)(void*)&gHooksNoContext, 448 addr, 449 sizeof(gHooksNoContext)); 450 setGlThreadSpecific(&gHooksNoContext); 451} 452 453static pthread_once_t once_control = PTHREAD_ONCE_INIT; 454static int sEarlyInitState = pthread_once(&once_control, &early_egl_init); 455 456 457static inline 458egl_display_t* get_display(EGLDisplay dpy) 459{ 460 uintptr_t index = uintptr_t(dpy)-1U; 461 return (index >= NUM_DISPLAYS) ? NULL : &gDisplay[index]; 462} 463 464template<typename NATIVE, typename EGL> 465static inline NATIVE* egl_to_native_cast(EGL arg) { 466 return reinterpret_cast<NATIVE*>(arg); 467} 468 469static inline 470egl_surface_t* get_surface(EGLSurface surface) { 471 return egl_to_native_cast<egl_surface_t>(surface); 472} 473 474static inline 475egl_context_t* get_context(EGLContext context) { 476 return egl_to_native_cast<egl_context_t>(context); 477} 478 479static inline 480egl_image_t* get_image(EGLImageKHR image) { 481 return egl_to_native_cast<egl_image_t>(image); 482} 483 484static egl_connection_t* validate_display_config( 485 EGLDisplay dpy, EGLConfig config, 486 egl_display_t const*& dp) 487{ 488 dp = get_display(dpy); 489 if (!dp) return setError(EGL_BAD_DISPLAY, (egl_connection_t*)NULL); 490 491 if (intptr_t(config) >= dp->numTotalConfigs) { 492 return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL); 493 } 494 egl_connection_t* const cnx = &gEGLImpl[dp->configs[intptr_t(config)].impl]; 495 if (cnx->dso == 0) { 496 return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL); 497 } 498 return cnx; 499} 500 501static EGLBoolean validate_display_context(EGLDisplay dpy, EGLContext ctx) 502{ 503 if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) 504 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 505 if (!get_display(dpy)->isAlive()) 506 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 507 if (!get_context(ctx)->isAlive()) 508 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 509 return EGL_TRUE; 510} 511 512static EGLBoolean validate_display_surface(EGLDisplay dpy, EGLSurface surface) 513{ 514 if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) 515 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 516 if (!get_display(dpy)->isAlive()) 517 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 518 if (!get_surface(surface)->isAlive()) 519 return setError(EGL_BAD_SURFACE, EGL_FALSE); 520 return EGL_TRUE; 521} 522 523EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image) 524{ 525 ImageRef _i(image); 526 if (!_i.get()) return EGL_NO_IMAGE_KHR; 527 528 EGLContext context = getContext(); 529 if (context == EGL_NO_CONTEXT || image == EGL_NO_IMAGE_KHR) 530 return EGL_NO_IMAGE_KHR; 531 532 egl_context_t const * const c = get_context(context); 533 if (!c->isAlive()) 534 return EGL_NO_IMAGE_KHR; 535 536 egl_image_t const * const i = get_image(image); 537 return i->images[c->impl]; 538} 539 540// ---------------------------------------------------------------------------- 541 542// this mutex protects: 543// d->disp[] 544// egl_init_drivers_locked() 545// 546static pthread_mutex_t gInitDriverMutex = PTHREAD_MUTEX_INITIALIZER; 547 548EGLBoolean egl_init_drivers_locked() 549{ 550 if (sEarlyInitState) { 551 // initialized by static ctor. should be set here. 552 return EGL_FALSE; 553 } 554 555 // get our driver loader 556 Loader& loader(Loader::getInstance()); 557 558 // dynamically load all our EGL implementations for all displays 559 // and retrieve the corresponding EGLDisplay 560 // if that fails, don't use this driver. 561 // TODO: currently we only deal with EGL_DEFAULT_DISPLAY 562 egl_connection_t* cnx; 563 egl_display_t* d = &gDisplay[0]; 564 565 cnx = &gEGLImpl[IMPL_SOFTWARE]; 566 if (cnx->dso == 0) { 567 cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_SOFTWARE]; 568 cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_SOFTWARE]; 569 cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 0, cnx); 570 if (cnx->dso) { 571 EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY); 572 LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for software EGL!"); 573 d->disp[IMPL_SOFTWARE].dpy = dpy; 574 if (dpy == EGL_NO_DISPLAY) { 575 loader.close(cnx->dso); 576 cnx->dso = NULL; 577 } 578 } 579 } 580 581 cnx = &gEGLImpl[IMPL_HARDWARE]; 582 if (cnx->dso == 0) { 583 char value[PROPERTY_VALUE_MAX]; 584 property_get("debug.egl.hw", value, "1"); 585 if (atoi(value) != 0) { 586 cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_HARDWARE]; 587 cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_HARDWARE]; 588 cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 1, cnx); 589 if (cnx->dso) { 590 EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY); 591 LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for hardware EGL!"); 592 d->disp[IMPL_HARDWARE].dpy = dpy; 593 if (dpy == EGL_NO_DISPLAY) { 594 loader.close(cnx->dso); 595 cnx->dso = NULL; 596 } 597 } 598 } else { 599 LOGD("3D hardware acceleration is disabled"); 600 } 601 } 602 603 if (!gEGLImpl[IMPL_SOFTWARE].dso && !gEGLImpl[IMPL_HARDWARE].dso) { 604 return EGL_FALSE; 605 } 606 607 return EGL_TRUE; 608} 609 610EGLBoolean egl_init_drivers() 611{ 612 EGLBoolean res; 613 pthread_mutex_lock(&gInitDriverMutex); 614 res = egl_init_drivers_locked(); 615 pthread_mutex_unlock(&gInitDriverMutex); 616 return res; 617} 618 619// ---------------------------------------------------------------------------- 620}; // namespace android 621// ---------------------------------------------------------------------------- 622 623using namespace android; 624 625EGLDisplay eglGetDisplay(NativeDisplayType display) 626{ 627 uint32_t index = uint32_t(display); 628 if (index >= NUM_DISPLAYS) { 629 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 630 } 631 632 if (egl_init_drivers() == EGL_FALSE) { 633 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 634 } 635 636 EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU); 637 return dpy; 638} 639 640// ---------------------------------------------------------------------------- 641// Initialization 642// ---------------------------------------------------------------------------- 643 644EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) 645{ 646 egl_display_t * const dp = get_display(dpy); 647 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 648 649 Mutex::Autolock _l(dp->lock); 650 651 if (dp->refs > 0) { 652 if (major != NULL) *major = VERSION_MAJOR; 653 if (minor != NULL) *minor = VERSION_MINOR; 654 dp->refs++; 655 return EGL_TRUE; 656 } 657 658 setGlThreadSpecific(&gHooksNoContext); 659 660 // initialize each EGL and 661 // build our own extension string first, based on the extension we know 662 // and the extension supported by our client implementation 663 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 664 egl_connection_t* const cnx = &gEGLImpl[i]; 665 cnx->major = -1; 666 cnx->minor = -1; 667 if (!cnx->dso) 668 continue; 669 670#if defined(ADRENO130) 671#warning "Adreno-130 eglInitialize() workaround" 672 /* 673 * The ADRENO 130 driver returns a different EGLDisplay each time 674 * eglGetDisplay() is called, but also makes the EGLDisplay invalid 675 * after eglTerminate() has been called, so that eglInitialize() 676 * cannot be called again. Therefore, we need to make sure to call 677 * eglGetDisplay() before calling eglInitialize(); 678 */ 679 if (i == IMPL_HARDWARE) { 680 dp->disp[i].dpy = 681 cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY); 682 } 683#endif 684 685 686 EGLDisplay idpy = dp->disp[i].dpy; 687 if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) { 688 //LOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p", 689 // i, idpy, cnx->major, cnx->minor, cnx); 690 691 // display is now initialized 692 dp->disp[i].state = egl_display_t::INITIALIZED; 693 694 // get the query-strings for this display for each implementation 695 dp->disp[i].queryString.vendor = 696 cnx->egl.eglQueryString(idpy, EGL_VENDOR); 697 dp->disp[i].queryString.version = 698 cnx->egl.eglQueryString(idpy, EGL_VERSION); 699 dp->disp[i].queryString.extensions = 700 cnx->egl.eglQueryString(idpy, EGL_EXTENSIONS); 701 dp->disp[i].queryString.clientApi = 702 cnx->egl.eglQueryString(idpy, EGL_CLIENT_APIS); 703 704 } else { 705 LOGW("%d: eglInitialize(%p) failed (%s)", i, idpy, 706 egl_strerror(cnx->egl.eglGetError())); 707 } 708 } 709 710 EGLBoolean res = EGL_FALSE; 711 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 712 egl_connection_t* const cnx = &gEGLImpl[i]; 713 if (cnx->dso && cnx->major>=0 && cnx->minor>=0) { 714 EGLint n; 715 if (cnx->egl.eglGetConfigs(dp->disp[i].dpy, 0, 0, &n)) { 716 dp->disp[i].config = (EGLConfig*)malloc(sizeof(EGLConfig)*n); 717 if (dp->disp[i].config) { 718 if (cnx->egl.eglGetConfigs( 719 dp->disp[i].dpy, dp->disp[i].config, n, 720 &dp->disp[i].numConfigs)) 721 { 722 dp->numTotalConfigs += n; 723 res = EGL_TRUE; 724 } 725 } 726 } 727 } 728 } 729 730 if (res == EGL_TRUE) { 731 dp->configs = new egl_config_t[ dp->numTotalConfigs ]; 732 for (int i=0, k=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 733 egl_connection_t* const cnx = &gEGLImpl[i]; 734 if (cnx->dso && cnx->major>=0 && cnx->minor>=0) { 735 for (int j=0 ; j<dp->disp[i].numConfigs ; j++) { 736 dp->configs[k].impl = i; 737 dp->configs[k].config = dp->disp[i].config[j]; 738 dp->configs[k].configId = k + 1; // CONFIG_ID start at 1 739 // store the implementation's CONFIG_ID 740 cnx->egl.eglGetConfigAttrib( 741 dp->disp[i].dpy, 742 dp->disp[i].config[j], 743 EGL_CONFIG_ID, 744 &dp->configs[k].implConfigId); 745 k++; 746 } 747 } 748 } 749 750 // sort our configurations so we can do binary-searches 751 qsort( dp->configs, 752 dp->numTotalConfigs, 753 sizeof(egl_config_t), cmp_configs); 754 755 dp->refs++; 756 if (major != NULL) *major = VERSION_MAJOR; 757 if (minor != NULL) *minor = VERSION_MINOR; 758 return EGL_TRUE; 759 } 760 return setError(EGL_NOT_INITIALIZED, EGL_FALSE); 761} 762 763EGLBoolean eglTerminate(EGLDisplay dpy) 764{ 765 // NOTE: don't unload the drivers b/c some APIs can be called 766 // after eglTerminate() has been called. eglTerminate() only 767 // terminates an EGLDisplay, not a EGL itself. 768 769 egl_display_t* const dp = get_display(dpy); 770 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 771 772 Mutex::Autolock _l(dp->lock); 773 774 if (dp->refs == 0) { 775 return setError(EGL_NOT_INITIALIZED, EGL_FALSE); 776 } 777 778 // this is specific to Android, display termination is ref-counted. 779 if (dp->refs > 1) { 780 dp->refs--; 781 return EGL_TRUE; 782 } 783 784 EGLBoolean res = EGL_FALSE; 785 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 786 egl_connection_t* const cnx = &gEGLImpl[i]; 787 if (cnx->dso && dp->disp[i].state == egl_display_t::INITIALIZED) { 788 if (cnx->egl.eglTerminate(dp->disp[i].dpy) == EGL_FALSE) { 789 LOGW("%d: eglTerminate(%p) failed (%s)", i, dp->disp[i].dpy, 790 egl_strerror(cnx->egl.eglGetError())); 791 } 792 // REVISIT: it's unclear what to do if eglTerminate() fails 793 free(dp->disp[i].config); 794 795 dp->disp[i].numConfigs = 0; 796 dp->disp[i].config = 0; 797 dp->disp[i].state = egl_display_t::TERMINATED; 798 799 res = EGL_TRUE; 800 } 801 } 802 803 // TODO: all egl_object_t should be marked for termination 804 805 dp->refs--; 806 dp->numTotalConfigs = 0; 807 delete [] dp->configs; 808 clearTLS(); 809 return res; 810} 811 812// ---------------------------------------------------------------------------- 813// configuration 814// ---------------------------------------------------------------------------- 815 816EGLBoolean eglGetConfigs( EGLDisplay dpy, 817 EGLConfig *configs, 818 EGLint config_size, EGLint *num_config) 819{ 820 egl_display_t const * const dp = get_display(dpy); 821 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 822 823 GLint numConfigs = dp->numTotalConfigs; 824 if (!configs) { 825 *num_config = numConfigs; 826 return EGL_TRUE; 827 } 828 829 GLint n = 0; 830 for (intptr_t i=0 ; i<dp->numTotalConfigs && config_size ; i++) { 831 *configs++ = EGLConfig(i); 832 config_size--; 833 n++; 834 } 835 836 *num_config = n; 837 return EGL_TRUE; 838} 839 840EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, 841 EGLConfig *configs, EGLint config_size, 842 EGLint *num_config) 843{ 844 egl_display_t const * const dp = get_display(dpy); 845 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 846 847 if (num_config==0) { 848 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 849 } 850 851 EGLint n; 852 EGLBoolean res = EGL_FALSE; 853 *num_config = 0; 854 855 856 // It is unfortunate, but we need to remap the EGL_CONFIG_IDs, 857 // to do this, we have to go through the attrib_list array once 858 // to figure out both its size and if it contains an EGL_CONFIG_ID 859 // key. If so, the full array is copied and patched. 860 // NOTE: we assume that there can be only one occurrence 861 // of EGL_CONFIG_ID. 862 863 EGLint patch_index = -1; 864 GLint attr; 865 size_t size = 0; 866 if (attrib_list) { 867 while ((attr=attrib_list[size]) != EGL_NONE) { 868 if (attr == EGL_CONFIG_ID) 869 patch_index = size; 870 size += 2; 871 } 872 } 873 if (patch_index >= 0) { 874 size += 2; // we need copy the sentinel as well 875 EGLint* new_list = (EGLint*)malloc(size*sizeof(EGLint)); 876 if (new_list == 0) 877 return setError(EGL_BAD_ALLOC, EGL_FALSE); 878 memcpy(new_list, attrib_list, size*sizeof(EGLint)); 879 880 // patch the requested EGL_CONFIG_ID 881 bool found = false; 882 EGLConfig ourConfig(0); 883 EGLint& configId(new_list[patch_index+1]); 884 for (intptr_t i=0 ; i<dp->numTotalConfigs ; i++) { 885 if (dp->configs[i].configId == configId) { 886 ourConfig = EGLConfig(i); 887 configId = dp->configs[i].implConfigId; 888 found = true; 889 break; 890 } 891 } 892 893 egl_connection_t* const cnx = &gEGLImpl[dp->configs[intptr_t(ourConfig)].impl]; 894 if (found && cnx->dso) { 895 // and switch to the new list 896 attrib_list = const_cast<const EGLint *>(new_list); 897 898 // At this point, the only configuration that can match is 899 // dp->configs[i][index], however, we don't know if it would be 900 // rejected because of the other attributes, so we do have to call 901 // cnx->egl.eglChooseConfig() -- but we don't have to loop 902 // through all the EGLimpl[]. 903 // We also know we can only get a single config back, and we know 904 // which one. 905 906 res = cnx->egl.eglChooseConfig( 907 dp->disp[ dp->configs[intptr_t(ourConfig)].impl ].dpy, 908 attrib_list, configs, config_size, &n); 909 if (res && n>0) { 910 // n has to be 0 or 1, by construction, and we already know 911 // which config it will return (since there can be only one). 912 if (configs) { 913 configs[0] = ourConfig; 914 } 915 *num_config = 1; 916 } 917 } 918 919 free(const_cast<EGLint *>(attrib_list)); 920 return res; 921 } 922 923 924 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 925 egl_connection_t* const cnx = &gEGLImpl[i]; 926 if (cnx->dso) { 927 if (cnx->egl.eglChooseConfig( 928 dp->disp[i].dpy, attrib_list, configs, config_size, &n)) { 929 if (configs) { 930 // now we need to convert these client EGLConfig to our 931 // internal EGLConfig format. 932 // This is done in O(n Log(n)) time. 933 for (int j=0 ; j<n ; j++) { 934 egl_config_t key(i, configs[j]); 935 intptr_t index = binarySearch<egl_config_t>( 936 dp->configs, 0, dp->numTotalConfigs, key); 937 if (index >= 0) { 938 configs[j] = EGLConfig(index); 939 } else { 940 return setError(EGL_BAD_CONFIG, EGL_FALSE); 941 } 942 } 943 configs += n; 944 config_size -= n; 945 } 946 *num_config += n; 947 res = EGL_TRUE; 948 } 949 } 950 } 951 return res; 952} 953 954EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, 955 EGLint attribute, EGLint *value) 956{ 957 egl_display_t const* dp = 0; 958 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 959 if (!cnx) return EGL_FALSE; 960 961 if (attribute == EGL_CONFIG_ID) { 962 *value = dp->configs[intptr_t(config)].configId; 963 return EGL_TRUE; 964 } 965 return cnx->egl.eglGetConfigAttrib( 966 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 967 dp->configs[intptr_t(config)].config, attribute, value); 968} 969 970// ---------------------------------------------------------------------------- 971// surfaces 972// ---------------------------------------------------------------------------- 973 974EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, 975 NativeWindowType window, 976 const EGLint *attrib_list) 977{ 978 egl_display_t const* dp = 0; 979 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 980 if (cnx) { 981 EGLSurface surface = cnx->egl.eglCreateWindowSurface( 982 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 983 dp->configs[intptr_t(config)].config, window, attrib_list); 984 if (surface != EGL_NO_SURFACE) { 985 egl_surface_t* s = new egl_surface_t(dpy, surface, config, 986 dp->configs[intptr_t(config)].impl, cnx); 987 return s; 988 } 989 } 990 return EGL_NO_SURFACE; 991} 992 993EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, 994 NativePixmapType pixmap, 995 const EGLint *attrib_list) 996{ 997 egl_display_t const* dp = 0; 998 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 999 if (cnx) { 1000 EGLSurface surface = cnx->egl.eglCreatePixmapSurface( 1001 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 1002 dp->configs[intptr_t(config)].config, pixmap, attrib_list); 1003 if (surface != EGL_NO_SURFACE) { 1004 egl_surface_t* s = new egl_surface_t(dpy, surface, config, 1005 dp->configs[intptr_t(config)].impl, cnx); 1006 return s; 1007 } 1008 } 1009 return EGL_NO_SURFACE; 1010} 1011 1012EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, 1013 const EGLint *attrib_list) 1014{ 1015 egl_display_t const* dp = 0; 1016 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 1017 if (cnx) { 1018 EGLSurface surface = cnx->egl.eglCreatePbufferSurface( 1019 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 1020 dp->configs[intptr_t(config)].config, attrib_list); 1021 if (surface != EGL_NO_SURFACE) { 1022 egl_surface_t* s = new egl_surface_t(dpy, surface, config, 1023 dp->configs[intptr_t(config)].impl, cnx); 1024 return s; 1025 } 1026 } 1027 return EGL_NO_SURFACE; 1028} 1029 1030EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) 1031{ 1032 SurfaceRef _s(surface); 1033 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1034 1035 if (!validate_display_surface(dpy, surface)) 1036 return EGL_FALSE; 1037 egl_display_t const * const dp = get_display(dpy); 1038 1039 egl_surface_t * const s = get_surface(surface); 1040 EGLBoolean result = s->cnx->egl.eglDestroySurface( 1041 dp->disp[s->impl].dpy, s->surface); 1042 if (result == EGL_TRUE) { 1043 _s.terminate(); 1044 } 1045 return result; 1046} 1047 1048EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface, 1049 EGLint attribute, EGLint *value) 1050{ 1051 SurfaceRef _s(surface); 1052 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1053 1054 if (!validate_display_surface(dpy, surface)) 1055 return EGL_FALSE; 1056 egl_display_t const * const dp = get_display(dpy); 1057 egl_surface_t const * const s = get_surface(surface); 1058 1059 EGLBoolean result(EGL_TRUE); 1060 if (attribute == EGL_CONFIG_ID) { 1061 // We need to remap EGL_CONFIG_IDs 1062 *value = dp->configs[intptr_t(s->config)].configId; 1063 } else { 1064 result = s->cnx->egl.eglQuerySurface( 1065 dp->disp[s->impl].dpy, s->surface, attribute, value); 1066 } 1067 1068 return result; 1069} 1070 1071// ---------------------------------------------------------------------------- 1072// Contexts 1073// ---------------------------------------------------------------------------- 1074 1075EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, 1076 EGLContext share_list, const EGLint *attrib_list) 1077{ 1078 egl_display_t const* dp = 0; 1079 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 1080 if (cnx) { 1081 if (share_list != EGL_NO_CONTEXT) { 1082 egl_context_t* const c = get_context(share_list); 1083 share_list = c->context; 1084 } 1085 EGLContext context = cnx->egl.eglCreateContext( 1086 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 1087 dp->configs[intptr_t(config)].config, 1088 share_list, attrib_list); 1089 if (context != EGL_NO_CONTEXT) { 1090 // figure out if it's a GLESv1 or GLESv2 1091 int version = 0; 1092 if (attrib_list) { 1093 while (*attrib_list != EGL_NONE) { 1094 GLint attr = *attrib_list++; 1095 GLint value = *attrib_list++; 1096 if (attr == EGL_CONTEXT_CLIENT_VERSION) { 1097 if (value == 1) { 1098 version = GLESv1_INDEX; 1099 } else if (value == 2) { 1100 version = GLESv2_INDEX; 1101 } 1102 } 1103 }; 1104 } 1105 egl_context_t* c = new egl_context_t(dpy, context, config, 1106 dp->configs[intptr_t(config)].impl, cnx, version); 1107 return c; 1108 } 1109 } 1110 return EGL_NO_CONTEXT; 1111} 1112 1113EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) 1114{ 1115 ContextRef _c(ctx); 1116 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1117 1118 if (!validate_display_context(dpy, ctx)) 1119 return EGL_FALSE; 1120 egl_display_t const * const dp = get_display(dpy); 1121 egl_context_t * const c = get_context(ctx); 1122 EGLBoolean result = c->cnx->egl.eglDestroyContext( 1123 dp->disp[c->impl].dpy, c->context); 1124 if (result == EGL_TRUE) { 1125 _c.terminate(); 1126 } 1127 return result; 1128} 1129 1130EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, 1131 EGLSurface read, EGLContext ctx) 1132{ 1133 // get a reference to the object passed in 1134 ContextRef _c(ctx); 1135 SurfaceRef _d(draw); 1136 SurfaceRef _r(read); 1137 1138 // validate the display and the context (if not EGL_NO_CONTEXT) 1139 egl_display_t const * const dp = get_display(dpy); 1140 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1141 if ((ctx != EGL_NO_CONTEXT) && (!validate_display_context(dpy, ctx))) { 1142 // EGL_NO_CONTEXT is valid 1143 return EGL_FALSE; 1144 } 1145 1146 // these are the underlying implementation's object 1147 EGLContext impl_ctx = EGL_NO_CONTEXT; 1148 EGLSurface impl_draw = EGL_NO_SURFACE; 1149 EGLSurface impl_read = EGL_NO_SURFACE; 1150 1151 // these are our objects structs passed in 1152 egl_context_t * c = NULL; 1153 egl_surface_t const * d = NULL; 1154 egl_surface_t const * r = NULL; 1155 1156 // these are the current objects structs 1157 egl_context_t * cur_c = get_context(getContext()); 1158 egl_surface_t * cur_r = NULL; 1159 egl_surface_t * cur_d = NULL; 1160 1161 if (ctx != EGL_NO_CONTEXT) { 1162 c = get_context(ctx); 1163 cur_r = get_surface(c->read); 1164 cur_d = get_surface(c->draw); 1165 impl_ctx = c->context; 1166 } else { 1167 // no context given, use the implementation of the current context 1168 if (cur_c == NULL) { 1169 // no current context 1170 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) { 1171 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT); 1172 return setError(EGL_BAD_MATCH, EGL_FALSE); 1173 } 1174 // not an error, there is just no current context. 1175 return EGL_TRUE; 1176 } 1177 } 1178 1179 // retrieve the underlying implementation's draw EGLSurface 1180 if (draw != EGL_NO_SURFACE) { 1181 d = get_surface(draw); 1182 // make sure the EGLContext and EGLSurface passed in are for 1183 // the same driver 1184 if (c && d->impl != c->impl) 1185 return setError(EGL_BAD_MATCH, EGL_FALSE); 1186 impl_draw = d->surface; 1187 } 1188 1189 // retrieve the underlying implementation's read EGLSurface 1190 if (read != EGL_NO_SURFACE) { 1191 r = get_surface(read); 1192 // make sure the EGLContext and EGLSurface passed in are for 1193 // the same driver 1194 if (c && r->impl != c->impl) 1195 return setError(EGL_BAD_MATCH, EGL_FALSE); 1196 impl_read = r->surface; 1197 } 1198 1199 EGLBoolean result; 1200 1201 if (c) { 1202 result = c->cnx->egl.eglMakeCurrent( 1203 dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx); 1204 } else { 1205 result = cur_c->cnx->egl.eglMakeCurrent( 1206 dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx); 1207 } 1208 1209 if (result == EGL_TRUE) { 1210 // by construction, these are either 0 or valid (possibly terminated) 1211 // it should be impossible for these to be invalid 1212 ContextRef _cur_c(cur_c); 1213 SurfaceRef _cur_r(cur_r); 1214 SurfaceRef _cur_d(cur_d); 1215 1216 // cur_c has to be valid here (but could be terminated) 1217 if (ctx != EGL_NO_CONTEXT) { 1218 setGlThreadSpecific(c->cnx->hooks[c->version]); 1219 setContext(ctx); 1220 _c.acquire(); 1221 } else { 1222 setGlThreadSpecific(&gHooksNoContext); 1223 setContext(EGL_NO_CONTEXT); 1224 } 1225 _cur_c.release(); 1226 1227 _r.acquire(); 1228 _cur_r.release(); 1229 if (c) c->read = read; 1230 1231 _d.acquire(); 1232 _cur_d.release(); 1233 if (c) c->draw = draw; 1234 } 1235 return result; 1236} 1237 1238 1239EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, 1240 EGLint attribute, EGLint *value) 1241{ 1242 ContextRef _c(ctx); 1243 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1244 1245 if (!validate_display_context(dpy, ctx)) 1246 return EGL_FALSE; 1247 1248 egl_display_t const * const dp = get_display(dpy); 1249 egl_context_t * const c = get_context(ctx); 1250 1251 EGLBoolean result(EGL_TRUE); 1252 if (attribute == EGL_CONFIG_ID) { 1253 *value = dp->configs[intptr_t(c->config)].configId; 1254 } else { 1255 // We need to remap EGL_CONFIG_IDs 1256 result = c->cnx->egl.eglQueryContext( 1257 dp->disp[c->impl].dpy, c->context, attribute, value); 1258 } 1259 1260 return result; 1261} 1262 1263EGLContext eglGetCurrentContext(void) 1264{ 1265 // could be called before eglInitialize(), but we wouldn't have a context 1266 // then, and this function would correctly return EGL_NO_CONTEXT. 1267 1268 EGLContext ctx = getContext(); 1269 return ctx; 1270} 1271 1272EGLSurface eglGetCurrentSurface(EGLint readdraw) 1273{ 1274 // could be called before eglInitialize(), but we wouldn't have a context 1275 // then, and this function would correctly return EGL_NO_SURFACE. 1276 1277 EGLContext ctx = getContext(); 1278 if (ctx) { 1279 egl_context_t const * const c = get_context(ctx); 1280 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 1281 switch (readdraw) { 1282 case EGL_READ: return c->read; 1283 case EGL_DRAW: return c->draw; 1284 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 1285 } 1286 } 1287 return EGL_NO_SURFACE; 1288} 1289 1290EGLDisplay eglGetCurrentDisplay(void) 1291{ 1292 // could be called before eglInitialize(), but we wouldn't have a context 1293 // then, and this function would correctly return EGL_NO_DISPLAY. 1294 1295 EGLContext ctx = getContext(); 1296 if (ctx) { 1297 egl_context_t const * const c = get_context(ctx); 1298 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 1299 return c->dpy; 1300 } 1301 return EGL_NO_DISPLAY; 1302} 1303 1304EGLBoolean eglWaitGL(void) 1305{ 1306 // could be called before eglInitialize(), but we wouldn't have a context 1307 // then, and this function would return GL_TRUE, which isn't wrong. 1308 1309 EGLBoolean res = EGL_TRUE; 1310 EGLContext ctx = getContext(); 1311 if (ctx) { 1312 egl_context_t const * const c = get_context(ctx); 1313 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1314 if (uint32_t(c->impl)>=2) 1315 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1316 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 1317 if (!cnx->dso) 1318 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1319 res = cnx->egl.eglWaitGL(); 1320 } 1321 return res; 1322} 1323 1324EGLBoolean eglWaitNative(EGLint engine) 1325{ 1326 // could be called before eglInitialize(), but we wouldn't have a context 1327 // then, and this function would return GL_TRUE, which isn't wrong. 1328 1329 EGLBoolean res = EGL_TRUE; 1330 EGLContext ctx = getContext(); 1331 if (ctx) { 1332 egl_context_t const * const c = get_context(ctx); 1333 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1334 if (uint32_t(c->impl)>=2) 1335 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1336 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 1337 if (!cnx->dso) 1338 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1339 res = cnx->egl.eglWaitNative(engine); 1340 } 1341 return res; 1342} 1343 1344EGLint eglGetError(void) 1345{ 1346 EGLint result = EGL_SUCCESS; 1347 EGLint err; 1348 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1349 err = EGL_SUCCESS; 1350 egl_connection_t* const cnx = &gEGLImpl[i]; 1351 if (cnx->dso) 1352 err = cnx->egl.eglGetError(); 1353 if (err!=EGL_SUCCESS && result==EGL_SUCCESS) 1354 result = err; 1355 } 1356 err = getError(); 1357 if (result == EGL_SUCCESS) 1358 result = err; 1359 return result; 1360} 1361 1362__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) 1363{ 1364 // eglGetProcAddress() could be the very first function called 1365 // in which case we must make sure we've initialized ourselves, this 1366 // happens the first time egl_get_display() is called. 1367 1368 if (egl_init_drivers() == EGL_FALSE) { 1369 setError(EGL_BAD_PARAMETER, NULL); 1370 return NULL; 1371 } 1372 1373 __eglMustCastToProperFunctionPointerType addr; 1374 addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap)); 1375 if (addr) return addr; 1376 1377 // this protects accesses to gGLExtentionMap and gGLExtentionSlot 1378 pthread_mutex_lock(&gInitDriverMutex); 1379 1380 /* 1381 * Since eglGetProcAddress() is not associated to anything, it needs 1382 * to return a function pointer that "works" regardless of what 1383 * the current context is. 1384 * 1385 * For this reason, we return a "forwarder", a small stub that takes 1386 * care of calling the function associated with the context 1387 * currently bound. 1388 * 1389 * We first look for extensions we've already resolved, if we're seeing 1390 * this extension for the first time, we go through all our 1391 * implementations and call eglGetProcAddress() and record the 1392 * result in the appropriate implementation hooks and return the 1393 * address of the forwarder corresponding to that hook set. 1394 * 1395 */ 1396 1397 const String8 name(procname); 1398 addr = gGLExtentionMap.valueFor(name); 1399 const int slot = gGLExtentionSlot; 1400 1401 LOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS, 1402 "no more slots for eglGetProcAddress(\"%s\")", 1403 procname); 1404 1405 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) { 1406 bool found = false; 1407 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1408 egl_connection_t* const cnx = &gEGLImpl[i]; 1409 if (cnx->dso && cnx->egl.eglGetProcAddress) { 1410 found = true; 1411 // Extensions are independent of the bound context 1412 cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] = 1413 cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] = 1414 cnx->egl.eglGetProcAddress(procname); 1415 } 1416 } 1417 if (found) { 1418 addr = gExtensionForwarders[slot]; 1419 gGLExtentionMap.add(name, addr); 1420 gGLExtentionSlot++; 1421 } 1422 } 1423 1424 pthread_mutex_unlock(&gInitDriverMutex); 1425 return addr; 1426} 1427 1428EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) 1429{ 1430 SurfaceRef _s(draw); 1431 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1432 1433 if (!validate_display_surface(dpy, draw)) 1434 return EGL_FALSE; 1435 egl_display_t const * const dp = get_display(dpy); 1436 egl_surface_t const * const s = get_surface(draw); 1437 return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface); 1438} 1439 1440EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, 1441 NativePixmapType target) 1442{ 1443 SurfaceRef _s(surface); 1444 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1445 1446 if (!validate_display_surface(dpy, surface)) 1447 return EGL_FALSE; 1448 egl_display_t const * const dp = get_display(dpy); 1449 egl_surface_t const * const s = get_surface(surface); 1450 return s->cnx->egl.eglCopyBuffers( 1451 dp->disp[s->impl].dpy, s->surface, target); 1452} 1453 1454const char* eglQueryString(EGLDisplay dpy, EGLint name) 1455{ 1456 egl_display_t const * const dp = get_display(dpy); 1457 switch (name) { 1458 case EGL_VENDOR: 1459 return gVendorString; 1460 case EGL_VERSION: 1461 return gVersionString; 1462 case EGL_EXTENSIONS: 1463 return gExtensionString; 1464 case EGL_CLIENT_APIS: 1465 return gClientApiString; 1466 } 1467 return setError(EGL_BAD_PARAMETER, (const char *)0); 1468} 1469 1470 1471// ---------------------------------------------------------------------------- 1472// EGL 1.1 1473// ---------------------------------------------------------------------------- 1474 1475EGLBoolean eglSurfaceAttrib( 1476 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 1477{ 1478 SurfaceRef _s(surface); 1479 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1480 1481 if (!validate_display_surface(dpy, surface)) 1482 return EGL_FALSE; 1483 egl_display_t const * const dp = get_display(dpy); 1484 egl_surface_t const * const s = get_surface(surface); 1485 if (s->cnx->egl.eglSurfaceAttrib) { 1486 return s->cnx->egl.eglSurfaceAttrib( 1487 dp->disp[s->impl].dpy, s->surface, attribute, value); 1488 } 1489 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1490} 1491 1492EGLBoolean eglBindTexImage( 1493 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1494{ 1495 SurfaceRef _s(surface); 1496 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1497 1498 if (!validate_display_surface(dpy, surface)) 1499 return EGL_FALSE; 1500 egl_display_t const * const dp = get_display(dpy); 1501 egl_surface_t const * const s = get_surface(surface); 1502 if (s->cnx->egl.eglBindTexImage) { 1503 return s->cnx->egl.eglBindTexImage( 1504 dp->disp[s->impl].dpy, s->surface, buffer); 1505 } 1506 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1507} 1508 1509EGLBoolean eglReleaseTexImage( 1510 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1511{ 1512 SurfaceRef _s(surface); 1513 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1514 1515 if (!validate_display_surface(dpy, surface)) 1516 return EGL_FALSE; 1517 egl_display_t const * const dp = get_display(dpy); 1518 egl_surface_t const * const s = get_surface(surface); 1519 if (s->cnx->egl.eglReleaseTexImage) { 1520 return s->cnx->egl.eglReleaseTexImage( 1521 dp->disp[s->impl].dpy, s->surface, buffer); 1522 } 1523 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1524} 1525 1526EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 1527{ 1528 egl_display_t * const dp = get_display(dpy); 1529 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1530 1531 EGLBoolean res = EGL_TRUE; 1532 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1533 egl_connection_t* const cnx = &gEGLImpl[i]; 1534 if (cnx->dso) { 1535 if (cnx->egl.eglSwapInterval) { 1536 if (cnx->egl.eglSwapInterval( 1537 dp->disp[i].dpy, interval) == EGL_FALSE) { 1538 res = EGL_FALSE; 1539 } 1540 } 1541 } 1542 } 1543 return res; 1544} 1545 1546 1547// ---------------------------------------------------------------------------- 1548// EGL 1.2 1549// ---------------------------------------------------------------------------- 1550 1551EGLBoolean eglWaitClient(void) 1552{ 1553 // could be called before eglInitialize(), but we wouldn't have a context 1554 // then, and this function would return GL_TRUE, which isn't wrong. 1555 EGLBoolean res = EGL_TRUE; 1556 EGLContext ctx = getContext(); 1557 if (ctx) { 1558 egl_context_t const * const c = get_context(ctx); 1559 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1560 if (uint32_t(c->impl)>=2) 1561 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1562 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 1563 if (!cnx->dso) 1564 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1565 if (cnx->egl.eglWaitClient) { 1566 res = cnx->egl.eglWaitClient(); 1567 } else { 1568 res = cnx->egl.eglWaitGL(); 1569 } 1570 } 1571 return res; 1572} 1573 1574EGLBoolean eglBindAPI(EGLenum api) 1575{ 1576 if (egl_init_drivers() == EGL_FALSE) { 1577 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1578 } 1579 1580 // bind this API on all EGLs 1581 EGLBoolean res = EGL_TRUE; 1582 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1583 egl_connection_t* const cnx = &gEGLImpl[i]; 1584 if (cnx->dso) { 1585 if (cnx->egl.eglBindAPI) { 1586 if (cnx->egl.eglBindAPI(api) == EGL_FALSE) { 1587 res = EGL_FALSE; 1588 } 1589 } 1590 } 1591 } 1592 return res; 1593} 1594 1595EGLenum eglQueryAPI(void) 1596{ 1597 if (egl_init_drivers() == EGL_FALSE) { 1598 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1599 } 1600 1601 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1602 egl_connection_t* const cnx = &gEGLImpl[i]; 1603 if (cnx->dso) { 1604 if (cnx->egl.eglQueryAPI) { 1605 // the first one we find is okay, because they all 1606 // should be the same 1607 return cnx->egl.eglQueryAPI(); 1608 } 1609 } 1610 } 1611 // or, it can only be OpenGL ES 1612 return EGL_OPENGL_ES_API; 1613} 1614 1615EGLBoolean eglReleaseThread(void) 1616{ 1617 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1618 egl_connection_t* const cnx = &gEGLImpl[i]; 1619 if (cnx->dso) { 1620 if (cnx->egl.eglReleaseThread) { 1621 cnx->egl.eglReleaseThread(); 1622 } 1623 } 1624 } 1625 clearTLS(); 1626 return EGL_TRUE; 1627} 1628 1629EGLSurface eglCreatePbufferFromClientBuffer( 1630 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 1631 EGLConfig config, const EGLint *attrib_list) 1632{ 1633 egl_display_t const* dp = 0; 1634 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 1635 if (!cnx) return EGL_FALSE; 1636 if (cnx->egl.eglCreatePbufferFromClientBuffer) { 1637 return cnx->egl.eglCreatePbufferFromClientBuffer( 1638 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 1639 buftype, buffer, 1640 dp->configs[intptr_t(config)].config, attrib_list); 1641 } 1642 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); 1643} 1644 1645// ---------------------------------------------------------------------------- 1646// EGL_EGLEXT_VERSION 3 1647// ---------------------------------------------------------------------------- 1648 1649EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, 1650 const EGLint *attrib_list) 1651{ 1652 SurfaceRef _s(surface); 1653 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1654 1655 if (!validate_display_surface(dpy, surface)) 1656 return EGL_FALSE; 1657 1658 egl_display_t const * const dp = get_display(dpy); 1659 egl_surface_t const * const s = get_surface(surface); 1660 1661 if (s->cnx->egl.eglLockSurfaceKHR) { 1662 return s->cnx->egl.eglLockSurfaceKHR( 1663 dp->disp[s->impl].dpy, s->surface, attrib_list); 1664 } 1665 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1666} 1667 1668EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) 1669{ 1670 SurfaceRef _s(surface); 1671 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1672 1673 if (!validate_display_surface(dpy, surface)) 1674 return EGL_FALSE; 1675 1676 egl_display_t const * const dp = get_display(dpy); 1677 egl_surface_t const * const s = get_surface(surface); 1678 1679 if (s->cnx->egl.eglUnlockSurfaceKHR) { 1680 return s->cnx->egl.eglUnlockSurfaceKHR( 1681 dp->disp[s->impl].dpy, s->surface); 1682 } 1683 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1684} 1685 1686EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1687 EGLClientBuffer buffer, const EGLint *attrib_list) 1688{ 1689 if (ctx != EGL_NO_CONTEXT) { 1690 ContextRef _c(ctx); 1691 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR); 1692 if (!validate_display_context(dpy, ctx)) 1693 return EGL_NO_IMAGE_KHR; 1694 egl_display_t const * const dp = get_display(dpy); 1695 egl_context_t * const c = get_context(ctx); 1696 // since we have an EGLContext, we know which implementation to use 1697 EGLImageKHR image = c->cnx->egl.eglCreateImageKHR( 1698 dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list); 1699 if (image == EGL_NO_IMAGE_KHR) 1700 return image; 1701 1702 egl_image_t* result = new egl_image_t(dpy, ctx); 1703 result->images[c->impl] = image; 1704 return (EGLImageKHR)result; 1705 } else { 1706 // EGL_NO_CONTEXT is a valid parameter 1707 egl_display_t const * const dp = get_display(dpy); 1708 if (dp == 0) { 1709 return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR); 1710 } 1711 1712 /* Since we don't have a way to know which implementation to call, 1713 * we're calling all of them. If at least one of the implementation 1714 * succeeded, this is a success. 1715 */ 1716 1717 EGLint currentError = eglGetError(); 1718 1719 EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS]; 1720 bool success = false; 1721 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1722 egl_connection_t* const cnx = &gEGLImpl[i]; 1723 implImages[i] = EGL_NO_IMAGE_KHR; 1724 if (cnx->dso) { 1725 if (cnx->egl.eglCreateImageKHR) { 1726 implImages[i] = cnx->egl.eglCreateImageKHR( 1727 dp->disp[i].dpy, ctx, target, buffer, attrib_list); 1728 if (implImages[i] != EGL_NO_IMAGE_KHR) { 1729 success = true; 1730 } 1731 } 1732 } 1733 } 1734 1735 if (!success) { 1736 // failure, if there was an error when we entered this function, 1737 // the error flag must not be updated. 1738 // Otherwise, the error is whatever happened in the implementation 1739 // that faulted. 1740 if (currentError != EGL_SUCCESS) { 1741 setError(currentError, EGL_NO_IMAGE_KHR); 1742 } 1743 return EGL_NO_IMAGE_KHR; 1744 } else { 1745 // In case of success, we need to clear all error flags 1746 // (especially those caused by the implementation that didn't 1747 // succeed). TODO: we could avoid this if we knew this was 1748 // a "full" success (all implementation succeeded). 1749 eglGetError(); 1750 } 1751 1752 egl_image_t* result = new egl_image_t(dpy, ctx); 1753 memcpy(result->images, implImages, sizeof(implImages)); 1754 return (EGLImageKHR)result; 1755 } 1756} 1757 1758EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 1759{ 1760 egl_display_t const * const dp = get_display(dpy); 1761 if (dp == 0) { 1762 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1763 } 1764 1765 ImageRef _i(img); 1766 if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1767 1768 egl_image_t* image = get_image(img); 1769 bool success = false; 1770 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1771 egl_connection_t* const cnx = &gEGLImpl[i]; 1772 if (image->images[i] != EGL_NO_IMAGE_KHR) { 1773 if (cnx->dso) { 1774 if (cnx->egl.eglDestroyImageKHR) { 1775 if (cnx->egl.eglDestroyImageKHR( 1776 dp->disp[i].dpy, image->images[i])) { 1777 success = true; 1778 } 1779 } 1780 } 1781 } 1782 } 1783 if (!success) 1784 return EGL_FALSE; 1785 1786 _i.terminate(); 1787 1788 return EGL_TRUE; 1789} 1790 1791 1792// ---------------------------------------------------------------------------- 1793// ANDROID extensions 1794// ---------------------------------------------------------------------------- 1795 1796EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw, 1797 EGLint left, EGLint top, EGLint width, EGLint height) 1798{ 1799 SurfaceRef _s(draw); 1800 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1801 1802 if (!validate_display_surface(dpy, draw)) 1803 return EGL_FALSE; 1804 egl_display_t const * const dp = get_display(dpy); 1805 egl_surface_t const * const s = get_surface(draw); 1806 if (s->cnx->egl.eglSetSwapRectangleANDROID) { 1807 return s->cnx->egl.eglSetSwapRectangleANDROID( 1808 dp->disp[s->impl].dpy, s->surface, left, top, width, height); 1809 } 1810 return setError(EGL_BAD_DISPLAY, NULL); 1811} 1812