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