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