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