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