eglApi.cpp revision 0469dd6d55fa331bfd7de9431da98b6340d82271
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 21#include <hardware/gralloc.h> 22#include <system/window.h> 23 24#include <EGL/egl.h> 25#include <EGL/eglext.h> 26#include <GLES/gl.h> 27#include <GLES/glext.h> 28 29#include <cutils/log.h> 30#include <cutils/atomic.h> 31#include <cutils/properties.h> 32#include <cutils/memory.h> 33 34#include <utils/KeyedVector.h> 35#include <utils/SortedVector.h> 36#include <utils/String8.h> 37 38#include "egl_impl.h" 39#include "egl_tls.h" 40#include "glestrace.h" 41#include "hooks.h" 42 43#include "egl_display.h" 44#include "egl_impl.h" 45#include "egl_object.h" 46#include "egl_tls.h" 47 48using namespace android; 49 50// ---------------------------------------------------------------------------- 51 52struct extention_map_t { 53 const char* name; 54 __eglMustCastToProperFunctionPointerType address; 55}; 56 57static const extention_map_t sExtentionMap[] = { 58 { "eglLockSurfaceKHR", 59 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR }, 60 { "eglUnlockSurfaceKHR", 61 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR }, 62 { "eglCreateImageKHR", 63 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, 64 { "eglDestroyImageKHR", 65 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, 66 { "eglGetSystemTimeFrequencyNV", 67 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV }, 68 { "eglGetSystemTimeNV", 69 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV }, 70}; 71 72// accesses protected by sExtensionMapMutex 73static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap; 74static int sGLExtentionSlot = 0; 75static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER; 76 77static void(*findProcAddress(const char* name, 78 const extention_map_t* map, size_t n))() { 79 for (uint32_t i=0 ; i<n ; i++) { 80 if (!strcmp(name, map[i].name)) { 81 return map[i].address; 82 } 83 } 84 return NULL; 85} 86 87// ---------------------------------------------------------------------------- 88 89template<typename T> 90static __attribute__((noinline)) 91int binarySearch(T const sortedArray[], int first, int last, T key) { 92 while (first <= last) { 93 int mid = (first + last) / 2; 94 if (sortedArray[mid] < key) { 95 first = mid + 1; 96 } else if (key < sortedArray[mid]) { 97 last = mid - 1; 98 } else { 99 return mid; 100 } 101 } 102 return -1; 103} 104 105// ---------------------------------------------------------------------------- 106 107namespace android { 108extern void setGLHooksThreadSpecific(gl_hooks_t const *value); 109extern EGLBoolean egl_init_drivers(); 110extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS]; 111extern int gEGLDebugLevel; 112extern gl_hooks_t gHooksTrace; 113} // namespace android; 114 115// ---------------------------------------------------------------------------- 116 117static inline void clearError() { egl_tls_t::clearError(); } 118static inline EGLContext getContext() { return egl_tls_t::getContext(); } 119 120// ---------------------------------------------------------------------------- 121 122EGLDisplay eglGetDisplay(EGLNativeDisplayType display) 123{ 124 clearError(); 125 126 uint32_t index = uint32_t(display); 127 if (index >= NUM_DISPLAYS) { 128 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 129 } 130 131 if (egl_init_drivers() == EGL_FALSE) { 132 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 133 } 134 135 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display); 136 return dpy; 137} 138 139// ---------------------------------------------------------------------------- 140// Initialization 141// ---------------------------------------------------------------------------- 142 143EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) 144{ 145 clearError(); 146 147 egl_display_t * const dp = get_display(dpy); 148 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 149 150 EGLBoolean res = dp->initialize(major, minor); 151 152 return res; 153} 154 155EGLBoolean eglTerminate(EGLDisplay dpy) 156{ 157 // NOTE: don't unload the drivers b/c some APIs can be called 158 // after eglTerminate() has been called. eglTerminate() only 159 // terminates an EGLDisplay, not a EGL itself. 160 161 clearError(); 162 163 egl_display_t* const dp = get_display(dpy); 164 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 165 166 EGLBoolean res = dp->terminate(); 167 168 return res; 169} 170 171// ---------------------------------------------------------------------------- 172// configuration 173// ---------------------------------------------------------------------------- 174 175EGLBoolean eglGetConfigs( EGLDisplay dpy, 176 EGLConfig *configs, 177 EGLint config_size, EGLint *num_config) 178{ 179 clearError(); 180 181 egl_display_t const * const dp = validate_display(dpy); 182 if (!dp) return EGL_FALSE; 183 184 GLint numConfigs = dp->numTotalConfigs; 185 if (!configs) { 186 *num_config = numConfigs; 187 return EGL_TRUE; 188 } 189 190 GLint n = 0; 191 for (intptr_t i=0 ; i<dp->numTotalConfigs && config_size ; i++) { 192 *configs++ = EGLConfig(i); 193 config_size--; 194 n++; 195 } 196 197 *num_config = n; 198 return EGL_TRUE; 199} 200 201EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, 202 EGLConfig *configs, EGLint config_size, 203 EGLint *num_config) 204{ 205 clearError(); 206 207 egl_display_t const * const dp = validate_display(dpy); 208 if (!dp) return EGL_FALSE; 209 210 if (num_config==0) { 211 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 212 } 213 214 EGLint n; 215 EGLBoolean res = EGL_FALSE; 216 *num_config = 0; 217 218 219 // It is unfortunate, but we need to remap the EGL_CONFIG_IDs, 220 // to do this, we have to go through the attrib_list array once 221 // to figure out both its size and if it contains an EGL_CONFIG_ID 222 // key. If so, the full array is copied and patched. 223 // NOTE: we assume that there can be only one occurrence 224 // of EGL_CONFIG_ID. 225 226 EGLint patch_index = -1; 227 GLint attr; 228 size_t size = 0; 229 if (attrib_list) { 230 while ((attr=attrib_list[size]) != EGL_NONE) { 231 if (attr == EGL_CONFIG_ID) 232 patch_index = size; 233 size += 2; 234 } 235 } 236 if (patch_index >= 0) { 237 size += 2; // we need copy the sentinel as well 238 EGLint* new_list = (EGLint*)malloc(size*sizeof(EGLint)); 239 if (new_list == 0) 240 return setError(EGL_BAD_ALLOC, EGL_FALSE); 241 memcpy(new_list, attrib_list, size*sizeof(EGLint)); 242 243 // patch the requested EGL_CONFIG_ID 244 bool found = false; 245 EGLConfig ourConfig(0); 246 EGLint& configId(new_list[patch_index+1]); 247 for (intptr_t i=0 ; i<dp->numTotalConfigs ; i++) { 248 if (dp->configs[i].configId == configId) { 249 ourConfig = EGLConfig(i); 250 configId = dp->configs[i].implConfigId; 251 found = true; 252 break; 253 } 254 } 255 256 egl_connection_t* const cnx = &gEGLImpl[dp->configs[intptr_t(ourConfig)].impl]; 257 if (found && cnx->dso) { 258 // and switch to the new list 259 attrib_list = const_cast<const EGLint *>(new_list); 260 261 // At this point, the only configuration that can match is 262 // dp->configs[i][index], however, we don't know if it would be 263 // rejected because of the other attributes, so we do have to call 264 // cnx->egl.eglChooseConfig() -- but we don't have to loop 265 // through all the EGLimpl[]. 266 // We also know we can only get a single config back, and we know 267 // which one. 268 269 res = cnx->egl.eglChooseConfig( 270 dp->disp[ dp->configs[intptr_t(ourConfig)].impl ].dpy, 271 attrib_list, configs, config_size, &n); 272 if (res && n>0) { 273 // n has to be 0 or 1, by construction, and we already know 274 // which config it will return (since there can be only one). 275 if (configs) { 276 configs[0] = ourConfig; 277 } 278 *num_config = 1; 279 } 280 } 281 282 free(const_cast<EGLint *>(attrib_list)); 283 return res; 284 } 285 286 287 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 288 egl_connection_t* const cnx = &gEGLImpl[i]; 289 if (cnx->dso) { 290 if (cnx->egl.eglChooseConfig( 291 dp->disp[i].dpy, attrib_list, configs, config_size, &n)) { 292 if (configs) { 293 // now we need to convert these client EGLConfig to our 294 // internal EGLConfig format. 295 // This is done in O(n Log(n)) time. 296 for (int j=0 ; j<n ; j++) { 297 egl_config_t key(i, configs[j]); 298 intptr_t index = binarySearch<egl_config_t>( 299 dp->configs, 0, dp->numTotalConfigs, key); 300 if (index >= 0) { 301 configs[j] = EGLConfig(index); 302 } else { 303 return setError(EGL_BAD_CONFIG, EGL_FALSE); 304 } 305 } 306 configs += n; 307 config_size -= n; 308 } 309 *num_config += n; 310 res = EGL_TRUE; 311 } 312 } 313 } 314 return res; 315} 316 317EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, 318 EGLint attribute, EGLint *value) 319{ 320 clearError(); 321 322 egl_display_t const* dp = 0; 323 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 324 if (!cnx) return EGL_FALSE; 325 326 if (attribute == EGL_CONFIG_ID) { 327 *value = dp->configs[intptr_t(config)].configId; 328 return EGL_TRUE; 329 } 330 return cnx->egl.eglGetConfigAttrib( 331 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 332 dp->configs[intptr_t(config)].config, attribute, value); 333} 334 335// ---------------------------------------------------------------------------- 336// surfaces 337// ---------------------------------------------------------------------------- 338 339EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, 340 NativeWindowType window, 341 const EGLint *attrib_list) 342{ 343 clearError(); 344 345 egl_display_t const* dp = 0; 346 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 347 if (cnx) { 348 EGLDisplay iDpy = dp->disp[ dp->configs[intptr_t(config)].impl ].dpy; 349 EGLConfig iConfig = dp->configs[intptr_t(config)].config; 350 EGLint format; 351 352 if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != OK) { 353 LOGE("EGLNativeWindowType %p already connected to another API", 354 window); 355 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 356 } 357 358 // set the native window's buffers format to match this config 359 if (cnx->egl.eglGetConfigAttrib(iDpy, 360 iConfig, EGL_NATIVE_VISUAL_ID, &format)) { 361 if (format != 0) { 362 int err = native_window_set_buffers_format(window, format); 363 if (err != 0) { 364 LOGE("error setting native window pixel format: %s (%d)", 365 strerror(-err), err); 366 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 367 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 368 } 369 } 370 } 371 372 // the EGL spec requires that a new EGLSurface default to swap interval 373 // 1, so explicitly set that on the window here. 374 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window); 375 anw->setSwapInterval(anw, 1); 376 377 EGLSurface surface = cnx->egl.eglCreateWindowSurface( 378 iDpy, iConfig, window, attrib_list); 379 if (surface != EGL_NO_SURFACE) { 380 egl_surface_t* s = new egl_surface_t(dpy, config, window, surface, 381 dp->configs[intptr_t(config)].impl, cnx); 382 return s; 383 } 384 385 // EGLSurface creation failed 386 native_window_set_buffers_format(window, 0); 387 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 388 } 389 return EGL_NO_SURFACE; 390} 391 392EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, 393 NativePixmapType pixmap, 394 const EGLint *attrib_list) 395{ 396 clearError(); 397 398 egl_display_t const* dp = 0; 399 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 400 if (cnx) { 401 EGLSurface surface = cnx->egl.eglCreatePixmapSurface( 402 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 403 dp->configs[intptr_t(config)].config, pixmap, attrib_list); 404 if (surface != EGL_NO_SURFACE) { 405 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface, 406 dp->configs[intptr_t(config)].impl, cnx); 407 return s; 408 } 409 } 410 return EGL_NO_SURFACE; 411} 412 413EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, 414 const EGLint *attrib_list) 415{ 416 clearError(); 417 418 egl_display_t const* dp = 0; 419 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 420 if (cnx) { 421 EGLSurface surface = cnx->egl.eglCreatePbufferSurface( 422 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 423 dp->configs[intptr_t(config)].config, attrib_list); 424 if (surface != EGL_NO_SURFACE) { 425 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface, 426 dp->configs[intptr_t(config)].impl, cnx); 427 return s; 428 } 429 } 430 return EGL_NO_SURFACE; 431} 432 433EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) 434{ 435 clearError(); 436 437 egl_display_t const * const dp = validate_display(dpy); 438 if (!dp) return EGL_FALSE; 439 440 SurfaceRef _s(dp, surface); 441 if (!_s.get()) 442 return setError(EGL_BAD_SURFACE, EGL_FALSE); 443 444 egl_surface_t * const s = get_surface(surface); 445 EGLBoolean result = s->cnx->egl.eglDestroySurface( 446 dp->disp[s->impl].dpy, s->surface); 447 if (result == EGL_TRUE) { 448 _s.terminate(); 449 } 450 return result; 451} 452 453EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface, 454 EGLint attribute, EGLint *value) 455{ 456 clearError(); 457 458 egl_display_t const * const dp = validate_display(dpy); 459 if (!dp) return EGL_FALSE; 460 461 SurfaceRef _s(dp, surface); 462 if (!_s.get()) 463 return setError(EGL_BAD_SURFACE, EGL_FALSE); 464 465 egl_surface_t const * const s = get_surface(surface); 466 EGLBoolean result(EGL_TRUE); 467 if (attribute == EGL_CONFIG_ID) { 468 // We need to remap EGL_CONFIG_IDs 469 *value = dp->configs[intptr_t(s->config)].configId; 470 } else { 471 result = s->cnx->egl.eglQuerySurface( 472 dp->disp[s->impl].dpy, s->surface, attribute, value); 473 } 474 475 return result; 476} 477 478// ---------------------------------------------------------------------------- 479// Contexts 480// ---------------------------------------------------------------------------- 481 482EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, 483 EGLContext share_list, const EGLint *attrib_list) 484{ 485 clearError(); 486 487 egl_display_t const* dp = 0; 488 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 489 if (cnx) { 490 if (share_list != EGL_NO_CONTEXT) { 491 egl_context_t* const c = get_context(share_list); 492 share_list = c->context; 493 } 494 EGLContext context = cnx->egl.eglCreateContext( 495 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 496 dp->configs[intptr_t(config)].config, 497 share_list, attrib_list); 498 if (context != EGL_NO_CONTEXT) { 499 // figure out if it's a GLESv1 or GLESv2 500 int version = 0; 501 if (attrib_list) { 502 while (*attrib_list != EGL_NONE) { 503 GLint attr = *attrib_list++; 504 GLint value = *attrib_list++; 505 if (attr == EGL_CONTEXT_CLIENT_VERSION) { 506 if (value == 1) { 507 version = GLESv1_INDEX; 508 } else if (value == 2) { 509 version = GLESv2_INDEX; 510 } 511 } 512 }; 513 } 514 egl_context_t* c = new egl_context_t(dpy, context, config, 515 dp->configs[intptr_t(config)].impl, cnx, version); 516#if EGL_TRACE 517 if (gEGLDebugLevel > 0) 518 GLTrace_eglCreateContext(version, c); 519#endif 520 return c; 521 } 522 } 523 return EGL_NO_CONTEXT; 524} 525 526EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) 527{ 528 clearError(); 529 530 egl_display_t const * const dp = validate_display(dpy); 531 if (!dp) 532 return EGL_FALSE; 533 534 ContextRef _c(dp, ctx); 535 if (!_c.get()) 536 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 537 538 egl_context_t * const c = get_context(ctx); 539 EGLBoolean result = c->cnx->egl.eglDestroyContext( 540 dp->disp[c->impl].dpy, c->context); 541 if (result == EGL_TRUE) { 542 _c.terminate(); 543 } 544 return result; 545} 546 547static void loseCurrent(egl_context_t * cur_c) 548{ 549 if (cur_c) { 550 egl_surface_t * cur_r = get_surface(cur_c->read); 551 egl_surface_t * cur_d = get_surface(cur_c->draw); 552 553 // by construction, these are either 0 or valid (possibly terminated) 554 // it should be impossible for these to be invalid 555 ContextRef _cur_c(cur_c); 556 SurfaceRef _cur_r(cur_r); 557 SurfaceRef _cur_d(cur_d); 558 559 cur_c->read = NULL; 560 cur_c->draw = NULL; 561 562 _cur_c.release(); 563 _cur_r.release(); 564 _cur_d.release(); 565 } 566} 567 568EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, 569 EGLSurface read, EGLContext ctx) 570{ 571 clearError(); 572 573 egl_display_t const * const dp = get_display(dpy); 574 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 575 576 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not 577 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is 578 // a valid but uninitialized display. 579 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) || 580 (draw != EGL_NO_SURFACE) ) { 581 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE); 582 } 583 584 // get a reference to the object passed in 585 ContextRef _c(dp, ctx); 586 SurfaceRef _d(dp, draw); 587 SurfaceRef _r(dp, read); 588 589 // validate the context (if not EGL_NO_CONTEXT) 590 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) { 591 // EGL_NO_CONTEXT is valid 592 return EGL_FALSE; 593 } 594 595 // these are the underlying implementation's object 596 EGLContext impl_ctx = EGL_NO_CONTEXT; 597 EGLSurface impl_draw = EGL_NO_SURFACE; 598 EGLSurface impl_read = EGL_NO_SURFACE; 599 600 // these are our objects structs passed in 601 egl_context_t * c = NULL; 602 egl_surface_t const * d = NULL; 603 egl_surface_t const * r = NULL; 604 605 // these are the current objects structs 606 egl_context_t * cur_c = get_context(getContext()); 607 608 if (ctx != EGL_NO_CONTEXT) { 609 c = get_context(ctx); 610 impl_ctx = c->context; 611 } else { 612 // no context given, use the implementation of the current context 613 if (cur_c == NULL) { 614 // no current context 615 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) { 616 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT); 617 return setError(EGL_BAD_MATCH, EGL_FALSE); 618 } 619 // not an error, there is just no current context. 620 return EGL_TRUE; 621 } 622 } 623 624 // retrieve the underlying implementation's draw EGLSurface 625 if (draw != EGL_NO_SURFACE) { 626 d = get_surface(draw); 627 // make sure the EGLContext and EGLSurface passed in are for 628 // the same driver 629 if (c && d->impl != c->impl) 630 return setError(EGL_BAD_MATCH, EGL_FALSE); 631 impl_draw = d->surface; 632 } 633 634 // retrieve the underlying implementation's read EGLSurface 635 if (read != EGL_NO_SURFACE) { 636 r = get_surface(read); 637 // make sure the EGLContext and EGLSurface passed in are for 638 // the same driver 639 if (c && r->impl != c->impl) 640 return setError(EGL_BAD_MATCH, EGL_FALSE); 641 impl_read = r->surface; 642 } 643 644 EGLBoolean result; 645 646 if (c) { 647 result = c->cnx->egl.eglMakeCurrent( 648 dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx); 649 } else { 650 result = cur_c->cnx->egl.eglMakeCurrent( 651 dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx); 652 } 653 654 if (result == EGL_TRUE) { 655 656 loseCurrent(cur_c); 657 658 if (ctx != EGL_NO_CONTEXT) { 659 setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 660 egl_tls_t::setContext(ctx); 661#if EGL_TRACE 662 if (gEGLDebugLevel > 0) 663 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version]); 664#endif 665 _c.acquire(); 666 _r.acquire(); 667 _d.acquire(); 668 c->read = read; 669 c->draw = draw; 670 } else { 671 setGLHooksThreadSpecific(&gHooksNoContext); 672 egl_tls_t::setContext(EGL_NO_CONTEXT); 673 } 674 } else { 675 // this will LOGE the error 676 result = setError(c->cnx->egl.eglGetError(), EGL_FALSE); 677 } 678 return result; 679} 680 681 682EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, 683 EGLint attribute, EGLint *value) 684{ 685 clearError(); 686 687 egl_display_t const * const dp = validate_display(dpy); 688 if (!dp) return EGL_FALSE; 689 690 ContextRef _c(dp, ctx); 691 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 692 693 egl_context_t * const c = get_context(ctx); 694 695 EGLBoolean result(EGL_TRUE); 696 if (attribute == EGL_CONFIG_ID) { 697 *value = dp->configs[intptr_t(c->config)].configId; 698 } else { 699 // We need to remap EGL_CONFIG_IDs 700 result = c->cnx->egl.eglQueryContext( 701 dp->disp[c->impl].dpy, c->context, attribute, value); 702 } 703 704 return result; 705} 706 707EGLContext eglGetCurrentContext(void) 708{ 709 // could be called before eglInitialize(), but we wouldn't have a context 710 // then, and this function would correctly return EGL_NO_CONTEXT. 711 712 clearError(); 713 714 EGLContext ctx = getContext(); 715 return ctx; 716} 717 718EGLSurface eglGetCurrentSurface(EGLint readdraw) 719{ 720 // could be called before eglInitialize(), but we wouldn't have a context 721 // then, and this function would correctly return EGL_NO_SURFACE. 722 723 clearError(); 724 725 EGLContext ctx = getContext(); 726 if (ctx) { 727 egl_context_t const * const c = get_context(ctx); 728 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 729 switch (readdraw) { 730 case EGL_READ: return c->read; 731 case EGL_DRAW: return c->draw; 732 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 733 } 734 } 735 return EGL_NO_SURFACE; 736} 737 738EGLDisplay eglGetCurrentDisplay(void) 739{ 740 // could be called before eglInitialize(), but we wouldn't have a context 741 // then, and this function would correctly return EGL_NO_DISPLAY. 742 743 clearError(); 744 745 EGLContext ctx = getContext(); 746 if (ctx) { 747 egl_context_t const * const c = get_context(ctx); 748 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 749 return c->dpy; 750 } 751 return EGL_NO_DISPLAY; 752} 753 754EGLBoolean eglWaitGL(void) 755{ 756 // could be called before eglInitialize(), but we wouldn't have a context 757 // then, and this function would return GL_TRUE, which isn't wrong. 758 759 clearError(); 760 761 EGLBoolean res = EGL_TRUE; 762 EGLContext ctx = getContext(); 763 if (ctx) { 764 egl_context_t const * const c = get_context(ctx); 765 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 766 if (uint32_t(c->impl)>=2) 767 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 768 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 769 if (!cnx->dso) 770 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 771 res = cnx->egl.eglWaitGL(); 772 } 773 return res; 774} 775 776EGLBoolean eglWaitNative(EGLint engine) 777{ 778 // could be called before eglInitialize(), but we wouldn't have a context 779 // then, and this function would return GL_TRUE, which isn't wrong. 780 781 clearError(); 782 783 EGLBoolean res = EGL_TRUE; 784 EGLContext ctx = getContext(); 785 if (ctx) { 786 egl_context_t const * const c = get_context(ctx); 787 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 788 if (uint32_t(c->impl)>=2) 789 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 790 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 791 if (!cnx->dso) 792 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 793 res = cnx->egl.eglWaitNative(engine); 794 } 795 return res; 796} 797 798EGLint eglGetError(void) 799{ 800 EGLint result = EGL_SUCCESS; 801 EGLint err; 802 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 803 err = EGL_SUCCESS; 804 egl_connection_t* const cnx = &gEGLImpl[i]; 805 if (cnx->dso) 806 err = cnx->egl.eglGetError(); 807 if (err!=EGL_SUCCESS && result==EGL_SUCCESS) 808 result = err; 809 } 810 err = egl_tls_t::getError(); 811 if (result == EGL_SUCCESS) 812 result = err; 813 return result; 814} 815 816// Note: Similar implementations of these functions also exist in 817// gl2.cpp and gl.cpp, and are used by applications that call the 818// exported entry points directly. 819typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image); 820typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image); 821 822static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_impl = NULL; 823static PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES_impl = NULL; 824 825static void glEGLImageTargetTexture2DOES_wrapper(GLenum target, GLeglImageOES image) 826{ 827 GLeglImageOES implImage = 828 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image); 829 glEGLImageTargetTexture2DOES_impl(target, implImage); 830} 831 832static void glEGLImageTargetRenderbufferStorageOES_wrapper(GLenum target, GLeglImageOES image) 833{ 834 GLeglImageOES implImage = 835 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image); 836 glEGLImageTargetRenderbufferStorageOES_impl(target, implImage); 837} 838 839__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) 840{ 841 // eglGetProcAddress() could be the very first function called 842 // in which case we must make sure we've initialized ourselves, this 843 // happens the first time egl_get_display() is called. 844 845 clearError(); 846 847 if (egl_init_drivers() == EGL_FALSE) { 848 setError(EGL_BAD_PARAMETER, NULL); 849 return NULL; 850 } 851 852 // The EGL_ANDROID_blob_cache extension should not be exposed to 853 // applications. It is used internally by the Android EGL layer. 854 if (!strcmp(procname, "eglSetBlobCacheFuncsANDROID")) { 855 return NULL; 856 } 857 858 __eglMustCastToProperFunctionPointerType addr; 859 addr = findProcAddress(procname, sExtentionMap, NELEM(sExtentionMap)); 860 if (addr) return addr; 861 862 863 // this protects accesses to sGLExtentionMap and sGLExtentionSlot 864 pthread_mutex_lock(&sExtensionMapMutex); 865 866 /* 867 * Since eglGetProcAddress() is not associated to anything, it needs 868 * to return a function pointer that "works" regardless of what 869 * the current context is. 870 * 871 * For this reason, we return a "forwarder", a small stub that takes 872 * care of calling the function associated with the context 873 * currently bound. 874 * 875 * We first look for extensions we've already resolved, if we're seeing 876 * this extension for the first time, we go through all our 877 * implementations and call eglGetProcAddress() and record the 878 * result in the appropriate implementation hooks and return the 879 * address of the forwarder corresponding to that hook set. 880 * 881 */ 882 883 const String8 name(procname); 884 addr = sGLExtentionMap.valueFor(name); 885 const int slot = sGLExtentionSlot; 886 887 LOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS, 888 "no more slots for eglGetProcAddress(\"%s\")", 889 procname); 890 891#if EGL_TRACE 892 gl_hooks_t *debugHooks = GLTrace_getGLHooks(); 893#endif 894 895 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) { 896 bool found = false; 897 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 898 egl_connection_t* const cnx = &gEGLImpl[i]; 899 if (cnx->dso && cnx->egl.eglGetProcAddress) { 900 found = true; 901 // Extensions are independent of the bound context 902 cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] = 903 cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] = 904#if EGL_TRACE 905 debugHooks->ext.extensions[slot] = gHooksTrace.ext.extensions[slot] = 906#endif 907 cnx->egl.eglGetProcAddress(procname); 908 } 909 } 910 if (found) { 911 addr = gExtensionForwarders[slot]; 912 913 if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) { 914 glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr; 915 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper; 916 } 917 if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) { 918 glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr; 919 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper; 920 } 921 922 sGLExtentionMap.add(name, addr); 923 sGLExtentionSlot++; 924 } 925 } 926 927 pthread_mutex_unlock(&sExtensionMapMutex); 928 return addr; 929} 930 931EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) 932{ 933 clearError(); 934 935 egl_display_t const * const dp = validate_display(dpy); 936 if (!dp) return EGL_FALSE; 937 938 SurfaceRef _s(dp, draw); 939 if (!_s.get()) 940 return setError(EGL_BAD_SURFACE, EGL_FALSE); 941 942#if EGL_TRACE 943 if (gEGLDebugLevel > 0) 944 GLTrace_eglSwapBuffers(dpy, draw); 945#endif 946 947 egl_surface_t const * const s = get_surface(draw); 948 return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface); 949} 950 951EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, 952 NativePixmapType target) 953{ 954 clearError(); 955 956 egl_display_t const * const dp = validate_display(dpy); 957 if (!dp) return EGL_FALSE; 958 959 SurfaceRef _s(dp, surface); 960 if (!_s.get()) 961 return setError(EGL_BAD_SURFACE, EGL_FALSE); 962 963 egl_surface_t const * const s = get_surface(surface); 964 return s->cnx->egl.eglCopyBuffers( 965 dp->disp[s->impl].dpy, s->surface, target); 966} 967 968const char* eglQueryString(EGLDisplay dpy, EGLint name) 969{ 970 clearError(); 971 972 egl_display_t const * const dp = validate_display(dpy); 973 if (!dp) return (const char *) NULL; 974 975 switch (name) { 976 case EGL_VENDOR: 977 return dp->getVendorString(); 978 case EGL_VERSION: 979 return dp->getVersionString(); 980 case EGL_EXTENSIONS: 981 return dp->getExtensionString(); 982 case EGL_CLIENT_APIS: 983 return dp->getClientApiString(); 984 } 985 return setError(EGL_BAD_PARAMETER, (const char *)0); 986} 987 988 989// ---------------------------------------------------------------------------- 990// EGL 1.1 991// ---------------------------------------------------------------------------- 992 993EGLBoolean eglSurfaceAttrib( 994 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 995{ 996 clearError(); 997 998 egl_display_t const * const dp = validate_display(dpy); 999 if (!dp) return EGL_FALSE; 1000 1001 SurfaceRef _s(dp, surface); 1002 if (!_s.get()) 1003 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1004 1005 egl_surface_t const * const s = get_surface(surface); 1006 if (s->cnx->egl.eglSurfaceAttrib) { 1007 return s->cnx->egl.eglSurfaceAttrib( 1008 dp->disp[s->impl].dpy, s->surface, attribute, value); 1009 } 1010 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1011} 1012 1013EGLBoolean eglBindTexImage( 1014 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1015{ 1016 clearError(); 1017 1018 egl_display_t const * const dp = validate_display(dpy); 1019 if (!dp) return EGL_FALSE; 1020 1021 SurfaceRef _s(dp, surface); 1022 if (!_s.get()) 1023 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1024 1025 egl_surface_t const * const s = get_surface(surface); 1026 if (s->cnx->egl.eglBindTexImage) { 1027 return s->cnx->egl.eglBindTexImage( 1028 dp->disp[s->impl].dpy, s->surface, buffer); 1029 } 1030 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1031} 1032 1033EGLBoolean eglReleaseTexImage( 1034 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1035{ 1036 clearError(); 1037 1038 egl_display_t const * const dp = validate_display(dpy); 1039 if (!dp) return EGL_FALSE; 1040 1041 SurfaceRef _s(dp, surface); 1042 if (!_s.get()) 1043 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1044 1045 egl_surface_t const * const s = get_surface(surface); 1046 if (s->cnx->egl.eglReleaseTexImage) { 1047 return s->cnx->egl.eglReleaseTexImage( 1048 dp->disp[s->impl].dpy, s->surface, buffer); 1049 } 1050 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1051} 1052 1053EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 1054{ 1055 clearError(); 1056 1057 egl_display_t const * const dp = validate_display(dpy); 1058 if (!dp) return EGL_FALSE; 1059 1060 EGLBoolean res = EGL_TRUE; 1061 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1062 egl_connection_t* const cnx = &gEGLImpl[i]; 1063 if (cnx->dso) { 1064 if (cnx->egl.eglSwapInterval) { 1065 if (cnx->egl.eglSwapInterval( 1066 dp->disp[i].dpy, interval) == EGL_FALSE) { 1067 res = EGL_FALSE; 1068 } 1069 } 1070 } 1071 } 1072 return res; 1073} 1074 1075 1076// ---------------------------------------------------------------------------- 1077// EGL 1.2 1078// ---------------------------------------------------------------------------- 1079 1080EGLBoolean eglWaitClient(void) 1081{ 1082 clearError(); 1083 1084 // could be called before eglInitialize(), but we wouldn't have a context 1085 // then, and this function would return GL_TRUE, which isn't wrong. 1086 EGLBoolean res = EGL_TRUE; 1087 EGLContext ctx = getContext(); 1088 if (ctx) { 1089 egl_context_t const * const c = get_context(ctx); 1090 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1091 if (uint32_t(c->impl)>=2) 1092 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1093 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 1094 if (!cnx->dso) 1095 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1096 if (cnx->egl.eglWaitClient) { 1097 res = cnx->egl.eglWaitClient(); 1098 } else { 1099 res = cnx->egl.eglWaitGL(); 1100 } 1101 } 1102 return res; 1103} 1104 1105EGLBoolean eglBindAPI(EGLenum api) 1106{ 1107 clearError(); 1108 1109 if (egl_init_drivers() == EGL_FALSE) { 1110 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1111 } 1112 1113 // bind this API on all EGLs 1114 EGLBoolean res = EGL_TRUE; 1115 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1116 egl_connection_t* const cnx = &gEGLImpl[i]; 1117 if (cnx->dso) { 1118 if (cnx->egl.eglBindAPI) { 1119 if (cnx->egl.eglBindAPI(api) == EGL_FALSE) { 1120 res = EGL_FALSE; 1121 } 1122 } 1123 } 1124 } 1125 return res; 1126} 1127 1128EGLenum eglQueryAPI(void) 1129{ 1130 clearError(); 1131 1132 if (egl_init_drivers() == EGL_FALSE) { 1133 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1134 } 1135 1136 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1137 egl_connection_t* const cnx = &gEGLImpl[i]; 1138 if (cnx->dso) { 1139 if (cnx->egl.eglQueryAPI) { 1140 // the first one we find is okay, because they all 1141 // should be the same 1142 return cnx->egl.eglQueryAPI(); 1143 } 1144 } 1145 } 1146 // or, it can only be OpenGL ES 1147 return EGL_OPENGL_ES_API; 1148} 1149 1150EGLBoolean eglReleaseThread(void) 1151{ 1152 clearError(); 1153 1154 // If there is context bound to the thread, release it 1155 loseCurrent(get_context(getContext())); 1156 1157 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1158 egl_connection_t* const cnx = &gEGLImpl[i]; 1159 if (cnx->dso) { 1160 if (cnx->egl.eglReleaseThread) { 1161 cnx->egl.eglReleaseThread(); 1162 } 1163 } 1164 } 1165 egl_tls_t::clearTLS(); 1166#if EGL_TRACE 1167 if (gEGLDebugLevel > 0) 1168 GLTrace_eglReleaseThread(); 1169#endif 1170 return EGL_TRUE; 1171} 1172 1173EGLSurface eglCreatePbufferFromClientBuffer( 1174 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 1175 EGLConfig config, const EGLint *attrib_list) 1176{ 1177 clearError(); 1178 1179 egl_display_t const* dp = 0; 1180 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 1181 if (!cnx) return EGL_FALSE; 1182 if (cnx->egl.eglCreatePbufferFromClientBuffer) { 1183 return cnx->egl.eglCreatePbufferFromClientBuffer( 1184 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 1185 buftype, buffer, 1186 dp->configs[intptr_t(config)].config, attrib_list); 1187 } 1188 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); 1189} 1190 1191// ---------------------------------------------------------------------------- 1192// EGL_EGLEXT_VERSION 3 1193// ---------------------------------------------------------------------------- 1194 1195EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, 1196 const EGLint *attrib_list) 1197{ 1198 clearError(); 1199 1200 egl_display_t const * const dp = validate_display(dpy); 1201 if (!dp) return EGL_FALSE; 1202 1203 SurfaceRef _s(dp, surface); 1204 if (!_s.get()) 1205 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1206 1207 egl_surface_t const * const s = get_surface(surface); 1208 if (s->cnx->egl.eglLockSurfaceKHR) { 1209 return s->cnx->egl.eglLockSurfaceKHR( 1210 dp->disp[s->impl].dpy, s->surface, attrib_list); 1211 } 1212 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1213} 1214 1215EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) 1216{ 1217 clearError(); 1218 1219 egl_display_t const * const dp = validate_display(dpy); 1220 if (!dp) return EGL_FALSE; 1221 1222 SurfaceRef _s(dp, surface); 1223 if (!_s.get()) 1224 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1225 1226 egl_surface_t const * const s = get_surface(surface); 1227 if (s->cnx->egl.eglUnlockSurfaceKHR) { 1228 return s->cnx->egl.eglUnlockSurfaceKHR( 1229 dp->disp[s->impl].dpy, s->surface); 1230 } 1231 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1232} 1233 1234EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1235 EGLClientBuffer buffer, const EGLint *attrib_list) 1236{ 1237 clearError(); 1238 1239 egl_display_t const * const dp = validate_display(dpy); 1240 if (!dp) return EGL_NO_IMAGE_KHR; 1241 1242 if (ctx != EGL_NO_CONTEXT) { 1243 ContextRef _c(dp, ctx); 1244 if (!_c.get()) 1245 return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR); 1246 egl_context_t * const c = get_context(ctx); 1247 // since we have an EGLContext, we know which implementation to use 1248 EGLImageKHR image = c->cnx->egl.eglCreateImageKHR( 1249 dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list); 1250 if (image == EGL_NO_IMAGE_KHR) 1251 return image; 1252 1253 egl_image_t* result = new egl_image_t(dpy, ctx); 1254 result->images[c->impl] = image; 1255 return (EGLImageKHR)result; 1256 } else { 1257 // EGL_NO_CONTEXT is a valid parameter 1258 1259 /* Since we don't have a way to know which implementation to call, 1260 * we're calling all of them. If at least one of the implementation 1261 * succeeded, this is a success. 1262 */ 1263 1264 EGLint currentError = eglGetError(); 1265 1266 EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS]; 1267 bool success = false; 1268 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1269 egl_connection_t* const cnx = &gEGLImpl[i]; 1270 implImages[i] = EGL_NO_IMAGE_KHR; 1271 if (cnx->dso) { 1272 if (cnx->egl.eglCreateImageKHR) { 1273 implImages[i] = cnx->egl.eglCreateImageKHR( 1274 dp->disp[i].dpy, ctx, target, buffer, attrib_list); 1275 if (implImages[i] != EGL_NO_IMAGE_KHR) { 1276 success = true; 1277 } 1278 } 1279 } 1280 } 1281 1282 if (!success) { 1283 // failure, if there was an error when we entered this function, 1284 // the error flag must not be updated. 1285 // Otherwise, the error is whatever happened in the implementation 1286 // that faulted. 1287 if (currentError != EGL_SUCCESS) { 1288 setError(currentError, EGL_NO_IMAGE_KHR); 1289 } 1290 return EGL_NO_IMAGE_KHR; 1291 } else { 1292 // In case of success, we need to clear all error flags 1293 // (especially those caused by the implementation that didn't 1294 // succeed). TODO: we could avoid this if we knew this was 1295 // a "full" success (all implementation succeeded). 1296 eglGetError(); 1297 } 1298 1299 egl_image_t* result = new egl_image_t(dpy, ctx); 1300 memcpy(result->images, implImages, sizeof(implImages)); 1301 return (EGLImageKHR)result; 1302 } 1303} 1304 1305EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 1306{ 1307 clearError(); 1308 1309 egl_display_t const * const dp = validate_display(dpy); 1310 if (!dp) return EGL_FALSE; 1311 1312 ImageRef _i(dp, img); 1313 if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1314 1315 egl_image_t* image = get_image(img); 1316 bool success = false; 1317 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1318 egl_connection_t* const cnx = &gEGLImpl[i]; 1319 if (image->images[i] != EGL_NO_IMAGE_KHR) { 1320 if (cnx->dso) { 1321 if (cnx->egl.eglDestroyImageKHR) { 1322 if (cnx->egl.eglDestroyImageKHR( 1323 dp->disp[i].dpy, image->images[i])) { 1324 success = true; 1325 } 1326 } 1327 } 1328 } 1329 } 1330 if (!success) 1331 return EGL_FALSE; 1332 1333 _i.terminate(); 1334 1335 return EGL_TRUE; 1336} 1337 1338// ---------------------------------------------------------------------------- 1339// EGL_EGLEXT_VERSION 5 1340// ---------------------------------------------------------------------------- 1341 1342 1343EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) 1344{ 1345 clearError(); 1346 1347 egl_display_t const * const dp = validate_display(dpy); 1348 if (!dp) return EGL_NO_SYNC_KHR; 1349 1350 EGLContext ctx = eglGetCurrentContext(); 1351 ContextRef _c(dp, ctx); 1352 if (!_c.get()) 1353 return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR); 1354 1355 egl_context_t * const c = get_context(ctx); 1356 EGLSyncKHR result = EGL_NO_SYNC_KHR; 1357 if (c->cnx->egl.eglCreateSyncKHR) { 1358 EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR( 1359 dp->disp[c->impl].dpy, type, attrib_list); 1360 if (sync == EGL_NO_SYNC_KHR) 1361 return sync; 1362 result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync); 1363 } 1364 return (EGLSyncKHR)result; 1365} 1366 1367EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) 1368{ 1369 clearError(); 1370 1371 egl_display_t const * const dp = validate_display(dpy); 1372 if (!dp) return EGL_FALSE; 1373 1374 SyncRef _s(dp, sync); 1375 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1376 egl_sync_t* syncObject = get_sync(sync); 1377 1378 EGLContext ctx = syncObject->context; 1379 ContextRef _c(dp, ctx); 1380 if (!_c.get()) 1381 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1382 1383 EGLBoolean result = EGL_FALSE; 1384 egl_context_t * const c = get_context(ctx); 1385 if (c->cnx->egl.eglDestroySyncKHR) { 1386 result = c->cnx->egl.eglDestroySyncKHR( 1387 dp->disp[c->impl].dpy, syncObject->sync); 1388 if (result) 1389 _s.terminate(); 1390 } 1391 return result; 1392} 1393 1394EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout) 1395{ 1396 clearError(); 1397 1398 egl_display_t const * const dp = validate_display(dpy); 1399 if (!dp) return EGL_FALSE; 1400 1401 SyncRef _s(dp, sync); 1402 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1403 egl_sync_t* syncObject = get_sync(sync); 1404 1405 EGLContext ctx = syncObject->context; 1406 ContextRef _c(dp, ctx); 1407 if (!_c.get()) 1408 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1409 1410 egl_context_t * const c = get_context(ctx); 1411 if (c->cnx->egl.eglClientWaitSyncKHR) { 1412 return c->cnx->egl.eglClientWaitSyncKHR( 1413 dp->disp[c->impl].dpy, syncObject->sync, flags, timeout); 1414 } 1415 1416 return EGL_FALSE; 1417} 1418 1419EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value) 1420{ 1421 clearError(); 1422 1423 egl_display_t const * const dp = validate_display(dpy); 1424 if (!dp) return EGL_FALSE; 1425 1426 SyncRef _s(dp, sync); 1427 if (!_s.get()) 1428 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1429 1430 egl_sync_t* syncObject = get_sync(sync); 1431 EGLContext ctx = syncObject->context; 1432 ContextRef _c(dp, ctx); 1433 if (!_c.get()) 1434 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1435 1436 egl_context_t * const c = get_context(ctx); 1437 if (c->cnx->egl.eglGetSyncAttribKHR) { 1438 return c->cnx->egl.eglGetSyncAttribKHR( 1439 dp->disp[c->impl].dpy, syncObject->sync, attribute, value); 1440 } 1441 1442 return EGL_FALSE; 1443} 1444 1445// ---------------------------------------------------------------------------- 1446// ANDROID extensions 1447// ---------------------------------------------------------------------------- 1448 1449/* ANDROID extensions entry-point go here */ 1450 1451// ---------------------------------------------------------------------------- 1452// NVIDIA extensions 1453// ---------------------------------------------------------------------------- 1454EGLuint64NV eglGetSystemTimeFrequencyNV() 1455{ 1456 clearError(); 1457 1458 if (egl_init_drivers() == EGL_FALSE) { 1459 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1460 } 1461 1462 EGLuint64NV ret = 0; 1463 egl_connection_t* const cnx = &gEGLImpl[IMPL_HARDWARE]; 1464 1465 if (cnx->dso) { 1466 if (cnx->egl.eglGetSystemTimeFrequencyNV) { 1467 return cnx->egl.eglGetSystemTimeFrequencyNV(); 1468 } 1469 } 1470 1471 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1472} 1473 1474EGLuint64NV eglGetSystemTimeNV() 1475{ 1476 clearError(); 1477 1478 if (egl_init_drivers() == EGL_FALSE) { 1479 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1480 } 1481 1482 EGLuint64NV ret = 0; 1483 egl_connection_t* const cnx = &gEGLImpl[IMPL_HARDWARE]; 1484 1485 if (cnx->dso) { 1486 if (cnx->egl.eglGetSystemTimeNV) { 1487 return cnx->egl.eglGetSystemTimeNV(); 1488 } 1489 } 1490 1491 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1492} 1493