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