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