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