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