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