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