egl.cpp revision 53238bddeab7b4633bfdb59fac67b0af1211955a
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#define LOG_TAG "libEGL" 18 19#include <ctype.h> 20#include <string.h> 21#include <errno.h> 22#include <dlfcn.h> 23 24#include <sys/ioctl.h> 25 26#if HAVE_ANDROID_OS 27#include <linux/android_pmem.h> 28#endif 29 30#include <EGL/egl.h> 31#include <EGL/eglext.h> 32#include <GLES/gl.h> 33#include <GLES/glext.h> 34 35#include <cutils/log.h> 36#include <cutils/atomic.h> 37#include <cutils/properties.h> 38#include <cutils/memory.h> 39 40#include <utils/RefBase.h> 41 42#include "hooks.h" 43#include "egl_impl.h" 44 45 46#define MAKE_CONFIG(_impl, _index) ((EGLConfig)(((_impl)<<24) | (_index))) 47#define setError(_e, _r) setErrorEtc(__FUNCTION__, __LINE__, _e, _r) 48 49// ---------------------------------------------------------------------------- 50namespace android { 51// ---------------------------------------------------------------------------- 52 53#define VERSION_MAJOR 1 54#define VERSION_MINOR 4 55static char const * const gVendorString = "Android"; 56static char const * const gVersionString = "1.31 Android META-EGL"; 57static char const * const gClientApiString = "OpenGL ES"; 58static char const * const gExtensionString = ""; 59 60template <int MAGIC> 61struct egl_object_t 62{ 63 egl_object_t() : magic(MAGIC) { } 64 ~egl_object_t() { magic = 0; } 65 bool isValid() const { return magic == MAGIC; } 66private: 67 uint32_t magic; 68}; 69 70struct egl_display_t : public egl_object_t<'_dpy'> 71{ 72 EGLDisplay dpys[IMPL_NUM_DRIVERS_IMPLEMENTATIONS]; 73 EGLConfig* configs[IMPL_NUM_DRIVERS_IMPLEMENTATIONS]; 74 EGLint numConfigs[IMPL_NUM_DRIVERS_IMPLEMENTATIONS]; 75 EGLint numTotalConfigs; 76 char const* extensionsString; 77 volatile int32_t refs; 78 struct strings_t { 79 char const * vendor; 80 char const * version; 81 char const * clientApi; 82 char const * extensions; 83 }; 84 strings_t queryString[IMPL_NUM_DRIVERS_IMPLEMENTATIONS]; 85}; 86 87struct egl_surface_t : public egl_object_t<'_srf'> 88{ 89 egl_surface_t(EGLDisplay dpy, EGLSurface surface, 90 NativeWindowType window, int impl, egl_connection_t const* cnx) 91 : dpy(dpy), surface(surface), window(window), impl(impl), cnx(cnx) 92 { 93 // NOTE: window must be incRef'ed and connected already 94 } 95 ~egl_surface_t() { 96 if (window) { 97 if (window->disconnect) 98 window->disconnect(window); 99 window->decRef(window); 100 } 101 } 102 EGLDisplay dpy; 103 EGLSurface surface; 104 NativeWindowType window; 105 int impl; 106 egl_connection_t const* cnx; 107}; 108 109struct egl_context_t : public egl_object_t<'_ctx'> 110{ 111 egl_context_t(EGLDisplay dpy, EGLContext context, 112 int impl, egl_connection_t const* cnx) 113 : dpy(dpy), context(context), read(0), draw(0), impl(impl), cnx(cnx) 114 { 115 } 116 EGLDisplay dpy; 117 EGLContext context; 118 EGLSurface read; 119 EGLSurface draw; 120 int impl; 121 egl_connection_t const* cnx; 122}; 123 124struct tls_t 125{ 126 tls_t() : error(EGL_SUCCESS), ctx(0) { } 127 EGLint error; 128 EGLContext ctx; 129}; 130 131static void gl_unimplemented() { 132 LOGE("called unimplemented OpenGL ES API"); 133} 134 135// ---------------------------------------------------------------------------- 136// GL / EGL hooks 137// ---------------------------------------------------------------------------- 138 139#undef GL_ENTRY 140#undef EGL_ENTRY 141#define GL_ENTRY(_r, _api, ...) #_api, 142#define EGL_ENTRY(_r, _api, ...) #_api, 143 144static char const * const gl_names[] = { 145 #include "gl_entries.in" 146 NULL 147}; 148 149static char const * const egl_names[] = { 150 #include "egl_entries.in" 151 NULL 152}; 153 154#undef GL_ENTRY 155#undef EGL_ENTRY 156 157// ---------------------------------------------------------------------------- 158 159egl_connection_t gEGLImpl[IMPL_NUM_DRIVERS_IMPLEMENTATIONS]; 160static egl_display_t gDisplay[NUM_DISPLAYS]; 161static pthread_mutex_t gThreadLocalStorageKeyMutex = PTHREAD_MUTEX_INITIALIZER; 162static pthread_key_t gEGLThreadLocalStorageKey = -1; 163 164// ---------------------------------------------------------------------------- 165 166gl_hooks_t gHooks[IMPL_NUM_IMPLEMENTATIONS]; 167pthread_key_t gGLWrapperKey = -1; 168 169// ---------------------------------------------------------------------------- 170 171static __attribute__((noinline)) 172const char *egl_strerror(EGLint err) 173{ 174 switch (err){ 175 case EGL_SUCCESS: return "EGL_SUCCESS"; 176 case EGL_NOT_INITIALIZED: return "EGL_NOT_INITIALIZED"; 177 case EGL_BAD_ACCESS: return "EGL_BAD_ACCESS"; 178 case EGL_BAD_ALLOC: return "EGL_BAD_ALLOC"; 179 case EGL_BAD_ATTRIBUTE: return "EGL_BAD_ATTRIBUTE"; 180 case EGL_BAD_CONFIG: return "EGL_BAD_CONFIG"; 181 case EGL_BAD_CONTEXT: return "EGL_BAD_CONTEXT"; 182 case EGL_BAD_CURRENT_SURFACE: return "EGL_BAD_CURRENT_SURFACE"; 183 case EGL_BAD_DISPLAY: return "EGL_BAD_DISPLAY"; 184 case EGL_BAD_MATCH: return "EGL_BAD_MATCH"; 185 case EGL_BAD_NATIVE_PIXMAP: return "EGL_BAD_NATIVE_PIXMAP"; 186 case EGL_BAD_NATIVE_WINDOW: return "EGL_BAD_NATIVE_WINDOW"; 187 case EGL_BAD_PARAMETER: return "EGL_BAD_PARAMETER"; 188 case EGL_BAD_SURFACE: return "EGL_BAD_SURFACE"; 189 case EGL_CONTEXT_LOST: return "EGL_CONTEXT_LOST"; 190 default: return "UNKNOWN"; 191 } 192} 193 194static __attribute__((noinline)) 195void clearTLS() { 196 if (gEGLThreadLocalStorageKey != -1) { 197 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey); 198 if (tls) { 199 delete tls; 200 pthread_setspecific(gEGLThreadLocalStorageKey, 0); 201 } 202 } 203} 204 205static tls_t* getTLS() 206{ 207 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey); 208 if (tls == 0) { 209 tls = new tls_t; 210 pthread_setspecific(gEGLThreadLocalStorageKey, tls); 211 } 212 return tls; 213} 214 215template<typename T> 216static __attribute__((noinline)) 217T setErrorEtc(const char* caller, int line, EGLint error, T returnValue) { 218 if (gEGLThreadLocalStorageKey == -1) { 219 pthread_mutex_lock(&gThreadLocalStorageKeyMutex); 220 if (gEGLThreadLocalStorageKey == -1) 221 pthread_key_create(&gEGLThreadLocalStorageKey, NULL); 222 pthread_mutex_unlock(&gThreadLocalStorageKeyMutex); 223 } 224 tls_t* tls = getTLS(); 225 if (tls->error != error) { 226 LOGE("%s:%d error %x (%s)", caller, line, error, egl_strerror(error)); 227 tls->error = error; 228 } 229 return returnValue; 230} 231 232static __attribute__((noinline)) 233GLint getError() { 234 if (gEGLThreadLocalStorageKey == -1) 235 return EGL_SUCCESS; 236 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey); 237 if (!tls) return EGL_SUCCESS; 238 GLint error = tls->error; 239 tls->error = EGL_SUCCESS; 240 return error; 241} 242 243static __attribute__((noinline)) 244void setContext(EGLContext ctx) { 245 if (gEGLThreadLocalStorageKey == -1) { 246 pthread_mutex_lock(&gThreadLocalStorageKeyMutex); 247 if (gEGLThreadLocalStorageKey == -1) 248 pthread_key_create(&gEGLThreadLocalStorageKey, NULL); 249 pthread_mutex_unlock(&gThreadLocalStorageKeyMutex); 250 } 251 tls_t* tls = getTLS(); 252 tls->ctx = ctx; 253} 254 255static __attribute__((noinline)) 256EGLContext getContext() { 257 if (gEGLThreadLocalStorageKey == -1) 258 return EGL_NO_CONTEXT; 259 tls_t* tls = (tls_t*)pthread_getspecific(gEGLThreadLocalStorageKey); 260 if (!tls) return EGL_NO_CONTEXT; 261 return tls->ctx; 262} 263 264 265/*****************************************************************************/ 266 267class ISurfaceComposer; 268const sp<ISurfaceComposer>& getSurfaceFlinger(); 269request_gpu_t* gpu_acquire(void* user); 270int gpu_release(void*, request_gpu_t* gpu); 271 272static __attribute__((noinline)) 273void *load_driver(const char* driver, gl_hooks_t* hooks) 274{ 275 void* dso = dlopen(driver, RTLD_NOW | RTLD_LOCAL); 276 LOGE_IF(!dso, 277 "couldn't load <%s> library (%s)", 278 driver, dlerror()); 279 280 if (dso) { 281 // first find the symbol for eglGetProcAddress 282 283 typedef __eglMustCastToProperFunctionPointerType (*getProcAddressType)( 284 const char*); 285 286 getProcAddressType getProcAddress = 287 (getProcAddressType)dlsym(dso, "eglGetProcAddress"); 288 289 LOGE_IF(!getProcAddress, 290 "can't find eglGetProcAddress() in %s", driver); 291 292 __eglMustCastToProperFunctionPointerType* curr; 293 char const * const * api; 294 295 gl_hooks_t::egl_t* egl = &hooks->egl; 296 curr = (__eglMustCastToProperFunctionPointerType*)egl; 297 api = egl_names; 298 while (*api) { 299 char const * name = *api; 300 __eglMustCastToProperFunctionPointerType f = 301 (__eglMustCastToProperFunctionPointerType)dlsym(dso, name); 302 if (f == NULL) { 303 // couldn't find the entry-point, use eglGetProcAddress() 304 f = getProcAddress(name); 305 if (f == NULL) { 306 f = (__eglMustCastToProperFunctionPointerType)0; 307 } 308 } 309 *curr++ = f; 310 api++; 311 } 312 313 gl_hooks_t::gl_t* gl = &hooks->gl; 314 curr = (__eglMustCastToProperFunctionPointerType*)gl; 315 api = gl_names; 316 while (*api) { 317 char const * name = *api; 318 // if the function starts with '__' it's a special case that 319 // uses a wrapper. skip the '__' when looking into the real lib. 320 if (name[0] == '_' && name[1] == '_') { 321 name += 2; 322 } 323 __eglMustCastToProperFunctionPointerType f = 324 (__eglMustCastToProperFunctionPointerType)dlsym(dso, name); 325 if (f == NULL) { 326 // couldn't find the entry-point, use eglGetProcAddress() 327 f = getProcAddress(name); 328 if (f == NULL) { 329 f = (__eglMustCastToProperFunctionPointerType)gl_unimplemented; 330 } 331 } 332 *curr++ = f; 333 api++; 334 } 335 336 // hook this driver up with surfaceflinger if needed 337 register_gpu_t register_gpu = 338 (register_gpu_t)dlsym(dso, "oem_register_gpu"); 339 340 if (register_gpu != NULL) { 341 if (getSurfaceFlinger() != 0) { 342 register_gpu(dso, gpu_acquire, gpu_release); 343 } 344 } 345 } 346 return dso; 347} 348 349template<typename T> 350static __attribute__((noinline)) 351int binarySearch( 352 T const sortedArray[], int first, int last, T key) 353{ 354 while (first <= last) { 355 int mid = (first + last) / 2; 356 if (key > sortedArray[mid]) { 357 first = mid + 1; 358 } else if (key < sortedArray[mid]) { 359 last = mid - 1; 360 } else { 361 return mid; 362 } 363 } 364 return -1; 365} 366 367static EGLint configToUniqueId(egl_display_t const* dp, int i, int index) 368{ 369 // NOTE: this mapping works only if we have no more than two EGLimpl 370 return (i>0 ? dp->numConfigs[0] : 0) + index; 371} 372 373static void uniqueIdToConfig(egl_display_t const* dp, EGLint configId, 374 int& i, int& index) 375{ 376 // NOTE: this mapping works only if we have no more than two EGLimpl 377 size_t numConfigs = dp->numConfigs[0]; 378 i = configId / numConfigs; 379 index = configId % numConfigs; 380} 381 382static int cmp_configs(const void* a, const void *b) 383{ 384 EGLConfig c0 = *(EGLConfig const *)a; 385 EGLConfig c1 = *(EGLConfig const *)b; 386 return c0<c1 ? -1 : (c0>c1 ? 1 : 0); 387} 388 389struct extention_map_t { 390 const char* name; 391 __eglMustCastToProperFunctionPointerType address; 392}; 393 394static const extention_map_t gExtentionMap[] = { 395}; 396 397static extention_map_t gGLExtentionMap[MAX_NUMBER_OF_GL_EXTENSIONS]; 398 399static void(*findProcAddress(const char* name, 400 const extention_map_t* map, size_t n))() 401{ 402 for (uint32_t i=0 ; i<n ; i++) { 403 if (!strcmp(name, map[i].name)) { 404 return map[i].address; 405 } 406 } 407 return NULL; 408} 409 410// ---------------------------------------------------------------------------- 411 412static int gl_context_lost() { 413 setGlThreadSpecific(&gHooks[IMPL_CONTEXT_LOST]); 414 return 0; 415} 416static int egl_context_lost() { 417 setGlThreadSpecific(&gHooks[IMPL_CONTEXT_LOST]); 418 return EGL_FALSE; 419} 420static EGLBoolean egl_context_lost_swap_buffers(void*, void*) { 421 usleep(100000); // don't use all the CPU 422 setGlThreadSpecific(&gHooks[IMPL_CONTEXT_LOST]); 423 return EGL_FALSE; 424} 425static GLint egl_context_lost_get_error() { 426 return EGL_CONTEXT_LOST; 427} 428static int ext_context_lost() { 429 return 0; 430} 431 432static void gl_no_context() { 433 LOGE("call to OpenGL ES API with no current context"); 434} 435static void early_egl_init(void) 436{ 437#if !USE_FAST_TLS_KEY 438 pthread_key_create(&gGLWrapperKey, NULL); 439#endif 440 uint32_t addr = (uint32_t)((void*)gl_no_context); 441 android_memset32( 442 (uint32_t*)(void*)&gHooks[IMPL_NO_CONTEXT], 443 addr, 444 sizeof(gHooks[IMPL_NO_CONTEXT])); 445 setGlThreadSpecific(&gHooks[IMPL_NO_CONTEXT]); 446} 447 448static pthread_once_t once_control = PTHREAD_ONCE_INIT; 449static int sEarlyInitState = pthread_once(&once_control, &early_egl_init); 450 451 452static inline 453egl_display_t* get_display(EGLDisplay dpy) 454{ 455 uintptr_t index = uintptr_t(dpy)-1U; 456 return (index >= NUM_DISPLAYS) ? NULL : &gDisplay[index]; 457} 458 459template<typename NATIVE, typename EGL> 460static inline NATIVE* egl_to_native_cast(EGL arg) { 461 return reinterpret_cast<NATIVE*>(arg); 462} 463 464static inline 465egl_surface_t* get_surface(EGLSurface surface) { 466 return egl_to_native_cast<egl_surface_t>(surface); 467} 468 469static inline 470egl_context_t* get_context(EGLContext context) { 471 return egl_to_native_cast<egl_context_t>(context); 472} 473 474static egl_connection_t* validate_display_config( 475 EGLDisplay dpy, EGLConfig config, 476 egl_display_t const*& dp, int& impl, int& index) 477{ 478 dp = get_display(dpy); 479 if (!dp) return setError(EGL_BAD_DISPLAY, (egl_connection_t*)NULL); 480 481 impl = uintptr_t(config)>>24; 482 if (uint32_t(impl) >= IMPL_NUM_DRIVERS_IMPLEMENTATIONS) { 483 return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL); 484 } 485 index = uintptr_t(config) & 0xFFFFFF; 486 if (index >= dp->numConfigs[impl]) { 487 return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL); 488 } 489 egl_connection_t* const cnx = &gEGLImpl[impl]; 490 if (cnx->dso == 0) { 491 return setError(EGL_BAD_CONFIG, (egl_connection_t*)NULL); 492 } 493 return cnx; 494} 495 496static EGLBoolean validate_display_context(EGLDisplay dpy, EGLContext ctx) 497{ 498 if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) 499 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 500 if (!get_display(dpy)->isValid()) 501 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 502 if (!ctx) // TODO: make sure context is a valid object 503 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 504 if (!get_context(ctx)->isValid()) 505 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 506 return EGL_TRUE; 507} 508 509static EGLBoolean validate_display_surface(EGLDisplay dpy, EGLSurface surface) 510{ 511 if ((uintptr_t(dpy)-1U) >= NUM_DISPLAYS) 512 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 513 if (!get_display(dpy)->isValid()) 514 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 515 if (!surface) // TODO: make sure surface is a valid object 516 return setError(EGL_BAD_SURFACE, EGL_FALSE); 517 if (!get_surface(surface)->isValid()) 518 return setError(EGL_BAD_SURFACE, EGL_FALSE); 519 return EGL_TRUE; 520} 521 522 523EGLDisplay egl_init_displays(NativeDisplayType display) 524{ 525 if (sEarlyInitState) { 526 return EGL_NO_DISPLAY; 527 } 528 529 uint32_t index = uint32_t(display); 530 if (index >= NUM_DISPLAYS) { 531 return EGL_NO_DISPLAY; 532 } 533 534 EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU); 535 egl_display_t* d = &gDisplay[index]; 536 537 // dynamically load all our EGL implementations for that display 538 // and call into the real eglGetGisplay() 539 egl_connection_t* cnx = &gEGLImpl[IMPL_SOFTWARE]; 540 if (cnx->dso == 0) { 541 cnx->hooks = &gHooks[IMPL_SOFTWARE]; 542 cnx->dso = load_driver("libagl.so", cnx->hooks); 543 } 544 if (cnx->dso && d->dpys[IMPL_SOFTWARE]==EGL_NO_DISPLAY) { 545 d->dpys[IMPL_SOFTWARE] = cnx->hooks->egl.eglGetDisplay(display); 546 LOGE_IF(d->dpys[IMPL_SOFTWARE]==EGL_NO_DISPLAY, 547 "No EGLDisplay for software EGL!"); 548 } 549 550 cnx = &gEGLImpl[IMPL_HARDWARE]; 551 if (cnx->dso == 0 && cnx->unavailable == 0) { 552 char value[PROPERTY_VALUE_MAX]; 553 property_get("debug.egl.hw", value, "1"); 554 if (atoi(value) != 0) { 555 cnx->hooks = &gHooks[IMPL_HARDWARE]; 556 cnx->dso = load_driver("libhgl.so", cnx->hooks); 557 } else { 558 LOGD("3D hardware acceleration is disabled"); 559 } 560 } 561 if (cnx->dso && d->dpys[IMPL_HARDWARE]==EGL_NO_DISPLAY) { 562 android_memset32( 563 (uint32_t*)(void*)&gHooks[IMPL_CONTEXT_LOST].gl, 564 (uint32_t)((void*)gl_context_lost), 565 sizeof(gHooks[IMPL_CONTEXT_LOST].gl)); 566 android_memset32( 567 (uint32_t*)(void*)&gHooks[IMPL_CONTEXT_LOST].egl, 568 (uint32_t)((void*)egl_context_lost), 569 sizeof(gHooks[IMPL_CONTEXT_LOST].egl)); 570 android_memset32( 571 (uint32_t*)(void*)&gHooks[IMPL_CONTEXT_LOST].ext, 572 (uint32_t)((void*)ext_context_lost), 573 sizeof(gHooks[IMPL_CONTEXT_LOST].ext)); 574 575 gHooks[IMPL_CONTEXT_LOST].egl.eglSwapBuffers = 576 egl_context_lost_swap_buffers; 577 578 gHooks[IMPL_CONTEXT_LOST].egl.eglGetError = 579 egl_context_lost_get_error; 580 581 gHooks[IMPL_CONTEXT_LOST].egl.eglTerminate = 582 gHooks[IMPL_HARDWARE].egl.eglTerminate; 583 584 d->dpys[IMPL_HARDWARE] = cnx->hooks->egl.eglGetDisplay(display); 585 if (d->dpys[IMPL_HARDWARE] == EGL_NO_DISPLAY) { 586 LOGE("h/w accelerated eglGetDisplay() failed (%s)", 587 egl_strerror(cnx->hooks->egl.eglGetError())); 588 dlclose((void*)cnx->dso); 589 cnx->dso = 0; 590 // in case of failure, we want to make sure we don't try again 591 // as it's expensive. 592 cnx->unavailable = 1; 593 } 594 } 595 596 return dpy; 597} 598 599 600// ---------------------------------------------------------------------------- 601}; // namespace android 602// ---------------------------------------------------------------------------- 603 604using namespace android; 605 606EGLDisplay eglGetDisplay(NativeDisplayType display) 607{ 608 return egl_init_displays(display); 609} 610 611// ---------------------------------------------------------------------------- 612// Initialization 613// ---------------------------------------------------------------------------- 614 615EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) 616{ 617 egl_display_t * const dp = get_display(dpy); 618 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 619 620 if (android_atomic_inc(&dp->refs) > 0) { 621 if (major != NULL) *major = VERSION_MAJOR; 622 if (minor != NULL) *minor = VERSION_MINOR; 623 return EGL_TRUE; 624 } 625 626 setGlThreadSpecific(&gHooks[IMPL_NO_CONTEXT]); 627 628 // initialize each EGL and 629 // build our own extension string first, based on the extension we know 630 // and the extension supported by our client implementation 631 dp->extensionsString = strdup(gExtensionString); 632 for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { 633 egl_connection_t* const cnx = &gEGLImpl[i]; 634 cnx->major = -1; 635 cnx->minor = -1; 636 if (!cnx->dso) 637 continue; 638 639 if (cnx->hooks->egl.eglInitialize( 640 dp->dpys[i], &cnx->major, &cnx->minor)) { 641 642 //LOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p", 643 // i, dp->dpys[i], cnx->major, cnx->minor, cnx); 644 645 // get the query-strings for this display for each implementation 646 dp->queryString[i].vendor = 647 cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_VENDOR); 648 dp->queryString[i].version = 649 cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_VERSION); 650 dp->queryString[i].extensions = strdup( 651 cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_EXTENSIONS)); 652 dp->queryString[i].clientApi = 653 cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_CLIENT_APIS); 654 655 } else { 656 LOGD("%d: eglInitialize() failed (%s)", 657 i, egl_strerror(cnx->hooks->egl.eglGetError())); 658 } 659 } 660 661 EGLBoolean res = EGL_FALSE; 662 for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { 663 egl_connection_t* const cnx = &gEGLImpl[i]; 664 if (cnx->dso && cnx->major>=0 && cnx->minor>=0) { 665 EGLint n; 666 if (cnx->hooks->egl.eglGetConfigs(dp->dpys[i], 0, 0, &n)) { 667 dp->configs[i] = (EGLConfig*)malloc(sizeof(EGLConfig)*n); 668 if (dp->configs[i]) { 669 if (cnx->hooks->egl.eglGetConfigs( 670 dp->dpys[i], dp->configs[i], n, &dp->numConfigs[i])) 671 { 672 // sort the configurations so we can do binary searches 673 qsort( dp->configs[i], 674 dp->numConfigs[i], 675 sizeof(EGLConfig), cmp_configs); 676 677 dp->numTotalConfigs += n; 678 res = EGL_TRUE; 679 } 680 } 681 } 682 } 683 } 684 685 if (res == EGL_TRUE) { 686 if (major != NULL) *major = VERSION_MAJOR; 687 if (minor != NULL) *minor = VERSION_MINOR; 688 return EGL_TRUE; 689 } 690 return setError(EGL_NOT_INITIALIZED, EGL_FALSE); 691} 692 693EGLBoolean eglTerminate(EGLDisplay dpy) 694{ 695 egl_display_t* const dp = get_display(dpy); 696 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 697 if (android_atomic_dec(&dp->refs) != 1) 698 return EGL_TRUE; 699 700 EGLBoolean res = EGL_FALSE; 701 for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { 702 egl_connection_t* const cnx = &gEGLImpl[i]; 703 if (cnx->dso) { 704 cnx->hooks->egl.eglTerminate(dp->dpys[i]); 705 706 /* REVISIT: it's unclear what to do if eglTerminate() fails, 707 * on one end we shouldn't care, on the other end if it fails 708 * it might not be safe to call dlclose() (there could be some 709 * threads around). */ 710 711 free(dp->configs[i]); 712 free((void*)dp->queryString[i].extensions); 713 dp->numConfigs[i] = 0; 714 dp->dpys[i] = EGL_NO_DISPLAY; 715 dlclose((void*)cnx->dso); 716 cnx->dso = 0; 717 res = EGL_TRUE; 718 } 719 } 720 free((void*)dp->extensionsString); 721 dp->extensionsString = 0; 722 dp->numTotalConfigs = 0; 723 clearTLS(); 724 return res; 725} 726 727// ---------------------------------------------------------------------------- 728// configuration 729// ---------------------------------------------------------------------------- 730 731EGLBoolean eglGetConfigs( EGLDisplay dpy, 732 EGLConfig *configs, 733 EGLint config_size, EGLint *num_config) 734{ 735 egl_display_t const * const dp = get_display(dpy); 736 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 737 738 GLint numConfigs = dp->numTotalConfigs; 739 if (!configs) { 740 *num_config = numConfigs; 741 return EGL_TRUE; 742 } 743 GLint n = 0; 744 for (int j=0 ; j<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; j++) { 745 for (int i=0 ; i<dp->numConfigs[j] && config_size ; i++) { 746 *configs++ = MAKE_CONFIG(j, i); 747 config_size--; 748 n++; 749 } 750 } 751 752 *num_config = n; 753 return EGL_TRUE; 754} 755 756EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, 757 EGLConfig *configs, EGLint config_size, 758 EGLint *num_config) 759{ 760 egl_display_t const * const dp = get_display(dpy); 761 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 762 763 if (num_config==0) { 764 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 765 } 766 767 EGLint n; 768 EGLBoolean res = EGL_FALSE; 769 *num_config = 0; 770 771 772 // It is unfortunate, but we need to remap the EGL_CONFIG_IDs, 773 // to do this, we have to go through the attrib_list array once 774 // to figure out both its size and if it contains an EGL_CONFIG_ID 775 // key. If so, the full array is copied and patched. 776 // NOTE: we assume that there can be only one occurrence 777 // of EGL_CONFIG_ID. 778 779 EGLint patch_index = -1; 780 GLint attr; 781 size_t size = 0; 782 while ((attr=attrib_list[size])) { 783 if (attr == EGL_CONFIG_ID) 784 patch_index = size; 785 size += 2; 786 } 787 if (patch_index >= 0) { 788 size += 2; // we need copy the sentinel as well 789 EGLint* new_list = (EGLint*)malloc(size*sizeof(EGLint)); 790 if (new_list == 0) 791 return setError(EGL_BAD_ALLOC, EGL_FALSE); 792 memcpy(new_list, attrib_list, size*sizeof(EGLint)); 793 794 // patch the requested EGL_CONFIG_ID 795 int i, index; 796 EGLint& configId(new_list[patch_index+1]); 797 uniqueIdToConfig(dp, configId, i, index); 798 799 egl_connection_t* const cnx = &gEGLImpl[i]; 800 if (cnx->dso) { 801 cnx->hooks->egl.eglGetConfigAttrib( 802 dp->dpys[i], dp->configs[i][index], 803 EGL_CONFIG_ID, &configId); 804 805 // and switch to the new list 806 attrib_list = const_cast<const EGLint *>(new_list); 807 808 // At this point, the only configuration that can match is 809 // dp->configs[i][index], however, we don't know if it would be 810 // rejected because of the other attributes, so we do have to call 811 // cnx->hooks->egl.eglChooseConfig() -- but we don't have to loop 812 // through all the EGLimpl[]. 813 // We also know we can only get a single config back, and we know 814 // which one. 815 816 res = cnx->hooks->egl.eglChooseConfig( 817 dp->dpys[i], attrib_list, configs, config_size, &n); 818 if (res && n>0) { 819 // n has to be 0 or 1, by construction, and we already know 820 // which config it will return (since there can be only one). 821 if (configs) { 822 configs[0] = MAKE_CONFIG(i, index); 823 } 824 *num_config = 1; 825 } 826 } 827 828 free(const_cast<EGLint *>(attrib_list)); 829 return res; 830 } 831 832 for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { 833 egl_connection_t* const cnx = &gEGLImpl[i]; 834 if (cnx->dso) { 835 if (cnx->hooks->egl.eglChooseConfig( 836 dp->dpys[i], attrib_list, configs, config_size, &n)) { 837 if (configs) { 838 // now we need to convert these client EGLConfig to our 839 // internal EGLConfig format. This is done in O(n log n). 840 for (int j=0 ; j<n ; j++) { 841 int index = binarySearch<EGLConfig>( 842 dp->configs[i], 0, dp->numConfigs[i]-1, configs[j]); 843 if (index >= 0) { 844 if (configs) { 845 configs[j] = MAKE_CONFIG(i, index); 846 } 847 } else { 848 return setError(EGL_BAD_CONFIG, EGL_FALSE); 849 } 850 } 851 configs += n; 852 config_size -= n; 853 } 854 *num_config += n; 855 res = EGL_TRUE; 856 } 857 } 858 } 859 return res; 860} 861 862EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, 863 EGLint attribute, EGLint *value) 864{ 865 egl_display_t const* dp = 0; 866 int i=0, index=0; 867 egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); 868 if (!cnx) return EGL_FALSE; 869 870 if (attribute == EGL_CONFIG_ID) { 871 // EGL_CONFIG_IDs must be unique, just use the order of the selected 872 // EGLConfig. 873 *value = configToUniqueId(dp, i, index); 874 return EGL_TRUE; 875 } 876 return cnx->hooks->egl.eglGetConfigAttrib( 877 dp->dpys[i], dp->configs[i][index], attribute, value); 878} 879 880// ---------------------------------------------------------------------------- 881// surfaces 882// ---------------------------------------------------------------------------- 883 884EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, 885 NativeWindowType window, 886 const EGLint *attrib_list) 887{ 888 egl_display_t const* dp = 0; 889 int i=0, index=0; 890 egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); 891 if (cnx) { 892 // window must be connected upon calling underlying 893 // eglCreateWindowSurface 894 if (window) { 895 window->incRef(window); 896 if (window->connect) 897 window->connect(window); 898 } 899 900 EGLSurface surface = cnx->hooks->egl.eglCreateWindowSurface( 901 dp->dpys[i], dp->configs[i][index], window, attrib_list); 902 if (surface != EGL_NO_SURFACE) { 903 egl_surface_t* s = new egl_surface_t(dpy, surface, window, i, cnx); 904 return s; 905 } 906 907 // something went wrong, disconnect and free window 908 // (will disconnect() automatically) 909 if (window) { 910 window->decRef(window); 911 } 912 } 913 return EGL_NO_SURFACE; 914} 915 916EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, 917 NativePixmapType pixmap, 918 const EGLint *attrib_list) 919{ 920 egl_display_t const* dp = 0; 921 int i=0, index=0; 922 egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); 923 if (cnx) { 924 EGLSurface surface = cnx->hooks->egl.eglCreatePixmapSurface( 925 dp->dpys[i], dp->configs[i][index], pixmap, attrib_list); 926 if (surface != EGL_NO_SURFACE) { 927 egl_surface_t* s = new egl_surface_t(dpy, surface, NULL, i, cnx); 928 return s; 929 } 930 } 931 return EGL_NO_SURFACE; 932} 933 934EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, 935 const EGLint *attrib_list) 936{ 937 egl_display_t const* dp = 0; 938 int i=0, index=0; 939 egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); 940 if (cnx) { 941 EGLSurface surface = cnx->hooks->egl.eglCreatePbufferSurface( 942 dp->dpys[i], dp->configs[i][index], attrib_list); 943 if (surface != EGL_NO_SURFACE) { 944 egl_surface_t* s = new egl_surface_t(dpy, surface, NULL, i, cnx); 945 return s; 946 } 947 } 948 return EGL_NO_SURFACE; 949} 950 951EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) 952{ 953 if (!validate_display_surface(dpy, surface)) 954 return EGL_FALSE; 955 egl_display_t const * const dp = get_display(dpy); 956 egl_surface_t const * const s = get_surface(surface); 957 958 EGLBoolean result = s->cnx->hooks->egl.eglDestroySurface( 959 dp->dpys[s->impl], s->surface); 960 961 delete s; 962 return result; 963} 964 965EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface, 966 EGLint attribute, EGLint *value) 967{ 968 if (!validate_display_surface(dpy, surface)) 969 return EGL_FALSE; 970 egl_display_t const * const dp = get_display(dpy); 971 egl_surface_t const * const s = get_surface(surface); 972 973 return s->cnx->hooks->egl.eglQuerySurface( 974 dp->dpys[s->impl], s->surface, attribute, value); 975} 976 977// ---------------------------------------------------------------------------- 978// contextes 979// ---------------------------------------------------------------------------- 980 981EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, 982 EGLContext share_list, const EGLint *attrib_list) 983{ 984 egl_display_t const* dp = 0; 985 int i=0, index=0; 986 egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); 987 if (cnx) { 988 EGLContext context = cnx->hooks->egl.eglCreateContext( 989 dp->dpys[i], dp->configs[i][index], share_list, attrib_list); 990 if (context != EGL_NO_CONTEXT) { 991 egl_context_t* c = new egl_context_t(dpy, context, i, cnx); 992 return c; 993 } 994 } 995 return EGL_NO_CONTEXT; 996} 997 998EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) 999{ 1000 if (!validate_display_context(dpy, ctx)) 1001 return EGL_FALSE; 1002 egl_display_t const * const dp = get_display(dpy); 1003 egl_context_t * const c = get_context(ctx); 1004 EGLBoolean result = c->cnx->hooks->egl.eglDestroyContext( 1005 dp->dpys[c->impl], c->context); 1006 delete c; 1007 return result; 1008} 1009 1010EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, 1011 EGLSurface read, EGLContext ctx) 1012{ 1013 egl_display_t const * const dp = get_display(dpy); 1014 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1015 1016 if (read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE && 1017 ctx == EGL_NO_CONTEXT) 1018 { 1019 EGLBoolean result = EGL_TRUE; 1020 ctx = getContext(); 1021 if (ctx) { 1022 egl_context_t * const c = get_context(ctx); 1023 result = c->cnx->hooks->egl.eglMakeCurrent(dp->dpys[c->impl], 0, 0, 0); 1024 if (result == EGL_TRUE) { 1025 setGlThreadSpecific(&gHooks[IMPL_NO_CONTEXT]); 1026 setContext(EGL_NO_CONTEXT); 1027 } 1028 } 1029 return result; 1030 } 1031 1032 if (!validate_display_context(dpy, ctx)) 1033 return EGL_FALSE; 1034 1035 egl_context_t * const c = get_context(ctx); 1036 if (draw != EGL_NO_SURFACE) { 1037 egl_surface_t const * d = get_surface(draw); 1038 if (!d) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1039 if (d->impl != c->impl) 1040 return setError(EGL_BAD_MATCH, EGL_FALSE); 1041 draw = d->surface; 1042 } 1043 if (read != EGL_NO_SURFACE) { 1044 egl_surface_t const * r = get_surface(read); 1045 if (!r) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1046 if (r->impl != c->impl) 1047 return setError(EGL_BAD_MATCH, EGL_FALSE); 1048 read = r->surface; 1049 } 1050 EGLBoolean result = c->cnx->hooks->egl.eglMakeCurrent( 1051 dp->dpys[c->impl], draw, read, c->context); 1052 1053 if (result == EGL_TRUE) { 1054 setGlThreadSpecific(c->cnx->hooks); 1055 setContext(ctx); 1056 c->read = read; 1057 c->draw = draw; 1058 } 1059 return result; 1060} 1061 1062 1063EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, 1064 EGLint attribute, EGLint *value) 1065{ 1066 if (!validate_display_context(dpy, ctx)) 1067 return EGL_FALSE; 1068 1069 egl_display_t const * const dp = get_display(dpy); 1070 egl_context_t * const c = get_context(ctx); 1071 1072 return c->cnx->hooks->egl.eglQueryContext( 1073 dp->dpys[c->impl], c->context, attribute, value); 1074} 1075 1076EGLContext eglGetCurrentContext(void) 1077{ 1078 EGLContext ctx = getContext(); 1079 return ctx; 1080} 1081 1082EGLSurface eglGetCurrentSurface(EGLint readdraw) 1083{ 1084 EGLContext ctx = getContext(); 1085 if (ctx) { 1086 egl_context_t const * const c = get_context(ctx); 1087 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 1088 switch (readdraw) { 1089 case EGL_READ: return c->read; 1090 case EGL_DRAW: return c->draw; 1091 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 1092 } 1093 } 1094 return EGL_NO_SURFACE; 1095} 1096 1097EGLDisplay eglGetCurrentDisplay(void) 1098{ 1099 EGLContext ctx = getContext(); 1100 if (ctx) { 1101 egl_context_t const * const c = get_context(ctx); 1102 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 1103 return c->dpy; 1104 } 1105 return EGL_NO_DISPLAY; 1106} 1107 1108EGLBoolean eglWaitGL(void) 1109{ 1110 EGLBoolean res = EGL_TRUE; 1111 EGLContext ctx = getContext(); 1112 if (ctx) { 1113 egl_context_t const * const c = get_context(ctx); 1114 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1115 if (uint32_t(c->impl)>=2) 1116 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1117 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 1118 if (!cnx->dso) 1119 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1120 res = cnx->hooks->egl.eglWaitGL(); 1121 } 1122 return res; 1123} 1124 1125EGLBoolean eglWaitNative(EGLint engine) 1126{ 1127 EGLBoolean res = EGL_TRUE; 1128 EGLContext ctx = getContext(); 1129 if (ctx) { 1130 egl_context_t const * const c = get_context(ctx); 1131 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1132 if (uint32_t(c->impl)>=2) 1133 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1134 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 1135 if (!cnx->dso) 1136 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1137 res = cnx->hooks->egl.eglWaitNative(engine); 1138 } 1139 return res; 1140} 1141 1142EGLint eglGetError(void) 1143{ 1144 EGLint result = EGL_SUCCESS; 1145 for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { 1146 EGLint err = EGL_SUCCESS; 1147 egl_connection_t* const cnx = &gEGLImpl[i]; 1148 if (cnx->dso) 1149 err = cnx->hooks->egl.eglGetError(); 1150 if (err!=EGL_SUCCESS && result==EGL_SUCCESS) 1151 result = err; 1152 } 1153 if (result == EGL_SUCCESS) 1154 result = getError(); 1155 return result; 1156} 1157 1158__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) 1159{ 1160 // eglGetProcAddress() could be the very first function called 1161 // in which case we must make sure we've initialized ourselves, this 1162 // happens the first time egl_get_display() is called. 1163 1164 if (egl_init_displays(EGL_DEFAULT_DISPLAY) == EGL_NO_DISPLAY) 1165 return NULL; 1166 1167 __eglMustCastToProperFunctionPointerType addr; 1168 addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap)); 1169 if (addr) return addr; 1170 1171 return NULL; // TODO: finish implementation below 1172 1173 addr = findProcAddress(procname, gGLExtentionMap, NELEM(gGLExtentionMap)); 1174 if (addr) return addr; 1175 1176 addr = 0; 1177 int slot = -1; 1178 for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { 1179 egl_connection_t* const cnx = &gEGLImpl[i]; 1180 if (cnx->dso) { 1181 if (cnx->hooks->egl.eglGetProcAddress) { 1182 addr = cnx->hooks->egl.eglGetProcAddress(procname); 1183 if (addr) { 1184 if (slot == -1) { 1185 slot = 0; // XXX: find free slot 1186 if (slot == -1) { 1187 addr = 0; 1188 break; 1189 } 1190 } 1191 cnx->hooks->ext.extensions[slot] = addr; 1192 } 1193 } 1194 } 1195 } 1196 1197 if (slot >= 0) { 1198 addr = 0; // XXX: address of stub 'slot' 1199 gGLExtentionMap[slot].name = strdup(procname); 1200 gGLExtentionMap[slot].address = addr; 1201 } 1202 1203 return addr; 1204 1205 1206 /* 1207 * TODO: For OpenGL ES extensions, we must generate a stub 1208 * that looks like 1209 * mov r12, #0xFFFF0FFF 1210 * ldr r12, [r12, #-15] 1211 * ldr r12, [r12, #TLS_SLOT_OPENGL_API*4] 1212 * mov r12, [r12, #api_offset] 1213 * ldrne pc, r12 1214 * mov pc, #unsupported_extension 1215 * 1216 * and write the address of the extension in *all* 1217 * gl_hooks_t::gl_ext_t at offset "api_offset" from gl_hooks_t 1218 * 1219 */ 1220} 1221 1222EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) 1223{ 1224 if (!validate_display_surface(dpy, draw)) 1225 return EGL_FALSE; 1226 egl_display_t const * const dp = get_display(dpy); 1227 egl_surface_t const * const s = get_surface(draw); 1228 return s->cnx->hooks->egl.eglSwapBuffers(dp->dpys[s->impl], s->surface); 1229} 1230 1231EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, 1232 NativePixmapType target) 1233{ 1234 if (!validate_display_surface(dpy, surface)) 1235 return EGL_FALSE; 1236 egl_display_t const * const dp = get_display(dpy); 1237 egl_surface_t const * const s = get_surface(surface); 1238 return s->cnx->hooks->egl.eglCopyBuffers( 1239 dp->dpys[s->impl], s->surface, target); 1240} 1241 1242const char* eglQueryString(EGLDisplay dpy, EGLint name) 1243{ 1244 egl_display_t const * const dp = get_display(dpy); 1245 switch (name) { 1246 case EGL_VENDOR: 1247 return gVendorString; 1248 case EGL_VERSION: 1249 return gVersionString; 1250 case EGL_EXTENSIONS: 1251 return gExtensionString; 1252 case EGL_CLIENT_APIS: 1253 return gClientApiString; 1254 } 1255 return setError(EGL_BAD_PARAMETER, (const char *)0); 1256} 1257 1258 1259// ---------------------------------------------------------------------------- 1260// EGL 1.1 1261// ---------------------------------------------------------------------------- 1262 1263EGLBoolean eglSurfaceAttrib( 1264 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 1265{ 1266 if (!validate_display_surface(dpy, surface)) 1267 return EGL_FALSE; 1268 egl_display_t const * const dp = get_display(dpy); 1269 egl_surface_t const * const s = get_surface(surface); 1270 if (s->cnx->hooks->egl.eglSurfaceAttrib) { 1271 return s->cnx->hooks->egl.eglSurfaceAttrib( 1272 dp->dpys[s->impl], s->surface, attribute, value); 1273 } 1274 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1275} 1276 1277EGLBoolean eglBindTexImage( 1278 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1279{ 1280 if (!validate_display_surface(dpy, surface)) 1281 return EGL_FALSE; 1282 egl_display_t const * const dp = get_display(dpy); 1283 egl_surface_t const * const s = get_surface(surface); 1284 if (s->cnx->hooks->egl.eglBindTexImage) { 1285 return s->cnx->hooks->egl.eglBindTexImage( 1286 dp->dpys[s->impl], s->surface, buffer); 1287 } 1288 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1289} 1290 1291EGLBoolean eglReleaseTexImage( 1292 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1293{ 1294 if (!validate_display_surface(dpy, surface)) 1295 return EGL_FALSE; 1296 egl_display_t const * const dp = get_display(dpy); 1297 egl_surface_t const * const s = get_surface(surface); 1298 if (s->cnx->hooks->egl.eglReleaseTexImage) { 1299 return s->cnx->hooks->egl.eglReleaseTexImage( 1300 dp->dpys[s->impl], s->surface, buffer); 1301 } 1302 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1303} 1304 1305EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 1306{ 1307 egl_display_t * const dp = get_display(dpy); 1308 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1309 1310 EGLBoolean res = EGL_TRUE; 1311 for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { 1312 egl_connection_t* const cnx = &gEGLImpl[i]; 1313 if (cnx->dso) { 1314 if (cnx->hooks->egl.eglSwapInterval) { 1315 if (cnx->hooks->egl.eglSwapInterval(dp->dpys[i], interval) == EGL_FALSE) { 1316 res = EGL_FALSE; 1317 } 1318 } 1319 } 1320 } 1321 return res; 1322} 1323 1324 1325// ---------------------------------------------------------------------------- 1326// EGL 1.2 1327// ---------------------------------------------------------------------------- 1328 1329EGLBoolean eglWaitClient(void) 1330{ 1331 EGLBoolean res = EGL_TRUE; 1332 EGLContext ctx = getContext(); 1333 if (ctx) { 1334 egl_context_t const * const c = get_context(ctx); 1335 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1336 if (uint32_t(c->impl)>=2) 1337 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1338 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 1339 if (!cnx->dso) 1340 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1341 if (cnx->hooks->egl.eglWaitClient) { 1342 res = cnx->hooks->egl.eglWaitClient(); 1343 } else { 1344 res = cnx->hooks->egl.eglWaitGL(); 1345 } 1346 } 1347 return res; 1348} 1349 1350EGLBoolean eglBindAPI(EGLenum api) 1351{ 1352 // bind this API on all EGLs 1353 EGLBoolean res = EGL_TRUE; 1354 for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { 1355 egl_connection_t* const cnx = &gEGLImpl[i]; 1356 if (cnx->dso) { 1357 if (cnx->hooks->egl.eglBindAPI) { 1358 if (cnx->hooks->egl.eglBindAPI(api) == EGL_FALSE) { 1359 res = EGL_FALSE; 1360 } 1361 } 1362 } 1363 } 1364 return res; 1365} 1366 1367EGLenum eglQueryAPI(void) 1368{ 1369 for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { 1370 egl_connection_t* const cnx = &gEGLImpl[i]; 1371 if (cnx->dso) { 1372 if (cnx->hooks->egl.eglQueryAPI) { 1373 // the first one we find is okay, because they all 1374 // should be the same 1375 return cnx->hooks->egl.eglQueryAPI(); 1376 } 1377 } 1378 } 1379 // or, it can only be OpenGL ES 1380 return EGL_OPENGL_ES_API; 1381} 1382 1383EGLBoolean eglReleaseThread(void) 1384{ 1385 for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) { 1386 egl_connection_t* const cnx = &gEGLImpl[i]; 1387 if (cnx->dso) { 1388 if (cnx->hooks->egl.eglReleaseThread) { 1389 cnx->hooks->egl.eglReleaseThread(); 1390 } 1391 } 1392 } 1393 clearTLS(); 1394 return EGL_TRUE; 1395} 1396 1397EGLSurface eglCreatePbufferFromClientBuffer( 1398 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 1399 EGLConfig config, const EGLint *attrib_list) 1400{ 1401 egl_display_t const* dp = 0; 1402 int i=0, index=0; 1403 egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); 1404 if (!cnx) return EGL_FALSE; 1405 if (cnx->hooks->egl.eglCreatePbufferFromClientBuffer) { 1406 return cnx->hooks->egl.eglCreatePbufferFromClientBuffer( 1407 dp->dpys[i], buftype, buffer, dp->configs[i][index], attrib_list); 1408 } 1409 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); 1410} 1411