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