eglApi.cpp revision 1c3d72a2291827fb15e2ef311a571c860e0dba41
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 __eglMustCastToProperFunctionPointerType addr; 862 addr = findProcAddress(procname, sExtentionMap, NELEM(sExtentionMap)); 863 if (addr) return addr; 864 865 // this protects accesses to sGLExtentionMap and sGLExtentionSlot 866 pthread_mutex_lock(&sExtensionMapMutex); 867 868 /* 869 * Since eglGetProcAddress() is not associated to anything, it needs 870 * to return a function pointer that "works" regardless of what 871 * the current context is. 872 * 873 * For this reason, we return a "forwarder", a small stub that takes 874 * care of calling the function associated with the context 875 * currently bound. 876 * 877 * We first look for extensions we've already resolved, if we're seeing 878 * this extension for the first time, we go through all our 879 * implementations and call eglGetProcAddress() and record the 880 * result in the appropriate implementation hooks and return the 881 * address of the forwarder corresponding to that hook set. 882 * 883 */ 884 885 const String8 name(procname); 886 addr = sGLExtentionMap.valueFor(name); 887 const int slot = sGLExtentionSlot; 888 889 LOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS, 890 "no more slots for eglGetProcAddress(\"%s\")", 891 procname); 892 893 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) { 894 bool found = false; 895 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 896 egl_connection_t* const cnx = &gEGLImpl[i]; 897 if (cnx->dso && cnx->egl.eglGetProcAddress) { 898 found = true; 899 // Extensions are independent of the bound context 900 cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] = 901 cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] = 902#if EGL_TRACE 903 gHooksDebug.ext.extensions[slot] = gHooksTrace.ext.extensions[slot] = 904#endif 905 cnx->egl.eglGetProcAddress(procname); 906 } 907 } 908 if (found) { 909 addr = gExtensionForwarders[slot]; 910 911 if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) { 912 glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr; 913 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper; 914 } 915 if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) { 916 glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr; 917 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper; 918 } 919 920 sGLExtentionMap.add(name, addr); 921 sGLExtentionSlot++; 922 } 923 } 924 925 pthread_mutex_unlock(&sExtensionMapMutex); 926 return addr; 927} 928 929EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) 930{ 931 EGLBoolean Debug_eglSwapBuffers(EGLDisplay dpy, EGLSurface draw); 932 if (gEGLDebugLevel > 0) 933 Debug_eglSwapBuffers(dpy, draw); 934 935 clearError(); 936 937 egl_display_t const * const dp = validate_display(dpy); 938 if (!dp) return EGL_FALSE; 939 940 SurfaceRef _s(draw); 941 if (!_s.get()) 942 return setError(EGL_BAD_SURFACE, EGL_FALSE); 943 944 egl_surface_t const * const s = get_surface(draw); 945 return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface); 946} 947 948EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, 949 NativePixmapType target) 950{ 951 clearError(); 952 953 egl_display_t const * const dp = validate_display(dpy); 954 if (!dp) return EGL_FALSE; 955 956 SurfaceRef _s(surface); 957 if (!_s.get()) 958 return setError(EGL_BAD_SURFACE, EGL_FALSE); 959 960 egl_surface_t const * const s = get_surface(surface); 961 return s->cnx->egl.eglCopyBuffers( 962 dp->disp[s->impl].dpy, s->surface, target); 963} 964 965const char* eglQueryString(EGLDisplay dpy, EGLint name) 966{ 967 clearError(); 968 969 egl_display_t const * const dp = validate_display(dpy); 970 if (!dp) return (const char *) NULL; 971 972 switch (name) { 973 case EGL_VENDOR: 974 return sVendorString; 975 case EGL_VERSION: 976 return sVersionString; 977 case EGL_EXTENSIONS: 978 return sExtensionString; 979 case EGL_CLIENT_APIS: 980 return sClientApiString; 981 } 982 return setError(EGL_BAD_PARAMETER, (const char *)0); 983} 984 985 986// ---------------------------------------------------------------------------- 987// EGL 1.1 988// ---------------------------------------------------------------------------- 989 990EGLBoolean eglSurfaceAttrib( 991 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 992{ 993 clearError(); 994 995 egl_display_t const * const dp = validate_display(dpy); 996 if (!dp) return EGL_FALSE; 997 998 SurfaceRef _s(surface); 999 if (!_s.get()) 1000 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1001 1002 egl_surface_t const * const s = get_surface(surface); 1003 if (s->cnx->egl.eglSurfaceAttrib) { 1004 return s->cnx->egl.eglSurfaceAttrib( 1005 dp->disp[s->impl].dpy, s->surface, attribute, value); 1006 } 1007 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1008} 1009 1010EGLBoolean eglBindTexImage( 1011 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1012{ 1013 clearError(); 1014 1015 egl_display_t const * const dp = validate_display(dpy); 1016 if (!dp) return EGL_FALSE; 1017 1018 SurfaceRef _s(surface); 1019 if (!_s.get()) 1020 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1021 1022 egl_surface_t const * const s = get_surface(surface); 1023 if (s->cnx->egl.eglBindTexImage) { 1024 return s->cnx->egl.eglBindTexImage( 1025 dp->disp[s->impl].dpy, s->surface, buffer); 1026 } 1027 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1028} 1029 1030EGLBoolean eglReleaseTexImage( 1031 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1032{ 1033 clearError(); 1034 1035 egl_display_t const * const dp = validate_display(dpy); 1036 if (!dp) return EGL_FALSE; 1037 1038 SurfaceRef _s(surface); 1039 if (!_s.get()) 1040 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1041 1042 egl_surface_t const * const s = get_surface(surface); 1043 if (s->cnx->egl.eglReleaseTexImage) { 1044 return s->cnx->egl.eglReleaseTexImage( 1045 dp->disp[s->impl].dpy, s->surface, buffer); 1046 } 1047 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1048} 1049 1050EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 1051{ 1052 clearError(); 1053 1054 egl_display_t const * const dp = validate_display(dpy); 1055 if (!dp) return EGL_FALSE; 1056 1057 EGLBoolean res = EGL_TRUE; 1058 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1059 egl_connection_t* const cnx = &gEGLImpl[i]; 1060 if (cnx->dso) { 1061 if (cnx->egl.eglSwapInterval) { 1062 if (cnx->egl.eglSwapInterval( 1063 dp->disp[i].dpy, interval) == EGL_FALSE) { 1064 res = EGL_FALSE; 1065 } 1066 } 1067 } 1068 } 1069 return res; 1070} 1071 1072 1073// ---------------------------------------------------------------------------- 1074// EGL 1.2 1075// ---------------------------------------------------------------------------- 1076 1077EGLBoolean eglWaitClient(void) 1078{ 1079 clearError(); 1080 1081 // could be called before eglInitialize(), but we wouldn't have a context 1082 // then, and this function would return GL_TRUE, which isn't wrong. 1083 EGLBoolean res = EGL_TRUE; 1084 EGLContext ctx = getContext(); 1085 if (ctx) { 1086 egl_context_t const * const c = get_context(ctx); 1087 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1088 if (uint32_t(c->impl)>=2) 1089 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1090 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 1091 if (!cnx->dso) 1092 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1093 if (cnx->egl.eglWaitClient) { 1094 res = cnx->egl.eglWaitClient(); 1095 } else { 1096 res = cnx->egl.eglWaitGL(); 1097 } 1098 } 1099 return res; 1100} 1101 1102EGLBoolean eglBindAPI(EGLenum api) 1103{ 1104 clearError(); 1105 1106 if (egl_init_drivers() == EGL_FALSE) { 1107 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1108 } 1109 1110 // bind this API on all EGLs 1111 EGLBoolean res = EGL_TRUE; 1112 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1113 egl_connection_t* const cnx = &gEGLImpl[i]; 1114 if (cnx->dso) { 1115 if (cnx->egl.eglBindAPI) { 1116 if (cnx->egl.eglBindAPI(api) == EGL_FALSE) { 1117 res = EGL_FALSE; 1118 } 1119 } 1120 } 1121 } 1122 return res; 1123} 1124 1125EGLenum eglQueryAPI(void) 1126{ 1127 clearError(); 1128 1129 if (egl_init_drivers() == EGL_FALSE) { 1130 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1131 } 1132 1133 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1134 egl_connection_t* const cnx = &gEGLImpl[i]; 1135 if (cnx->dso) { 1136 if (cnx->egl.eglQueryAPI) { 1137 // the first one we find is okay, because they all 1138 // should be the same 1139 return cnx->egl.eglQueryAPI(); 1140 } 1141 } 1142 } 1143 // or, it can only be OpenGL ES 1144 return EGL_OPENGL_ES_API; 1145} 1146 1147EGLBoolean eglReleaseThread(void) 1148{ 1149 clearError(); 1150 1151 // If there is context bound to the thread, release it 1152 loseCurrent(get_context(getContext())); 1153 1154 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1155 egl_connection_t* const cnx = &gEGLImpl[i]; 1156 if (cnx->dso) { 1157 if (cnx->egl.eglReleaseThread) { 1158 cnx->egl.eglReleaseThread(); 1159 } 1160 } 1161 } 1162 egl_tls_t::clearTLS(); 1163 dbgReleaseThread(); 1164 return EGL_TRUE; 1165} 1166 1167EGLSurface eglCreatePbufferFromClientBuffer( 1168 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 1169 EGLConfig config, const EGLint *attrib_list) 1170{ 1171 clearError(); 1172 1173 egl_display_t const* dp = 0; 1174 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 1175 if (!cnx) return EGL_FALSE; 1176 if (cnx->egl.eglCreatePbufferFromClientBuffer) { 1177 return cnx->egl.eglCreatePbufferFromClientBuffer( 1178 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 1179 buftype, buffer, 1180 dp->configs[intptr_t(config)].config, attrib_list); 1181 } 1182 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); 1183} 1184 1185// ---------------------------------------------------------------------------- 1186// EGL_EGLEXT_VERSION 3 1187// ---------------------------------------------------------------------------- 1188 1189EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, 1190 const EGLint *attrib_list) 1191{ 1192 clearError(); 1193 1194 egl_display_t const * const dp = validate_display(dpy); 1195 if (!dp) return EGL_FALSE; 1196 1197 SurfaceRef _s(surface); 1198 if (!_s.get()) 1199 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1200 1201 egl_surface_t const * const s = get_surface(surface); 1202 if (s->cnx->egl.eglLockSurfaceKHR) { 1203 return s->cnx->egl.eglLockSurfaceKHR( 1204 dp->disp[s->impl].dpy, s->surface, attrib_list); 1205 } 1206 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1207} 1208 1209EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) 1210{ 1211 clearError(); 1212 1213 egl_display_t const * const dp = validate_display(dpy); 1214 if (!dp) return EGL_FALSE; 1215 1216 SurfaceRef _s(surface); 1217 if (!_s.get()) 1218 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1219 1220 egl_surface_t const * const s = get_surface(surface); 1221 if (s->cnx->egl.eglUnlockSurfaceKHR) { 1222 return s->cnx->egl.eglUnlockSurfaceKHR( 1223 dp->disp[s->impl].dpy, s->surface); 1224 } 1225 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1226} 1227 1228EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1229 EGLClientBuffer buffer, const EGLint *attrib_list) 1230{ 1231 clearError(); 1232 1233 egl_display_t const * const dp = validate_display(dpy); 1234 if (!dp) return EGL_NO_IMAGE_KHR; 1235 1236 if (ctx != EGL_NO_CONTEXT) { 1237 ContextRef _c(ctx); 1238 if (!_c.get()) 1239 return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR); 1240 egl_context_t * const c = get_context(ctx); 1241 // since we have an EGLContext, we know which implementation to use 1242 EGLImageKHR image = c->cnx->egl.eglCreateImageKHR( 1243 dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list); 1244 if (image == EGL_NO_IMAGE_KHR) 1245 return image; 1246 1247 egl_image_t* result = new egl_image_t(dpy, ctx); 1248 result->images[c->impl] = image; 1249 return (EGLImageKHR)result; 1250 } else { 1251 // EGL_NO_CONTEXT is a valid parameter 1252 1253 /* Since we don't have a way to know which implementation to call, 1254 * we're calling all of them. If at least one of the implementation 1255 * succeeded, this is a success. 1256 */ 1257 1258 EGLint currentError = eglGetError(); 1259 1260 EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS]; 1261 bool success = false; 1262 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1263 egl_connection_t* const cnx = &gEGLImpl[i]; 1264 implImages[i] = EGL_NO_IMAGE_KHR; 1265 if (cnx->dso) { 1266 if (cnx->egl.eglCreateImageKHR) { 1267 implImages[i] = cnx->egl.eglCreateImageKHR( 1268 dp->disp[i].dpy, ctx, target, buffer, attrib_list); 1269 if (implImages[i] != EGL_NO_IMAGE_KHR) { 1270 success = true; 1271 } 1272 } 1273 } 1274 } 1275 1276 if (!success) { 1277 // failure, if there was an error when we entered this function, 1278 // the error flag must not be updated. 1279 // Otherwise, the error is whatever happened in the implementation 1280 // that faulted. 1281 if (currentError != EGL_SUCCESS) { 1282 setError(currentError, EGL_NO_IMAGE_KHR); 1283 } 1284 return EGL_NO_IMAGE_KHR; 1285 } else { 1286 // In case of success, we need to clear all error flags 1287 // (especially those caused by the implementation that didn't 1288 // succeed). TODO: we could avoid this if we knew this was 1289 // a "full" success (all implementation succeeded). 1290 eglGetError(); 1291 } 1292 1293 egl_image_t* result = new egl_image_t(dpy, ctx); 1294 memcpy(result->images, implImages, sizeof(implImages)); 1295 return (EGLImageKHR)result; 1296 } 1297} 1298 1299EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 1300{ 1301 clearError(); 1302 1303 egl_display_t const * const dp = validate_display(dpy); 1304 if (!dp) return EGL_FALSE; 1305 1306 ImageRef _i(img); 1307 if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1308 1309 egl_image_t* image = get_image(img); 1310 bool success = false; 1311 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1312 egl_connection_t* const cnx = &gEGLImpl[i]; 1313 if (image->images[i] != EGL_NO_IMAGE_KHR) { 1314 if (cnx->dso) { 1315 if (cnx->egl.eglDestroyImageKHR) { 1316 if (cnx->egl.eglDestroyImageKHR( 1317 dp->disp[i].dpy, image->images[i])) { 1318 success = true; 1319 } 1320 } 1321 } 1322 } 1323 } 1324 if (!success) 1325 return EGL_FALSE; 1326 1327 _i.terminate(); 1328 1329 return EGL_TRUE; 1330} 1331 1332// ---------------------------------------------------------------------------- 1333// EGL_EGLEXT_VERSION 5 1334// ---------------------------------------------------------------------------- 1335 1336 1337EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) 1338{ 1339 clearError(); 1340 1341 egl_display_t const * const dp = validate_display(dpy); 1342 if (!dp) return EGL_NO_SYNC_KHR; 1343 1344 EGLContext ctx = eglGetCurrentContext(); 1345 ContextRef _c(ctx); 1346 if (!_c.get()) 1347 return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR); 1348 1349 egl_context_t * const c = get_context(ctx); 1350 EGLSyncKHR result = EGL_NO_SYNC_KHR; 1351 if (c->cnx->egl.eglCreateSyncKHR) { 1352 EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR( 1353 dp->disp[c->impl].dpy, type, attrib_list); 1354 if (sync == EGL_NO_SYNC_KHR) 1355 return sync; 1356 result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync); 1357 } 1358 return (EGLSyncKHR)result; 1359} 1360 1361EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) 1362{ 1363 clearError(); 1364 1365 egl_display_t const * const dp = validate_display(dpy); 1366 if (!dp) return EGL_FALSE; 1367 1368 SyncRef _s(sync); 1369 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1370 egl_sync_t* syncObject = get_sync(sync); 1371 1372 EGLContext ctx = syncObject->context; 1373 ContextRef _c(ctx); 1374 if (!_c.get()) 1375 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1376 1377 EGLBoolean result = EGL_FALSE; 1378 egl_context_t * const c = get_context(ctx); 1379 if (c->cnx->egl.eglDestroySyncKHR) { 1380 result = c->cnx->egl.eglDestroySyncKHR( 1381 dp->disp[c->impl].dpy, syncObject->sync); 1382 if (result) 1383 _s.terminate(); 1384 } 1385 return result; 1386} 1387 1388EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout) 1389{ 1390 clearError(); 1391 1392 egl_display_t const * const dp = validate_display(dpy); 1393 if (!dp) return EGL_FALSE; 1394 1395 SyncRef _s(sync); 1396 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1397 egl_sync_t* syncObject = get_sync(sync); 1398 1399 EGLContext ctx = syncObject->context; 1400 ContextRef _c(ctx); 1401 if (!_c.get()) 1402 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1403 1404 egl_context_t * const c = get_context(ctx); 1405 if (c->cnx->egl.eglClientWaitSyncKHR) { 1406 return c->cnx->egl.eglClientWaitSyncKHR( 1407 dp->disp[c->impl].dpy, syncObject->sync, flags, timeout); 1408 } 1409 1410 return EGL_FALSE; 1411} 1412 1413EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value) 1414{ 1415 clearError(); 1416 1417 egl_display_t const * const dp = validate_display(dpy); 1418 if (!dp) return EGL_FALSE; 1419 1420 SyncRef _s(sync); 1421 if (!_s.get()) 1422 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1423 1424 egl_sync_t* syncObject = get_sync(sync); 1425 EGLContext ctx = syncObject->context; 1426 ContextRef _c(ctx); 1427 if (!_c.get()) 1428 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1429 1430 egl_context_t * const c = get_context(ctx); 1431 if (c->cnx->egl.eglGetSyncAttribKHR) { 1432 return c->cnx->egl.eglGetSyncAttribKHR( 1433 dp->disp[c->impl].dpy, syncObject->sync, attribute, value); 1434 } 1435 1436 return EGL_FALSE; 1437} 1438 1439// ---------------------------------------------------------------------------- 1440// ANDROID extensions 1441// ---------------------------------------------------------------------------- 1442 1443EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw, 1444 EGLint left, EGLint top, EGLint width, EGLint height) 1445{ 1446 clearError(); 1447 1448 egl_display_t const * const dp = validate_display(dpy); 1449 if (!dp) return EGL_FALSE; 1450 1451 SurfaceRef _s(draw); 1452 if (!_s.get()) 1453 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1454 1455 egl_surface_t const * const s = get_surface(draw); 1456 if (s->cnx->egl.eglSetSwapRectangleANDROID) { 1457 return s->cnx->egl.eglSetSwapRectangleANDROID( 1458 dp->disp[s->impl].dpy, s->surface, left, top, width, height); 1459 } 1460 return setError(EGL_BAD_DISPLAY, NULL); 1461} 1462 1463// ---------------------------------------------------------------------------- 1464// NVIDIA extensions 1465// ---------------------------------------------------------------------------- 1466EGLuint64NV eglGetSystemTimeFrequencyNV() 1467{ 1468 clearError(); 1469 1470 if (egl_init_drivers() == EGL_FALSE) { 1471 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1472 } 1473 1474 EGLuint64NV ret = 0; 1475 egl_connection_t* const cnx = &gEGLImpl[IMPL_HARDWARE]; 1476 1477 if (cnx->dso) { 1478 if (cnx->egl.eglGetSystemTimeFrequencyNV) { 1479 return cnx->egl.eglGetSystemTimeFrequencyNV(); 1480 } 1481 } 1482 1483 return setError(EGL_BAD_DISPLAY, 0);; 1484} 1485 1486EGLuint64NV eglGetSystemTimeNV() 1487{ 1488 clearError(); 1489 1490 if (egl_init_drivers() == EGL_FALSE) { 1491 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1492 } 1493 1494 EGLuint64NV ret = 0; 1495 egl_connection_t* const cnx = &gEGLImpl[IMPL_HARDWARE]; 1496 1497 if (cnx->dso) { 1498 if (cnx->egl.eglGetSystemTimeNV) { 1499 return cnx->egl.eglGetSystemTimeNV(); 1500 } 1501 } 1502 1503 return setError(EGL_BAD_DISPLAY, 0);; 1504} 1505