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