egl.cpp revision f1cde8e0ed019791641bd07c5c1f965b0f8cf7c5
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 // 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 // set the native window's buffers format to match this config 1098 if (cnx->egl.eglGetConfigAttrib(iDpy, 1099 iConfig, EGL_NATIVE_VISUAL_ID, &format)) { 1100 if (format != 0) { 1101 native_window_set_buffers_geometry(window, 0, 0, format); 1102 } 1103 } 1104 1105 EGLSurface surface = cnx->egl.eglCreateWindowSurface( 1106 iDpy, iConfig, window, attrib_list); 1107 if (surface != EGL_NO_SURFACE) { 1108 egl_surface_t* s = new egl_surface_t(dpy, config, window, surface, 1109 dp->configs[intptr_t(config)].impl, cnx); 1110 return s; 1111 } 1112 } 1113 return EGL_NO_SURFACE; 1114} 1115 1116EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, 1117 NativePixmapType pixmap, 1118 const EGLint *attrib_list) 1119{ 1120 clearError(); 1121 1122 egl_display_t const* dp = 0; 1123 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 1124 if (cnx) { 1125 EGLSurface surface = cnx->egl.eglCreatePixmapSurface( 1126 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 1127 dp->configs[intptr_t(config)].config, pixmap, attrib_list); 1128 if (surface != EGL_NO_SURFACE) { 1129 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface, 1130 dp->configs[intptr_t(config)].impl, cnx); 1131 return s; 1132 } 1133 } 1134 return EGL_NO_SURFACE; 1135} 1136 1137EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, 1138 const EGLint *attrib_list) 1139{ 1140 clearError(); 1141 1142 egl_display_t const* dp = 0; 1143 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 1144 if (cnx) { 1145 EGLSurface surface = cnx->egl.eglCreatePbufferSurface( 1146 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 1147 dp->configs[intptr_t(config)].config, attrib_list); 1148 if (surface != EGL_NO_SURFACE) { 1149 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface, 1150 dp->configs[intptr_t(config)].impl, cnx); 1151 return s; 1152 } 1153 } 1154 return EGL_NO_SURFACE; 1155} 1156 1157EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) 1158{ 1159 clearError(); 1160 1161 SurfaceRef _s(surface); 1162 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1163 1164 if (!validate_display_surface(dpy, surface)) 1165 return EGL_FALSE; 1166 egl_display_t const * const dp = get_display(dpy); 1167 1168 egl_surface_t * const s = get_surface(surface); 1169 EGLBoolean result = s->cnx->egl.eglDestroySurface( 1170 dp->disp[s->impl].dpy, s->surface); 1171 if (result == EGL_TRUE) { 1172 if (s->win != NULL) { 1173 native_window_set_buffers_geometry(s->win.get(), 0, 0, 0); 1174 } 1175 _s.terminate(); 1176 } 1177 return result; 1178} 1179 1180EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface, 1181 EGLint attribute, EGLint *value) 1182{ 1183 clearError(); 1184 1185 SurfaceRef _s(surface); 1186 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1187 1188 if (!validate_display_surface(dpy, surface)) 1189 return EGL_FALSE; 1190 egl_display_t const * const dp = get_display(dpy); 1191 egl_surface_t const * const s = get_surface(surface); 1192 1193 EGLBoolean result(EGL_TRUE); 1194 if (attribute == EGL_CONFIG_ID) { 1195 // We need to remap EGL_CONFIG_IDs 1196 *value = dp->configs[intptr_t(s->config)].configId; 1197 } else { 1198 result = s->cnx->egl.eglQuerySurface( 1199 dp->disp[s->impl].dpy, s->surface, attribute, value); 1200 } 1201 1202 return result; 1203} 1204 1205// ---------------------------------------------------------------------------- 1206// Contexts 1207// ---------------------------------------------------------------------------- 1208 1209EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, 1210 EGLContext share_list, const EGLint *attrib_list) 1211{ 1212 clearError(); 1213 1214 egl_display_t const* dp = 0; 1215 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 1216 if (cnx) { 1217 if (share_list != EGL_NO_CONTEXT) { 1218 egl_context_t* const c = get_context(share_list); 1219 share_list = c->context; 1220 } 1221 EGLContext context = cnx->egl.eglCreateContext( 1222 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 1223 dp->configs[intptr_t(config)].config, 1224 share_list, attrib_list); 1225 if (context != EGL_NO_CONTEXT) { 1226 // figure out if it's a GLESv1 or GLESv2 1227 int version = 0; 1228 if (attrib_list) { 1229 while (*attrib_list != EGL_NONE) { 1230 GLint attr = *attrib_list++; 1231 GLint value = *attrib_list++; 1232 if (attr == EGL_CONTEXT_CLIENT_VERSION) { 1233 if (value == 1) { 1234 version = GLESv1_INDEX; 1235 } else if (value == 2) { 1236 version = GLESv2_INDEX; 1237 } 1238 } 1239 }; 1240 } 1241 egl_context_t* c = new egl_context_t(dpy, context, config, 1242 dp->configs[intptr_t(config)].impl, cnx, version); 1243 return c; 1244 } 1245 } 1246 return EGL_NO_CONTEXT; 1247} 1248 1249EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) 1250{ 1251 clearError(); 1252 1253 ContextRef _c(ctx); 1254 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1255 1256 if (!validate_display_context(dpy, ctx)) 1257 return EGL_FALSE; 1258 egl_display_t const * const dp = get_display(dpy); 1259 egl_context_t * const c = get_context(ctx); 1260 EGLBoolean result = c->cnx->egl.eglDestroyContext( 1261 dp->disp[c->impl].dpy, c->context); 1262 if (result == EGL_TRUE) { 1263 _c.terminate(); 1264 } 1265 return result; 1266} 1267 1268static void loseCurrent(egl_context_t * cur_c) 1269{ 1270 if (cur_c) { 1271 egl_surface_t * cur_r = get_surface(cur_c->read); 1272 egl_surface_t * cur_d = get_surface(cur_c->draw); 1273 1274 // by construction, these are either 0 or valid (possibly terminated) 1275 // it should be impossible for these to be invalid 1276 ContextRef _cur_c(cur_c); 1277 SurfaceRef _cur_r(cur_r); 1278 SurfaceRef _cur_d(cur_d); 1279 1280 cur_c->read = NULL; 1281 cur_c->draw = NULL; 1282 1283 _cur_c.release(); 1284 _cur_r.release(); 1285 _cur_d.release(); 1286 } 1287} 1288 1289EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, 1290 EGLSurface read, EGLContext ctx) 1291{ 1292 clearError(); 1293 1294 // get a reference to the object passed in 1295 ContextRef _c(ctx); 1296 SurfaceRef _d(draw); 1297 SurfaceRef _r(read); 1298 1299 // validate the display and the context (if not EGL_NO_CONTEXT) 1300 egl_display_t const * const dp = get_display(dpy); 1301 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1302 if ((ctx != EGL_NO_CONTEXT) && (!validate_display_context(dpy, ctx))) { 1303 // EGL_NO_CONTEXT is valid 1304 return EGL_FALSE; 1305 } 1306 1307 // these are the underlying implementation's object 1308 EGLContext impl_ctx = EGL_NO_CONTEXT; 1309 EGLSurface impl_draw = EGL_NO_SURFACE; 1310 EGLSurface impl_read = EGL_NO_SURFACE; 1311 1312 // these are our objects structs passed in 1313 egl_context_t * c = NULL; 1314 egl_surface_t const * d = NULL; 1315 egl_surface_t const * r = NULL; 1316 1317 // these are the current objects structs 1318 egl_context_t * cur_c = get_context(getContext()); 1319 1320 if (ctx != EGL_NO_CONTEXT) { 1321 c = get_context(ctx); 1322 impl_ctx = c->context; 1323 } else { 1324 // no context given, use the implementation of the current context 1325 if (cur_c == NULL) { 1326 // no current context 1327 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) { 1328 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT); 1329 return setError(EGL_BAD_MATCH, EGL_FALSE); 1330 } 1331 // not an error, there is just no current context. 1332 return EGL_TRUE; 1333 } 1334 } 1335 1336 // retrieve the underlying implementation's draw EGLSurface 1337 if (draw != EGL_NO_SURFACE) { 1338 d = get_surface(draw); 1339 // make sure the EGLContext and EGLSurface passed in are for 1340 // the same driver 1341 if (c && d->impl != c->impl) 1342 return setError(EGL_BAD_MATCH, EGL_FALSE); 1343 impl_draw = d->surface; 1344 } 1345 1346 // retrieve the underlying implementation's read EGLSurface 1347 if (read != EGL_NO_SURFACE) { 1348 r = get_surface(read); 1349 // make sure the EGLContext and EGLSurface passed in are for 1350 // the same driver 1351 if (c && r->impl != c->impl) 1352 return setError(EGL_BAD_MATCH, EGL_FALSE); 1353 impl_read = r->surface; 1354 } 1355 1356 EGLBoolean result; 1357 1358 if (c) { 1359 result = c->cnx->egl.eglMakeCurrent( 1360 dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx); 1361 } else { 1362 result = cur_c->cnx->egl.eglMakeCurrent( 1363 dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx); 1364 } 1365 1366 if (result == EGL_TRUE) { 1367 1368 loseCurrent(cur_c); 1369 1370 if (ctx != EGL_NO_CONTEXT) { 1371 setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 1372 setContext(ctx); 1373 _c.acquire(); 1374 _r.acquire(); 1375 _d.acquire(); 1376 c->read = read; 1377 c->draw = draw; 1378 } else { 1379 setGLHooksThreadSpecific(&gHooksNoContext); 1380 setContext(EGL_NO_CONTEXT); 1381 } 1382 } 1383 return result; 1384} 1385 1386 1387EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, 1388 EGLint attribute, EGLint *value) 1389{ 1390 clearError(); 1391 1392 ContextRef _c(ctx); 1393 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1394 1395 if (!validate_display_context(dpy, ctx)) 1396 return EGL_FALSE; 1397 1398 egl_display_t const * const dp = get_display(dpy); 1399 egl_context_t * const c = get_context(ctx); 1400 1401 EGLBoolean result(EGL_TRUE); 1402 if (attribute == EGL_CONFIG_ID) { 1403 *value = dp->configs[intptr_t(c->config)].configId; 1404 } else { 1405 // We need to remap EGL_CONFIG_IDs 1406 result = c->cnx->egl.eglQueryContext( 1407 dp->disp[c->impl].dpy, c->context, attribute, value); 1408 } 1409 1410 return result; 1411} 1412 1413EGLContext eglGetCurrentContext(void) 1414{ 1415 // could be called before eglInitialize(), but we wouldn't have a context 1416 // then, and this function would correctly return EGL_NO_CONTEXT. 1417 1418 clearError(); 1419 1420 EGLContext ctx = getContext(); 1421 return ctx; 1422} 1423 1424EGLSurface eglGetCurrentSurface(EGLint readdraw) 1425{ 1426 // could be called before eglInitialize(), but we wouldn't have a context 1427 // then, and this function would correctly return EGL_NO_SURFACE. 1428 1429 clearError(); 1430 1431 EGLContext ctx = getContext(); 1432 if (ctx) { 1433 egl_context_t const * const c = get_context(ctx); 1434 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 1435 switch (readdraw) { 1436 case EGL_READ: return c->read; 1437 case EGL_DRAW: return c->draw; 1438 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 1439 } 1440 } 1441 return EGL_NO_SURFACE; 1442} 1443 1444EGLDisplay eglGetCurrentDisplay(void) 1445{ 1446 // could be called before eglInitialize(), but we wouldn't have a context 1447 // then, and this function would correctly return EGL_NO_DISPLAY. 1448 1449 clearError(); 1450 1451 EGLContext ctx = getContext(); 1452 if (ctx) { 1453 egl_context_t const * const c = get_context(ctx); 1454 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 1455 return c->dpy; 1456 } 1457 return EGL_NO_DISPLAY; 1458} 1459 1460EGLBoolean eglWaitGL(void) 1461{ 1462 // could be called before eglInitialize(), but we wouldn't have a context 1463 // then, and this function would return GL_TRUE, which isn't wrong. 1464 1465 clearError(); 1466 1467 EGLBoolean res = EGL_TRUE; 1468 EGLContext ctx = getContext(); 1469 if (ctx) { 1470 egl_context_t const * const c = get_context(ctx); 1471 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1472 if (uint32_t(c->impl)>=2) 1473 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1474 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 1475 if (!cnx->dso) 1476 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1477 res = cnx->egl.eglWaitGL(); 1478 } 1479 return res; 1480} 1481 1482EGLBoolean eglWaitNative(EGLint engine) 1483{ 1484 // could be called before eglInitialize(), but we wouldn't have a context 1485 // then, and this function would return GL_TRUE, which isn't wrong. 1486 1487 clearError(); 1488 1489 EGLBoolean res = EGL_TRUE; 1490 EGLContext ctx = getContext(); 1491 if (ctx) { 1492 egl_context_t const * const c = get_context(ctx); 1493 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1494 if (uint32_t(c->impl)>=2) 1495 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1496 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 1497 if (!cnx->dso) 1498 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1499 res = cnx->egl.eglWaitNative(engine); 1500 } 1501 return res; 1502} 1503 1504EGLint eglGetError(void) 1505{ 1506 EGLint result = EGL_SUCCESS; 1507 EGLint err; 1508 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1509 err = EGL_SUCCESS; 1510 egl_connection_t* const cnx = &gEGLImpl[i]; 1511 if (cnx->dso) 1512 err = cnx->egl.eglGetError(); 1513 if (err!=EGL_SUCCESS && result==EGL_SUCCESS) 1514 result = err; 1515 } 1516 err = getError(); 1517 if (result == EGL_SUCCESS) 1518 result = err; 1519 return result; 1520} 1521 1522// Note: Similar implementations of these functions also exist in 1523// gl2.cpp and gl.cpp, and are used by applications that call the 1524// exported entry points directly. 1525typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image); 1526typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image); 1527 1528static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_impl = NULL; 1529static PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES_impl = NULL; 1530 1531static void glEGLImageTargetTexture2DOES_wrapper(GLenum target, GLeglImageOES image) 1532{ 1533 GLeglImageOES implImage = 1534 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image); 1535 glEGLImageTargetTexture2DOES_impl(target, implImage); 1536} 1537 1538static void glEGLImageTargetRenderbufferStorageOES_wrapper(GLenum target, GLeglImageOES image) 1539{ 1540 GLeglImageOES implImage = 1541 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image); 1542 glEGLImageTargetRenderbufferStorageOES_impl(target, implImage); 1543} 1544 1545__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) 1546{ 1547 // eglGetProcAddress() could be the very first function called 1548 // in which case we must make sure we've initialized ourselves, this 1549 // happens the first time egl_get_display() is called. 1550 1551 clearError(); 1552 1553 if (egl_init_drivers() == EGL_FALSE) { 1554 setError(EGL_BAD_PARAMETER, NULL); 1555 return NULL; 1556 } 1557 1558 __eglMustCastToProperFunctionPointerType addr; 1559 addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap)); 1560 if (addr) return addr; 1561 1562 // this protects accesses to gGLExtentionMap and gGLExtentionSlot 1563 pthread_mutex_lock(&gInitDriverMutex); 1564 1565 /* 1566 * Since eglGetProcAddress() is not associated to anything, it needs 1567 * to return a function pointer that "works" regardless of what 1568 * the current context is. 1569 * 1570 * For this reason, we return a "forwarder", a small stub that takes 1571 * care of calling the function associated with the context 1572 * currently bound. 1573 * 1574 * We first look for extensions we've already resolved, if we're seeing 1575 * this extension for the first time, we go through all our 1576 * implementations and call eglGetProcAddress() and record the 1577 * result in the appropriate implementation hooks and return the 1578 * address of the forwarder corresponding to that hook set. 1579 * 1580 */ 1581 1582 const String8 name(procname); 1583 addr = gGLExtentionMap.valueFor(name); 1584 const int slot = gGLExtentionSlot; 1585 1586 LOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS, 1587 "no more slots for eglGetProcAddress(\"%s\")", 1588 procname); 1589 1590 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) { 1591 bool found = false; 1592 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1593 egl_connection_t* const cnx = &gEGLImpl[i]; 1594 if (cnx->dso && cnx->egl.eglGetProcAddress) { 1595 found = true; 1596 // Extensions are independent of the bound context 1597 cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] = 1598 cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] = 1599#if EGL_TRACE 1600 gHooksTrace.ext.extensions[slot] = 1601#endif 1602 cnx->egl.eglGetProcAddress(procname); 1603 } 1604 } 1605 if (found) { 1606 addr = gExtensionForwarders[slot]; 1607 1608 if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) { 1609 glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr; 1610 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper; 1611 } 1612 if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) { 1613 glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr; 1614 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper; 1615 } 1616 1617 gGLExtentionMap.add(name, addr); 1618 gGLExtentionSlot++; 1619 } 1620 } 1621 1622 pthread_mutex_unlock(&gInitDriverMutex); 1623 return addr; 1624} 1625 1626EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) 1627{ 1628 clearError(); 1629 1630 SurfaceRef _s(draw); 1631 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1632 1633 if (!validate_display_surface(dpy, draw)) 1634 return EGL_FALSE; 1635 egl_display_t const * const dp = get_display(dpy); 1636 egl_surface_t const * const s = get_surface(draw); 1637 return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface); 1638} 1639 1640EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, 1641 NativePixmapType target) 1642{ 1643 clearError(); 1644 1645 SurfaceRef _s(surface); 1646 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1647 1648 if (!validate_display_surface(dpy, surface)) 1649 return EGL_FALSE; 1650 egl_display_t const * const dp = get_display(dpy); 1651 egl_surface_t const * const s = get_surface(surface); 1652 return s->cnx->egl.eglCopyBuffers( 1653 dp->disp[s->impl].dpy, s->surface, target); 1654} 1655 1656const char* eglQueryString(EGLDisplay dpy, EGLint name) 1657{ 1658 clearError(); 1659 1660 egl_display_t const * const dp = get_display(dpy); 1661 switch (name) { 1662 case EGL_VENDOR: 1663 return gVendorString; 1664 case EGL_VERSION: 1665 return gVersionString; 1666 case EGL_EXTENSIONS: 1667 return gExtensionString; 1668 case EGL_CLIENT_APIS: 1669 return gClientApiString; 1670 } 1671 return setError(EGL_BAD_PARAMETER, (const char *)0); 1672} 1673 1674 1675// ---------------------------------------------------------------------------- 1676// EGL 1.1 1677// ---------------------------------------------------------------------------- 1678 1679EGLBoolean eglSurfaceAttrib( 1680 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 1681{ 1682 clearError(); 1683 1684 SurfaceRef _s(surface); 1685 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1686 1687 if (!validate_display_surface(dpy, surface)) 1688 return EGL_FALSE; 1689 egl_display_t const * const dp = get_display(dpy); 1690 egl_surface_t const * const s = get_surface(surface); 1691 if (s->cnx->egl.eglSurfaceAttrib) { 1692 return s->cnx->egl.eglSurfaceAttrib( 1693 dp->disp[s->impl].dpy, s->surface, attribute, value); 1694 } 1695 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1696} 1697 1698EGLBoolean eglBindTexImage( 1699 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1700{ 1701 clearError(); 1702 1703 SurfaceRef _s(surface); 1704 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1705 1706 if (!validate_display_surface(dpy, surface)) 1707 return EGL_FALSE; 1708 egl_display_t const * const dp = get_display(dpy); 1709 egl_surface_t const * const s = get_surface(surface); 1710 if (s->cnx->egl.eglBindTexImage) { 1711 return s->cnx->egl.eglBindTexImage( 1712 dp->disp[s->impl].dpy, s->surface, buffer); 1713 } 1714 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1715} 1716 1717EGLBoolean eglReleaseTexImage( 1718 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1719{ 1720 clearError(); 1721 1722 SurfaceRef _s(surface); 1723 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1724 1725 if (!validate_display_surface(dpy, surface)) 1726 return EGL_FALSE; 1727 egl_display_t const * const dp = get_display(dpy); 1728 egl_surface_t const * const s = get_surface(surface); 1729 if (s->cnx->egl.eglReleaseTexImage) { 1730 return s->cnx->egl.eglReleaseTexImage( 1731 dp->disp[s->impl].dpy, s->surface, buffer); 1732 } 1733 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1734} 1735 1736EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 1737{ 1738 clearError(); 1739 1740 egl_display_t * const dp = get_display(dpy); 1741 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1742 1743 EGLBoolean res = EGL_TRUE; 1744 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1745 egl_connection_t* const cnx = &gEGLImpl[i]; 1746 if (cnx->dso) { 1747 if (cnx->egl.eglSwapInterval) { 1748 if (cnx->egl.eglSwapInterval( 1749 dp->disp[i].dpy, interval) == EGL_FALSE) { 1750 res = EGL_FALSE; 1751 } 1752 } 1753 } 1754 } 1755 return res; 1756} 1757 1758 1759// ---------------------------------------------------------------------------- 1760// EGL 1.2 1761// ---------------------------------------------------------------------------- 1762 1763EGLBoolean eglWaitClient(void) 1764{ 1765 clearError(); 1766 1767 // could be called before eglInitialize(), but we wouldn't have a context 1768 // then, and this function would return GL_TRUE, which isn't wrong. 1769 EGLBoolean res = EGL_TRUE; 1770 EGLContext ctx = getContext(); 1771 if (ctx) { 1772 egl_context_t const * const c = get_context(ctx); 1773 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1774 if (uint32_t(c->impl)>=2) 1775 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1776 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 1777 if (!cnx->dso) 1778 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1779 if (cnx->egl.eglWaitClient) { 1780 res = cnx->egl.eglWaitClient(); 1781 } else { 1782 res = cnx->egl.eglWaitGL(); 1783 } 1784 } 1785 return res; 1786} 1787 1788EGLBoolean eglBindAPI(EGLenum api) 1789{ 1790 clearError(); 1791 1792 if (egl_init_drivers() == EGL_FALSE) { 1793 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1794 } 1795 1796 // bind this API on all EGLs 1797 EGLBoolean res = EGL_TRUE; 1798 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1799 egl_connection_t* const cnx = &gEGLImpl[i]; 1800 if (cnx->dso) { 1801 if (cnx->egl.eglBindAPI) { 1802 if (cnx->egl.eglBindAPI(api) == EGL_FALSE) { 1803 res = EGL_FALSE; 1804 } 1805 } 1806 } 1807 } 1808 return res; 1809} 1810 1811EGLenum eglQueryAPI(void) 1812{ 1813 clearError(); 1814 1815 if (egl_init_drivers() == EGL_FALSE) { 1816 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1817 } 1818 1819 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1820 egl_connection_t* const cnx = &gEGLImpl[i]; 1821 if (cnx->dso) { 1822 if (cnx->egl.eglQueryAPI) { 1823 // the first one we find is okay, because they all 1824 // should be the same 1825 return cnx->egl.eglQueryAPI(); 1826 } 1827 } 1828 } 1829 // or, it can only be OpenGL ES 1830 return EGL_OPENGL_ES_API; 1831} 1832 1833EGLBoolean eglReleaseThread(void) 1834{ 1835 clearError(); 1836 1837 // If there is context bound to the thread, release it 1838 loseCurrent(get_context(getContext())); 1839 1840 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1841 egl_connection_t* const cnx = &gEGLImpl[i]; 1842 if (cnx->dso) { 1843 if (cnx->egl.eglReleaseThread) { 1844 cnx->egl.eglReleaseThread(); 1845 } 1846 } 1847 } 1848 clearTLS(); 1849 return EGL_TRUE; 1850} 1851 1852EGLSurface eglCreatePbufferFromClientBuffer( 1853 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 1854 EGLConfig config, const EGLint *attrib_list) 1855{ 1856 clearError(); 1857 1858 egl_display_t const* dp = 0; 1859 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 1860 if (!cnx) return EGL_FALSE; 1861 if (cnx->egl.eglCreatePbufferFromClientBuffer) { 1862 return cnx->egl.eglCreatePbufferFromClientBuffer( 1863 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 1864 buftype, buffer, 1865 dp->configs[intptr_t(config)].config, attrib_list); 1866 } 1867 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); 1868} 1869 1870// ---------------------------------------------------------------------------- 1871// EGL_EGLEXT_VERSION 3 1872// ---------------------------------------------------------------------------- 1873 1874EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, 1875 const EGLint *attrib_list) 1876{ 1877 clearError(); 1878 1879 SurfaceRef _s(surface); 1880 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1881 1882 if (!validate_display_surface(dpy, surface)) 1883 return EGL_FALSE; 1884 1885 egl_display_t const * const dp = get_display(dpy); 1886 egl_surface_t const * const s = get_surface(surface); 1887 1888 if (s->cnx->egl.eglLockSurfaceKHR) { 1889 return s->cnx->egl.eglLockSurfaceKHR( 1890 dp->disp[s->impl].dpy, s->surface, attrib_list); 1891 } 1892 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1893} 1894 1895EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) 1896{ 1897 clearError(); 1898 1899 SurfaceRef _s(surface); 1900 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1901 1902 if (!validate_display_surface(dpy, surface)) 1903 return EGL_FALSE; 1904 1905 egl_display_t const * const dp = get_display(dpy); 1906 egl_surface_t const * const s = get_surface(surface); 1907 1908 if (s->cnx->egl.eglUnlockSurfaceKHR) { 1909 return s->cnx->egl.eglUnlockSurfaceKHR( 1910 dp->disp[s->impl].dpy, s->surface); 1911 } 1912 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1913} 1914 1915EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1916 EGLClientBuffer buffer, const EGLint *attrib_list) 1917{ 1918 clearError(); 1919 1920 if (ctx != EGL_NO_CONTEXT) { 1921 ContextRef _c(ctx); 1922 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR); 1923 if (!validate_display_context(dpy, ctx)) 1924 return EGL_NO_IMAGE_KHR; 1925 egl_display_t const * const dp = get_display(dpy); 1926 egl_context_t * const c = get_context(ctx); 1927 // since we have an EGLContext, we know which implementation to use 1928 EGLImageKHR image = c->cnx->egl.eglCreateImageKHR( 1929 dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list); 1930 if (image == EGL_NO_IMAGE_KHR) 1931 return image; 1932 1933 egl_image_t* result = new egl_image_t(dpy, ctx); 1934 result->images[c->impl] = image; 1935 return (EGLImageKHR)result; 1936 } else { 1937 // EGL_NO_CONTEXT is a valid parameter 1938 egl_display_t const * const dp = get_display(dpy); 1939 if (dp == 0) { 1940 return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR); 1941 } 1942 1943 /* Since we don't have a way to know which implementation to call, 1944 * we're calling all of them. If at least one of the implementation 1945 * succeeded, this is a success. 1946 */ 1947 1948 EGLint currentError = eglGetError(); 1949 1950 EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS]; 1951 bool success = false; 1952 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1953 egl_connection_t* const cnx = &gEGLImpl[i]; 1954 implImages[i] = EGL_NO_IMAGE_KHR; 1955 if (cnx->dso) { 1956 if (cnx->egl.eglCreateImageKHR) { 1957 implImages[i] = cnx->egl.eglCreateImageKHR( 1958 dp->disp[i].dpy, ctx, target, buffer, attrib_list); 1959 if (implImages[i] != EGL_NO_IMAGE_KHR) { 1960 success = true; 1961 } 1962 } 1963 } 1964 } 1965 1966 if (!success) { 1967 // failure, if there was an error when we entered this function, 1968 // the error flag must not be updated. 1969 // Otherwise, the error is whatever happened in the implementation 1970 // that faulted. 1971 if (currentError != EGL_SUCCESS) { 1972 setError(currentError, EGL_NO_IMAGE_KHR); 1973 } 1974 return EGL_NO_IMAGE_KHR; 1975 } else { 1976 // In case of success, we need to clear all error flags 1977 // (especially those caused by the implementation that didn't 1978 // succeed). TODO: we could avoid this if we knew this was 1979 // a "full" success (all implementation succeeded). 1980 eglGetError(); 1981 } 1982 1983 egl_image_t* result = new egl_image_t(dpy, ctx); 1984 memcpy(result->images, implImages, sizeof(implImages)); 1985 return (EGLImageKHR)result; 1986 } 1987} 1988 1989EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 1990{ 1991 clearError(); 1992 1993 egl_display_t const * const dp = get_display(dpy); 1994 if (dp == 0) { 1995 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1996 } 1997 1998 ImageRef _i(img); 1999 if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); 2000 2001 egl_image_t* image = get_image(img); 2002 bool success = false; 2003 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 2004 egl_connection_t* const cnx = &gEGLImpl[i]; 2005 if (image->images[i] != EGL_NO_IMAGE_KHR) { 2006 if (cnx->dso) { 2007 if (cnx->egl.eglDestroyImageKHR) { 2008 if (cnx->egl.eglDestroyImageKHR( 2009 dp->disp[i].dpy, image->images[i])) { 2010 success = true; 2011 } 2012 } 2013 } 2014 } 2015 } 2016 if (!success) 2017 return EGL_FALSE; 2018 2019 _i.terminate(); 2020 2021 return EGL_TRUE; 2022} 2023 2024// ---------------------------------------------------------------------------- 2025// EGL_EGLEXT_VERSION 5 2026// ---------------------------------------------------------------------------- 2027 2028 2029EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) 2030{ 2031 clearError(); 2032 2033 EGLContext ctx = eglGetCurrentContext(); 2034 ContextRef _c(ctx); 2035 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR); 2036 if (!validate_display_context(dpy, ctx)) 2037 return EGL_NO_SYNC_KHR; 2038 egl_display_t const * const dp = get_display(dpy); 2039 egl_context_t * const c = get_context(ctx); 2040 EGLSyncKHR result = EGL_NO_SYNC_KHR; 2041 if (c->cnx->egl.eglCreateSyncKHR) { 2042 EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR( 2043 dp->disp[c->impl].dpy, type, attrib_list); 2044 if (sync == EGL_NO_SYNC_KHR) 2045 return sync; 2046 result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync); 2047 } 2048 return (EGLSyncKHR)result; 2049} 2050 2051EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) 2052{ 2053 clearError(); 2054 2055 egl_display_t const * const dp = get_display(dpy); 2056 if (dp == 0) { 2057 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 2058 } 2059 2060 SyncRef _s(sync); 2061 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); 2062 egl_sync_t* syncObject = get_sync(sync); 2063 2064 EGLContext ctx = syncObject->context; 2065 ContextRef _c(ctx); 2066 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 2067 if (!validate_display_context(dpy, ctx)) 2068 return EGL_FALSE; 2069 2070 egl_context_t * const c = get_context(ctx); 2071 2072 if (c->cnx->egl.eglDestroySyncKHR) { 2073 return c->cnx->egl.eglDestroySyncKHR( 2074 dp->disp[c->impl].dpy, syncObject->sync); 2075 } 2076 2077 return EGL_FALSE; 2078} 2079 2080EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout) 2081{ 2082 clearError(); 2083 2084 egl_display_t const * const dp = get_display(dpy); 2085 if (dp == 0) { 2086 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 2087 } 2088 2089 SyncRef _s(sync); 2090 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); 2091 egl_sync_t* syncObject = get_sync(sync); 2092 2093 EGLContext ctx = syncObject->context; 2094 ContextRef _c(ctx); 2095 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 2096 if (!validate_display_context(dpy, ctx)) 2097 return EGL_FALSE; 2098 2099 egl_context_t * const c = get_context(ctx); 2100 2101 if (c->cnx->egl.eglClientWaitSyncKHR) { 2102 return c->cnx->egl.eglClientWaitSyncKHR( 2103 dp->disp[c->impl].dpy, syncObject->sync, flags, timeout); 2104 } 2105 2106 return EGL_FALSE; 2107} 2108 2109EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value) 2110{ 2111 clearError(); 2112 2113 egl_display_t const * const dp = get_display(dpy); 2114 if (dp == 0) { 2115 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 2116 } 2117 2118 SyncRef _s(sync); 2119 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); 2120 egl_sync_t* syncObject = get_sync(sync); 2121 2122 EGLContext ctx = syncObject->context; 2123 ContextRef _c(ctx); 2124 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 2125 if (!validate_display_context(dpy, ctx)) 2126 return EGL_FALSE; 2127 2128 egl_context_t * const c = get_context(ctx); 2129 2130 if (c->cnx->egl.eglGetSyncAttribKHR) { 2131 return c->cnx->egl.eglGetSyncAttribKHR( 2132 dp->disp[c->impl].dpy, syncObject->sync, attribute, value); 2133 } 2134 2135 return EGL_FALSE; 2136} 2137 2138// ---------------------------------------------------------------------------- 2139// ANDROID extensions 2140// ---------------------------------------------------------------------------- 2141 2142EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw, 2143 EGLint left, EGLint top, EGLint width, EGLint height) 2144{ 2145 clearError(); 2146 2147 SurfaceRef _s(draw); 2148 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 2149 2150 if (!validate_display_surface(dpy, draw)) 2151 return EGL_FALSE; 2152 egl_display_t const * const dp = get_display(dpy); 2153 egl_surface_t const * const s = get_surface(draw); 2154 if (s->cnx->egl.eglSetSwapRectangleANDROID) { 2155 return s->cnx->egl.eglSetSwapRectangleANDROID( 2156 dp->disp[s->impl].dpy, s->surface, left, top, width, height); 2157 } 2158 return setError(EGL_BAD_DISPLAY, NULL); 2159} 2160