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