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