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