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