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