eglApi.cpp revision 518ec112f468eb67bf681b3eec896d7bfb4ff98d
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 // set the native window's buffers format to match this config 367 if (cnx->egl.eglGetConfigAttrib(iDpy, 368 iConfig, EGL_NATIVE_VISUAL_ID, &format)) { 369 if (format != 0) { 370 native_window_set_buffers_geometry(window, 0, 0, format); 371 } 372 } 373 374 EGLSurface surface = cnx->egl.eglCreateWindowSurface( 375 iDpy, iConfig, window, attrib_list); 376 if (surface != EGL_NO_SURFACE) { 377 egl_surface_t* s = new egl_surface_t(dpy, config, window, surface, 378 dp->configs[intptr_t(config)].impl, cnx); 379 return s; 380 } 381 } 382 return EGL_NO_SURFACE; 383} 384 385EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, 386 NativePixmapType pixmap, 387 const EGLint *attrib_list) 388{ 389 clearError(); 390 391 egl_display_t const* dp = 0; 392 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 393 if (cnx) { 394 EGLSurface surface = cnx->egl.eglCreatePixmapSurface( 395 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 396 dp->configs[intptr_t(config)].config, pixmap, attrib_list); 397 if (surface != EGL_NO_SURFACE) { 398 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface, 399 dp->configs[intptr_t(config)].impl, cnx); 400 return s; 401 } 402 } 403 return EGL_NO_SURFACE; 404} 405 406EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, 407 const EGLint *attrib_list) 408{ 409 clearError(); 410 411 egl_display_t const* dp = 0; 412 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 413 if (cnx) { 414 EGLSurface surface = cnx->egl.eglCreatePbufferSurface( 415 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 416 dp->configs[intptr_t(config)].config, attrib_list); 417 if (surface != EGL_NO_SURFACE) { 418 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface, 419 dp->configs[intptr_t(config)].impl, cnx); 420 return s; 421 } 422 } 423 return EGL_NO_SURFACE; 424} 425 426EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) 427{ 428 clearError(); 429 430 egl_display_t const * const dp = validate_display(dpy); 431 if (!dp) return EGL_FALSE; 432 433 SurfaceRef _s(surface); 434 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 435 436 if (!validate_display_surface(dpy, surface)) 437 return EGL_FALSE; 438 439 egl_surface_t * const s = get_surface(surface); 440 EGLBoolean result = s->cnx->egl.eglDestroySurface( 441 dp->disp[s->impl].dpy, s->surface); 442 if (result == EGL_TRUE) { 443 if (s->win != NULL) { 444 native_window_set_buffers_geometry(s->win.get(), 0, 0, 0); 445 } 446 _s.terminate(); 447 } 448 return result; 449} 450 451EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface, 452 EGLint attribute, EGLint *value) 453{ 454 clearError(); 455 456 egl_display_t const * const dp = validate_display(dpy); 457 if (!dp) return EGL_FALSE; 458 459 SurfaceRef _s(surface); 460 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 461 462 if (!validate_display_surface(dpy, surface)) 463 return EGL_FALSE; 464 egl_surface_t const * const s = get_surface(surface); 465 466 EGLBoolean result(EGL_TRUE); 467 if (attribute == EGL_CONFIG_ID) { 468 // We need to remap EGL_CONFIG_IDs 469 *value = dp->configs[intptr_t(s->config)].configId; 470 } else { 471 result = s->cnx->egl.eglQuerySurface( 472 dp->disp[s->impl].dpy, s->surface, attribute, value); 473 } 474 475 return result; 476} 477 478// ---------------------------------------------------------------------------- 479// Contexts 480// ---------------------------------------------------------------------------- 481 482EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, 483 EGLContext share_list, const EGLint *attrib_list) 484{ 485 clearError(); 486 487 egl_display_t const* dp = 0; 488 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 489 if (cnx) { 490 if (share_list != EGL_NO_CONTEXT) { 491 egl_context_t* const c = get_context(share_list); 492 share_list = c->context; 493 } 494 EGLContext context = cnx->egl.eglCreateContext( 495 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 496 dp->configs[intptr_t(config)].config, 497 share_list, attrib_list); 498 if (context != EGL_NO_CONTEXT) { 499 // figure out if it's a GLESv1 or GLESv2 500 int version = 0; 501 if (attrib_list) { 502 while (*attrib_list != EGL_NONE) { 503 GLint attr = *attrib_list++; 504 GLint value = *attrib_list++; 505 if (attr == EGL_CONTEXT_CLIENT_VERSION) { 506 if (value == 1) { 507 version = GLESv1_INDEX; 508 } else if (value == 2) { 509 version = GLESv2_INDEX; 510 } 511 } 512 }; 513 } 514 egl_context_t* c = new egl_context_t(dpy, context, config, 515 dp->configs[intptr_t(config)].impl, cnx, version); 516 return c; 517 } 518 } 519 return EGL_NO_CONTEXT; 520} 521 522EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) 523{ 524 clearError(); 525 526 egl_display_t const * const dp = validate_display(dpy); 527 if (!dp) return EGL_FALSE; 528 529 ContextRef _c(ctx); 530 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 531 532 if (!validate_display_context(dpy, ctx)) 533 return EGL_FALSE; 534 egl_context_t * const c = get_context(ctx); 535 EGLBoolean result = c->cnx->egl.eglDestroyContext( 536 dp->disp[c->impl].dpy, c->context); 537 if (result == EGL_TRUE) { 538 _c.terminate(); 539 } 540 return result; 541} 542 543static void loseCurrent(egl_context_t * cur_c) 544{ 545 if (cur_c) { 546 egl_surface_t * cur_r = get_surface(cur_c->read); 547 egl_surface_t * cur_d = get_surface(cur_c->draw); 548 549 // by construction, these are either 0 or valid (possibly terminated) 550 // it should be impossible for these to be invalid 551 ContextRef _cur_c(cur_c); 552 SurfaceRef _cur_r(cur_r); 553 SurfaceRef _cur_d(cur_d); 554 555 cur_c->read = NULL; 556 cur_c->draw = NULL; 557 558 _cur_c.release(); 559 _cur_r.release(); 560 _cur_d.release(); 561 } 562} 563 564EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, 565 EGLSurface read, EGLContext ctx) 566{ 567 clearError(); 568 569 egl_display_t const * const dp = get_display(dpy); 570 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 571 572 /* If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not 573 EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is 574 a valid but uninitialized display. */ 575 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) || 576 (draw != EGL_NO_SURFACE) ) { 577 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE); 578 } 579 580 // get a reference to the object passed in 581 ContextRef _c(ctx); 582 SurfaceRef _d(draw); 583 SurfaceRef _r(read); 584 585 // validate the context (if not EGL_NO_CONTEXT) 586 if ((ctx != EGL_NO_CONTEXT) && (!validate_display_context(dpy, ctx))) { 587 // EGL_NO_CONTEXT is valid 588 return EGL_FALSE; 589 } 590 591 // these are the underlying implementation's object 592 EGLContext impl_ctx = EGL_NO_CONTEXT; 593 EGLSurface impl_draw = EGL_NO_SURFACE; 594 EGLSurface impl_read = EGL_NO_SURFACE; 595 596 // these are our objects structs passed in 597 egl_context_t * c = NULL; 598 egl_surface_t const * d = NULL; 599 egl_surface_t const * r = NULL; 600 601 // these are the current objects structs 602 egl_context_t * cur_c = get_context(getContext()); 603 604 if (ctx != EGL_NO_CONTEXT) { 605 c = get_context(ctx); 606 impl_ctx = c->context; 607 } else { 608 // no context given, use the implementation of the current context 609 if (cur_c == NULL) { 610 // no current context 611 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) { 612 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT); 613 return setError(EGL_BAD_MATCH, EGL_FALSE); 614 } 615 // not an error, there is just no current context. 616 return EGL_TRUE; 617 } 618 } 619 620 // retrieve the underlying implementation's draw EGLSurface 621 if (draw != EGL_NO_SURFACE) { 622 d = get_surface(draw); 623 // make sure the EGLContext and EGLSurface passed in are for 624 // the same driver 625 if (c && d->impl != c->impl) 626 return setError(EGL_BAD_MATCH, EGL_FALSE); 627 impl_draw = d->surface; 628 } 629 630 // retrieve the underlying implementation's read EGLSurface 631 if (read != EGL_NO_SURFACE) { 632 r = get_surface(read); 633 // make sure the EGLContext and EGLSurface passed in are for 634 // the same driver 635 if (c && r->impl != c->impl) 636 return setError(EGL_BAD_MATCH, EGL_FALSE); 637 impl_read = r->surface; 638 } 639 640 EGLBoolean result; 641 642 if (c) { 643 result = c->cnx->egl.eglMakeCurrent( 644 dp->disp[c->impl].dpy, impl_draw, impl_read, impl_ctx); 645 } else { 646 result = cur_c->cnx->egl.eglMakeCurrent( 647 dp->disp[cur_c->impl].dpy, impl_draw, impl_read, impl_ctx); 648 } 649 650 if (result == EGL_TRUE) { 651 652 loseCurrent(cur_c); 653 654 if (ctx != EGL_NO_CONTEXT) { 655 setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 656 egl_tls_t::setContext(ctx); 657 if (gEGLDebugLevel > 0) { 658 CreateDbgContext(c->version, c->cnx->hooks[c->version]); 659 } 660 _c.acquire(); 661 _r.acquire(); 662 _d.acquire(); 663 c->read = read; 664 c->draw = draw; 665 } else { 666 setGLHooksThreadSpecific(&gHooksNoContext); 667 egl_tls_t::setContext(EGL_NO_CONTEXT); 668 } 669 } 670 return result; 671} 672 673 674EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, 675 EGLint attribute, EGLint *value) 676{ 677 clearError(); 678 679 egl_display_t const * const dp = validate_display(dpy); 680 if (!dp) return EGL_FALSE; 681 682 ContextRef _c(ctx); 683 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 684 685 if (!validate_display_context(dpy, ctx)) 686 return EGL_FALSE; 687 688 egl_context_t * const c = get_context(ctx); 689 690 EGLBoolean result(EGL_TRUE); 691 if (attribute == EGL_CONFIG_ID) { 692 *value = dp->configs[intptr_t(c->config)].configId; 693 } else { 694 // We need to remap EGL_CONFIG_IDs 695 result = c->cnx->egl.eglQueryContext( 696 dp->disp[c->impl].dpy, c->context, attribute, value); 697 } 698 699 return result; 700} 701 702EGLContext eglGetCurrentContext(void) 703{ 704 // could be called before eglInitialize(), but we wouldn't have a context 705 // then, and this function would correctly return EGL_NO_CONTEXT. 706 707 clearError(); 708 709 EGLContext ctx = getContext(); 710 return ctx; 711} 712 713EGLSurface eglGetCurrentSurface(EGLint readdraw) 714{ 715 // could be called before eglInitialize(), but we wouldn't have a context 716 // then, and this function would correctly return EGL_NO_SURFACE. 717 718 clearError(); 719 720 EGLContext ctx = getContext(); 721 if (ctx) { 722 egl_context_t const * const c = get_context(ctx); 723 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 724 switch (readdraw) { 725 case EGL_READ: return c->read; 726 case EGL_DRAW: return c->draw; 727 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 728 } 729 } 730 return EGL_NO_SURFACE; 731} 732 733EGLDisplay eglGetCurrentDisplay(void) 734{ 735 // could be called before eglInitialize(), but we wouldn't have a context 736 // then, and this function would correctly return EGL_NO_DISPLAY. 737 738 clearError(); 739 740 EGLContext ctx = getContext(); 741 if (ctx) { 742 egl_context_t const * const c = get_context(ctx); 743 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 744 return c->dpy; 745 } 746 return EGL_NO_DISPLAY; 747} 748 749EGLBoolean eglWaitGL(void) 750{ 751 // could be called before eglInitialize(), but we wouldn't have a context 752 // then, and this function would return GL_TRUE, which isn't wrong. 753 754 clearError(); 755 756 EGLBoolean res = EGL_TRUE; 757 EGLContext ctx = getContext(); 758 if (ctx) { 759 egl_context_t const * const c = get_context(ctx); 760 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 761 if (uint32_t(c->impl)>=2) 762 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 763 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 764 if (!cnx->dso) 765 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 766 res = cnx->egl.eglWaitGL(); 767 } 768 return res; 769} 770 771EGLBoolean eglWaitNative(EGLint engine) 772{ 773 // could be called before eglInitialize(), but we wouldn't have a context 774 // then, and this function would return GL_TRUE, which isn't wrong. 775 776 clearError(); 777 778 EGLBoolean res = EGL_TRUE; 779 EGLContext ctx = getContext(); 780 if (ctx) { 781 egl_context_t const * const c = get_context(ctx); 782 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 783 if (uint32_t(c->impl)>=2) 784 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 785 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 786 if (!cnx->dso) 787 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 788 res = cnx->egl.eglWaitNative(engine); 789 } 790 return res; 791} 792 793EGLint eglGetError(void) 794{ 795 EGLint result = EGL_SUCCESS; 796 EGLint err; 797 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 798 err = EGL_SUCCESS; 799 egl_connection_t* const cnx = &gEGLImpl[i]; 800 if (cnx->dso) 801 err = cnx->egl.eglGetError(); 802 if (err!=EGL_SUCCESS && result==EGL_SUCCESS) 803 result = err; 804 } 805 err = egl_tls_t::getError(); 806 if (result == EGL_SUCCESS) 807 result = err; 808 return result; 809} 810 811// Note: Similar implementations of these functions also exist in 812// gl2.cpp and gl.cpp, and are used by applications that call the 813// exported entry points directly. 814typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image); 815typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image); 816 817static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_impl = NULL; 818static PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES_impl = NULL; 819 820static void glEGLImageTargetTexture2DOES_wrapper(GLenum target, GLeglImageOES image) 821{ 822 GLeglImageOES implImage = 823 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image); 824 glEGLImageTargetTexture2DOES_impl(target, implImage); 825} 826 827static void glEGLImageTargetRenderbufferStorageOES_wrapper(GLenum target, GLeglImageOES image) 828{ 829 GLeglImageOES implImage = 830 (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image); 831 glEGLImageTargetRenderbufferStorageOES_impl(target, implImage); 832} 833 834__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) 835{ 836 // eglGetProcAddress() could be the very first function called 837 // in which case we must make sure we've initialized ourselves, this 838 // happens the first time egl_get_display() is called. 839 840 clearError(); 841 842 if (egl_init_drivers() == EGL_FALSE) { 843 setError(EGL_BAD_PARAMETER, NULL); 844 return NULL; 845 } 846 847 __eglMustCastToProperFunctionPointerType addr; 848 addr = findProcAddress(procname, sExtentionMap, NELEM(sExtentionMap)); 849 if (addr) return addr; 850 851 // this protects accesses to sGLExtentionMap and sGLExtentionSlot 852 pthread_mutex_lock(&sExtensionMapMutex); 853 854 /* 855 * Since eglGetProcAddress() is not associated to anything, it needs 856 * to return a function pointer that "works" regardless of what 857 * the current context is. 858 * 859 * For this reason, we return a "forwarder", a small stub that takes 860 * care of calling the function associated with the context 861 * currently bound. 862 * 863 * We first look for extensions we've already resolved, if we're seeing 864 * this extension for the first time, we go through all our 865 * implementations and call eglGetProcAddress() and record the 866 * result in the appropriate implementation hooks and return the 867 * address of the forwarder corresponding to that hook set. 868 * 869 */ 870 871 const String8 name(procname); 872 addr = sGLExtentionMap.valueFor(name); 873 const int slot = sGLExtentionSlot; 874 875 LOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS, 876 "no more slots for eglGetProcAddress(\"%s\")", 877 procname); 878 879 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) { 880 bool found = false; 881 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 882 egl_connection_t* const cnx = &gEGLImpl[i]; 883 if (cnx->dso && cnx->egl.eglGetProcAddress) { 884 found = true; 885 // Extensions are independent of the bound context 886 cnx->hooks[GLESv1_INDEX]->ext.extensions[slot] = 887 cnx->hooks[GLESv2_INDEX]->ext.extensions[slot] = 888#if EGL_TRACE 889 gHooksDebug.ext.extensions[slot] = gHooksTrace.ext.extensions[slot] = 890#endif 891 cnx->egl.eglGetProcAddress(procname); 892 } 893 } 894 if (found) { 895 addr = gExtensionForwarders[slot]; 896 897 if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) { 898 glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr; 899 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper; 900 } 901 if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) { 902 glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr; 903 addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper; 904 } 905 906 sGLExtentionMap.add(name, addr); 907 sGLExtentionSlot++; 908 } 909 } 910 911 pthread_mutex_unlock(&sExtensionMapMutex); 912 return addr; 913} 914 915EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) 916{ 917 EGLBoolean Debug_eglSwapBuffers(EGLDisplay dpy, EGLSurface draw); 918 if (gEGLDebugLevel > 0) 919 Debug_eglSwapBuffers(dpy, draw); 920 921 clearError(); 922 923 egl_display_t const * const dp = validate_display(dpy); 924 if (!dp) return EGL_FALSE; 925 926 SurfaceRef _s(draw); 927 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 928 929 if (!validate_display_surface(dpy, draw)) 930 return EGL_FALSE; 931 egl_surface_t const * const s = get_surface(draw); 932 return s->cnx->egl.eglSwapBuffers(dp->disp[s->impl].dpy, s->surface); 933} 934 935EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, 936 NativePixmapType target) 937{ 938 clearError(); 939 940 egl_display_t const * const dp = validate_display(dpy); 941 if (!dp) return EGL_FALSE; 942 943 SurfaceRef _s(surface); 944 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 945 946 if (!validate_display_surface(dpy, surface)) 947 return EGL_FALSE; 948 egl_surface_t const * const s = get_surface(surface); 949 return s->cnx->egl.eglCopyBuffers( 950 dp->disp[s->impl].dpy, s->surface, target); 951} 952 953const char* eglQueryString(EGLDisplay dpy, EGLint name) 954{ 955 clearError(); 956 957 egl_display_t const * const dp = validate_display(dpy); 958 if (!dp) return (const char *) NULL; 959 960 switch (name) { 961 case EGL_VENDOR: 962 return sVendorString; 963 case EGL_VERSION: 964 return sVersionString; 965 case EGL_EXTENSIONS: 966 return sExtensionString; 967 case EGL_CLIENT_APIS: 968 return sClientApiString; 969 } 970 return setError(EGL_BAD_PARAMETER, (const char *)0); 971} 972 973 974// ---------------------------------------------------------------------------- 975// EGL 1.1 976// ---------------------------------------------------------------------------- 977 978EGLBoolean eglSurfaceAttrib( 979 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 980{ 981 clearError(); 982 983 egl_display_t const * const dp = validate_display(dpy); 984 if (!dp) return EGL_FALSE; 985 986 SurfaceRef _s(surface); 987 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 988 989 if (!validate_display_surface(dpy, surface)) 990 return EGL_FALSE; 991 egl_surface_t const * const s = get_surface(surface); 992 if (s->cnx->egl.eglSurfaceAttrib) { 993 return s->cnx->egl.eglSurfaceAttrib( 994 dp->disp[s->impl].dpy, s->surface, attribute, value); 995 } 996 return setError(EGL_BAD_SURFACE, EGL_FALSE); 997} 998 999EGLBoolean eglBindTexImage( 1000 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1001{ 1002 clearError(); 1003 1004 egl_display_t const * const dp = validate_display(dpy); 1005 if (!dp) return EGL_FALSE; 1006 1007 SurfaceRef _s(surface); 1008 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1009 1010 if (!validate_display_surface(dpy, surface)) 1011 return EGL_FALSE; 1012 egl_surface_t const * const s = get_surface(surface); 1013 if (s->cnx->egl.eglBindTexImage) { 1014 return s->cnx->egl.eglBindTexImage( 1015 dp->disp[s->impl].dpy, s->surface, buffer); 1016 } 1017 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1018} 1019 1020EGLBoolean eglReleaseTexImage( 1021 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1022{ 1023 clearError(); 1024 1025 egl_display_t const * const dp = validate_display(dpy); 1026 if (!dp) return EGL_FALSE; 1027 1028 SurfaceRef _s(surface); 1029 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1030 1031 if (!validate_display_surface(dpy, surface)) 1032 return EGL_FALSE; 1033 egl_surface_t const * const s = get_surface(surface); 1034 if (s->cnx->egl.eglReleaseTexImage) { 1035 return s->cnx->egl.eglReleaseTexImage( 1036 dp->disp[s->impl].dpy, s->surface, buffer); 1037 } 1038 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1039} 1040 1041EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 1042{ 1043 clearError(); 1044 1045 egl_display_t const * const dp = validate_display(dpy); 1046 if (!dp) return EGL_FALSE; 1047 1048 EGLBoolean res = EGL_TRUE; 1049 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1050 egl_connection_t* const cnx = &gEGLImpl[i]; 1051 if (cnx->dso) { 1052 if (cnx->egl.eglSwapInterval) { 1053 if (cnx->egl.eglSwapInterval( 1054 dp->disp[i].dpy, interval) == EGL_FALSE) { 1055 res = EGL_FALSE; 1056 } 1057 } 1058 } 1059 } 1060 return res; 1061} 1062 1063 1064// ---------------------------------------------------------------------------- 1065// EGL 1.2 1066// ---------------------------------------------------------------------------- 1067 1068EGLBoolean eglWaitClient(void) 1069{ 1070 clearError(); 1071 1072 // could be called before eglInitialize(), but we wouldn't have a context 1073 // then, and this function would return GL_TRUE, which isn't wrong. 1074 EGLBoolean res = EGL_TRUE; 1075 EGLContext ctx = getContext(); 1076 if (ctx) { 1077 egl_context_t const * const c = get_context(ctx); 1078 if (!c) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1079 if (uint32_t(c->impl)>=2) 1080 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1081 egl_connection_t* const cnx = &gEGLImpl[c->impl]; 1082 if (!cnx->dso) 1083 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1084 if (cnx->egl.eglWaitClient) { 1085 res = cnx->egl.eglWaitClient(); 1086 } else { 1087 res = cnx->egl.eglWaitGL(); 1088 } 1089 } 1090 return res; 1091} 1092 1093EGLBoolean eglBindAPI(EGLenum api) 1094{ 1095 clearError(); 1096 1097 if (egl_init_drivers() == EGL_FALSE) { 1098 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1099 } 1100 1101 // bind this API on all EGLs 1102 EGLBoolean res = EGL_TRUE; 1103 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1104 egl_connection_t* const cnx = &gEGLImpl[i]; 1105 if (cnx->dso) { 1106 if (cnx->egl.eglBindAPI) { 1107 if (cnx->egl.eglBindAPI(api) == EGL_FALSE) { 1108 res = EGL_FALSE; 1109 } 1110 } 1111 } 1112 } 1113 return res; 1114} 1115 1116EGLenum eglQueryAPI(void) 1117{ 1118 clearError(); 1119 1120 if (egl_init_drivers() == EGL_FALSE) { 1121 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1122 } 1123 1124 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1125 egl_connection_t* const cnx = &gEGLImpl[i]; 1126 if (cnx->dso) { 1127 if (cnx->egl.eglQueryAPI) { 1128 // the first one we find is okay, because they all 1129 // should be the same 1130 return cnx->egl.eglQueryAPI(); 1131 } 1132 } 1133 } 1134 // or, it can only be OpenGL ES 1135 return EGL_OPENGL_ES_API; 1136} 1137 1138EGLBoolean eglReleaseThread(void) 1139{ 1140 clearError(); 1141 1142 // If there is context bound to the thread, release it 1143 loseCurrent(get_context(getContext())); 1144 1145 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1146 egl_connection_t* const cnx = &gEGLImpl[i]; 1147 if (cnx->dso) { 1148 if (cnx->egl.eglReleaseThread) { 1149 cnx->egl.eglReleaseThread(); 1150 } 1151 } 1152 } 1153 egl_tls_t::clearTLS(); 1154 dbgReleaseThread(); 1155 return EGL_TRUE; 1156} 1157 1158EGLSurface eglCreatePbufferFromClientBuffer( 1159 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 1160 EGLConfig config, const EGLint *attrib_list) 1161{ 1162 clearError(); 1163 1164 egl_display_t const* dp = 0; 1165 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 1166 if (!cnx) return EGL_FALSE; 1167 if (cnx->egl.eglCreatePbufferFromClientBuffer) { 1168 return cnx->egl.eglCreatePbufferFromClientBuffer( 1169 dp->disp[ dp->configs[intptr_t(config)].impl ].dpy, 1170 buftype, buffer, 1171 dp->configs[intptr_t(config)].config, attrib_list); 1172 } 1173 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); 1174} 1175 1176// ---------------------------------------------------------------------------- 1177// EGL_EGLEXT_VERSION 3 1178// ---------------------------------------------------------------------------- 1179 1180EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, 1181 const EGLint *attrib_list) 1182{ 1183 clearError(); 1184 1185 egl_display_t const * const dp = validate_display(dpy); 1186 if (!dp) return EGL_FALSE; 1187 1188 SurfaceRef _s(surface); 1189 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1190 1191 if (!validate_display_surface(dpy, surface)) 1192 return EGL_FALSE; 1193 1194 egl_surface_t const * const s = get_surface(surface); 1195 1196 if (s->cnx->egl.eglLockSurfaceKHR) { 1197 return s->cnx->egl.eglLockSurfaceKHR( 1198 dp->disp[s->impl].dpy, s->surface, attrib_list); 1199 } 1200 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1201} 1202 1203EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) 1204{ 1205 clearError(); 1206 1207 egl_display_t const * const dp = validate_display(dpy); 1208 if (!dp) return EGL_FALSE; 1209 1210 SurfaceRef _s(surface); 1211 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1212 1213 if (!validate_display_surface(dpy, surface)) 1214 return EGL_FALSE; 1215 1216 egl_surface_t const * const s = get_surface(surface); 1217 1218 if (s->cnx->egl.eglUnlockSurfaceKHR) { 1219 return s->cnx->egl.eglUnlockSurfaceKHR( 1220 dp->disp[s->impl].dpy, s->surface); 1221 } 1222 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1223} 1224 1225EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1226 EGLClientBuffer buffer, const EGLint *attrib_list) 1227{ 1228 clearError(); 1229 1230 egl_display_t const * const dp = validate_display(dpy); 1231 if (!dp) return EGL_NO_IMAGE_KHR; 1232 1233 if (ctx != EGL_NO_CONTEXT) { 1234 ContextRef _c(ctx); 1235 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR); 1236 if (!validate_display_context(dpy, ctx)) 1237 return EGL_NO_IMAGE_KHR; 1238 egl_context_t * const c = get_context(ctx); 1239 // since we have an EGLContext, we know which implementation to use 1240 EGLImageKHR image = c->cnx->egl.eglCreateImageKHR( 1241 dp->disp[c->impl].dpy, c->context, target, buffer, attrib_list); 1242 if (image == EGL_NO_IMAGE_KHR) 1243 return image; 1244 1245 egl_image_t* result = new egl_image_t(dpy, ctx); 1246 result->images[c->impl] = image; 1247 return (EGLImageKHR)result; 1248 } else { 1249 // EGL_NO_CONTEXT is a valid parameter 1250 1251 /* Since we don't have a way to know which implementation to call, 1252 * we're calling all of them. If at least one of the implementation 1253 * succeeded, this is a success. 1254 */ 1255 1256 EGLint currentError = eglGetError(); 1257 1258 EGLImageKHR implImages[IMPL_NUM_IMPLEMENTATIONS]; 1259 bool success = false; 1260 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1261 egl_connection_t* const cnx = &gEGLImpl[i]; 1262 implImages[i] = EGL_NO_IMAGE_KHR; 1263 if (cnx->dso) { 1264 if (cnx->egl.eglCreateImageKHR) { 1265 implImages[i] = cnx->egl.eglCreateImageKHR( 1266 dp->disp[i].dpy, ctx, target, buffer, attrib_list); 1267 if (implImages[i] != EGL_NO_IMAGE_KHR) { 1268 success = true; 1269 } 1270 } 1271 } 1272 } 1273 1274 if (!success) { 1275 // failure, if there was an error when we entered this function, 1276 // the error flag must not be updated. 1277 // Otherwise, the error is whatever happened in the implementation 1278 // that faulted. 1279 if (currentError != EGL_SUCCESS) { 1280 setError(currentError, EGL_NO_IMAGE_KHR); 1281 } 1282 return EGL_NO_IMAGE_KHR; 1283 } else { 1284 // In case of success, we need to clear all error flags 1285 // (especially those caused by the implementation that didn't 1286 // succeed). TODO: we could avoid this if we knew this was 1287 // a "full" success (all implementation succeeded). 1288 eglGetError(); 1289 } 1290 1291 egl_image_t* result = new egl_image_t(dpy, ctx); 1292 memcpy(result->images, implImages, sizeof(implImages)); 1293 return (EGLImageKHR)result; 1294 } 1295} 1296 1297EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 1298{ 1299 clearError(); 1300 1301 egl_display_t const * const dp = validate_display(dpy); 1302 if (!dp) return EGL_FALSE; 1303 1304 ImageRef _i(img); 1305 if (!_i.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1306 1307 egl_image_t* image = get_image(img); 1308 bool success = false; 1309 for (int i=0 ; i<IMPL_NUM_IMPLEMENTATIONS ; i++) { 1310 egl_connection_t* const cnx = &gEGLImpl[i]; 1311 if (image->images[i] != EGL_NO_IMAGE_KHR) { 1312 if (cnx->dso) { 1313 if (cnx->egl.eglDestroyImageKHR) { 1314 if (cnx->egl.eglDestroyImageKHR( 1315 dp->disp[i].dpy, image->images[i])) { 1316 success = true; 1317 } 1318 } 1319 } 1320 } 1321 } 1322 if (!success) 1323 return EGL_FALSE; 1324 1325 _i.terminate(); 1326 1327 return EGL_TRUE; 1328} 1329 1330// ---------------------------------------------------------------------------- 1331// EGL_EGLEXT_VERSION 5 1332// ---------------------------------------------------------------------------- 1333 1334 1335EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) 1336{ 1337 clearError(); 1338 1339 egl_display_t const * const dp = validate_display(dpy); 1340 if (!dp) return EGL_NO_SYNC_KHR; 1341 1342 EGLContext ctx = eglGetCurrentContext(); 1343 ContextRef _c(ctx); 1344 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_NO_SYNC_KHR); 1345 if (!validate_display_context(dpy, ctx)) 1346 return EGL_NO_SYNC_KHR; 1347 egl_context_t * const c = get_context(ctx); 1348 EGLSyncKHR result = EGL_NO_SYNC_KHR; 1349 if (c->cnx->egl.eglCreateSyncKHR) { 1350 EGLSyncKHR sync = c->cnx->egl.eglCreateSyncKHR( 1351 dp->disp[c->impl].dpy, type, attrib_list); 1352 if (sync == EGL_NO_SYNC_KHR) 1353 return sync; 1354 result = (egl_sync_t*)new egl_sync_t(dpy, ctx, sync); 1355 } 1356 return (EGLSyncKHR)result; 1357} 1358 1359EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) 1360{ 1361 clearError(); 1362 1363 egl_display_t const * const dp = validate_display(dpy); 1364 if (!dp) return EGL_FALSE; 1365 1366 SyncRef _s(sync); 1367 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1368 egl_sync_t* syncObject = get_sync(sync); 1369 1370 EGLContext ctx = syncObject->context; 1371 ContextRef _c(ctx); 1372 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1373 if (!validate_display_context(dpy, ctx)) 1374 return 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()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1401 if (!validate_display_context(dpy, ctx)) 1402 return EGL_FALSE; 1403 1404 egl_context_t * const c = get_context(ctx); 1405 1406 if (c->cnx->egl.eglClientWaitSyncKHR) { 1407 return c->cnx->egl.eglClientWaitSyncKHR( 1408 dp->disp[c->impl].dpy, syncObject->sync, flags, timeout); 1409 } 1410 1411 return EGL_FALSE; 1412} 1413 1414EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value) 1415{ 1416 clearError(); 1417 1418 egl_display_t const * const dp = validate_display(dpy); 1419 if (!dp) return EGL_FALSE; 1420 1421 SyncRef _s(sync); 1422 if (!_s.get()) return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1423 egl_sync_t* syncObject = get_sync(sync); 1424 1425 EGLContext ctx = syncObject->context; 1426 ContextRef _c(ctx); 1427 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1428 if (!validate_display_context(dpy, ctx)) 1429 return EGL_FALSE; 1430 1431 egl_context_t * const c = get_context(ctx); 1432 1433 if (c->cnx->egl.eglGetSyncAttribKHR) { 1434 return c->cnx->egl.eglGetSyncAttribKHR( 1435 dp->disp[c->impl].dpy, syncObject->sync, attribute, value); 1436 } 1437 1438 return EGL_FALSE; 1439} 1440 1441// ---------------------------------------------------------------------------- 1442// ANDROID extensions 1443// ---------------------------------------------------------------------------- 1444 1445EGLBoolean eglSetSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw, 1446 EGLint left, EGLint top, EGLint width, EGLint height) 1447{ 1448 clearError(); 1449 1450 egl_display_t const * const dp = validate_display(dpy); 1451 if (!dp) return EGL_FALSE; 1452 1453 SurfaceRef _s(draw); 1454 if (!_s.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 1455 1456 if (!validate_display_surface(dpy, draw)) 1457 return EGL_FALSE; 1458 egl_surface_t const * const s = get_surface(draw); 1459 if (s->cnx->egl.eglSetSwapRectangleANDROID) { 1460 return s->cnx->egl.eglSetSwapRectangleANDROID( 1461 dp->disp[s->impl].dpy, s->surface, left, top, width, height); 1462 } 1463 return setError(EGL_BAD_DISPLAY, NULL); 1464} 1465