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