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