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