egl.cpp revision 75bc27803efd96d15f48ef36429b27ab31182b67
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 242egl_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 return EGL_TRUE; 654 } 655 656 setGlThreadSpecific(&gHooksNoContext); 657 658 // initialize each EGL and 659 // build our own extension string first, based on the extension we know 660 // and the extension supported by our client implementation 661 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 662 egl_connection_t* const cnx = &gEGLImpl[i]; 663 cnx->major = -1; 664 cnx->minor = -1; 665 if (!cnx->dso) 666 continue; 667 668#if defined(ADRENO130) 669#warning "Adreno-130 eglInitialize() workaround" 670 /* 671 * The ADRENO 130 driver returns a different EGLDisplay each time 672 * eglGetDisplay() is called, but also makes the EGLDisplay invalid 673 * after eglTerminate() has been called, so that eglInitialize() 674 * cannot be called again. Therefore, we need to make sure to call 675 * eglGetDisplay() before calling eglInitialize(); 676 */ 677 if (i == IMPL_HARDWARE) { 678 dp->disp[i].dpy = 679 cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY); 680 } 681#endif 682 683 684 EGLDisplay idpy = dp->disp[i].dpy; 685 if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) { 686 //LOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p", 687 // i, idpy, cnx->major, cnx->minor, cnx); 688 689 // display is now initialized 690 dp->disp[i].state = egl_display_t::INITIALIZED; 691 692 // get the query-strings for this display for each implementation 693 dp->disp[i].queryString.vendor = 694 cnx->egl.eglQueryString(idpy, EGL_VENDOR); 695 dp->disp[i].queryString.version = 696 cnx->egl.eglQueryString(idpy, EGL_VERSION); 697 dp->disp[i].queryString.extensions = 698 cnx->egl.eglQueryString(idpy, EGL_EXTENSIONS); 699 dp->disp[i].queryString.clientApi = 700 cnx->egl.eglQueryString(idpy, EGL_CLIENT_APIS); 701 702 } else { 703 LOGW("%d: eglInitialize(%p) failed (%s)", i, idpy, 704 egl_strerror(cnx->egl.eglGetError())); 705 } 706 } 707 708 EGLBoolean res = EGL_FALSE; 709 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 710 egl_connection_t* const cnx = &gEGLImpl[i]; 711 if (cnx->dso && cnx->major>=0 && cnx->minor>=0) { 712 EGLint n; 713 if (cnx->egl.eglGetConfigs(dp->disp[i].dpy, 0, 0, &n)) { 714 dp->disp[i].config = (EGLConfig*)malloc(sizeof(EGLConfig)*n); 715 if (dp->disp[i].config) { 716 if (cnx->egl.eglGetConfigs( 717 dp->disp[i].dpy, dp->disp[i].config, n, 718 &dp->disp[i].numConfigs)) 719 { 720 // sort the configurations so we can do binary searches 721 qsort( dp->disp[i].config, 722 dp->disp[i].numConfigs, 723 sizeof(EGLConfig), cmp_configs); 724 725 dp->numTotalConfigs += n; 726 res = EGL_TRUE; 727 } 728 } 729 } 730 } 731 } 732 733 if (res == EGL_TRUE) { 734 dp->refs++; 735 if (major != NULL) *major = VERSION_MAJOR; 736 if (minor != NULL) *minor = VERSION_MINOR; 737 return EGL_TRUE; 738 } 739 return setError(EGL_NOT_INITIALIZED, EGL_FALSE); 740} 741 742EGLBoolean eglTerminate(EGLDisplay dpy) 743{ 744 // NOTE: don't unload the drivers b/c some APIs can be called 745 // after eglTerminate() has been called. eglTerminate() only 746 // terminates an EGLDisplay, not a EGL itself. 747 748 egl_display_t* const dp = get_display(dpy); 749 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 750 751 Mutex::Autolock _l(dp->lock); 752 753 if (dp->refs == 0) { 754 return setError(EGL_NOT_INITIALIZED, EGL_FALSE); 755 } 756 757 // this is specific to Android, display termination is ref-counted. 758 if (dp->refs > 1) 759 return EGL_TRUE; 760 761 EGLBoolean res = EGL_FALSE; 762 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 763 egl_connection_t* const cnx = &gEGLImpl[i]; 764 if (cnx->dso && dp->disp[i].state == egl_display_t::INITIALIZED) { 765 if (cnx->egl.eglTerminate(dp->disp[i].dpy) == EGL_FALSE) { 766 LOGW("%d: eglTerminate(%p) failed (%s)", i, dp->disp[i].dpy, 767 egl_strerror(cnx->egl.eglGetError())); 768 } 769 // REVISIT: it's unclear what to do if eglTerminate() fails 770 free(dp->disp[i].config); 771 772 dp->disp[i].numConfigs = 0; 773 dp->disp[i].config = 0; 774 dp->disp[i].state = egl_display_t::TERMINATED; 775 776 res = EGL_TRUE; 777 } 778 } 779 780 // TODO: all egl_object_t should be marked for termination 781 782 dp->refs--; 783 dp->numTotalConfigs = 0; 784 clearTLS(); 785 return res; 786} 787 788// ---------------------------------------------------------------------------- 789// configuration 790// ---------------------------------------------------------------------------- 791 792EGLBoolean eglGetConfigs( EGLDisplay dpy, 793 EGLConfig *configs, 794 EGLint config_size, EGLint *num_config) 795{ 796 egl_display_t const * const dp = get_display(dpy); 797 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 798 799 GLint numConfigs = dp->numTotalConfigs; 800 if (!configs) { 801 *num_config = numConfigs; 802 return EGL_TRUE; 803 } 804 GLint n = 0; 805 for (int j=0 ; j<IMPL_NUM_IMPLEMENTATIONS ; j++) { 806 for (int i=0 ; i<dp->disp[j].numConfigs && config_size ; i++) { 807 *configs++ = MAKE_CONFIG(j, i); 808 config_size--; 809 n++; 810 } 811 } 812 813 *num_config = n; 814 return EGL_TRUE; 815} 816 817EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, 818 EGLConfig *configs, EGLint config_size, 819 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 if (num_config==0) { 825 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 826 } 827 828 EGLint n; 829 EGLBoolean res = EGL_FALSE; 830 *num_config = 0; 831 832 833 // It is unfortunate, but we need to remap the EGL_CONFIG_IDs, 834 // to do this, we have to go through the attrib_list array once 835 // to figure out both its size and if it contains an EGL_CONFIG_ID 836 // key. If so, the full array is copied and patched. 837 // NOTE: we assume that there can be only one occurrence 838 // of EGL_CONFIG_ID. 839 840 EGLint patch_index = -1; 841 GLint attr; 842 size_t size = 0; 843 while ((attr=attrib_list[size]) != EGL_NONE) { 844 if (attr == EGL_CONFIG_ID) 845 patch_index = size; 846 size += 2; 847 } 848 if (patch_index >= 0) { 849 size += 2; // we need copy the sentinel as well 850 EGLint* new_list = (EGLint*)malloc(size*sizeof(EGLint)); 851 if (new_list == 0) 852 return setError(EGL_BAD_ALLOC, EGL_FALSE); 853 memcpy(new_list, attrib_list, size*sizeof(EGLint)); 854 855 // patch the requested EGL_CONFIG_ID 856 int i, index; 857 EGLint& configId(new_list[patch_index+1]); 858 uniqueIdToConfig(dp, configId, i, index); 859 860 egl_connection_t* const cnx = &gEGLImpl[i]; 861 if (cnx->dso) { 862 cnx->egl.eglGetConfigAttrib( 863 dp->disp[i].dpy, dp->disp[i].config[index], 864 EGL_CONFIG_ID, &configId); 865 866 // and switch to the new list 867 attrib_list = const_cast<const EGLint *>(new_list); 868 869 // At this point, the only configuration that can match is 870 // dp->configs[i][index], however, we don't know if it would be 871 // rejected because of the other attributes, so we do have to call 872 // cnx->egl.eglChooseConfig() -- but we don't have to loop 873 // through all the EGLimpl[]. 874 // We also know we can only get a single config back, and we know 875 // which one. 876 877 res = cnx->egl.eglChooseConfig( 878 dp->disp[i].dpy, attrib_list, configs, config_size, &n); 879 if (res && n>0) { 880 // n has to be 0 or 1, by construction, and we already know 881 // which config it will return (since there can be only one). 882 if (configs) { 883 configs[0] = MAKE_CONFIG(i, index); 884 } 885 *num_config = 1; 886 } 887 } 888 889 free(const_cast<EGLint *>(attrib_list)); 890 return res; 891 } 892 893 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 894 egl_connection_t* const cnx = &gEGLImpl[i]; 895 if (cnx->dso) { 896 if (cnx->egl.eglChooseConfig( 897 dp->disp[i].dpy, attrib_list, configs, config_size, &n)) { 898 if (configs) { 899 // now we need to convert these client EGLConfig to our 900 // internal EGLConfig format. This is done in O(n log n). 901 for (int j=0 ; j<n ; j++) { 902 int index = binarySearch<EGLConfig>( 903 dp->disp[i].config, 0, 904 dp->disp[i].numConfigs-1, configs[j]); 905 if (index >= 0) { 906 if (configs) { 907 configs[j] = MAKE_CONFIG(i, index); 908 } 909 } else { 910 return setError(EGL_BAD_CONFIG, EGL_FALSE); 911 } 912 } 913 configs += n; 914 config_size -= n; 915 } 916 *num_config += n; 917 res = EGL_TRUE; 918 } 919 } 920 } 921 return res; 922} 923 924EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, 925 EGLint attribute, EGLint *value) 926{ 927 egl_display_t const* dp = 0; 928 int i=0, index=0; 929 egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); 930 if (!cnx) return EGL_FALSE; 931 932 if (attribute == EGL_CONFIG_ID) { 933 // EGL_CONFIG_IDs must be unique, just use the order of the selected 934 // EGLConfig. 935 *value = configToUniqueId(dp, i, index); 936 return EGL_TRUE; 937 } 938 return cnx->egl.eglGetConfigAttrib( 939 dp->disp[i].dpy, dp->disp[i].config[index], attribute, value); 940} 941 942// ---------------------------------------------------------------------------- 943// surfaces 944// ---------------------------------------------------------------------------- 945 946EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, 947 NativeWindowType window, 948 const EGLint *attrib_list) 949{ 950 egl_display_t const* dp = 0; 951 int i=0, index=0; 952 egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); 953 if (cnx) { 954 EGLSurface surface = cnx->egl.eglCreateWindowSurface( 955 dp->disp[i].dpy, dp->disp[i].config[index], window, attrib_list); 956 if (surface != EGL_NO_SURFACE) { 957 egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx); 958 return s; 959 } 960 } 961 return EGL_NO_SURFACE; 962} 963 964EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, 965 NativePixmapType pixmap, 966 const EGLint *attrib_list) 967{ 968 egl_display_t const* dp = 0; 969 int i=0, index=0; 970 egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); 971 if (cnx) { 972 EGLSurface surface = cnx->egl.eglCreatePixmapSurface( 973 dp->disp[i].dpy, dp->disp[i].config[index], pixmap, attrib_list); 974 if (surface != EGL_NO_SURFACE) { 975 egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx); 976 return s; 977 } 978 } 979 return EGL_NO_SURFACE; 980} 981 982EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, 983 const EGLint *attrib_list) 984{ 985 egl_display_t const* dp = 0; 986 int i=0, index=0; 987 egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); 988 if (cnx) { 989 EGLSurface surface = cnx->egl.eglCreatePbufferSurface( 990 dp->disp[i].dpy, dp->disp[i].config[index], attrib_list); 991 if (surface != EGL_NO_SURFACE) { 992 egl_surface_t* s = new egl_surface_t(dpy, surface, i, cnx); 993 return s; 994 } 995 } 996 return EGL_NO_SURFACE; 997} 998 999EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) 1000{ 1001 SurfaceRef _s(surface); 1002 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1003 1004 if (!validate_display_surface(dpy, surface)) 1005 return EGL_FALSE; 1006 egl_display_t const * const dp = get_display(dpy); 1007 1008 egl_surface_t * const s = get_surface(surface); 1009 EGLBoolean result = s->cnx->egl.eglDestroySurface( 1010 dp->disp[s->impl].dpy, s->surface); 1011 if (result == EGL_TRUE) { 1012 _s.terminate(); 1013 } 1014 return result; 1015} 1016 1017EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface, 1018 EGLint attribute, EGLint *value) 1019{ 1020 SurfaceRef _s(surface); 1021 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1022 1023 if (!validate_display_surface(dpy, surface)) 1024 return EGL_FALSE; 1025 egl_display_t const * const dp = get_display(dpy); 1026 egl_surface_t const * const s = get_surface(surface); 1027 1028 return s->cnx->egl.eglQuerySurface( 1029 dp->disp[s->impl].dpy, s->surface, attribute, value); 1030} 1031 1032// ---------------------------------------------------------------------------- 1033// contextes 1034// ---------------------------------------------------------------------------- 1035 1036EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, 1037 EGLContext share_list, const EGLint *attrib_list) 1038{ 1039 egl_display_t const* dp = 0; 1040 int i=0, index=0; 1041 egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); 1042 if (cnx) { 1043 EGLContext context = cnx->egl.eglCreateContext( 1044 dp->disp[i].dpy, dp->disp[i].config[index], 1045 share_list, attrib_list); 1046 if (context != EGL_NO_CONTEXT) { 1047 // figure out if it's a GLESv1 or GLESv2 1048 int version = 0; 1049 if (attrib_list) { 1050 while (*attrib_list != EGL_NONE) { 1051 GLint attr = *attrib_list++; 1052 GLint value = *attrib_list++; 1053 if (attr == EGL_CONTEXT_CLIENT_VERSION) { 1054 if (value == 1) { 1055 version = GLESv1_INDEX; 1056 } else if (value == 2) { 1057 version = GLESv2_INDEX; 1058 } 1059 } 1060 }; 1061 } 1062 egl_context_t* c = new egl_context_t(dpy, context, i, cnx, version); 1063 return c; 1064 } 1065 } 1066 return EGL_NO_CONTEXT; 1067} 1068 1069EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) 1070{ 1071 ContextRef _c(ctx); 1072 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1073 1074 if (!validate_display_context(dpy, ctx)) 1075 return EGL_FALSE; 1076 egl_display_t const * const dp = get_display(dpy); 1077 egl_context_t * const c = get_context(ctx); 1078 EGLBoolean result = c->cnx->egl.eglDestroyContext( 1079 dp->disp[c->impl].dpy, c->context); 1080 if (result == EGL_TRUE) { 1081 _c.terminate(); 1082 } 1083 return result; 1084} 1085 1086EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, 1087 EGLSurface read, EGLContext ctx) 1088{ 1089 // get a reference to the object passed in 1090 ContextRef _c(ctx); 1091 SurfaceRef _d(draw); 1092 SurfaceRef _r(read); 1093 1094 // validate the display and the context (if not EGL_NO_CONTEXT) 1095 egl_display_t const * const dp = get_display(dpy); 1096 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1097 if ((ctx != EGL_NO_CONTEXT) && (!validate_display_context(dpy, ctx))) { 1098 // EGL_NO_CONTEXT is valid 1099 return EGL_FALSE; 1100 } 1101 1102 // these are the underlying implementation's object 1103 EGLContext impl_ctx = EGL_NO_CONTEXT; 1104 EGLSurface impl_draw = EGL_NO_SURFACE; 1105 EGLSurface impl_read = EGL_NO_SURFACE; 1106 1107 // these are our objects structs passed in 1108 egl_context_t * c = NULL; 1109 egl_surface_t const * d = NULL; 1110 egl_surface_t const * r = NULL; 1111 1112 // these are the current objects structs 1113 egl_context_t * cur_c = get_context(getContext()); 1114 egl_surface_t * cur_r = NULL; 1115 egl_surface_t * cur_d = NULL; 1116 1117 if (ctx != EGL_NO_CONTEXT) { 1118 c = get_context(ctx); 1119 cur_r = get_surface(c->read); 1120 cur_d = get_surface(c->draw); 1121 impl_ctx = c->context; 1122 } else { 1123 // no context given, use the implementation of the current context 1124 if (cur_c == NULL) { 1125 // no current context 1126 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) { 1127 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT); 1128 return setError(EGL_BAD_MATCH, EGL_FALSE); 1129 } 1130 // not an error, there is just no current context. 1131 return EGL_TRUE; 1132 } 1133 } 1134 1135 // retrieve the underlying implementation's draw EGLSurface 1136 if (draw != EGL_NO_SURFACE) { 1137 d = get_surface(draw); 1138 // make sure the EGLContext and EGLSurface passed in are for 1139 // the same driver 1140 if (c && d->impl != c->impl) 1141 return setError(EGL_BAD_MATCH, EGL_FALSE); 1142 impl_draw = d->surface; 1143 } 1144 1145 // retrieve the underlying implementation's read EGLSurface 1146 if (read != EGL_NO_SURFACE) { 1147 r = get_surface(read); 1148 // make sure the EGLContext and EGLSurface passed in are for 1149 // the same driver 1150 if (c && r->impl != c->impl) 1151 return setError(EGL_BAD_MATCH, EGL_FALSE); 1152 impl_read = r->surface; 1153 } 1154 1155 EGLBoolean result; 1156 1157 if (c) { 1158 result = c->cnx->egl.eglMakeCurrent( 1159 dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx); 1160 } else { 1161 result = cur_c->cnx->egl.eglMakeCurrent( 1162 dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx); 1163 } 1164 1165 if (result == EGL_TRUE) { 1166 // by construction, these are either 0 or valid (possibly terminated) 1167 // it should be impossible for these to be invalid 1168 ContextRef _cur_c(cur_c); 1169 SurfaceRef _cur_r(cur_r); 1170 SurfaceRef _cur_d(cur_d); 1171 1172 // cur_c has to be valid here (but could be terminated) 1173 if (ctx != EGL_NO_CONTEXT) { 1174 setGlThreadSpecific(c->cnx->hooks[c->version]); 1175 setContext(ctx); 1176 _c.acquire(); 1177 } else { 1178 setGlThreadSpecific(&gHooksNoContext); 1179 setContext(EGL_NO_CONTEXT); 1180 } 1181 _cur_c.release(); 1182 1183 _r.acquire(); 1184 _cur_r.release(); 1185 if (c) c->read = read; 1186 1187 _d.acquire(); 1188 _cur_d.release(); 1189 if (c) c->draw = draw; 1190 } 1191 return result; 1192} 1193 1194 1195EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, 1196 EGLint attribute, EGLint *value) 1197{ 1198 ContextRef _c(ctx); 1199 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1200 1201 if (!validate_display_context(dpy, ctx)) 1202 return EGL_FALSE; 1203 1204 egl_display_t const * const dp = get_display(dpy); 1205 egl_context_t * const c = get_context(ctx); 1206 1207 return c->cnx->egl.eglQueryContext( 1208 dp->disp[c->impl].dpy, c->context, attribute, value); 1209} 1210 1211EGLContext eglGetCurrentContext(void) 1212{ 1213 // could be called before eglInitialize(), but we wouldn't have a context 1214 // then, and this function would correctly return EGL_NO_CONTEXT. 1215 1216 EGLContext ctx = getContext(); 1217 return ctx; 1218} 1219 1220EGLSurface eglGetCurrentSurface(EGLint readdraw) 1221{ 1222 // could be called before eglInitialize(), but we wouldn't have a context 1223 // then, and this function would correctly return EGL_NO_SURFACE. 1224 1225 EGLContext ctx = getContext(); 1226 if (ctx) { 1227 egl_context_t const * const c = get_context(ctx); 1228 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 1229 switch (readdraw) { 1230 case EGL_READ: return c->read; 1231 case EGL_DRAW: return c->draw; 1232 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 1233 } 1234 } 1235 return EGL_NO_SURFACE; 1236} 1237 1238EGLDisplay eglGetCurrentDisplay(void) 1239{ 1240 // could be called before eglInitialize(), but we wouldn't have a context 1241 // then, and this function would correctly return EGL_NO_DISPLAY. 1242 1243 EGLContext ctx = getContext(); 1244 if (ctx) { 1245 egl_context_t const * const c = get_context(ctx); 1246 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 1247 return c->dpy; 1248 } 1249 return EGL_NO_DISPLAY; 1250} 1251 1252EGLBoolean eglWaitGL(void) 1253{ 1254 // could be called before eglInitialize(), but we wouldn't have a context 1255 // then, and this function would return GL_TRUE, which isn't wrong. 1256 1257 EGLBoolean res = EGL_TRUE; 1258 EGLContext ctx = getContext(); 1259 if (ctx) { 1260 egl_context_t const * const c = get_context(ctx); 1261 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1262 if (uint32_t(c->impl)>=2) 1263 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1264 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 1265 if (!cnx->dso) 1266 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1267 res = cnx->egl.eglWaitGL(); 1268 } 1269 return res; 1270} 1271 1272EGLBoolean eglWaitNative(EGLint engine) 1273{ 1274 // could be called before eglInitialize(), but we wouldn't have a context 1275 // then, and this function would return GL_TRUE, which isn't wrong. 1276 1277 EGLBoolean res = EGL_TRUE; 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_FALSE); 1282 if (uint32_t(c->impl)>=2) 1283 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1284 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 1285 if (!cnx->dso) 1286 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1287 res = cnx->egl.eglWaitNative(engine); 1288 } 1289 return res; 1290} 1291 1292EGLint eglGetError(void) 1293{ 1294 EGLint result = EGL_SUCCESS; 1295 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1296 EGLint err = EGL_SUCCESS; 1297 egl_connection_t* const cnx = &gEGLImpl[i]; 1298 if (cnx->dso) 1299 err = cnx->egl.eglGetError(); 1300 if (err!=EGL_SUCCESS && result==EGL_SUCCESS) 1301 result = err; 1302 } 1303 if (result == EGL_SUCCESS) 1304 result = getError(); 1305 return result; 1306} 1307 1308__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) 1309{ 1310 // eglGetProcAddress() could be the very first function called 1311 // in which case we must make sure we've initialized ourselves, this 1312 // happens the first time egl_get_display() is called. 1313 1314 if (egl_init_drivers() == EGL_FALSE) { 1315 setError(EGL_BAD_PARAMETER, NULL); 1316 return NULL; 1317 } 1318 1319 __eglMustCastToProperFunctionPointerType addr; 1320 addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap)); 1321 if (addr) return addr; 1322 1323 return NULL; // TODO: finish implementation below 1324 1325 addr = findProcAddress(procname, gGLExtentionMap, NELEM(gGLExtentionMap)); 1326 if (addr) return addr; 1327 1328 addr = 0; 1329 int slot = -1; 1330 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1331 egl_connection_t* const cnx = &gEGLImpl[i]; 1332 if (cnx->dso) { 1333 if (cnx->egl.eglGetProcAddress) { 1334 addr = cnx->egl.eglGetProcAddress(procname); 1335 if (addr) { 1336 if (slot == -1) { 1337 slot = 0; // XXX: find free slot 1338 if (slot == -1) { 1339 addr = 0; 1340 break; 1341 } 1342 } 1343 //cnx->hooks->ext.extensions[slot] = addr; 1344 } 1345 } 1346 } 1347 } 1348 1349 if (slot >= 0) { 1350 addr = 0; // XXX: address of stub 'slot' 1351 gGLExtentionMap[slot].name = strdup(procname); 1352 gGLExtentionMap[slot].address = addr; 1353 } 1354 1355 return addr; 1356 1357 1358 /* 1359 * TODO: For OpenGL ES extensions, we must generate a stub 1360 * that looks like 1361 * mov r12, #0xFFFF0FFF 1362 * ldr r12, [r12, #-15] 1363 * ldr r12, [r12, #TLS_SLOT_OPENGL_API*4] 1364 * mov r12, [r12, #api_offset] 1365 * ldrne pc, r12 1366 * mov pc, #unsupported_extension 1367 * 1368 * and write the address of the extension in *all* 1369 * gl_hooks_t::gl_ext_t at offset "api_offset" from gl_hooks_t 1370 * 1371 */ 1372} 1373 1374EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) 1375{ 1376 SurfaceRef _s(draw); 1377 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1378 1379 if (!validate_display_surface(dpy, draw)) 1380 return EGL_FALSE; 1381 egl_display_t const * const dp = get_display(dpy); 1382 egl_surface_t const * const s = get_surface(draw); 1383 return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface); 1384} 1385 1386EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, 1387 NativePixmapType target) 1388{ 1389 SurfaceRef _s(surface); 1390 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1391 1392 if (!validate_display_surface(dpy, surface)) 1393 return EGL_FALSE; 1394 egl_display_t const * const dp = get_display(dpy); 1395 egl_surface_t const * const s = get_surface(surface); 1396 return s->cnx->egl.eglCopyBuffers( 1397 dp->disp[s->impl].dpy, s->surface, target); 1398} 1399 1400const char* eglQueryString(EGLDisplay dpy, EGLint name) 1401{ 1402 egl_display_t const * const dp = get_display(dpy); 1403 switch (name) { 1404 case EGL_VENDOR: 1405 return gVendorString; 1406 case EGL_VERSION: 1407 return gVersionString; 1408 case EGL_EXTENSIONS: 1409 return gExtensionString; 1410 case EGL_CLIENT_APIS: 1411 return gClientApiString; 1412 } 1413 return setError(EGL_BAD_PARAMETER, (const char *)0); 1414} 1415 1416 1417// ---------------------------------------------------------------------------- 1418// EGL 1.1 1419// ---------------------------------------------------------------------------- 1420 1421EGLBoolean eglSurfaceAttrib( 1422 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 1423{ 1424 SurfaceRef _s(surface); 1425 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1426 1427 if (!validate_display_surface(dpy, surface)) 1428 return EGL_FALSE; 1429 egl_display_t const * const dp = get_display(dpy); 1430 egl_surface_t const * const s = get_surface(surface); 1431 if (s->cnx->egl.eglSurfaceAttrib) { 1432 return s->cnx->egl.eglSurfaceAttrib( 1433 dp->disp[s->impl].dpy, s->surface, attribute, value); 1434 } 1435 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1436} 1437 1438EGLBoolean eglBindTexImage( 1439 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1440{ 1441 SurfaceRef _s(surface); 1442 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1443 1444 if (!validate_display_surface(dpy, surface)) 1445 return EGL_FALSE; 1446 egl_display_t const * const dp = get_display(dpy); 1447 egl_surface_t const * const s = get_surface(surface); 1448 if (s->cnx->egl.eglBindTexImage) { 1449 return s->cnx->egl.eglBindTexImage( 1450 dp->disp[s->impl].dpy, s->surface, buffer); 1451 } 1452 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1453} 1454 1455EGLBoolean eglReleaseTexImage( 1456 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1457{ 1458 SurfaceRef _s(surface); 1459 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1460 1461 if (!validate_display_surface(dpy, surface)) 1462 return EGL_FALSE; 1463 egl_display_t const * const dp = get_display(dpy); 1464 egl_surface_t const * const s = get_surface(surface); 1465 if (s->cnx->egl.eglReleaseTexImage) { 1466 return s->cnx->egl.eglReleaseTexImage( 1467 dp->disp[s->impl].dpy, s->surface, buffer); 1468 } 1469 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1470} 1471 1472EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 1473{ 1474 egl_display_t * const dp = get_display(dpy); 1475 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1476 1477 EGLBoolean res = EGL_TRUE; 1478 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1479 egl_connection_t* const cnx = &gEGLImpl[i]; 1480 if (cnx->dso) { 1481 if (cnx->egl.eglSwapInterval) { 1482 if (cnx->egl.eglSwapInterval( 1483 dp->disp[i].dpy, interval) == EGL_FALSE) { 1484 res = EGL_FALSE; 1485 } 1486 } 1487 } 1488 } 1489 return res; 1490} 1491 1492 1493// ---------------------------------------------------------------------------- 1494// EGL 1.2 1495// ---------------------------------------------------------------------------- 1496 1497EGLBoolean eglWaitClient(void) 1498{ 1499 // could be called before eglInitialize(), but we wouldn't have a context 1500 // then, and this function would return GL_TRUE, which isn't wrong. 1501 EGLBoolean res = EGL_TRUE; 1502 EGLContext ctx = getContext(); 1503 if (ctx) { 1504 egl_context_t const * const c = get_context(ctx); 1505 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1506 if (uint32_t(c->impl)>=2) 1507 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1508 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 1509 if (!cnx->dso) 1510 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1511 if (cnx->egl.eglWaitClient) { 1512 res = cnx->egl.eglWaitClient(); 1513 } else { 1514 res = cnx->egl.eglWaitGL(); 1515 } 1516 } 1517 return res; 1518} 1519 1520EGLBoolean eglBindAPI(EGLenum api) 1521{ 1522 if (egl_init_drivers() == EGL_FALSE) { 1523 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1524 } 1525 1526 // bind this API on all EGLs 1527 EGLBoolean res = EGL_TRUE; 1528 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1529 egl_connection_t* const cnx = &gEGLImpl[i]; 1530 if (cnx->dso) { 1531 if (cnx->egl.eglBindAPI) { 1532 if (cnx->egl.eglBindAPI(api) == EGL_FALSE) { 1533 res = EGL_FALSE; 1534 } 1535 } 1536 } 1537 } 1538 return res; 1539} 1540 1541EGLenum eglQueryAPI(void) 1542{ 1543 if (egl_init_drivers() == EGL_FALSE) { 1544 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1545 } 1546 1547 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1548 egl_connection_t* const cnx = &gEGLImpl[i]; 1549 if (cnx->dso) { 1550 if (cnx->egl.eglQueryAPI) { 1551 // the first one we find is okay, because they all 1552 // should be the same 1553 return cnx->egl.eglQueryAPI(); 1554 } 1555 } 1556 } 1557 // or, it can only be OpenGL ES 1558 return EGL_OPENGL_ES_API; 1559} 1560 1561EGLBoolean eglReleaseThread(void) 1562{ 1563 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1564 egl_connection_t* const cnx = &gEGLImpl[i]; 1565 if (cnx->dso) { 1566 if (cnx->egl.eglReleaseThread) { 1567 cnx->egl.eglReleaseThread(); 1568 } 1569 } 1570 } 1571 clearTLS(); 1572 return EGL_TRUE; 1573} 1574 1575EGLSurface eglCreatePbufferFromClientBuffer( 1576 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 1577 EGLConfig config, const EGLint *attrib_list) 1578{ 1579 egl_display_t const* dp = 0; 1580 int i=0, index=0; 1581 egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); 1582 if (!cnx) return EGL_FALSE; 1583 if (cnx->egl.eglCreatePbufferFromClientBuffer) { 1584 return cnx->egl.eglCreatePbufferFromClientBuffer( 1585 dp->disp[i].dpy, buftype, buffer, 1586 dp->disp[i].config[index], attrib_list); 1587 } 1588 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); 1589} 1590 1591// ---------------------------------------------------------------------------- 1592// EGL_EGLEXT_VERSION 3 1593// ---------------------------------------------------------------------------- 1594 1595EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, 1596 const EGLint *attrib_list) 1597{ 1598 SurfaceRef _s(surface); 1599 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1600 1601 if (!validate_display_surface(dpy, surface)) 1602 return EGL_FALSE; 1603 1604 egl_display_t const * const dp = get_display(dpy); 1605 egl_surface_t const * const s = get_surface(surface); 1606 1607 if (s->cnx->egl.eglLockSurfaceKHR) { 1608 return s->cnx->egl.eglLockSurfaceKHR( 1609 dp->disp[s->impl].dpy, s->surface, attrib_list); 1610 } 1611 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1612} 1613 1614EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) 1615{ 1616 SurfaceRef _s(surface); 1617 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1618 1619 if (!validate_display_surface(dpy, surface)) 1620 return EGL_FALSE; 1621 1622 egl_display_t const * const dp = get_display(dpy); 1623 egl_surface_t const * const s = get_surface(surface); 1624 1625 if (s->cnx->egl.eglUnlockSurfaceKHR) { 1626 return s->cnx->egl.eglUnlockSurfaceKHR( 1627 dp->disp[s->impl].dpy, s->surface); 1628 } 1629 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1630} 1631 1632EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1633 EGLClientBuffer buffer, const EGLint *attrib_list) 1634{ 1635 if (ctx != EGL_NO_CONTEXT) { 1636 ContextRef _c(ctx); 1637 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR); 1638 if (!validate_display_context(dpy, ctx)) 1639 return EGL_NO_IMAGE_KHR; 1640 egl_display_t const * const dp = get_display(dpy); 1641 egl_context_t * const c = get_context(ctx); 1642 // since we have an EGLContext, we know which implementation to use 1643 EGLImageKHR image = c->cnx->egl.eglCreateImageKHR( 1644 dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list); 1645 if (image == EGL_NO_IMAGE_KHR) 1646 return image; 1647 1648 egl_image_t* result = new egl_image_t(dpy, ctx); 1649 result->images[c->impl] = image; 1650 return (EGLImageKHR)result; 1651 } else { 1652 // EGL_NO_CONTEXT is a valid parameter 1653 egl_display_t const * const dp = get_display(dpy); 1654 if (dp == 0) { 1655 return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR); 1656 } 1657 1658 /* Since we don't have a way to know which implementation to call, 1659 * we're calling all of them. If at least one of the implementation 1660 * succeeded, this is a success. 1661 */ 1662 1663 EGLint currentError = eglGetError(); 1664 1665 EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS]; 1666 bool success = false; 1667 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1668 egl_connection_t* const cnx = &gEGLImpl[i]; 1669 implImages[i] = EGL_NO_IMAGE_KHR; 1670 if (cnx->dso) { 1671 if (cnx->egl.eglCreateImageKHR) { 1672 implImages[i] = cnx->egl.eglCreateImageKHR( 1673 dp->disp[i].dpy, ctx, target, buffer, attrib_list); 1674 if (implImages[i] != EGL_NO_IMAGE_KHR) { 1675 success = true; 1676 } 1677 } 1678 } 1679 } 1680 1681 if (!success) { 1682 // failure, if there was an error when we entered this function, 1683 // the error flag must not be updated. 1684 // Otherwise, the error is whatever happened in the implementation 1685 // that faulted. 1686 if (currentError != EGL_SUCCESS) { 1687 setError(currentError, EGL_NO_IMAGE_KHR); 1688 } 1689 return EGL_NO_IMAGE_KHR; 1690 } else { 1691 // In case of success, we need to clear all error flags 1692 // (especially those caused by the implementation that didn't 1693 // succeed). TODO: we could avoid this if we knew this was 1694 // a "full" success (all implementation succeeded). 1695 eglGetError(); 1696 } 1697 1698 egl_image_t* result = new egl_image_t(dpy, ctx); 1699 memcpy(result->images, implImages, sizeof(implImages)); 1700 return (EGLImageKHR)result; 1701 } 1702} 1703 1704EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 1705{ 1706 egl_display_t const * const dp = get_display(dpy); 1707 if (dp == 0) { 1708 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1709 } 1710 1711 ImageRef _i(img); 1712 if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1713 1714 egl_image_t* image = get_image(img); 1715 bool success = false; 1716 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1717 egl_connection_t* const cnx = &gEGLImpl[i]; 1718 if (image->images[i] != EGL_NO_IMAGE_KHR) { 1719 if (cnx->dso) { 1720 if (cnx->egl.eglCreateImageKHR) { 1721 if (cnx->egl.eglDestroyImageKHR( 1722 dp->disp[i].dpy, image->images[i])) { 1723 success = true; 1724 } 1725 } 1726 } 1727 } 1728 } 1729 if (!success) 1730 return EGL_FALSE; 1731 1732 _i.terminate(); 1733 1734 return EGL_TRUE; 1735} 1736 1737 1738// ---------------------------------------------------------------------------- 1739// ANDROID extensions 1740// ---------------------------------------------------------------------------- 1741 1742EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw, 1743 EGLint left, EGLint top, EGLint width, EGLint height) 1744{ 1745 SurfaceRef _s(draw); 1746 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1747 1748 if (!validate_display_surface(dpy, draw)) 1749 return EGL_FALSE; 1750 egl_display_t const * const dp = get_display(dpy); 1751 egl_surface_t const * const s = get_surface(draw); 1752 if (s->cnx->egl.eglSetSwapRectangleANDROID) { 1753 return s->cnx->egl.eglSetSwapRectangleANDROID( 1754 dp->disp[s->impl].dpy, s->surface, left, top, width, height); 1755 } 1756 return setError(EGL_BAD_DISPLAY, NULL); 1757} 1758 1759EGLClientBuffer eglGetRenderBufferANDROID(EGLDisplay dpy, EGLSurface draw) 1760{ 1761 SurfaceRef _s(draw); 1762 if (!_s.get()) return setError(EGL_BAD_SURFACE, (EGLClientBuffer*)0); 1763 1764 if (!validate_display_surface(dpy, draw)) 1765 return 0; 1766 egl_display_t const * const dp = get_display(dpy); 1767 egl_surface_t const * const s = get_surface(draw); 1768 if (s->cnx->egl.eglGetRenderBufferANDROID) { 1769 return s->cnx->egl.eglGetRenderBufferANDROID( 1770 dp->disp[s->impl].dpy, s->surface); 1771 } 1772 return setError(EGL_BAD_DISPLAY, (EGLClientBuffer*)0); 1773} 1774