eglApi.cpp revision 0f288fcc9c1b2d23b1cff2f5c59689aef76b77ae
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#define ATRACE_TAG ATRACE_TAG_GRAPHICS 18 19#include <dlfcn.h> 20#include <ctype.h> 21#include <stdlib.h> 22#include <string.h> 23 24#include <hardware/gralloc.h> 25#include <system/window.h> 26 27#include <EGL/egl.h> 28#include <EGL/eglext.h> 29 30#include <cutils/log.h> 31#include <cutils/atomic.h> 32#include <cutils/compiler.h> 33#include <cutils/properties.h> 34#include <cutils/memory.h> 35 36#include <utils/KeyedVector.h> 37#include <utils/SortedVector.h> 38#include <utils/String8.h> 39#include <utils/Trace.h> 40 41#include "../egl_impl.h" 42#include "../glestrace.h" 43#include "../hooks.h" 44 45#include "egl_display.h" 46#include "egl_object.h" 47#include "egl_tls.h" 48#include "egldefs.h" 49 50using namespace android; 51 52// ---------------------------------------------------------------------------- 53 54namespace android { 55 56struct extention_map_t { 57 const char* name; 58 __eglMustCastToProperFunctionPointerType address; 59}; 60 61/* 62 * This is the list of EGL extensions exposed to applications. 63 * 64 * Some of them (gBuiltinExtensionString) are implemented entirely in this EGL 65 * wrapper and are always available. 66 * 67 * The rest (gExtensionString) depend on support in the EGL driver, and are 68 * only available if the driver supports them. However, some of these must be 69 * supported because they are used by the Android system itself; these are 70 * listd as mandatory below and are required by the CDD. The system *assumes* 71 * the mandatory extensions are present and may not function properly if some 72 * are missing. 73 * 74 * NOTE: Both strings MUST have a single space as the last character. 75 */ 76extern char const * const gBuiltinExtensionString = 77 "EGL_KHR_get_all_proc_addresses " 78 "EGL_ANDROID_presentation_time " 79 ; 80extern char const * const gExtensionString = 81 "EGL_KHR_image " // mandatory 82 "EGL_KHR_image_base " // mandatory 83 "EGL_KHR_image_pixmap " 84 "EGL_KHR_lock_surface " 85 "EGL_KHR_gl_colorspace " 86 "EGL_KHR_gl_texture_2D_image " 87 "EGL_KHR_gl_texture_cubemap_image " 88 "EGL_KHR_gl_renderbuffer_image " 89 "EGL_KHR_reusable_sync " 90 "EGL_KHR_fence_sync " 91 "EGL_KHR_create_context " 92 "EGL_EXT_create_context_robustness " 93 "EGL_NV_system_time " 94 "EGL_ANDROID_image_native_buffer " // mandatory 95 "EGL_KHR_wait_sync " // strongly recommended 96 ; 97 98// extensions not exposed to applications but used by the ANDROID system 99// "EGL_ANDROID_blob_cache " // strongly recommended 100// "EGL_IMG_hibernate_process " // optional 101// "EGL_ANDROID_native_fence_sync " // strongly recommended 102// "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1 103// "EGL_ANDROID_recordable " // mandatory 104 105 106/* 107 * EGL Extensions entry-points exposed to 3rd party applications 108 * (keep in sync with gExtensionString above) 109 * 110 */ 111static const extention_map_t sExtensionMap[] = { 112 // EGL_KHR_lock_surface 113 { "eglLockSurfaceKHR", 114 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR }, 115 { "eglUnlockSurfaceKHR", 116 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR }, 117 118 // EGL_KHR_image, EGL_KHR_image_base 119 { "eglCreateImageKHR", 120 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, 121 { "eglDestroyImageKHR", 122 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, 123 124 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync 125 { "eglCreateSyncKHR", 126 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR }, 127 { "eglDestroySyncKHR", 128 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR }, 129 { "eglClientWaitSyncKHR", 130 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR }, 131 { "eglSignalSyncKHR", 132 (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR }, 133 { "eglGetSyncAttribKHR", 134 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR }, 135 136 // EGL_NV_system_time 137 { "eglGetSystemTimeFrequencyNV", 138 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV }, 139 { "eglGetSystemTimeNV", 140 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV }, 141 142 // EGL_KHR_wait_sync 143 { "eglWaitSyncKHR", 144 (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR }, 145 146 // EGL_ANDROID_presentation_time 147 { "eglPresentationTimeANDROID", 148 (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID }, 149}; 150 151/* 152 * These extensions entry-points should not be exposed to applications. 153 * They're used internally by the Android EGL layer. 154 */ 155#define FILTER_EXTENSIONS(procname) \ 156 (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \ 157 !strcmp((procname), "eglHibernateProcessIMG") || \ 158 !strcmp((procname), "eglAwakenProcessIMG") || \ 159 !strcmp((procname), "eglDupNativeFenceFDANDROID")) 160 161 162 163// accesses protected by sExtensionMapMutex 164static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap; 165static int sGLExtentionSlot = 0; 166static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER; 167 168static void(*findProcAddress(const char* name, 169 const extention_map_t* map, size_t n))() { 170 for (uint32_t i=0 ; i<n ; i++) { 171 if (!strcmp(name, map[i].name)) { 172 return map[i].address; 173 } 174 } 175 return NULL; 176} 177 178// ---------------------------------------------------------------------------- 179 180extern void setGLHooksThreadSpecific(gl_hooks_t const *value); 181extern EGLBoolean egl_init_drivers(); 182extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS]; 183extern int getEGLDebugLevel(); 184extern void setEGLDebugLevel(int level); 185extern gl_hooks_t gHooksTrace; 186 187} // namespace android; 188 189 190// ---------------------------------------------------------------------------- 191 192static inline void clearError() { egl_tls_t::clearError(); } 193static inline EGLContext getContext() { return egl_tls_t::getContext(); } 194 195// ---------------------------------------------------------------------------- 196 197EGLDisplay eglGetDisplay(EGLNativeDisplayType display) 198{ 199 clearError(); 200 201 uint32_t index = uint32_t(display); 202 if (index >= NUM_DISPLAYS) { 203 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 204 } 205 206 if (egl_init_drivers() == EGL_FALSE) { 207 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 208 } 209 210 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display); 211 return dpy; 212} 213 214// ---------------------------------------------------------------------------- 215// Initialization 216// ---------------------------------------------------------------------------- 217 218EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) 219{ 220 clearError(); 221 222 egl_display_ptr dp = get_display(dpy); 223 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 224 225 EGLBoolean res = dp->initialize(major, minor); 226 227 return res; 228} 229 230EGLBoolean eglTerminate(EGLDisplay dpy) 231{ 232 // NOTE: don't unload the drivers b/c some APIs can be called 233 // after eglTerminate() has been called. eglTerminate() only 234 // terminates an EGLDisplay, not a EGL itself. 235 236 clearError(); 237 238 egl_display_ptr dp = get_display(dpy); 239 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 240 241 EGLBoolean res = dp->terminate(); 242 243 return res; 244} 245 246// ---------------------------------------------------------------------------- 247// configuration 248// ---------------------------------------------------------------------------- 249 250EGLBoolean eglGetConfigs( EGLDisplay dpy, 251 EGLConfig *configs, 252 EGLint config_size, EGLint *num_config) 253{ 254 clearError(); 255 256 const egl_display_ptr dp = validate_display(dpy); 257 if (!dp) return EGL_FALSE; 258 259 if (num_config==0) { 260 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 261 } 262 263 EGLBoolean res = EGL_FALSE; 264 *num_config = 0; 265 266 egl_connection_t* const cnx = &gEGLImpl; 267 if (cnx->dso) { 268 res = cnx->egl.eglGetConfigs( 269 dp->disp.dpy, configs, config_size, num_config); 270 } 271 272 return res; 273} 274 275EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, 276 EGLConfig *configs, EGLint config_size, 277 EGLint *num_config) 278{ 279 clearError(); 280 281 const egl_display_ptr dp = validate_display(dpy); 282 if (!dp) return EGL_FALSE; 283 284 if (num_config==0) { 285 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 286 } 287 288 EGLBoolean res = EGL_FALSE; 289 *num_config = 0; 290 291 egl_connection_t* const cnx = &gEGLImpl; 292 if (cnx->dso) { 293 if (attrib_list) { 294 char value[PROPERTY_VALUE_MAX]; 295 property_get("debug.egl.force_msaa", value, "false"); 296 297 if (!strcmp(value, "true")) { 298 size_t attribCount = 0; 299 EGLint attrib = attrib_list[0]; 300 301 // Only enable MSAA if the context is OpenGL ES 2.0 and 302 // if no caveat is requested 303 const EGLint *attribRendererable = NULL; 304 const EGLint *attribCaveat = NULL; 305 306 // Count the number of attributes and look for 307 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT 308 while (attrib != EGL_NONE) { 309 attrib = attrib_list[attribCount]; 310 switch (attrib) { 311 case EGL_RENDERABLE_TYPE: 312 attribRendererable = &attrib_list[attribCount]; 313 break; 314 case EGL_CONFIG_CAVEAT: 315 attribCaveat = &attrib_list[attribCount]; 316 break; 317 } 318 attribCount++; 319 } 320 321 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT && 322 (!attribCaveat || attribCaveat[1] != EGL_NONE)) { 323 324 // Insert 2 extra attributes to force-enable MSAA 4x 325 EGLint aaAttribs[attribCount + 4]; 326 aaAttribs[0] = EGL_SAMPLE_BUFFERS; 327 aaAttribs[1] = 1; 328 aaAttribs[2] = EGL_SAMPLES; 329 aaAttribs[3] = 4; 330 331 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint)); 332 333 EGLint numConfigAA; 334 EGLBoolean resAA = cnx->egl.eglChooseConfig( 335 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA); 336 337 if (resAA == EGL_TRUE && numConfigAA > 0) { 338 ALOGD("Enabling MSAA 4x"); 339 *num_config = numConfigAA; 340 return resAA; 341 } 342 } 343 } 344 } 345 346 res = cnx->egl.eglChooseConfig( 347 dp->disp.dpy, attrib_list, configs, config_size, num_config); 348 } 349 return res; 350} 351 352EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, 353 EGLint attribute, EGLint *value) 354{ 355 clearError(); 356 357 egl_connection_t* cnx = NULL; 358 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 359 if (!dp) return EGL_FALSE; 360 361 return cnx->egl.eglGetConfigAttrib( 362 dp->disp.dpy, config, attribute, value); 363} 364 365// ---------------------------------------------------------------------------- 366// surfaces 367// ---------------------------------------------------------------------------- 368 369// The EGL_KHR_gl_colorspace spec hasn't been published yet, so these haven't 370// been added to the Khronos egl.h. 371#define EGL_GL_COLORSPACE_KHR EGL_VG_COLORSPACE 372#define EGL_GL_COLORSPACE_SRGB_KHR EGL_VG_COLORSPACE_sRGB 373#define EGL_GL_COLORSPACE_LINEAR_KHR EGL_VG_COLORSPACE_LINEAR 374 375// Turn linear formats into corresponding sRGB formats when colorspace is 376// EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear 377// formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where 378// the modification isn't possible, the original format is returned. 379static int modifyFormatColorspace(int fmt, EGLint colorspace) { 380 if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) { 381 switch (fmt) { 382 case HAL_PIXEL_FORMAT_sRGB_A_8888: return HAL_PIXEL_FORMAT_RGBA_8888; 383 case HAL_PIXEL_FORMAT_sRGB_X_8888: return HAL_PIXEL_FORMAT_RGBX_8888; 384 } 385 } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) { 386 switch (fmt) { 387 case HAL_PIXEL_FORMAT_RGBA_8888: return HAL_PIXEL_FORMAT_sRGB_A_8888; 388 case HAL_PIXEL_FORMAT_RGBX_8888: return HAL_PIXEL_FORMAT_sRGB_X_8888; 389 } 390 } 391 return fmt; 392} 393 394EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, 395 NativeWindowType window, 396 const EGLint *attrib_list) 397{ 398 clearError(); 399 400 egl_connection_t* cnx = NULL; 401 egl_display_ptr dp = validate_display_connection(dpy, cnx); 402 if (dp) { 403 EGLDisplay iDpy = dp->disp.dpy; 404 405 if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != OK) { 406 ALOGE("EGLNativeWindowType %p already connected to another API", 407 window); 408 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); 409 } 410 411 // Set the native window's buffers format to match what this config requests. 412 // Whether to use sRGB gamma is not part of the EGLconfig, but is part 413 // of our native format. So if sRGB gamma is requested, we have to 414 // modify the EGLconfig's format before setting the native window's 415 // format. 416 417 // by default, just pick RGBA_8888 418 EGLint format = HAL_PIXEL_FORMAT_RGBA_8888; 419 420 EGLint a = 0; 421 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a); 422 if (a > 0) { 423 // alpha-channel requested, there's really only one suitable format 424 format = HAL_PIXEL_FORMAT_RGBA_8888; 425 } else { 426 EGLint r, g, b; 427 r = g = b = 0; 428 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE, &r); 429 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g); 430 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE, &b); 431 EGLint colorDepth = r + g + b; 432 if (colorDepth <= 16) { 433 format = HAL_PIXEL_FORMAT_RGB_565; 434 } else { 435 format = HAL_PIXEL_FORMAT_RGBX_8888; 436 } 437 } 438 439 // now select a corresponding sRGB format if needed 440 if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) { 441 for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) { 442 if (*attr == EGL_GL_COLORSPACE_KHR) { 443 format = modifyFormatColorspace(format, attr[1]); 444 } 445 } 446 } 447 if (format != 0) { 448 int err = native_window_set_buffers_format(window, format); 449 if (err != 0) { 450 ALOGE("error setting native window pixel format: %s (%d)", 451 strerror(-err), err); 452 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 453 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 454 } 455 } 456 457 // the EGL spec requires that a new EGLSurface default to swap interval 458 // 1, so explicitly set that on the window here. 459 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window); 460 anw->setSwapInterval(anw, 1); 461 462 EGLSurface surface = cnx->egl.eglCreateWindowSurface( 463 iDpy, config, window, attrib_list); 464 if (surface != EGL_NO_SURFACE) { 465 egl_surface_t* s = new egl_surface_t(dp.get(), config, window, 466 surface, cnx); 467 return s; 468 } 469 470 // EGLSurface creation failed 471 native_window_set_buffers_format(window, 0); 472 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 473 } 474 return EGL_NO_SURFACE; 475} 476 477EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, 478 NativePixmapType pixmap, 479 const EGLint *attrib_list) 480{ 481 clearError(); 482 483 egl_connection_t* cnx = NULL; 484 egl_display_ptr dp = validate_display_connection(dpy, cnx); 485 if (dp) { 486 EGLSurface surface = cnx->egl.eglCreatePixmapSurface( 487 dp->disp.dpy, config, pixmap, attrib_list); 488 if (surface != EGL_NO_SURFACE) { 489 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, 490 surface, cnx); 491 return s; 492 } 493 } 494 return EGL_NO_SURFACE; 495} 496 497EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, 498 const EGLint *attrib_list) 499{ 500 clearError(); 501 502 egl_connection_t* cnx = NULL; 503 egl_display_ptr dp = validate_display_connection(dpy, cnx); 504 if (dp) { 505 EGLSurface surface = cnx->egl.eglCreatePbufferSurface( 506 dp->disp.dpy, config, attrib_list); 507 if (surface != EGL_NO_SURFACE) { 508 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, 509 surface, cnx); 510 return s; 511 } 512 } 513 return EGL_NO_SURFACE; 514} 515 516EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) 517{ 518 clearError(); 519 520 const egl_display_ptr dp = validate_display(dpy); 521 if (!dp) return EGL_FALSE; 522 523 SurfaceRef _s(dp.get(), surface); 524 if (!_s.get()) 525 return setError(EGL_BAD_SURFACE, EGL_FALSE); 526 527 egl_surface_t * const s = get_surface(surface); 528 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface); 529 if (result == EGL_TRUE) { 530 _s.terminate(); 531 } 532 return result; 533} 534 535EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface, 536 EGLint attribute, EGLint *value) 537{ 538 clearError(); 539 540 const egl_display_ptr dp = validate_display(dpy); 541 if (!dp) return EGL_FALSE; 542 543 SurfaceRef _s(dp.get(), surface); 544 if (!_s.get()) 545 return setError(EGL_BAD_SURFACE, EGL_FALSE); 546 547 egl_surface_t const * const s = get_surface(surface); 548 return s->cnx->egl.eglQuerySurface( 549 dp->disp.dpy, s->surface, attribute, value); 550} 551 552void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) { 553 ATRACE_CALL(); 554 clearError(); 555 556 const egl_display_ptr dp = validate_display(dpy); 557 if (!dp) { 558 return; 559 } 560 561 SurfaceRef _s(dp.get(), surface); 562 if (!_s.get()) { 563 setError(EGL_BAD_SURFACE, EGL_FALSE); 564 return; 565 } 566} 567 568// ---------------------------------------------------------------------------- 569// Contexts 570// ---------------------------------------------------------------------------- 571 572EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, 573 EGLContext share_list, const EGLint *attrib_list) 574{ 575 clearError(); 576 577 egl_connection_t* cnx = NULL; 578 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 579 if (dp) { 580 if (share_list != EGL_NO_CONTEXT) { 581 if (!ContextRef(dp.get(), share_list).get()) { 582 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT); 583 } 584 egl_context_t* const c = get_context(share_list); 585 share_list = c->context; 586 } 587 EGLContext context = cnx->egl.eglCreateContext( 588 dp->disp.dpy, config, share_list, attrib_list); 589 if (context != EGL_NO_CONTEXT) { 590 // figure out if it's a GLESv1 or GLESv2 591 int version = 0; 592 if (attrib_list) { 593 while (*attrib_list != EGL_NONE) { 594 GLint attr = *attrib_list++; 595 GLint value = *attrib_list++; 596 if (attr == EGL_CONTEXT_CLIENT_VERSION) { 597 if (value == 1) { 598 version = egl_connection_t::GLESv1_INDEX; 599 } else if (value == 2 || value == 3) { 600 version = egl_connection_t::GLESv2_INDEX; 601 } 602 } 603 }; 604 } 605 egl_context_t* c = new egl_context_t(dpy, context, config, cnx, 606 version); 607#if EGL_TRACE 608 if (getEGLDebugLevel() > 0) 609 GLTrace_eglCreateContext(version, c); 610#endif 611 return c; 612 } 613 } 614 return EGL_NO_CONTEXT; 615} 616 617EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) 618{ 619 clearError(); 620 621 const egl_display_ptr dp = validate_display(dpy); 622 if (!dp) 623 return EGL_FALSE; 624 625 ContextRef _c(dp.get(), ctx); 626 if (!_c.get()) 627 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 628 629 egl_context_t * const c = get_context(ctx); 630 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context); 631 if (result == EGL_TRUE) { 632 _c.terminate(); 633 } 634 return result; 635} 636 637EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, 638 EGLSurface read, EGLContext ctx) 639{ 640 clearError(); 641 642 egl_display_ptr dp = validate_display(dpy); 643 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 644 645 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not 646 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is 647 // a valid but uninitialized display. 648 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) || 649 (draw != EGL_NO_SURFACE) ) { 650 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE); 651 } 652 653 // get a reference to the object passed in 654 ContextRef _c(dp.get(), ctx); 655 SurfaceRef _d(dp.get(), draw); 656 SurfaceRef _r(dp.get(), read); 657 658 // validate the context (if not EGL_NO_CONTEXT) 659 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) { 660 // EGL_NO_CONTEXT is valid 661 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 662 } 663 664 // these are the underlying implementation's object 665 EGLContext impl_ctx = EGL_NO_CONTEXT; 666 EGLSurface impl_draw = EGL_NO_SURFACE; 667 EGLSurface impl_read = EGL_NO_SURFACE; 668 669 // these are our objects structs passed in 670 egl_context_t * c = NULL; 671 egl_surface_t const * d = NULL; 672 egl_surface_t const * r = NULL; 673 674 // these are the current objects structs 675 egl_context_t * cur_c = get_context(getContext()); 676 677 if (ctx != EGL_NO_CONTEXT) { 678 c = get_context(ctx); 679 impl_ctx = c->context; 680 } else { 681 // no context given, use the implementation of the current context 682 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) { 683 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT); 684 return setError(EGL_BAD_MATCH, EGL_FALSE); 685 } 686 if (cur_c == NULL) { 687 // no current context 688 // not an error, there is just no current context. 689 return EGL_TRUE; 690 } 691 } 692 693 // retrieve the underlying implementation's draw EGLSurface 694 if (draw != EGL_NO_SURFACE) { 695 if (!_d.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 696 d = get_surface(draw); 697 impl_draw = d->surface; 698 } 699 700 // retrieve the underlying implementation's read EGLSurface 701 if (read != EGL_NO_SURFACE) { 702 if (!_r.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 703 r = get_surface(read); 704 impl_read = r->surface; 705 } 706 707 708 EGLBoolean result = dp->makeCurrent(c, cur_c, 709 draw, read, ctx, 710 impl_draw, impl_read, impl_ctx); 711 712 if (result == EGL_TRUE) { 713 if (c) { 714 setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 715 egl_tls_t::setContext(ctx); 716#if EGL_TRACE 717 if (getEGLDebugLevel() > 0) 718 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx); 719#endif 720 _c.acquire(); 721 _r.acquire(); 722 _d.acquire(); 723 } else { 724 setGLHooksThreadSpecific(&gHooksNoContext); 725 egl_tls_t::setContext(EGL_NO_CONTEXT); 726 } 727 } else { 728 // this will ALOGE the error 729 result = setError(c->cnx->egl.eglGetError(), EGL_FALSE); 730 } 731 return result; 732} 733 734 735EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, 736 EGLint attribute, EGLint *value) 737{ 738 clearError(); 739 740 const egl_display_ptr dp = validate_display(dpy); 741 if (!dp) return EGL_FALSE; 742 743 ContextRef _c(dp.get(), ctx); 744 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 745 746 egl_context_t * const c = get_context(ctx); 747 return c->cnx->egl.eglQueryContext( 748 dp->disp.dpy, c->context, attribute, value); 749 750} 751 752EGLContext eglGetCurrentContext(void) 753{ 754 // could be called before eglInitialize(), but we wouldn't have a context 755 // then, and this function would correctly return EGL_NO_CONTEXT. 756 757 clearError(); 758 759 EGLContext ctx = getContext(); 760 return ctx; 761} 762 763EGLSurface eglGetCurrentSurface(EGLint readdraw) 764{ 765 // could be called before eglInitialize(), but we wouldn't have a context 766 // then, and this function would correctly return EGL_NO_SURFACE. 767 768 clearError(); 769 770 EGLContext ctx = getContext(); 771 if (ctx) { 772 egl_context_t const * const c = get_context(ctx); 773 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 774 switch (readdraw) { 775 case EGL_READ: return c->read; 776 case EGL_DRAW: return c->draw; 777 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 778 } 779 } 780 return EGL_NO_SURFACE; 781} 782 783EGLDisplay eglGetCurrentDisplay(void) 784{ 785 // could be called before eglInitialize(), but we wouldn't have a context 786 // then, and this function would correctly return EGL_NO_DISPLAY. 787 788 clearError(); 789 790 EGLContext ctx = getContext(); 791 if (ctx) { 792 egl_context_t const * const c = get_context(ctx); 793 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 794 return c->dpy; 795 } 796 return EGL_NO_DISPLAY; 797} 798 799EGLBoolean eglWaitGL(void) 800{ 801 clearError(); 802 803 egl_connection_t* const cnx = &gEGLImpl; 804 if (!cnx->dso) 805 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 806 807 return cnx->egl.eglWaitGL(); 808} 809 810EGLBoolean eglWaitNative(EGLint engine) 811{ 812 clearError(); 813 814 egl_connection_t* const cnx = &gEGLImpl; 815 if (!cnx->dso) 816 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 817 818 return cnx->egl.eglWaitNative(engine); 819} 820 821EGLint eglGetError(void) 822{ 823 EGLint err = EGL_SUCCESS; 824 egl_connection_t* const cnx = &gEGLImpl; 825 if (cnx->dso) { 826 err = cnx->egl.eglGetError(); 827 } 828 if (err == EGL_SUCCESS) { 829 err = egl_tls_t::getError(); 830 } 831 return err; 832} 833 834static __eglMustCastToProperFunctionPointerType findBuiltinGLWrapper( 835 const char* procname) { 836 const egl_connection_t* cnx = &gEGLImpl; 837 void* proc = NULL; 838 839 proc = dlsym(cnx->libGles2, procname); 840 if (proc) return (__eglMustCastToProperFunctionPointerType)proc; 841 842 proc = dlsym(cnx->libGles1, procname); 843 if (proc) return (__eglMustCastToProperFunctionPointerType)proc; 844 845 return NULL; 846} 847 848__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) 849{ 850 // eglGetProcAddress() could be the very first function called 851 // in which case we must make sure we've initialized ourselves, this 852 // happens the first time egl_get_display() is called. 853 854 clearError(); 855 856 if (egl_init_drivers() == EGL_FALSE) { 857 setError(EGL_BAD_PARAMETER, NULL); 858 return NULL; 859 } 860 861 if (FILTER_EXTENSIONS(procname)) { 862 return NULL; 863 } 864 865 __eglMustCastToProperFunctionPointerType addr; 866 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap)); 867 if (addr) return addr; 868 869 addr = findBuiltinGLWrapper(procname); 870 if (addr) return addr; 871 872 // this protects accesses to sGLExtentionMap and sGLExtentionSlot 873 pthread_mutex_lock(&sExtensionMapMutex); 874 875 /* 876 * Since eglGetProcAddress() is not associated to anything, it needs 877 * to return a function pointer that "works" regardless of what 878 * the current context is. 879 * 880 * For this reason, we return a "forwarder", a small stub that takes 881 * care of calling the function associated with the context 882 * currently bound. 883 * 884 * We first look for extensions we've already resolved, if we're seeing 885 * this extension for the first time, we go through all our 886 * implementations and call eglGetProcAddress() and record the 887 * result in the appropriate implementation hooks and return the 888 * address of the forwarder corresponding to that hook set. 889 * 890 */ 891 892 const String8 name(procname); 893 addr = sGLExtentionMap.valueFor(name); 894 const int slot = sGLExtentionSlot; 895 896 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS, 897 "no more slots for eglGetProcAddress(\"%s\")", 898 procname); 899 900#if EGL_TRACE 901 gl_hooks_t *debugHooks = GLTrace_getGLHooks(); 902#endif 903 904 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) { 905 bool found = false; 906 907 egl_connection_t* const cnx = &gEGLImpl; 908 if (cnx->dso && cnx->egl.eglGetProcAddress) { 909 // Extensions are independent of the bound context 910 addr = 911 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] = 912 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] = 913#if EGL_TRACE 914 debugHooks->ext.extensions[slot] = 915 gHooksTrace.ext.extensions[slot] = 916#endif 917 cnx->egl.eglGetProcAddress(procname); 918 if (addr) found = true; 919 } 920 921 if (found) { 922 addr = gExtensionForwarders[slot]; 923 sGLExtentionMap.add(name, addr); 924 sGLExtentionSlot++; 925 } 926 } 927 928 pthread_mutex_unlock(&sExtensionMapMutex); 929 return addr; 930} 931 932class FrameCompletionThread : public Thread { 933public: 934 935 static void queueSync(EGLSyncKHR sync) { 936 static sp<FrameCompletionThread> thread(new FrameCompletionThread); 937 static bool running = false; 938 if (!running) { 939 thread->run("GPUFrameCompletion"); 940 running = true; 941 } 942 { 943 Mutex::Autolock lock(thread->mMutex); 944 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d", 945 thread->mFramesQueued).string()); 946 thread->mQueue.push_back(sync); 947 thread->mCondition.signal(); 948 thread->mFramesQueued++; 949 ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size()); 950 } 951 } 952 953private: 954 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {} 955 956 virtual bool threadLoop() { 957 EGLSyncKHR sync; 958 uint32_t frameNum; 959 { 960 Mutex::Autolock lock(mMutex); 961 while (mQueue.isEmpty()) { 962 mCondition.wait(mMutex); 963 } 964 sync = mQueue[0]; 965 frameNum = mFramesCompleted; 966 } 967 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); 968 { 969 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d", 970 frameNum).string()); 971 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR); 972 if (result == EGL_FALSE) { 973 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError()); 974 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { 975 ALOGE("FrameCompletion: timeout waiting for fence"); 976 } 977 eglDestroySyncKHR(dpy, sync); 978 } 979 { 980 Mutex::Autolock lock(mMutex); 981 mQueue.removeAt(0); 982 mFramesCompleted++; 983 ATRACE_INT("GPU Frames Outstanding", mQueue.size()); 984 } 985 return true; 986 } 987 988 uint32_t mFramesQueued; 989 uint32_t mFramesCompleted; 990 Vector<EGLSyncKHR> mQueue; 991 Condition mCondition; 992 Mutex mMutex; 993}; 994 995EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) 996{ 997 ATRACE_CALL(); 998 clearError(); 999 1000 const egl_display_ptr dp = validate_display(dpy); 1001 if (!dp) return EGL_FALSE; 1002 1003 SurfaceRef _s(dp.get(), draw); 1004 if (!_s.get()) 1005 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1006 1007#if EGL_TRACE 1008 gl_hooks_t const *trace_hooks = getGLTraceThreadSpecific(); 1009 if (getEGLDebugLevel() > 0) { 1010 if (trace_hooks == NULL) { 1011 if (GLTrace_start() < 0) { 1012 ALOGE("Disabling Tracer for OpenGL ES"); 1013 setEGLDebugLevel(0); 1014 } else { 1015 // switch over to the trace version of hooks 1016 EGLContext ctx = egl_tls_t::getContext(); 1017 egl_context_t * const c = get_context(ctx); 1018 if (c) { 1019 setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 1020 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx); 1021 } 1022 } 1023 } 1024 1025 GLTrace_eglSwapBuffers(dpy, draw); 1026 } else if (trace_hooks != NULL) { 1027 // tracing is now disabled, so switch back to the non trace version 1028 EGLContext ctx = egl_tls_t::getContext(); 1029 egl_context_t * const c = get_context(ctx); 1030 if (c) setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 1031 GLTrace_stop(); 1032 } 1033#endif 1034 1035 egl_surface_t const * const s = get_surface(draw); 1036 1037 if (CC_UNLIKELY(dp->traceGpuCompletion)) { 1038 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL); 1039 if (sync != EGL_NO_SYNC_KHR) { 1040 FrameCompletionThread::queueSync(sync); 1041 } 1042 } 1043 1044 if (CC_UNLIKELY(dp->finishOnSwap)) { 1045 uint32_t pixel; 1046 egl_context_t * const c = get_context( egl_tls_t::getContext() ); 1047 if (c) { 1048 // glReadPixels() ensures that the frame is complete 1049 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1, 1050 GL_RGBA,GL_UNSIGNED_BYTE,&pixel); 1051 } 1052 } 1053 1054 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface); 1055} 1056 1057EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, 1058 NativePixmapType target) 1059{ 1060 clearError(); 1061 1062 const egl_display_ptr dp = validate_display(dpy); 1063 if (!dp) return EGL_FALSE; 1064 1065 SurfaceRef _s(dp.get(), surface); 1066 if (!_s.get()) 1067 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1068 1069 egl_surface_t const * const s = get_surface(surface); 1070 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target); 1071} 1072 1073const char* eglQueryString(EGLDisplay dpy, EGLint name) 1074{ 1075 clearError(); 1076 1077 const egl_display_ptr dp = validate_display(dpy); 1078 if (!dp) return (const char *) NULL; 1079 1080 switch (name) { 1081 case EGL_VENDOR: 1082 return dp->getVendorString(); 1083 case EGL_VERSION: 1084 return dp->getVersionString(); 1085 case EGL_EXTENSIONS: 1086 return dp->getExtensionString(); 1087 case EGL_CLIENT_APIS: 1088 return dp->getClientApiString(); 1089 } 1090 return setError(EGL_BAD_PARAMETER, (const char *)0); 1091} 1092 1093EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name) 1094{ 1095 clearError(); 1096 1097 const egl_display_ptr dp = validate_display(dpy); 1098 if (!dp) return (const char *) NULL; 1099 1100 switch (name) { 1101 case EGL_VENDOR: 1102 return dp->disp.queryString.vendor; 1103 case EGL_VERSION: 1104 return dp->disp.queryString.version; 1105 case EGL_EXTENSIONS: 1106 return dp->disp.queryString.extensions; 1107 case EGL_CLIENT_APIS: 1108 return dp->disp.queryString.clientApi; 1109 } 1110 return setError(EGL_BAD_PARAMETER, (const char *)0); 1111} 1112 1113// ---------------------------------------------------------------------------- 1114// EGL 1.1 1115// ---------------------------------------------------------------------------- 1116 1117EGLBoolean eglSurfaceAttrib( 1118 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 1119{ 1120 clearError(); 1121 1122 const egl_display_ptr dp = validate_display(dpy); 1123 if (!dp) return EGL_FALSE; 1124 1125 SurfaceRef _s(dp.get(), surface); 1126 if (!_s.get()) 1127 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1128 1129 egl_surface_t const * const s = get_surface(surface); 1130 if (s->cnx->egl.eglSurfaceAttrib) { 1131 return s->cnx->egl.eglSurfaceAttrib( 1132 dp->disp.dpy, s->surface, attribute, value); 1133 } 1134 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1135} 1136 1137EGLBoolean eglBindTexImage( 1138 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1139{ 1140 clearError(); 1141 1142 const egl_display_ptr dp = validate_display(dpy); 1143 if (!dp) return EGL_FALSE; 1144 1145 SurfaceRef _s(dp.get(), surface); 1146 if (!_s.get()) 1147 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1148 1149 egl_surface_t const * const s = get_surface(surface); 1150 if (s->cnx->egl.eglBindTexImage) { 1151 return s->cnx->egl.eglBindTexImage( 1152 dp->disp.dpy, s->surface, buffer); 1153 } 1154 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1155} 1156 1157EGLBoolean eglReleaseTexImage( 1158 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1159{ 1160 clearError(); 1161 1162 const egl_display_ptr dp = validate_display(dpy); 1163 if (!dp) return EGL_FALSE; 1164 1165 SurfaceRef _s(dp.get(), surface); 1166 if (!_s.get()) 1167 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1168 1169 egl_surface_t const * const s = get_surface(surface); 1170 if (s->cnx->egl.eglReleaseTexImage) { 1171 return s->cnx->egl.eglReleaseTexImage( 1172 dp->disp.dpy, s->surface, buffer); 1173 } 1174 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1175} 1176 1177EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 1178{ 1179 clearError(); 1180 1181 const egl_display_ptr dp = validate_display(dpy); 1182 if (!dp) return EGL_FALSE; 1183 1184 EGLBoolean res = EGL_TRUE; 1185 egl_connection_t* const cnx = &gEGLImpl; 1186 if (cnx->dso && cnx->egl.eglSwapInterval) { 1187 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval); 1188 } 1189 1190 return res; 1191} 1192 1193 1194// ---------------------------------------------------------------------------- 1195// EGL 1.2 1196// ---------------------------------------------------------------------------- 1197 1198EGLBoolean eglWaitClient(void) 1199{ 1200 clearError(); 1201 1202 egl_connection_t* const cnx = &gEGLImpl; 1203 if (!cnx->dso) 1204 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1205 1206 EGLBoolean res; 1207 if (cnx->egl.eglWaitClient) { 1208 res = cnx->egl.eglWaitClient(); 1209 } else { 1210 res = cnx->egl.eglWaitGL(); 1211 } 1212 return res; 1213} 1214 1215EGLBoolean eglBindAPI(EGLenum api) 1216{ 1217 clearError(); 1218 1219 if (egl_init_drivers() == EGL_FALSE) { 1220 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1221 } 1222 1223 // bind this API on all EGLs 1224 EGLBoolean res = EGL_TRUE; 1225 egl_connection_t* const cnx = &gEGLImpl; 1226 if (cnx->dso && cnx->egl.eglBindAPI) { 1227 res = cnx->egl.eglBindAPI(api); 1228 } 1229 return res; 1230} 1231 1232EGLenum eglQueryAPI(void) 1233{ 1234 clearError(); 1235 1236 if (egl_init_drivers() == EGL_FALSE) { 1237 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1238 } 1239 1240 egl_connection_t* const cnx = &gEGLImpl; 1241 if (cnx->dso && cnx->egl.eglQueryAPI) { 1242 return cnx->egl.eglQueryAPI(); 1243 } 1244 1245 // or, it can only be OpenGL ES 1246 return EGL_OPENGL_ES_API; 1247} 1248 1249EGLBoolean eglReleaseThread(void) 1250{ 1251 clearError(); 1252 1253#if EGL_TRACE 1254 if (getEGLDebugLevel() > 0) 1255 GLTrace_eglReleaseThread(); 1256#endif 1257 1258 // If there is context bound to the thread, release it 1259 egl_display_t::loseCurrent(get_context(getContext())); 1260 1261 egl_connection_t* const cnx = &gEGLImpl; 1262 if (cnx->dso && cnx->egl.eglReleaseThread) { 1263 cnx->egl.eglReleaseThread(); 1264 } 1265 egl_tls_t::clearTLS(); 1266 return EGL_TRUE; 1267} 1268 1269EGLSurface eglCreatePbufferFromClientBuffer( 1270 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 1271 EGLConfig config, const EGLint *attrib_list) 1272{ 1273 clearError(); 1274 1275 egl_connection_t* cnx = NULL; 1276 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 1277 if (!dp) return EGL_FALSE; 1278 if (cnx->egl.eglCreatePbufferFromClientBuffer) { 1279 return cnx->egl.eglCreatePbufferFromClientBuffer( 1280 dp->disp.dpy, buftype, buffer, config, attrib_list); 1281 } 1282 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); 1283} 1284 1285// ---------------------------------------------------------------------------- 1286// EGL_EGLEXT_VERSION 3 1287// ---------------------------------------------------------------------------- 1288 1289EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, 1290 const EGLint *attrib_list) 1291{ 1292 clearError(); 1293 1294 const egl_display_ptr dp = validate_display(dpy); 1295 if (!dp) return EGL_FALSE; 1296 1297 SurfaceRef _s(dp.get(), surface); 1298 if (!_s.get()) 1299 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1300 1301 egl_surface_t const * const s = get_surface(surface); 1302 if (s->cnx->egl.eglLockSurfaceKHR) { 1303 return s->cnx->egl.eglLockSurfaceKHR( 1304 dp->disp.dpy, s->surface, attrib_list); 1305 } 1306 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1307} 1308 1309EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) 1310{ 1311 clearError(); 1312 1313 const egl_display_ptr dp = validate_display(dpy); 1314 if (!dp) return EGL_FALSE; 1315 1316 SurfaceRef _s(dp.get(), surface); 1317 if (!_s.get()) 1318 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1319 1320 egl_surface_t const * const s = get_surface(surface); 1321 if (s->cnx->egl.eglUnlockSurfaceKHR) { 1322 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface); 1323 } 1324 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1325} 1326 1327EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1328 EGLClientBuffer buffer, const EGLint *attrib_list) 1329{ 1330 clearError(); 1331 1332 const egl_display_ptr dp = validate_display(dpy); 1333 if (!dp) return EGL_NO_IMAGE_KHR; 1334 1335 ContextRef _c(dp.get(), ctx); 1336 egl_context_t * const c = _c.get(); 1337 1338 EGLImageKHR result = EGL_NO_IMAGE_KHR; 1339 egl_connection_t* const cnx = &gEGLImpl; 1340 if (cnx->dso && cnx->egl.eglCreateImageKHR) { 1341 result = cnx->egl.eglCreateImageKHR( 1342 dp->disp.dpy, 1343 c ? c->context : EGL_NO_CONTEXT, 1344 target, buffer, attrib_list); 1345 } 1346 return result; 1347} 1348 1349EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 1350{ 1351 clearError(); 1352 1353 const egl_display_ptr dp = validate_display(dpy); 1354 if (!dp) return EGL_FALSE; 1355 1356 EGLBoolean result = EGL_FALSE; 1357 egl_connection_t* const cnx = &gEGLImpl; 1358 if (cnx->dso && cnx->egl.eglDestroyImageKHR) { 1359 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img); 1360 } 1361 return result; 1362} 1363 1364// ---------------------------------------------------------------------------- 1365// EGL_EGLEXT_VERSION 5 1366// ---------------------------------------------------------------------------- 1367 1368 1369EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) 1370{ 1371 clearError(); 1372 1373 const egl_display_ptr dp = validate_display(dpy); 1374 if (!dp) return EGL_NO_SYNC_KHR; 1375 1376 EGLSyncKHR result = EGL_NO_SYNC_KHR; 1377 egl_connection_t* const cnx = &gEGLImpl; 1378 if (cnx->dso && cnx->egl.eglCreateSyncKHR) { 1379 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list); 1380 } 1381 return result; 1382} 1383 1384EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) 1385{ 1386 clearError(); 1387 1388 const egl_display_ptr dp = validate_display(dpy); 1389 if (!dp) return EGL_FALSE; 1390 1391 EGLBoolean result = EGL_FALSE; 1392 egl_connection_t* const cnx = &gEGLImpl; 1393 if (cnx->dso && cnx->egl.eglDestroySyncKHR) { 1394 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync); 1395 } 1396 return result; 1397} 1398 1399EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) { 1400 clearError(); 1401 1402 const egl_display_ptr dp = validate_display(dpy); 1403 if (!dp) return EGL_FALSE; 1404 1405 EGLBoolean result = EGL_FALSE; 1406 egl_connection_t* const cnx = &gEGLImpl; 1407 if (cnx->dso && cnx->egl.eglSignalSyncKHR) { 1408 result = cnx->egl.eglSignalSyncKHR( 1409 dp->disp.dpy, sync, mode); 1410 } 1411 return result; 1412} 1413 1414EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, 1415 EGLint flags, EGLTimeKHR timeout) 1416{ 1417 clearError(); 1418 1419 const egl_display_ptr dp = validate_display(dpy); 1420 if (!dp) return EGL_FALSE; 1421 1422 EGLBoolean result = EGL_FALSE; 1423 egl_connection_t* const cnx = &gEGLImpl; 1424 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) { 1425 result = cnx->egl.eglClientWaitSyncKHR( 1426 dp->disp.dpy, sync, flags, timeout); 1427 } 1428 return result; 1429} 1430 1431EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, 1432 EGLint attribute, EGLint *value) 1433{ 1434 clearError(); 1435 1436 const egl_display_ptr dp = validate_display(dpy); 1437 if (!dp) return EGL_FALSE; 1438 1439 EGLBoolean result = EGL_FALSE; 1440 egl_connection_t* const cnx = &gEGLImpl; 1441 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) { 1442 result = cnx->egl.eglGetSyncAttribKHR( 1443 dp->disp.dpy, sync, attribute, value); 1444 } 1445 return result; 1446} 1447 1448// ---------------------------------------------------------------------------- 1449// EGL_EGLEXT_VERSION 15 1450// ---------------------------------------------------------------------------- 1451 1452EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) { 1453 clearError(); 1454 const egl_display_ptr dp = validate_display(dpy); 1455 if (!dp) return EGL_FALSE; 1456 EGLint result = EGL_FALSE; 1457 egl_connection_t* const cnx = &gEGLImpl; 1458 if (cnx->dso && cnx->egl.eglWaitSyncKHR) { 1459 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags); 1460 } 1461 return result; 1462} 1463 1464// ---------------------------------------------------------------------------- 1465// ANDROID extensions 1466// ---------------------------------------------------------------------------- 1467 1468EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync) 1469{ 1470 clearError(); 1471 1472 const egl_display_ptr dp = validate_display(dpy); 1473 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID; 1474 1475 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID; 1476 egl_connection_t* const cnx = &gEGLImpl; 1477 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) { 1478 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync); 1479 } 1480 return result; 1481} 1482 1483EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface, 1484 EGLnsecsANDROID time) 1485{ 1486 clearError(); 1487 1488 const egl_display_ptr dp = validate_display(dpy); 1489 if (!dp) { 1490 return EGL_FALSE; 1491 } 1492 1493 SurfaceRef _s(dp.get(), surface); 1494 if (!_s.get()) { 1495 setError(EGL_BAD_SURFACE, EGL_FALSE); 1496 return EGL_FALSE; 1497 } 1498 1499 egl_surface_t const * const s = get_surface(surface); 1500 native_window_set_buffers_timestamp(s->win.get(), time); 1501 1502 return EGL_TRUE; 1503} 1504 1505// ---------------------------------------------------------------------------- 1506// NVIDIA extensions 1507// ---------------------------------------------------------------------------- 1508EGLuint64NV eglGetSystemTimeFrequencyNV() 1509{ 1510 clearError(); 1511 1512 if (egl_init_drivers() == EGL_FALSE) { 1513 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1514 } 1515 1516 EGLuint64NV ret = 0; 1517 egl_connection_t* const cnx = &gEGLImpl; 1518 1519 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) { 1520 return cnx->egl.eglGetSystemTimeFrequencyNV(); 1521 } 1522 1523 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1524} 1525 1526EGLuint64NV eglGetSystemTimeNV() 1527{ 1528 clearError(); 1529 1530 if (egl_init_drivers() == EGL_FALSE) { 1531 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1532 } 1533 1534 EGLuint64NV ret = 0; 1535 egl_connection_t* const cnx = &gEGLImpl; 1536 1537 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) { 1538 return cnx->egl.eglGetSystemTimeNV(); 1539 } 1540 1541 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1542} 1543