egl.cpp revision cd505aef7201ccd7f028ac99a2ecfed96bf474de
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 clearTLS(); 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 1234EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, 1235 EGLSurface read, EGLContext ctx) 1236{ 1237 // get a reference to the object passed in 1238 ContextRef _c(ctx); 1239 SurfaceRef _d(draw); 1240 SurfaceRef _r(read); 1241 1242 // validate the display and the context (if not EGL_NO_CONTEXT) 1243 egl_display_t const * const dp = get_display(dpy); 1244 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1245 if ((ctx != EGL_NO_CONTEXT) && (!validate_display_context(dpy, ctx))) { 1246 // EGL_NO_CONTEXT is valid 1247 return EGL_FALSE; 1248 } 1249 1250 // these are the underlying implementation's object 1251 EGLContext impl_ctx = EGL_NO_CONTEXT; 1252 EGLSurface impl_draw = EGL_NO_SURFACE; 1253 EGLSurface impl_read = EGL_NO_SURFACE; 1254 1255 // these are our objects structs passed in 1256 egl_context_t * c = NULL; 1257 egl_surface_t const * d = NULL; 1258 egl_surface_t const * r = NULL; 1259 1260 // these are the current objects structs 1261 egl_context_t * cur_c = get_context(getContext()); 1262 egl_surface_t * cur_r = NULL; 1263 egl_surface_t * cur_d = NULL; 1264 1265 if (ctx != EGL_NO_CONTEXT) { 1266 c = get_context(ctx); 1267 cur_r = get_surface(c->read); 1268 cur_d = get_surface(c->draw); 1269 impl_ctx = c->context; 1270 } else { 1271 // no context given, use the implementation of the current context 1272 if (cur_c == NULL) { 1273 // no current context 1274 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) { 1275 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT); 1276 return setError(EGL_BAD_MATCH, EGL_FALSE); 1277 } 1278 // not an error, there is just no current context. 1279 return EGL_TRUE; 1280 } 1281 } 1282 1283 // retrieve the underlying implementation's draw EGLSurface 1284 if (draw != EGL_NO_SURFACE) { 1285 d = get_surface(draw); 1286 // make sure the EGLContext and EGLSurface passed in are for 1287 // the same driver 1288 if (c && d->impl != c->impl) 1289 return setError(EGL_BAD_MATCH, EGL_FALSE); 1290 impl_draw = d->surface; 1291 } 1292 1293 // retrieve the underlying implementation's read EGLSurface 1294 if (read != EGL_NO_SURFACE) { 1295 r = get_surface(read); 1296 // make sure the EGLContext and EGLSurface passed in are for 1297 // the same driver 1298 if (c && r->impl != c->impl) 1299 return setError(EGL_BAD_MATCH, EGL_FALSE); 1300 impl_read = r->surface; 1301 } 1302 1303 EGLBoolean result; 1304 1305 if (c) { 1306 result = c->cnx->egl.eglMakeCurrent( 1307 dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx); 1308 } else { 1309 result = cur_c->cnx->egl.eglMakeCurrent( 1310 dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx); 1311 } 1312 1313 if (result == EGL_TRUE) { 1314 // by construction, these are either 0 or valid (possibly terminated) 1315 // it should be impossible for these to be invalid 1316 ContextRef _cur_c(cur_c); 1317 SurfaceRef _cur_r(cur_r); 1318 SurfaceRef _cur_d(cur_d); 1319 1320 // cur_c has to be valid here (but could be terminated) 1321 if (ctx != EGL_NO_CONTEXT) { 1322 setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 1323 setContext(ctx); 1324 _c.acquire(); 1325 } else { 1326 setGLHooksThreadSpecific(&gHooksNoContext); 1327 setContext(EGL_NO_CONTEXT); 1328 } 1329 _cur_c.release(); 1330 1331 _r.acquire(); 1332 _cur_r.release(); 1333 if (c) c->read = read; 1334 1335 _d.acquire(); 1336 _cur_d.release(); 1337 if (c) c->draw = draw; 1338 } 1339 return result; 1340} 1341 1342 1343EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, 1344 EGLint attribute, EGLint *value) 1345{ 1346 ContextRef _c(ctx); 1347 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1348 1349 if (!validate_display_context(dpy, ctx)) 1350 return EGL_FALSE; 1351 1352 egl_display_t const * const dp = get_display(dpy); 1353 egl_context_t * const c = get_context(ctx); 1354 1355 EGLBoolean result(EGL_TRUE); 1356 if (attribute == EGL_CONFIG_ID) { 1357 *value = dp->configs[intptr_t(c->config)].configId; 1358 } else { 1359 // We need to remap EGL_CONFIG_IDs 1360 result = c->cnx->egl.eglQueryContext( 1361 dp->disp[c->impl].dpy, c->context, attribute, value); 1362 } 1363 1364 return result; 1365} 1366 1367EGLContext eglGetCurrentContext(void) 1368{ 1369 // could be called before eglInitialize(), but we wouldn't have a context 1370 // then, and this function would correctly return EGL_NO_CONTEXT. 1371 1372 EGLContext ctx = getContext(); 1373 return ctx; 1374} 1375 1376EGLSurface eglGetCurrentSurface(EGLint readdraw) 1377{ 1378 // could be called before eglInitialize(), but we wouldn't have a context 1379 // then, and this function would correctly return EGL_NO_SURFACE. 1380 1381 EGLContext ctx = getContext(); 1382 if (ctx) { 1383 egl_context_t const * const c = get_context(ctx); 1384 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 1385 switch (readdraw) { 1386 case EGL_READ: return c->read; 1387 case EGL_DRAW: return c->draw; 1388 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 1389 } 1390 } 1391 return EGL_NO_SURFACE; 1392} 1393 1394EGLDisplay eglGetCurrentDisplay(void) 1395{ 1396 // could be called before eglInitialize(), but we wouldn't have a context 1397 // then, and this function would correctly return EGL_NO_DISPLAY. 1398 1399 EGLContext ctx = getContext(); 1400 if (ctx) { 1401 egl_context_t const * const c = get_context(ctx); 1402 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 1403 return c->dpy; 1404 } 1405 return EGL_NO_DISPLAY; 1406} 1407 1408EGLBoolean eglWaitGL(void) 1409{ 1410 // could be called before eglInitialize(), but we wouldn't have a context 1411 // then, and this function would return GL_TRUE, which isn't wrong. 1412 1413 EGLBoolean res = EGL_TRUE; 1414 EGLContext ctx = getContext(); 1415 if (ctx) { 1416 egl_context_t const * const c = get_context(ctx); 1417 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1418 if (uint32_t(c->impl)>=2) 1419 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1420 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 1421 if (!cnx->dso) 1422 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1423 res = cnx->egl.eglWaitGL(); 1424 } 1425 return res; 1426} 1427 1428EGLBoolean eglWaitNative(EGLint engine) 1429{ 1430 // could be called before eglInitialize(), but we wouldn't have a context 1431 // then, and this function would return GL_TRUE, which isn't wrong. 1432 1433 EGLBoolean res = EGL_TRUE; 1434 EGLContext ctx = getContext(); 1435 if (ctx) { 1436 egl_context_t const * const c = get_context(ctx); 1437 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1438 if (uint32_t(c->impl)>=2) 1439 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1440 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 1441 if (!cnx->dso) 1442 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1443 res = cnx->egl.eglWaitNative(engine); 1444 } 1445 return res; 1446} 1447 1448EGLint eglGetError(void) 1449{ 1450 EGLint result = EGL_SUCCESS; 1451 EGLint err; 1452 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1453 err = EGL_SUCCESS; 1454 egl_connection_t* const cnx = &gEGLImpl[i]; 1455 if (cnx->dso) 1456 err = cnx->egl.eglGetError(); 1457 if (err!=EGL_SUCCESS && result==EGL_SUCCESS) 1458 result = err; 1459 } 1460 err = getError(); 1461 if (result == EGL_SUCCESS) 1462 result = err; 1463 return result; 1464} 1465 1466__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) 1467{ 1468 // eglGetProcAddress() could be the very first function called 1469 // in which case we must make sure we've initialized ourselves, this 1470 // happens the first time egl_get_display() is called. 1471 1472 if (egl_init_drivers() == EGL_FALSE) { 1473 setError(EGL_BAD_PARAMETER, NULL); 1474 return NULL; 1475 } 1476 1477 __eglMustCastToProperFunctionPointerType addr; 1478 addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap)); 1479 if (addr) return addr; 1480 1481 // this protects accesses to gGLExtentionMap and gGLExtentionSlot 1482 pthread_mutex_lock(&gInitDriverMutex); 1483 1484 /* 1485 * Since eglGetProcAddress() is not associated to anything, it needs 1486 * to return a function pointer that "works" regardless of what 1487 * the current context is. 1488 * 1489 * For this reason, we return a "forwarder", a small stub that takes 1490 * care of calling the function associated with the context 1491 * currently bound. 1492 * 1493 * We first look for extensions we've already resolved, if we're seeing 1494 * this extension for the first time, we go through all our 1495 * implementations and call eglGetProcAddress() and record the 1496 * result in the appropriate implementation hooks and return the 1497 * address of the forwarder corresponding to that hook set. 1498 * 1499 */ 1500 1501 const String8 name(procname); 1502 addr = gGLExtentionMap.valueFor(name); 1503 const int slot = gGLExtentionSlot; 1504 1505 LOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS, 1506 "no more slots for eglGetProcAddress(\"%s\")", 1507 procname); 1508 1509 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) { 1510 bool found = false; 1511 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1512 egl_connection_t* const cnx = &gEGLImpl[i]; 1513 if (cnx->dso && cnx->egl.eglGetProcAddress) { 1514 found = true; 1515 // Extensions are independent of the bound context 1516 cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] = 1517 cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] = 1518#if EGL_TRACE 1519 gHooksTrace.ext.extensions[slot] = 1520#endif 1521 cnx->egl.eglGetProcAddress(procname); 1522 } 1523 } 1524 if (found) { 1525 addr = gExtensionForwarders[slot]; 1526 gGLExtentionMap.add(name, addr); 1527 gGLExtentionSlot++; 1528 } 1529 } 1530 1531 pthread_mutex_unlock(&gInitDriverMutex); 1532 return addr; 1533} 1534 1535EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) 1536{ 1537 SurfaceRef _s(draw); 1538 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1539 1540 if (!validate_display_surface(dpy, draw)) 1541 return EGL_FALSE; 1542 egl_display_t const * const dp = get_display(dpy); 1543 egl_surface_t const * const s = get_surface(draw); 1544 return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface); 1545} 1546 1547EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, 1548 NativePixmapType target) 1549{ 1550 SurfaceRef _s(surface); 1551 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1552 1553 if (!validate_display_surface(dpy, surface)) 1554 return EGL_FALSE; 1555 egl_display_t const * const dp = get_display(dpy); 1556 egl_surface_t const * const s = get_surface(surface); 1557 return s->cnx->egl.eglCopyBuffers( 1558 dp->disp[s->impl].dpy, s->surface, target); 1559} 1560 1561const char* eglQueryString(EGLDisplay dpy, EGLint name) 1562{ 1563 egl_display_t const * const dp = get_display(dpy); 1564 switch (name) { 1565 case EGL_VENDOR: 1566 return gVendorString; 1567 case EGL_VERSION: 1568 return gVersionString; 1569 case EGL_EXTENSIONS: 1570 return gExtensionString; 1571 case EGL_CLIENT_APIS: 1572 return gClientApiString; 1573 } 1574 return setError(EGL_BAD_PARAMETER, (const char *)0); 1575} 1576 1577 1578// ---------------------------------------------------------------------------- 1579// EGL 1.1 1580// ---------------------------------------------------------------------------- 1581 1582EGLBoolean eglSurfaceAttrib( 1583 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 1584{ 1585 SurfaceRef _s(surface); 1586 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1587 1588 if (!validate_display_surface(dpy, surface)) 1589 return EGL_FALSE; 1590 egl_display_t const * const dp = get_display(dpy); 1591 egl_surface_t const * const s = get_surface(surface); 1592 if (s->cnx->egl.eglSurfaceAttrib) { 1593 return s->cnx->egl.eglSurfaceAttrib( 1594 dp->disp[s->impl].dpy, s->surface, attribute, value); 1595 } 1596 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1597} 1598 1599EGLBoolean eglBindTexImage( 1600 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1601{ 1602 SurfaceRef _s(surface); 1603 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1604 1605 if (!validate_display_surface(dpy, surface)) 1606 return EGL_FALSE; 1607 egl_display_t const * const dp = get_display(dpy); 1608 egl_surface_t const * const s = get_surface(surface); 1609 if (s->cnx->egl.eglBindTexImage) { 1610 return s->cnx->egl.eglBindTexImage( 1611 dp->disp[s->impl].dpy, s->surface, buffer); 1612 } 1613 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1614} 1615 1616EGLBoolean eglReleaseTexImage( 1617 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1618{ 1619 SurfaceRef _s(surface); 1620 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1621 1622 if (!validate_display_surface(dpy, surface)) 1623 return EGL_FALSE; 1624 egl_display_t const * const dp = get_display(dpy); 1625 egl_surface_t const * const s = get_surface(surface); 1626 if (s->cnx->egl.eglReleaseTexImage) { 1627 return s->cnx->egl.eglReleaseTexImage( 1628 dp->disp[s->impl].dpy, s->surface, buffer); 1629 } 1630 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1631} 1632 1633EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 1634{ 1635 egl_display_t * const dp = get_display(dpy); 1636 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1637 1638 EGLBoolean res = EGL_TRUE; 1639 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1640 egl_connection_t* const cnx = &gEGLImpl[i]; 1641 if (cnx->dso) { 1642 if (cnx->egl.eglSwapInterval) { 1643 if (cnx->egl.eglSwapInterval( 1644 dp->disp[i].dpy, interval) == EGL_FALSE) { 1645 res = EGL_FALSE; 1646 } 1647 } 1648 } 1649 } 1650 return res; 1651} 1652 1653 1654// ---------------------------------------------------------------------------- 1655// EGL 1.2 1656// ---------------------------------------------------------------------------- 1657 1658EGLBoolean eglWaitClient(void) 1659{ 1660 // could be called before eglInitialize(), but we wouldn't have a context 1661 // then, and this function would return GL_TRUE, which isn't wrong. 1662 EGLBoolean res = EGL_TRUE; 1663 EGLContext ctx = getContext(); 1664 if (ctx) { 1665 egl_context_t const * const c = get_context(ctx); 1666 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1667 if (uint32_t(c->impl)>=2) 1668 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1669 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 1670 if (!cnx->dso) 1671 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1672 if (cnx->egl.eglWaitClient) { 1673 res = cnx->egl.eglWaitClient(); 1674 } else { 1675 res = cnx->egl.eglWaitGL(); 1676 } 1677 } 1678 return res; 1679} 1680 1681EGLBoolean eglBindAPI(EGLenum api) 1682{ 1683 if (egl_init_drivers() == EGL_FALSE) { 1684 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1685 } 1686 1687 // bind this API on all EGLs 1688 EGLBoolean res = EGL_TRUE; 1689 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1690 egl_connection_t* const cnx = &gEGLImpl[i]; 1691 if (cnx->dso) { 1692 if (cnx->egl.eglBindAPI) { 1693 if (cnx->egl.eglBindAPI(api) == EGL_FALSE) { 1694 res = EGL_FALSE; 1695 } 1696 } 1697 } 1698 } 1699 return res; 1700} 1701 1702EGLenum eglQueryAPI(void) 1703{ 1704 if (egl_init_drivers() == EGL_FALSE) { 1705 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1706 } 1707 1708 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1709 egl_connection_t* const cnx = &gEGLImpl[i]; 1710 if (cnx->dso) { 1711 if (cnx->egl.eglQueryAPI) { 1712 // the first one we find is okay, because they all 1713 // should be the same 1714 return cnx->egl.eglQueryAPI(); 1715 } 1716 } 1717 } 1718 // or, it can only be OpenGL ES 1719 return EGL_OPENGL_ES_API; 1720} 1721 1722EGLBoolean eglReleaseThread(void) 1723{ 1724 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1725 egl_connection_t* const cnx = &gEGLImpl[i]; 1726 if (cnx->dso) { 1727 if (cnx->egl.eglReleaseThread) { 1728 cnx->egl.eglReleaseThread(); 1729 } 1730 } 1731 } 1732 clearTLS(); 1733 return EGL_TRUE; 1734} 1735 1736EGLSurface eglCreatePbufferFromClientBuffer( 1737 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 1738 EGLConfig config, const EGLint *attrib_list) 1739{ 1740 egl_display_t const* dp = 0; 1741 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 1742 if (!cnx) return EGL_FALSE; 1743 if (cnx->egl.eglCreatePbufferFromClientBuffer) { 1744 return cnx->egl.eglCreatePbufferFromClientBuffer( 1745 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 1746 buftype, buffer, 1747 dp->configs[intptr_t(config)].config, attrib_list); 1748 } 1749 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); 1750} 1751 1752// ---------------------------------------------------------------------------- 1753// EGL_EGLEXT_VERSION 3 1754// ---------------------------------------------------------------------------- 1755 1756EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, 1757 const EGLint *attrib_list) 1758{ 1759 SurfaceRef _s(surface); 1760 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1761 1762 if (!validate_display_surface(dpy, surface)) 1763 return EGL_FALSE; 1764 1765 egl_display_t const * const dp = get_display(dpy); 1766 egl_surface_t const * const s = get_surface(surface); 1767 1768 if (s->cnx->egl.eglLockSurfaceKHR) { 1769 return s->cnx->egl.eglLockSurfaceKHR( 1770 dp->disp[s->impl].dpy, s->surface, attrib_list); 1771 } 1772 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1773} 1774 1775EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) 1776{ 1777 SurfaceRef _s(surface); 1778 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1779 1780 if (!validate_display_surface(dpy, surface)) 1781 return EGL_FALSE; 1782 1783 egl_display_t const * const dp = get_display(dpy); 1784 egl_surface_t const * const s = get_surface(surface); 1785 1786 if (s->cnx->egl.eglUnlockSurfaceKHR) { 1787 return s->cnx->egl.eglUnlockSurfaceKHR( 1788 dp->disp[s->impl].dpy, s->surface); 1789 } 1790 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1791} 1792 1793EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1794 EGLClientBuffer buffer, const EGLint *attrib_list) 1795{ 1796 if (ctx != EGL_NO_CONTEXT) { 1797 ContextRef _c(ctx); 1798 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR); 1799 if (!validate_display_context(dpy, ctx)) 1800 return EGL_NO_IMAGE_KHR; 1801 egl_display_t const * const dp = get_display(dpy); 1802 egl_context_t * const c = get_context(ctx); 1803 // since we have an EGLContext, we know which implementation to use 1804 EGLImageKHR image = c->cnx->egl.eglCreateImageKHR( 1805 dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list); 1806 if (image == EGL_NO_IMAGE_KHR) 1807 return image; 1808 1809 egl_image_t* result = new egl_image_t(dpy, ctx); 1810 result->images[c->impl] = image; 1811 return (EGLImageKHR)result; 1812 } else { 1813 // EGL_NO_CONTEXT is a valid parameter 1814 egl_display_t const * const dp = get_display(dpy); 1815 if (dp == 0) { 1816 return setError(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR); 1817 } 1818 1819 /* Since we don't have a way to know which implementation to call, 1820 * we're calling all of them. If at least one of the implementation 1821 * succeeded, this is a success. 1822 */ 1823 1824 EGLint currentError = eglGetError(); 1825 1826 EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS]; 1827 bool success = false; 1828 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1829 egl_connection_t* const cnx = &gEGLImpl[i]; 1830 implImages[i] = EGL_NO_IMAGE_KHR; 1831 if (cnx->dso) { 1832 if (cnx->egl.eglCreateImageKHR) { 1833 implImages[i] = cnx->egl.eglCreateImageKHR( 1834 dp->disp[i].dpy, ctx, target, buffer, attrib_list); 1835 if (implImages[i] != EGL_NO_IMAGE_KHR) { 1836 success = true; 1837 } 1838 } 1839 } 1840 } 1841 1842 if (!success) { 1843 // failure, if there was an error when we entered this function, 1844 // the error flag must not be updated. 1845 // Otherwise, the error is whatever happened in the implementation 1846 // that faulted. 1847 if (currentError != EGL_SUCCESS) { 1848 setError(currentError, EGL_NO_IMAGE_KHR); 1849 } 1850 return EGL_NO_IMAGE_KHR; 1851 } else { 1852 // In case of success, we need to clear all error flags 1853 // (especially those caused by the implementation that didn't 1854 // succeed). TODO: we could avoid this if we knew this was 1855 // a "full" success (all implementation succeeded). 1856 eglGetError(); 1857 } 1858 1859 egl_image_t* result = new egl_image_t(dpy, ctx); 1860 memcpy(result->images, implImages, sizeof(implImages)); 1861 return (EGLImageKHR)result; 1862 } 1863} 1864 1865EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 1866{ 1867 egl_display_t const * const dp = get_display(dpy); 1868 if (dp == 0) { 1869 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1870 } 1871 1872 ImageRef _i(img); 1873 if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1874 1875 egl_image_t* image = get_image(img); 1876 bool success = false; 1877 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1878 egl_connection_t* const cnx = &gEGLImpl[i]; 1879 if (image->images[i] != EGL_NO_IMAGE_KHR) { 1880 if (cnx->dso) { 1881 if (cnx->egl.eglDestroyImageKHR) { 1882 if (cnx->egl.eglDestroyImageKHR( 1883 dp->disp[i].dpy, image->images[i])) { 1884 success = true; 1885 } 1886 } 1887 } 1888 } 1889 } 1890 if (!success) 1891 return EGL_FALSE; 1892 1893 _i.terminate(); 1894 1895 return EGL_TRUE; 1896} 1897 1898// ---------------------------------------------------------------------------- 1899// EGL_EGLEXT_VERSION 5 1900// ---------------------------------------------------------------------------- 1901 1902 1903EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) 1904{ 1905 EGLContext ctx = eglGetCurrentContext(); 1906 ContextRef _c(ctx); 1907 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR); 1908 if (!validate_display_context(dpy, ctx)) 1909 return EGL_NO_SYNC_KHR; 1910 egl_display_t const * const dp = get_display(dpy); 1911 egl_context_t * const c = get_context(ctx); 1912 EGLSyncKHR result = EGL_NO_SYNC_KHR; 1913 if (c->cnx->egl.eglCreateSyncKHR) { 1914 EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR( 1915 dp->disp[c->impl].dpy, type, attrib_list); 1916 if (sync == EGL_NO_SYNC_KHR) 1917 return sync; 1918 result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync); 1919 } 1920 return (EGLSyncKHR)result; 1921} 1922 1923EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) 1924{ 1925 egl_display_t const * const dp = get_display(dpy); 1926 if (dp == 0) { 1927 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1928 } 1929 1930 SyncRef _s(sync); 1931 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1932 egl_sync_t* syncObject = get_sync(sync); 1933 1934 EGLContext ctx = syncObject->context; 1935 ContextRef _c(ctx); 1936 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1937 if (!validate_display_context(dpy, ctx)) 1938 return EGL_FALSE; 1939 1940 egl_context_t * const c = get_context(ctx); 1941 1942 if (c->cnx->egl.eglDestroySyncKHR) { 1943 return c->cnx->egl.eglDestroySyncKHR( 1944 dp->disp[c->impl].dpy, syncObject->sync); 1945 } 1946 1947 return EGL_FALSE; 1948} 1949 1950EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout) 1951{ 1952 egl_display_t const * const dp = get_display(dpy); 1953 if (dp == 0) { 1954 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1955 } 1956 1957 SyncRef _s(sync); 1958 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1959 egl_sync_t* syncObject = get_sync(sync); 1960 1961 EGLContext ctx = syncObject->context; 1962 ContextRef _c(ctx); 1963 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1964 if (!validate_display_context(dpy, ctx)) 1965 return EGL_FALSE; 1966 1967 egl_context_t * const c = get_context(ctx); 1968 1969 if (c->cnx->egl.eglClientWaitSyncKHR) { 1970 return c->cnx->egl.eglClientWaitSyncKHR( 1971 dp->disp[c->impl].dpy, syncObject->sync, flags, timeout); 1972 } 1973 1974 return EGL_FALSE; 1975} 1976 1977EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value) 1978{ 1979 egl_display_t const * const dp = get_display(dpy); 1980 if (dp == 0) { 1981 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1982 } 1983 1984 SyncRef _s(sync); 1985 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1986 egl_sync_t* syncObject = get_sync(sync); 1987 1988 EGLContext ctx = syncObject->context; 1989 ContextRef _c(ctx); 1990 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1991 if (!validate_display_context(dpy, ctx)) 1992 return EGL_FALSE; 1993 1994 egl_context_t * const c = get_context(ctx); 1995 1996 if (c->cnx->egl.eglGetSyncAttribKHR) { 1997 return c->cnx->egl.eglGetSyncAttribKHR( 1998 dp->disp[c->impl].dpy, syncObject->sync, attribute, value); 1999 } 2000 2001 return EGL_FALSE; 2002} 2003 2004// ---------------------------------------------------------------------------- 2005// ANDROID extensions 2006// ---------------------------------------------------------------------------- 2007 2008EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw, 2009 EGLint left, EGLint top, EGLint width, EGLint height) 2010{ 2011 SurfaceRef _s(draw); 2012 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 2013 2014 if (!validate_display_surface(dpy, draw)) 2015 return EGL_FALSE; 2016 egl_display_t const * const dp = get_display(dpy); 2017 egl_surface_t const * const s = get_surface(draw); 2018 if (s->cnx->egl.eglSetSwapRectangleANDROID) { 2019 return s->cnx->egl.eglSetSwapRectangleANDROID( 2020 dp->disp[s->impl].dpy, s->surface, left, top, width, height); 2021 } 2022 return setError(EGL_BAD_DISPLAY, NULL); 2023} 2024