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