eglApi.cpp revision 4b9511c16195a646242eff833b0af212933b6eca
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 EGLSurface surface = cnx->egl.eglCreateWindowSurface( 374 iDpy, iConfig, window, attrib_list); 375 if (surface != EGL_NO_SURFACE) { 376 egl_surface_t* s = new egl_surface_t(dpy, config, window, surface, 377 dp->configs[intptr_t(config)].impl, cnx); 378 return s; 379 } 380 381 // EGLSurface creation failed 382 native_window_set_buffers_format(window, 0); 383 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 384 } 385 return EGL_NO_SURFACE; 386} 387 388EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, 389 NativePixmapType pixmap, 390 const EGLint *attrib_list) 391{ 392 clearError(); 393 394 egl_display_t const* dp = 0; 395 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 396 if (cnx) { 397 EGLSurface surface = cnx->egl.eglCreatePixmapSurface( 398 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 399 dp->configs[intptr_t(config)].config, pixmap, attrib_list); 400 if (surface != EGL_NO_SURFACE) { 401 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface, 402 dp->configs[intptr_t(config)].impl, cnx); 403 return s; 404 } 405 } 406 return EGL_NO_SURFACE; 407} 408 409EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, 410 const EGLint *attrib_list) 411{ 412 clearError(); 413 414 egl_display_t const* dp = 0; 415 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 416 if (cnx) { 417 EGLSurface surface = cnx->egl.eglCreatePbufferSurface( 418 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 419 dp->configs[intptr_t(config)].config, attrib_list); 420 if (surface != EGL_NO_SURFACE) { 421 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface, 422 dp->configs[intptr_t(config)].impl, cnx); 423 return s; 424 } 425 } 426 return EGL_NO_SURFACE; 427} 428 429EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) 430{ 431 clearError(); 432 433 egl_display_t const * const dp = validate_display(dpy); 434 if (!dp) return EGL_FALSE; 435 436 SurfaceRef _s(dp, surface); 437 if (!_s.get()) 438 return setError(EGL_BAD_SURFACE, EGL_FALSE); 439 440 egl_surface_t * const s = get_surface(surface); 441 EGLBoolean result = s->cnx->egl.eglDestroySurface( 442 dp->disp[s->impl].dpy, s->surface); 443 if (result == EGL_TRUE) { 444 _s.terminate(); 445 } 446 return result; 447} 448 449EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface, 450 EGLint attribute, EGLint *value) 451{ 452 clearError(); 453 454 egl_display_t const * const dp = validate_display(dpy); 455 if (!dp) return EGL_FALSE; 456 457 SurfaceRef _s(dp, surface); 458 if (!_s.get()) 459 return setError(EGL_BAD_SURFACE, EGL_FALSE); 460 461 egl_surface_t const * const s = get_surface(surface); 462 EGLBoolean result(EGL_TRUE); 463 if (attribute == EGL_CONFIG_ID) { 464 // We need to remap EGL_CONFIG_IDs 465 *value = dp->configs[intptr_t(s->config)].configId; 466 } else { 467 result = s->cnx->egl.eglQuerySurface( 468 dp->disp[s->impl].dpy, s->surface, attribute, value); 469 } 470 471 return result; 472} 473 474// ---------------------------------------------------------------------------- 475// Contexts 476// ---------------------------------------------------------------------------- 477 478EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, 479 EGLContext share_list, const EGLint *attrib_list) 480{ 481 clearError(); 482 483 egl_display_t const* dp = 0; 484 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 485 if (cnx) { 486 if (share_list != EGL_NO_CONTEXT) { 487 egl_context_t* const c = get_context(share_list); 488 share_list = c->context; 489 } 490 EGLContext context = cnx->egl.eglCreateContext( 491 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 492 dp->configs[intptr_t(config)].config, 493 share_list, attrib_list); 494 if (context != EGL_NO_CONTEXT) { 495 // figure out if it's a GLESv1 or GLESv2 496 int version = 0; 497 if (attrib_list) { 498 while (*attrib_list != EGL_NONE) { 499 GLint attr = *attrib_list++; 500 GLint value = *attrib_list++; 501 if (attr == EGL_CONTEXT_CLIENT_VERSION) { 502 if (value == 1) { 503 version = GLESv1_INDEX; 504 } else if (value == 2) { 505 version = GLESv2_INDEX; 506 } 507 } 508 }; 509 } 510 egl_context_t* c = new egl_context_t(dpy, context, config, 511 dp->configs[intptr_t(config)].impl, cnx, version); 512 return c; 513 } 514 } 515 return EGL_NO_CONTEXT; 516} 517 518EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) 519{ 520 clearError(); 521 522 egl_display_t const * const dp = validate_display(dpy); 523 if (!dp) 524 return EGL_FALSE; 525 526 ContextRef _c(dp, ctx); 527 if (!_c.get()) 528 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 529 530 egl_context_t * const c = get_context(ctx); 531 EGLBoolean result = c->cnx->egl.eglDestroyContext( 532 dp->disp[c->impl].dpy, c->context); 533 if (result == EGL_TRUE) { 534 _c.terminate(); 535 } 536 return result; 537} 538 539static void loseCurrent(egl_context_t * cur_c) 540{ 541 if (cur_c) { 542 egl_surface_t * cur_r = get_surface(cur_c->read); 543 egl_surface_t * cur_d = get_surface(cur_c->draw); 544 545 // by construction, these are either 0 or valid (possibly terminated) 546 // it should be impossible for these to be invalid 547 ContextRef _cur_c(cur_c); 548 SurfaceRef _cur_r(cur_r); 549 SurfaceRef _cur_d(cur_d); 550 551 cur_c->read = NULL; 552 cur_c->draw = NULL; 553 554 _cur_c.release(); 555 _cur_r.release(); 556 _cur_d.release(); 557 } 558} 559 560EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, 561 EGLSurface read, EGLContext ctx) 562{ 563 clearError(); 564 565 egl_display_t const * const dp = get_display(dpy); 566 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 567 568 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not 569 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is 570 // a valid but uninitialized display. 571 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) || 572 (draw != EGL_NO_SURFACE) ) { 573 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE); 574 } 575 576 // get a reference to the object passed in 577 ContextRef _c(dp, ctx); 578 SurfaceRef _d(dp, draw); 579 SurfaceRef _r(dp, read); 580 581 // validate the context (if not EGL_NO_CONTEXT) 582 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) { 583 // EGL_NO_CONTEXT is valid 584 return EGL_FALSE; 585 } 586 587 // these are the underlying implementation's object 588 EGLContext impl_ctx = EGL_NO_CONTEXT; 589 EGLSurface impl_draw = EGL_NO_SURFACE; 590 EGLSurface impl_read = EGL_NO_SURFACE; 591 592 // these are our objects structs passed in 593 egl_context_t * c = NULL; 594 egl_surface_t const * d = NULL; 595 egl_surface_t const * r = NULL; 596 597 // these are the current objects structs 598 egl_context_t * cur_c = get_context(getContext()); 599 600 if (ctx != EGL_NO_CONTEXT) { 601 c = get_context(ctx); 602 impl_ctx = c->context; 603 } else { 604 // no context given, use the implementation of the current context 605 if (cur_c == NULL) { 606 // no current context 607 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) { 608 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT); 609 return setError(EGL_BAD_MATCH, EGL_FALSE); 610 } 611 // not an error, there is just no current context. 612 return EGL_TRUE; 613 } 614 } 615 616 // retrieve the underlying implementation's draw EGLSurface 617 if (draw != EGL_NO_SURFACE) { 618 d = get_surface(draw); 619 // make sure the EGLContext and EGLSurface passed in are for 620 // the same driver 621 if (c && d->impl != c->impl) 622 return setError(EGL_BAD_MATCH, EGL_FALSE); 623 impl_draw = d->surface; 624 } 625 626 // retrieve the underlying implementation's read EGLSurface 627 if (read != EGL_NO_SURFACE) { 628 r = get_surface(read); 629 // make sure the EGLContext and EGLSurface passed in are for 630 // the same driver 631 if (c && r->impl != c->impl) 632 return setError(EGL_BAD_MATCH, EGL_FALSE); 633 impl_read = r->surface; 634 } 635 636 EGLBoolean result; 637 638 if (c) { 639 result = c->cnx->egl.eglMakeCurrent( 640 dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx); 641 } else { 642 result = cur_c->cnx->egl.eglMakeCurrent( 643 dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx); 644 } 645 646 if (result == EGL_TRUE) { 647 648 loseCurrent(cur_c); 649 650 if (ctx != EGL_NO_CONTEXT) { 651 setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 652 egl_tls_t::setContext(ctx); 653 if (gEGLDebugLevel > 0) { 654 CreateDbgContext(c->version, c->cnx->hooks[c->version]); 655 } 656 _c.acquire(); 657 _r.acquire(); 658 _d.acquire(); 659 c->read = read; 660 c->draw = draw; 661 } else { 662 setGLHooksThreadSpecific(&gHooksNoContext); 663 egl_tls_t::setContext(EGL_NO_CONTEXT); 664 } 665 } else { 666 // this will LOGE the error 667 result = setError(c->cnx->egl.eglGetError(), EGL_FALSE); 668 } 669 return result; 670} 671 672 673EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, 674 EGLint attribute, EGLint *value) 675{ 676 clearError(); 677 678 egl_display_t const * const dp = validate_display(dpy); 679 if (!dp) return EGL_FALSE; 680 681 ContextRef _c(dp, ctx); 682 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 683 684 egl_context_t * const c = get_context(ctx); 685 686 EGLBoolean result(EGL_TRUE); 687 if (attribute == EGL_CONFIG_ID) { 688 *value = dp->configs[intptr_t(c->config)].configId; 689 } else { 690 // We need to remap EGL_CONFIG_IDs 691 result = c->cnx->egl.eglQueryContext( 692 dp->disp[c->impl].dpy, c->context, attribute, value); 693 } 694 695 return result; 696} 697 698EGLContext eglGetCurrentContext(void) 699{ 700 // could be called before eglInitialize(), but we wouldn't have a context 701 // then, and this function would correctly return EGL_NO_CONTEXT. 702 703 clearError(); 704 705 EGLContext ctx = getContext(); 706 return ctx; 707} 708 709EGLSurface eglGetCurrentSurface(EGLint readdraw) 710{ 711 // could be called before eglInitialize(), but we wouldn't have a context 712 // then, and this function would correctly return EGL_NO_SURFACE. 713 714 clearError(); 715 716 EGLContext ctx = getContext(); 717 if (ctx) { 718 egl_context_t const * const c = get_context(ctx); 719 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 720 switch (readdraw) { 721 case EGL_READ: return c->read; 722 case EGL_DRAW: return c->draw; 723 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 724 } 725 } 726 return EGL_NO_SURFACE; 727} 728 729EGLDisplay eglGetCurrentDisplay(void) 730{ 731 // could be called before eglInitialize(), but we wouldn't have a context 732 // then, and this function would correctly return EGL_NO_DISPLAY. 733 734 clearError(); 735 736 EGLContext ctx = getContext(); 737 if (ctx) { 738 egl_context_t const * const c = get_context(ctx); 739 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 740 return c->dpy; 741 } 742 return EGL_NO_DISPLAY; 743} 744 745EGLBoolean eglWaitGL(void) 746{ 747 // could be called before eglInitialize(), but we wouldn't have a context 748 // then, and this function would return GL_TRUE, which isn't wrong. 749 750 clearError(); 751 752 EGLBoolean res = EGL_TRUE; 753 EGLContext ctx = getContext(); 754 if (ctx) { 755 egl_context_t const * const c = get_context(ctx); 756 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 757 if (uint32_t(c->impl)>=2) 758 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 759 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 760 if (!cnx->dso) 761 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 762 res = cnx->egl.eglWaitGL(); 763 } 764 return res; 765} 766 767EGLBoolean eglWaitNative(EGLint engine) 768{ 769 // could be called before eglInitialize(), but we wouldn't have a context 770 // then, and this function would return GL_TRUE, which isn't wrong. 771 772 clearError(); 773 774 EGLBoolean res = EGL_TRUE; 775 EGLContext ctx = getContext(); 776 if (ctx) { 777 egl_context_t const * const c = get_context(ctx); 778 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 779 if (uint32_t(c->impl)>=2) 780 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 781 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 782 if (!cnx->dso) 783 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 784 res = cnx->egl.eglWaitNative(engine); 785 } 786 return res; 787} 788 789EGLint eglGetError(void) 790{ 791 EGLint result = EGL_SUCCESS; 792 EGLint err; 793 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 794 err = EGL_SUCCESS; 795 egl_connection_t* const cnx = &gEGLImpl[i]; 796 if (cnx->dso) 797 err = cnx->egl.eglGetError(); 798 if (err!=EGL_SUCCESS && result==EGL_SUCCESS) 799 result = err; 800 } 801 err = egl_tls_t::getError(); 802 if (result == EGL_SUCCESS) 803 result = err; 804 return result; 805} 806 807// Note: Similar implementations of these functions also exist in 808// gl2.cpp and gl.cpp, and are used by applications that call the 809// exported entry points directly. 810typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image); 811typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image); 812 813static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_impl = NULL; 814static PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES_impl = NULL; 815 816static void glEGLImageTargetTexture2DOES_wrapper(GLenum target, GLeglImageOES image) 817{ 818 GLeglImageOES implImage = 819 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image); 820 glEGLImageTargetTexture2DOES_impl(target, implImage); 821} 822 823static void glEGLImageTargetRenderbufferStorageOES_wrapper(GLenum target, GLeglImageOES image) 824{ 825 GLeglImageOES implImage = 826 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image); 827 glEGLImageTargetRenderbufferStorageOES_impl(target, implImage); 828} 829 830__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) 831{ 832 // eglGetProcAddress() could be the very first function called 833 // in which case we must make sure we've initialized ourselves, this 834 // happens the first time egl_get_display() is called. 835 836 clearError(); 837 838 if (egl_init_drivers() == EGL_FALSE) { 839 setError(EGL_BAD_PARAMETER, NULL); 840 return NULL; 841 } 842 843 // The EGL_ANDROID_blob_cache extension should not be exposed to 844 // applications. It is used internally by the Android EGL layer. 845 if (!strcmp(procname, "eglSetBlobCacheFuncsANDROID")) { 846 return NULL; 847 } 848 849 __eglMustCastToProperFunctionPointerType addr; 850 addr = findProcAddress(procname, sExtentionMap, NELEM(sExtentionMap)); 851 if (addr) return addr; 852 853 854 // this protects accesses to sGLExtentionMap and sGLExtentionSlot 855 pthread_mutex_lock(&sExtensionMapMutex); 856 857 /* 858 * Since eglGetProcAddress() is not associated to anything, it needs 859 * to return a function pointer that "works" regardless of what 860 * the current context is. 861 * 862 * For this reason, we return a "forwarder", a small stub that takes 863 * care of calling the function associated with the context 864 * currently bound. 865 * 866 * We first look for extensions we've already resolved, if we're seeing 867 * this extension for the first time, we go through all our 868 * implementations and call eglGetProcAddress() and record the 869 * result in the appropriate implementation hooks and return the 870 * address of the forwarder corresponding to that hook set. 871 * 872 */ 873 874 const String8 name(procname); 875 addr = sGLExtentionMap.valueFor(name); 876 const int slot = sGLExtentionSlot; 877 878 LOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS, 879 "no more slots for eglGetProcAddress(\"%s\")", 880 procname); 881 882 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) { 883 bool found = false; 884 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 885 egl_connection_t* const cnx = &gEGLImpl[i]; 886 if (cnx->dso && cnx->egl.eglGetProcAddress) { 887 found = true; 888 // Extensions are independent of the bound context 889 cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] = 890 cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] = 891#if EGL_TRACE 892 gHooksDebug.ext.extensions[slot] = gHooksTrace.ext.extensions[slot] = 893#endif 894 cnx->egl.eglGetProcAddress(procname); 895 } 896 } 897 if (found) { 898 addr = gExtensionForwarders[slot]; 899 900 if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) { 901 glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr; 902 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper; 903 } 904 if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) { 905 glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr; 906 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper; 907 } 908 909 sGLExtentionMap.add(name, addr); 910 sGLExtentionSlot++; 911 } 912 } 913 914 pthread_mutex_unlock(&sExtensionMapMutex); 915 return addr; 916} 917 918EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) 919{ 920 EGLBoolean Debug_eglSwapBuffers(EGLDisplay dpy, EGLSurface draw); 921 if (gEGLDebugLevel > 0) 922 Debug_eglSwapBuffers(dpy, draw); 923 924 clearError(); 925 926 egl_display_t const * const dp = validate_display(dpy); 927 if (!dp) return EGL_FALSE; 928 929 SurfaceRef _s(dp, draw); 930 if (!_s.get()) 931 return setError(EGL_BAD_SURFACE, EGL_FALSE); 932 933 egl_surface_t const * const s = get_surface(draw); 934 return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface); 935} 936 937EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, 938 NativePixmapType target) 939{ 940 clearError(); 941 942 egl_display_t const * const dp = validate_display(dpy); 943 if (!dp) return EGL_FALSE; 944 945 SurfaceRef _s(dp, surface); 946 if (!_s.get()) 947 return setError(EGL_BAD_SURFACE, EGL_FALSE); 948 949 egl_surface_t const * const s = get_surface(surface); 950 return s->cnx->egl.eglCopyBuffers( 951 dp->disp[s->impl].dpy, s->surface, target); 952} 953 954const char* eglQueryString(EGLDisplay dpy, EGLint name) 955{ 956 clearError(); 957 958 egl_display_t const * const dp = validate_display(dpy); 959 if (!dp) return (const char *) NULL; 960 961 switch (name) { 962 case EGL_VENDOR: 963 return dp->getVendorString(); 964 case EGL_VERSION: 965 return dp->getVersionString(); 966 case EGL_EXTENSIONS: 967 return dp->getExtensionString(); 968 case EGL_CLIENT_APIS: 969 return dp->getClientApiString(); 970 } 971 return setError(EGL_BAD_PARAMETER, (const char *)0); 972} 973 974 975// ---------------------------------------------------------------------------- 976// EGL 1.1 977// ---------------------------------------------------------------------------- 978 979EGLBoolean eglSurfaceAttrib( 980 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 981{ 982 clearError(); 983 984 egl_display_t const * const dp = validate_display(dpy); 985 if (!dp) return EGL_FALSE; 986 987 SurfaceRef _s(dp, surface); 988 if (!_s.get()) 989 return setError(EGL_BAD_SURFACE, EGL_FALSE); 990 991 egl_surface_t const * const s = get_surface(surface); 992 if (s->cnx->egl.eglSurfaceAttrib) { 993 return s->cnx->egl.eglSurfaceAttrib( 994 dp->disp[s->impl].dpy, s->surface, attribute, value); 995 } 996 return setError(EGL_BAD_SURFACE, EGL_FALSE); 997} 998 999EGLBoolean eglBindTexImage( 1000 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1001{ 1002 clearError(); 1003 1004 egl_display_t const * const dp = validate_display(dpy); 1005 if (!dp) return EGL_FALSE; 1006 1007 SurfaceRef _s(dp, surface); 1008 if (!_s.get()) 1009 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1010 1011 egl_surface_t const * const s = get_surface(surface); 1012 if (s->cnx->egl.eglBindTexImage) { 1013 return s->cnx->egl.eglBindTexImage( 1014 dp->disp[s->impl].dpy, s->surface, buffer); 1015 } 1016 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1017} 1018 1019EGLBoolean eglReleaseTexImage( 1020 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1021{ 1022 clearError(); 1023 1024 egl_display_t const * const dp = validate_display(dpy); 1025 if (!dp) return EGL_FALSE; 1026 1027 SurfaceRef _s(dp, surface); 1028 if (!_s.get()) 1029 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1030 1031 egl_surface_t const * const s = get_surface(surface); 1032 if (s->cnx->egl.eglReleaseTexImage) { 1033 return s->cnx->egl.eglReleaseTexImage( 1034 dp->disp[s->impl].dpy, s->surface, buffer); 1035 } 1036 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1037} 1038 1039EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 1040{ 1041 clearError(); 1042 1043 egl_display_t const * const dp = validate_display(dpy); 1044 if (!dp) return EGL_FALSE; 1045 1046 EGLBoolean res = EGL_TRUE; 1047 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1048 egl_connection_t* const cnx = &gEGLImpl[i]; 1049 if (cnx->dso) { 1050 if (cnx->egl.eglSwapInterval) { 1051 if (cnx->egl.eglSwapInterval( 1052 dp->disp[i].dpy, interval) == EGL_FALSE) { 1053 res = EGL_FALSE; 1054 } 1055 } 1056 } 1057 } 1058 return res; 1059} 1060 1061 1062// ---------------------------------------------------------------------------- 1063// EGL 1.2 1064// ---------------------------------------------------------------------------- 1065 1066EGLBoolean eglWaitClient(void) 1067{ 1068 clearError(); 1069 1070 // could be called before eglInitialize(), but we wouldn't have a context 1071 // then, and this function would return GL_TRUE, which isn't wrong. 1072 EGLBoolean res = EGL_TRUE; 1073 EGLContext ctx = getContext(); 1074 if (ctx) { 1075 egl_context_t const * const c = get_context(ctx); 1076 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1077 if (uint32_t(c->impl)>=2) 1078 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1079 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 1080 if (!cnx->dso) 1081 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1082 if (cnx->egl.eglWaitClient) { 1083 res = cnx->egl.eglWaitClient(); 1084 } else { 1085 res = cnx->egl.eglWaitGL(); 1086 } 1087 } 1088 return res; 1089} 1090 1091EGLBoolean eglBindAPI(EGLenum api) 1092{ 1093 clearError(); 1094 1095 if (egl_init_drivers() == EGL_FALSE) { 1096 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1097 } 1098 1099 // bind this API on all EGLs 1100 EGLBoolean res = EGL_TRUE; 1101 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1102 egl_connection_t* const cnx = &gEGLImpl[i]; 1103 if (cnx->dso) { 1104 if (cnx->egl.eglBindAPI) { 1105 if (cnx->egl.eglBindAPI(api) == EGL_FALSE) { 1106 res = EGL_FALSE; 1107 } 1108 } 1109 } 1110 } 1111 return res; 1112} 1113 1114EGLenum eglQueryAPI(void) 1115{ 1116 clearError(); 1117 1118 if (egl_init_drivers() == EGL_FALSE) { 1119 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1120 } 1121 1122 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1123 egl_connection_t* const cnx = &gEGLImpl[i]; 1124 if (cnx->dso) { 1125 if (cnx->egl.eglQueryAPI) { 1126 // the first one we find is okay, because they all 1127 // should be the same 1128 return cnx->egl.eglQueryAPI(); 1129 } 1130 } 1131 } 1132 // or, it can only be OpenGL ES 1133 return EGL_OPENGL_ES_API; 1134} 1135 1136EGLBoolean eglReleaseThread(void) 1137{ 1138 clearError(); 1139 1140 // If there is context bound to the thread, release it 1141 loseCurrent(get_context(getContext())); 1142 1143 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1144 egl_connection_t* const cnx = &gEGLImpl[i]; 1145 if (cnx->dso) { 1146 if (cnx->egl.eglReleaseThread) { 1147 cnx->egl.eglReleaseThread(); 1148 } 1149 } 1150 } 1151 egl_tls_t::clearTLS(); 1152 dbgReleaseThread(); 1153 return EGL_TRUE; 1154} 1155 1156EGLSurface eglCreatePbufferFromClientBuffer( 1157 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 1158 EGLConfig config, const EGLint *attrib_list) 1159{ 1160 clearError(); 1161 1162 egl_display_t const* dp = 0; 1163 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 1164 if (!cnx) return EGL_FALSE; 1165 if (cnx->egl.eglCreatePbufferFromClientBuffer) { 1166 return cnx->egl.eglCreatePbufferFromClientBuffer( 1167 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 1168 buftype, buffer, 1169 dp->configs[intptr_t(config)].config, attrib_list); 1170 } 1171 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); 1172} 1173 1174// ---------------------------------------------------------------------------- 1175// EGL_EGLEXT_VERSION 3 1176// ---------------------------------------------------------------------------- 1177 1178EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, 1179 const EGLint *attrib_list) 1180{ 1181 clearError(); 1182 1183 egl_display_t const * const dp = validate_display(dpy); 1184 if (!dp) return EGL_FALSE; 1185 1186 SurfaceRef _s(dp, surface); 1187 if (!_s.get()) 1188 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1189 1190 egl_surface_t const * const s = get_surface(surface); 1191 if (s->cnx->egl.eglLockSurfaceKHR) { 1192 return s->cnx->egl.eglLockSurfaceKHR( 1193 dp->disp[s->impl].dpy, s->surface, attrib_list); 1194 } 1195 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1196} 1197 1198EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) 1199{ 1200 clearError(); 1201 1202 egl_display_t const * const dp = validate_display(dpy); 1203 if (!dp) return EGL_FALSE; 1204 1205 SurfaceRef _s(dp, surface); 1206 if (!_s.get()) 1207 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1208 1209 egl_surface_t const * const s = get_surface(surface); 1210 if (s->cnx->egl.eglUnlockSurfaceKHR) { 1211 return s->cnx->egl.eglUnlockSurfaceKHR( 1212 dp->disp[s->impl].dpy, s->surface); 1213 } 1214 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1215} 1216 1217EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1218 EGLClientBuffer buffer, const EGLint *attrib_list) 1219{ 1220 clearError(); 1221 1222 egl_display_t const * const dp = validate_display(dpy); 1223 if (!dp) return EGL_NO_IMAGE_KHR; 1224 1225 if (ctx != EGL_NO_CONTEXT) { 1226 ContextRef _c(dp, ctx); 1227 if (!_c.get()) 1228 return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR); 1229 egl_context_t * const c = get_context(ctx); 1230 // since we have an EGLContext, we know which implementation to use 1231 EGLImageKHR image = c->cnx->egl.eglCreateImageKHR( 1232 dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list); 1233 if (image == EGL_NO_IMAGE_KHR) 1234 return image; 1235 1236 egl_image_t* result = new egl_image_t(dpy, ctx); 1237 result->images[c->impl] = image; 1238 return (EGLImageKHR)result; 1239 } else { 1240 // EGL_NO_CONTEXT is a valid parameter 1241 1242 /* Since we don't have a way to know which implementation to call, 1243 * we're calling all of them. If at least one of the implementation 1244 * succeeded, this is a success. 1245 */ 1246 1247 EGLint currentError = eglGetError(); 1248 1249 EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS]; 1250 bool success = false; 1251 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1252 egl_connection_t* const cnx = &gEGLImpl[i]; 1253 implImages[i] = EGL_NO_IMAGE_KHR; 1254 if (cnx->dso) { 1255 if (cnx->egl.eglCreateImageKHR) { 1256 implImages[i] = cnx->egl.eglCreateImageKHR( 1257 dp->disp[i].dpy, ctx, target, buffer, attrib_list); 1258 if (implImages[i] != EGL_NO_IMAGE_KHR) { 1259 success = true; 1260 } 1261 } 1262 } 1263 } 1264 1265 if (!success) { 1266 // failure, if there was an error when we entered this function, 1267 // the error flag must not be updated. 1268 // Otherwise, the error is whatever happened in the implementation 1269 // that faulted. 1270 if (currentError != EGL_SUCCESS) { 1271 setError(currentError, EGL_NO_IMAGE_KHR); 1272 } 1273 return EGL_NO_IMAGE_KHR; 1274 } else { 1275 // In case of success, we need to clear all error flags 1276 // (especially those caused by the implementation that didn't 1277 // succeed). TODO: we could avoid this if we knew this was 1278 // a "full" success (all implementation succeeded). 1279 eglGetError(); 1280 } 1281 1282 egl_image_t* result = new egl_image_t(dpy, ctx); 1283 memcpy(result->images, implImages, sizeof(implImages)); 1284 return (EGLImageKHR)result; 1285 } 1286} 1287 1288EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 1289{ 1290 clearError(); 1291 1292 egl_display_t const * const dp = validate_display(dpy); 1293 if (!dp) return EGL_FALSE; 1294 1295 ImageRef _i(dp, img); 1296 if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1297 1298 egl_image_t* image = get_image(img); 1299 bool success = false; 1300 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1301 egl_connection_t* const cnx = &gEGLImpl[i]; 1302 if (image->images[i] != EGL_NO_IMAGE_KHR) { 1303 if (cnx->dso) { 1304 if (cnx->egl.eglDestroyImageKHR) { 1305 if (cnx->egl.eglDestroyImageKHR( 1306 dp->disp[i].dpy, image->images[i])) { 1307 success = true; 1308 } 1309 } 1310 } 1311 } 1312 } 1313 if (!success) 1314 return EGL_FALSE; 1315 1316 _i.terminate(); 1317 1318 return EGL_TRUE; 1319} 1320 1321// ---------------------------------------------------------------------------- 1322// EGL_EGLEXT_VERSION 5 1323// ---------------------------------------------------------------------------- 1324 1325 1326EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) 1327{ 1328 clearError(); 1329 1330 egl_display_t const * const dp = validate_display(dpy); 1331 if (!dp) return EGL_NO_SYNC_KHR; 1332 1333 EGLContext ctx = eglGetCurrentContext(); 1334 ContextRef _c(dp, ctx); 1335 if (!_c.get()) 1336 return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR); 1337 1338 egl_context_t * const c = get_context(ctx); 1339 EGLSyncKHR result = EGL_NO_SYNC_KHR; 1340 if (c->cnx->egl.eglCreateSyncKHR) { 1341 EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR( 1342 dp->disp[c->impl].dpy, type, attrib_list); 1343 if (sync == EGL_NO_SYNC_KHR) 1344 return sync; 1345 result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync); 1346 } 1347 return (EGLSyncKHR)result; 1348} 1349 1350EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) 1351{ 1352 clearError(); 1353 1354 egl_display_t const * const dp = validate_display(dpy); 1355 if (!dp) return EGL_FALSE; 1356 1357 SyncRef _s(dp, sync); 1358 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1359 egl_sync_t* syncObject = get_sync(sync); 1360 1361 EGLContext ctx = syncObject->context; 1362 ContextRef _c(dp, ctx); 1363 if (!_c.get()) 1364 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1365 1366 EGLBoolean result = EGL_FALSE; 1367 egl_context_t * const c = get_context(ctx); 1368 if (c->cnx->egl.eglDestroySyncKHR) { 1369 result = c->cnx->egl.eglDestroySyncKHR( 1370 dp->disp[c->impl].dpy, syncObject->sync); 1371 if (result) 1372 _s.terminate(); 1373 } 1374 return result; 1375} 1376 1377EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout) 1378{ 1379 clearError(); 1380 1381 egl_display_t const * const dp = validate_display(dpy); 1382 if (!dp) return EGL_FALSE; 1383 1384 SyncRef _s(dp, sync); 1385 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1386 egl_sync_t* syncObject = get_sync(sync); 1387 1388 EGLContext ctx = syncObject->context; 1389 ContextRef _c(dp, ctx); 1390 if (!_c.get()) 1391 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1392 1393 egl_context_t * const c = get_context(ctx); 1394 if (c->cnx->egl.eglClientWaitSyncKHR) { 1395 return c->cnx->egl.eglClientWaitSyncKHR( 1396 dp->disp[c->impl].dpy, syncObject->sync, flags, timeout); 1397 } 1398 1399 return EGL_FALSE; 1400} 1401 1402EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value) 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()) 1411 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1412 1413 egl_sync_t* syncObject = get_sync(sync); 1414 EGLContext ctx = syncObject->context; 1415 ContextRef _c(dp, ctx); 1416 if (!_c.get()) 1417 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1418 1419 egl_context_t * const c = get_context(ctx); 1420 if (c->cnx->egl.eglGetSyncAttribKHR) { 1421 return c->cnx->egl.eglGetSyncAttribKHR( 1422 dp->disp[c->impl].dpy, syncObject->sync, attribute, value); 1423 } 1424 1425 return EGL_FALSE; 1426} 1427 1428// ---------------------------------------------------------------------------- 1429// ANDROID extensions 1430// ---------------------------------------------------------------------------- 1431 1432/* ANDROID extensions entry-point go here */ 1433 1434// ---------------------------------------------------------------------------- 1435// NVIDIA extensions 1436// ---------------------------------------------------------------------------- 1437EGLuint64NV eglGetSystemTimeFrequencyNV() 1438{ 1439 clearError(); 1440 1441 if (egl_init_drivers() == EGL_FALSE) { 1442 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1443 } 1444 1445 EGLuint64NV ret = 0; 1446 egl_connection_t* const cnx = &gEGLImpl[IMPL_HARDWARE]; 1447 1448 if (cnx->dso) { 1449 if (cnx->egl.eglGetSystemTimeFrequencyNV) { 1450 return cnx->egl.eglGetSystemTimeFrequencyNV(); 1451 } 1452 } 1453 1454 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1455} 1456 1457EGLuint64NV eglGetSystemTimeNV() 1458{ 1459 clearError(); 1460 1461 if (egl_init_drivers() == EGL_FALSE) { 1462 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1463 } 1464 1465 EGLuint64NV ret = 0; 1466 egl_connection_t* const cnx = &gEGLImpl[IMPL_HARDWARE]; 1467 1468 if (cnx->dso) { 1469 if (cnx->egl.eglGetSystemTimeNV) { 1470 return cnx->egl.eglGetSystemTimeNV(); 1471 } 1472 } 1473 1474 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1475} 1476