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