eglApi.cpp revision f4486c6ea4bcb728ee0f38df7a8ec75c389d9d2e
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#if WORKAROUND_BUG_10194508 417#warning "WORKAROUND_10194508 enabled" 418 EGLint format; 419 if (!cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_NATIVE_VISUAL_ID, 420 &format)) { 421 ALOGE("eglGetConfigAttrib(EGL_NATIVE_VISUAL_ID) failed: %#x", 422 eglGetError()); 423 format = 0; 424 } 425 if (attrib_list) { 426 for (const EGLint* attr = attrib_list; *attr != EGL_NONE; 427 attr += 2) { 428 if (*attr == EGL_GL_COLORSPACE_KHR && 429 dp->haveExtension("EGL_KHR_gl_colorspace")) { 430 format = modifyFormatColorspace(format, *(attr+1)); 431 } 432 } 433 } 434#else 435 // by default, just pick RGBA_8888 436 EGLint format = HAL_PIXEL_FORMAT_RGBA_8888; 437 438 EGLint a = 0; 439 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a); 440 if (a > 0) { 441 // alpha-channel requested, there's really only one suitable format 442 format = HAL_PIXEL_FORMAT_RGBA_8888; 443 } else { 444 EGLint r, g, b; 445 r = g = b = 0; 446 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE, &r); 447 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g); 448 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE, &b); 449 EGLint colorDepth = r + g + b; 450 if (colorDepth <= 16) { 451 format = HAL_PIXEL_FORMAT_RGB_565; 452 } else { 453 format = HAL_PIXEL_FORMAT_RGBX_8888; 454 } 455 } 456 457 // now select a corresponding sRGB format if needed 458 if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) { 459 for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) { 460 if (*attr == EGL_GL_COLORSPACE_KHR) { 461 format = modifyFormatColorspace(format, attr[1]); 462 } 463 } 464 } 465#endif 466 if (format != 0) { 467 int err = native_window_set_buffers_format(window, format); 468 if (err != 0) { 469 ALOGE("error setting native window pixel format: %s (%d)", 470 strerror(-err), err); 471 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 472 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 473 } 474 } 475 476 // the EGL spec requires that a new EGLSurface default to swap interval 477 // 1, so explicitly set that on the window here. 478 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window); 479 anw->setSwapInterval(anw, 1); 480 481 EGLSurface surface = cnx->egl.eglCreateWindowSurface( 482 iDpy, config, window, attrib_list); 483 if (surface != EGL_NO_SURFACE) { 484 egl_surface_t* s = new egl_surface_t(dp.get(), config, window, 485 surface, cnx); 486 return s; 487 } 488 489 // EGLSurface creation failed 490 native_window_set_buffers_format(window, 0); 491 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 492 } 493 return EGL_NO_SURFACE; 494} 495 496EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, 497 NativePixmapType pixmap, 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.eglCreatePixmapSurface( 506 dp->disp.dpy, config, pixmap, 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 516EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, 517 const EGLint *attrib_list) 518{ 519 clearError(); 520 521 egl_connection_t* cnx = NULL; 522 egl_display_ptr dp = validate_display_connection(dpy, cnx); 523 if (dp) { 524 EGLSurface surface = cnx->egl.eglCreatePbufferSurface( 525 dp->disp.dpy, config, attrib_list); 526 if (surface != EGL_NO_SURFACE) { 527 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, 528 surface, cnx); 529 return s; 530 } 531 } 532 return EGL_NO_SURFACE; 533} 534 535EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) 536{ 537 clearError(); 538 539 const egl_display_ptr dp = validate_display(dpy); 540 if (!dp) return EGL_FALSE; 541 542 SurfaceRef _s(dp.get(), surface); 543 if (!_s.get()) 544 return setError(EGL_BAD_SURFACE, EGL_FALSE); 545 546 egl_surface_t * const s = get_surface(surface); 547 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface); 548 if (result == EGL_TRUE) { 549 _s.terminate(); 550 } 551 return result; 552} 553 554EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface, 555 EGLint attribute, EGLint *value) 556{ 557 clearError(); 558 559 const egl_display_ptr dp = validate_display(dpy); 560 if (!dp) return EGL_FALSE; 561 562 SurfaceRef _s(dp.get(), surface); 563 if (!_s.get()) 564 return setError(EGL_BAD_SURFACE, EGL_FALSE); 565 566 egl_surface_t const * const s = get_surface(surface); 567 return s->cnx->egl.eglQuerySurface( 568 dp->disp.dpy, s->surface, attribute, value); 569} 570 571void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) { 572 ATRACE_CALL(); 573 clearError(); 574 575 const egl_display_ptr dp = validate_display(dpy); 576 if (!dp) { 577 return; 578 } 579 580 SurfaceRef _s(dp.get(), surface); 581 if (!_s.get()) { 582 setError(EGL_BAD_SURFACE, EGL_FALSE); 583 return; 584 } 585} 586 587// ---------------------------------------------------------------------------- 588// Contexts 589// ---------------------------------------------------------------------------- 590 591EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, 592 EGLContext share_list, const EGLint *attrib_list) 593{ 594 clearError(); 595 596 egl_connection_t* cnx = NULL; 597 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 598 if (dp) { 599 if (share_list != EGL_NO_CONTEXT) { 600 if (!ContextRef(dp.get(), share_list).get()) { 601 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT); 602 } 603 egl_context_t* const c = get_context(share_list); 604 share_list = c->context; 605 } 606 EGLContext context = cnx->egl.eglCreateContext( 607 dp->disp.dpy, config, share_list, attrib_list); 608 if (context != EGL_NO_CONTEXT) { 609 // figure out if it's a GLESv1 or GLESv2 610 int version = 0; 611 if (attrib_list) { 612 while (*attrib_list != EGL_NONE) { 613 GLint attr = *attrib_list++; 614 GLint value = *attrib_list++; 615 if (attr == EGL_CONTEXT_CLIENT_VERSION) { 616 if (value == 1) { 617 version = egl_connection_t::GLESv1_INDEX; 618 } else if (value == 2 || value == 3) { 619 version = egl_connection_t::GLESv2_INDEX; 620 } 621 } 622 }; 623 } 624 egl_context_t* c = new egl_context_t(dpy, context, config, cnx, 625 version); 626#if EGL_TRACE 627 if (getEGLDebugLevel() > 0) 628 GLTrace_eglCreateContext(version, c); 629#endif 630 return c; 631 } 632 } 633 return EGL_NO_CONTEXT; 634} 635 636EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) 637{ 638 clearError(); 639 640 const egl_display_ptr dp = validate_display(dpy); 641 if (!dp) 642 return EGL_FALSE; 643 644 ContextRef _c(dp.get(), ctx); 645 if (!_c.get()) 646 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 647 648 egl_context_t * const c = get_context(ctx); 649 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context); 650 if (result == EGL_TRUE) { 651 _c.terminate(); 652 } 653 return result; 654} 655 656EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, 657 EGLSurface read, EGLContext ctx) 658{ 659 clearError(); 660 661 egl_display_ptr dp = validate_display(dpy); 662 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 663 664 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not 665 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is 666 // a valid but uninitialized display. 667 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) || 668 (draw != EGL_NO_SURFACE) ) { 669 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE); 670 } 671 672 // get a reference to the object passed in 673 ContextRef _c(dp.get(), ctx); 674 SurfaceRef _d(dp.get(), draw); 675 SurfaceRef _r(dp.get(), read); 676 677 // validate the context (if not EGL_NO_CONTEXT) 678 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) { 679 // EGL_NO_CONTEXT is valid 680 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 681 } 682 683 // these are the underlying implementation's object 684 EGLContext impl_ctx = EGL_NO_CONTEXT; 685 EGLSurface impl_draw = EGL_NO_SURFACE; 686 EGLSurface impl_read = EGL_NO_SURFACE; 687 688 // these are our objects structs passed in 689 egl_context_t * c = NULL; 690 egl_surface_t const * d = NULL; 691 egl_surface_t const * r = NULL; 692 693 // these are the current objects structs 694 egl_context_t * cur_c = get_context(getContext()); 695 696 if (ctx != EGL_NO_CONTEXT) { 697 c = get_context(ctx); 698 impl_ctx = c->context; 699 } else { 700 // no context given, use the implementation of the current context 701 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) { 702 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT); 703 return setError(EGL_BAD_MATCH, EGL_FALSE); 704 } 705 if (cur_c == NULL) { 706 // no current context 707 // not an error, there is just no current context. 708 return EGL_TRUE; 709 } 710 } 711 712 // retrieve the underlying implementation's draw EGLSurface 713 if (draw != EGL_NO_SURFACE) { 714 if (!_d.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 715 d = get_surface(draw); 716 impl_draw = d->surface; 717 } 718 719 // retrieve the underlying implementation's read EGLSurface 720 if (read != EGL_NO_SURFACE) { 721 if (!_r.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 722 r = get_surface(read); 723 impl_read = r->surface; 724 } 725 726 727 EGLBoolean result = dp->makeCurrent(c, cur_c, 728 draw, read, ctx, 729 impl_draw, impl_read, impl_ctx); 730 731 if (result == EGL_TRUE) { 732 if (c) { 733 setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 734 egl_tls_t::setContext(ctx); 735#if EGL_TRACE 736 if (getEGLDebugLevel() > 0) 737 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx); 738#endif 739 _c.acquire(); 740 _r.acquire(); 741 _d.acquire(); 742 } else { 743 setGLHooksThreadSpecific(&gHooksNoContext); 744 egl_tls_t::setContext(EGL_NO_CONTEXT); 745 } 746 } else { 747 // this will ALOGE the error 748 result = setError(c->cnx->egl.eglGetError(), EGL_FALSE); 749 } 750 return result; 751} 752 753 754EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, 755 EGLint attribute, EGLint *value) 756{ 757 clearError(); 758 759 const egl_display_ptr dp = validate_display(dpy); 760 if (!dp) return EGL_FALSE; 761 762 ContextRef _c(dp.get(), ctx); 763 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 764 765 egl_context_t * const c = get_context(ctx); 766 return c->cnx->egl.eglQueryContext( 767 dp->disp.dpy, c->context, attribute, value); 768 769} 770 771EGLContext eglGetCurrentContext(void) 772{ 773 // could be called before eglInitialize(), but we wouldn't have a context 774 // then, and this function would correctly return EGL_NO_CONTEXT. 775 776 clearError(); 777 778 EGLContext ctx = getContext(); 779 return ctx; 780} 781 782EGLSurface eglGetCurrentSurface(EGLint readdraw) 783{ 784 // could be called before eglInitialize(), but we wouldn't have a context 785 // then, and this function would correctly return EGL_NO_SURFACE. 786 787 clearError(); 788 789 EGLContext ctx = getContext(); 790 if (ctx) { 791 egl_context_t const * const c = get_context(ctx); 792 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 793 switch (readdraw) { 794 case EGL_READ: return c->read; 795 case EGL_DRAW: return c->draw; 796 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 797 } 798 } 799 return EGL_NO_SURFACE; 800} 801 802EGLDisplay eglGetCurrentDisplay(void) 803{ 804 // could be called before eglInitialize(), but we wouldn't have a context 805 // then, and this function would correctly return EGL_NO_DISPLAY. 806 807 clearError(); 808 809 EGLContext ctx = getContext(); 810 if (ctx) { 811 egl_context_t const * const c = get_context(ctx); 812 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 813 return c->dpy; 814 } 815 return EGL_NO_DISPLAY; 816} 817 818EGLBoolean eglWaitGL(void) 819{ 820 clearError(); 821 822 egl_connection_t* const cnx = &gEGLImpl; 823 if (!cnx->dso) 824 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 825 826 return cnx->egl.eglWaitGL(); 827} 828 829EGLBoolean eglWaitNative(EGLint engine) 830{ 831 clearError(); 832 833 egl_connection_t* const cnx = &gEGLImpl; 834 if (!cnx->dso) 835 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 836 837 return cnx->egl.eglWaitNative(engine); 838} 839 840EGLint eglGetError(void) 841{ 842 EGLint err = EGL_SUCCESS; 843 egl_connection_t* const cnx = &gEGLImpl; 844 if (cnx->dso) { 845 err = cnx->egl.eglGetError(); 846 } 847 if (err == EGL_SUCCESS) { 848 err = egl_tls_t::getError(); 849 } 850 return err; 851} 852 853static __eglMustCastToProperFunctionPointerType findBuiltinGLWrapper( 854 const char* procname) { 855 const egl_connection_t* cnx = &gEGLImpl; 856 void* proc = NULL; 857 858 proc = dlsym(cnx->libGles2, procname); 859 if (proc) return (__eglMustCastToProperFunctionPointerType)proc; 860 861 proc = dlsym(cnx->libGles1, procname); 862 if (proc) return (__eglMustCastToProperFunctionPointerType)proc; 863 864 return NULL; 865} 866 867__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) 868{ 869 // eglGetProcAddress() could be the very first function called 870 // in which case we must make sure we've initialized ourselves, this 871 // happens the first time egl_get_display() is called. 872 873 clearError(); 874 875 if (egl_init_drivers() == EGL_FALSE) { 876 setError(EGL_BAD_PARAMETER, NULL); 877 return NULL; 878 } 879 880 if (FILTER_EXTENSIONS(procname)) { 881 return NULL; 882 } 883 884 __eglMustCastToProperFunctionPointerType addr; 885 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap)); 886 if (addr) return addr; 887 888 addr = findBuiltinGLWrapper(procname); 889 if (addr) return addr; 890 891 // this protects accesses to sGLExtentionMap and sGLExtentionSlot 892 pthread_mutex_lock(&sExtensionMapMutex); 893 894 /* 895 * Since eglGetProcAddress() is not associated to anything, it needs 896 * to return a function pointer that "works" regardless of what 897 * the current context is. 898 * 899 * For this reason, we return a "forwarder", a small stub that takes 900 * care of calling the function associated with the context 901 * currently bound. 902 * 903 * We first look for extensions we've already resolved, if we're seeing 904 * this extension for the first time, we go through all our 905 * implementations and call eglGetProcAddress() and record the 906 * result in the appropriate implementation hooks and return the 907 * address of the forwarder corresponding to that hook set. 908 * 909 */ 910 911 const String8 name(procname); 912 addr = sGLExtentionMap.valueFor(name); 913 const int slot = sGLExtentionSlot; 914 915 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS, 916 "no more slots for eglGetProcAddress(\"%s\")", 917 procname); 918 919#if EGL_TRACE 920 gl_hooks_t *debugHooks = GLTrace_getGLHooks(); 921#endif 922 923 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) { 924 bool found = false; 925 926 egl_connection_t* const cnx = &gEGLImpl; 927 if (cnx->dso && cnx->egl.eglGetProcAddress) { 928 // Extensions are independent of the bound context 929 addr = 930 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] = 931 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] = 932#if EGL_TRACE 933 debugHooks->ext.extensions[slot] = 934 gHooksTrace.ext.extensions[slot] = 935#endif 936 cnx->egl.eglGetProcAddress(procname); 937 if (addr) found = true; 938 } 939 940 if (found) { 941 addr = gExtensionForwarders[slot]; 942 sGLExtentionMap.add(name, addr); 943 sGLExtentionSlot++; 944 } 945 } 946 947 pthread_mutex_unlock(&sExtensionMapMutex); 948 return addr; 949} 950 951class FrameCompletionThread : public Thread { 952public: 953 954 static void queueSync(EGLSyncKHR sync) { 955 static sp<FrameCompletionThread> thread(new FrameCompletionThread); 956 static bool running = false; 957 if (!running) { 958 thread->run("GPUFrameCompletion"); 959 running = true; 960 } 961 { 962 Mutex::Autolock lock(thread->mMutex); 963 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d", 964 thread->mFramesQueued).string()); 965 thread->mQueue.push_back(sync); 966 thread->mCondition.signal(); 967 thread->mFramesQueued++; 968 ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size()); 969 } 970 } 971 972private: 973 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {} 974 975 virtual bool threadLoop() { 976 EGLSyncKHR sync; 977 uint32_t frameNum; 978 { 979 Mutex::Autolock lock(mMutex); 980 while (mQueue.isEmpty()) { 981 mCondition.wait(mMutex); 982 } 983 sync = mQueue[0]; 984 frameNum = mFramesCompleted; 985 } 986 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); 987 { 988 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d", 989 frameNum).string()); 990 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR); 991 if (result == EGL_FALSE) { 992 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError()); 993 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { 994 ALOGE("FrameCompletion: timeout waiting for fence"); 995 } 996 eglDestroySyncKHR(dpy, sync); 997 } 998 { 999 Mutex::Autolock lock(mMutex); 1000 mQueue.removeAt(0); 1001 mFramesCompleted++; 1002 ATRACE_INT("GPU Frames Outstanding", mQueue.size()); 1003 } 1004 return true; 1005 } 1006 1007 uint32_t mFramesQueued; 1008 uint32_t mFramesCompleted; 1009 Vector<EGLSyncKHR> mQueue; 1010 Condition mCondition; 1011 Mutex mMutex; 1012}; 1013 1014EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) 1015{ 1016 ATRACE_CALL(); 1017 clearError(); 1018 1019 const egl_display_ptr dp = validate_display(dpy); 1020 if (!dp) return EGL_FALSE; 1021 1022 SurfaceRef _s(dp.get(), draw); 1023 if (!_s.get()) 1024 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1025 1026#if EGL_TRACE 1027 gl_hooks_t const *trace_hooks = getGLTraceThreadSpecific(); 1028 if (getEGLDebugLevel() > 0) { 1029 if (trace_hooks == NULL) { 1030 if (GLTrace_start() < 0) { 1031 ALOGE("Disabling Tracer for OpenGL ES"); 1032 setEGLDebugLevel(0); 1033 } else { 1034 // switch over to the trace version of hooks 1035 EGLContext ctx = egl_tls_t::getContext(); 1036 egl_context_t * const c = get_context(ctx); 1037 if (c) { 1038 setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 1039 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx); 1040 } 1041 } 1042 } 1043 1044 GLTrace_eglSwapBuffers(dpy, draw); 1045 } else if (trace_hooks != NULL) { 1046 // tracing is now disabled, so switch back to the non trace version 1047 EGLContext ctx = egl_tls_t::getContext(); 1048 egl_context_t * const c = get_context(ctx); 1049 if (c) setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 1050 GLTrace_stop(); 1051 } 1052#endif 1053 1054 egl_surface_t const * const s = get_surface(draw); 1055 1056 if (CC_UNLIKELY(dp->traceGpuCompletion)) { 1057 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL); 1058 if (sync != EGL_NO_SYNC_KHR) { 1059 FrameCompletionThread::queueSync(sync); 1060 } 1061 } 1062 1063 if (CC_UNLIKELY(dp->finishOnSwap)) { 1064 uint32_t pixel; 1065 egl_context_t * const c = get_context( egl_tls_t::getContext() ); 1066 if (c) { 1067 // glReadPixels() ensures that the frame is complete 1068 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1, 1069 GL_RGBA,GL_UNSIGNED_BYTE,&pixel); 1070 } 1071 } 1072 1073 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface); 1074} 1075 1076EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, 1077 NativePixmapType target) 1078{ 1079 clearError(); 1080 1081 const egl_display_ptr dp = validate_display(dpy); 1082 if (!dp) return EGL_FALSE; 1083 1084 SurfaceRef _s(dp.get(), surface); 1085 if (!_s.get()) 1086 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1087 1088 egl_surface_t const * const s = get_surface(surface); 1089 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target); 1090} 1091 1092const char* eglQueryString(EGLDisplay dpy, EGLint name) 1093{ 1094 clearError(); 1095 1096 const egl_display_ptr dp = validate_display(dpy); 1097 if (!dp) return (const char *) NULL; 1098 1099 switch (name) { 1100 case EGL_VENDOR: 1101 return dp->getVendorString(); 1102 case EGL_VERSION: 1103 return dp->getVersionString(); 1104 case EGL_EXTENSIONS: 1105 return dp->getExtensionString(); 1106 case EGL_CLIENT_APIS: 1107 return dp->getClientApiString(); 1108 } 1109 return setError(EGL_BAD_PARAMETER, (const char *)0); 1110} 1111 1112EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name) 1113{ 1114 clearError(); 1115 1116 const egl_display_ptr dp = validate_display(dpy); 1117 if (!dp) return (const char *) NULL; 1118 1119 switch (name) { 1120 case EGL_VENDOR: 1121 return dp->disp.queryString.vendor; 1122 case EGL_VERSION: 1123 return dp->disp.queryString.version; 1124 case EGL_EXTENSIONS: 1125 return dp->disp.queryString.extensions; 1126 case EGL_CLIENT_APIS: 1127 return dp->disp.queryString.clientApi; 1128 } 1129 return setError(EGL_BAD_PARAMETER, (const char *)0); 1130} 1131 1132// ---------------------------------------------------------------------------- 1133// EGL 1.1 1134// ---------------------------------------------------------------------------- 1135 1136EGLBoolean eglSurfaceAttrib( 1137 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 1138{ 1139 clearError(); 1140 1141 const egl_display_ptr dp = validate_display(dpy); 1142 if (!dp) return EGL_FALSE; 1143 1144 SurfaceRef _s(dp.get(), surface); 1145 if (!_s.get()) 1146 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1147 1148 egl_surface_t const * const s = get_surface(surface); 1149 if (s->cnx->egl.eglSurfaceAttrib) { 1150 return s->cnx->egl.eglSurfaceAttrib( 1151 dp->disp.dpy, s->surface, attribute, value); 1152 } 1153 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1154} 1155 1156EGLBoolean eglBindTexImage( 1157 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1158{ 1159 clearError(); 1160 1161 const egl_display_ptr dp = validate_display(dpy); 1162 if (!dp) return EGL_FALSE; 1163 1164 SurfaceRef _s(dp.get(), surface); 1165 if (!_s.get()) 1166 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1167 1168 egl_surface_t const * const s = get_surface(surface); 1169 if (s->cnx->egl.eglBindTexImage) { 1170 return s->cnx->egl.eglBindTexImage( 1171 dp->disp.dpy, s->surface, buffer); 1172 } 1173 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1174} 1175 1176EGLBoolean eglReleaseTexImage( 1177 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1178{ 1179 clearError(); 1180 1181 const egl_display_ptr dp = validate_display(dpy); 1182 if (!dp) return EGL_FALSE; 1183 1184 SurfaceRef _s(dp.get(), surface); 1185 if (!_s.get()) 1186 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1187 1188 egl_surface_t const * const s = get_surface(surface); 1189 if (s->cnx->egl.eglReleaseTexImage) { 1190 return s->cnx->egl.eglReleaseTexImage( 1191 dp->disp.dpy, s->surface, buffer); 1192 } 1193 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1194} 1195 1196EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 1197{ 1198 clearError(); 1199 1200 const egl_display_ptr dp = validate_display(dpy); 1201 if (!dp) return EGL_FALSE; 1202 1203 EGLBoolean res = EGL_TRUE; 1204 egl_connection_t* const cnx = &gEGLImpl; 1205 if (cnx->dso && cnx->egl.eglSwapInterval) { 1206 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval); 1207 } 1208 1209 return res; 1210} 1211 1212 1213// ---------------------------------------------------------------------------- 1214// EGL 1.2 1215// ---------------------------------------------------------------------------- 1216 1217EGLBoolean eglWaitClient(void) 1218{ 1219 clearError(); 1220 1221 egl_connection_t* const cnx = &gEGLImpl; 1222 if (!cnx->dso) 1223 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1224 1225 EGLBoolean res; 1226 if (cnx->egl.eglWaitClient) { 1227 res = cnx->egl.eglWaitClient(); 1228 } else { 1229 res = cnx->egl.eglWaitGL(); 1230 } 1231 return res; 1232} 1233 1234EGLBoolean eglBindAPI(EGLenum api) 1235{ 1236 clearError(); 1237 1238 if (egl_init_drivers() == EGL_FALSE) { 1239 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1240 } 1241 1242 // bind this API on all EGLs 1243 EGLBoolean res = EGL_TRUE; 1244 egl_connection_t* const cnx = &gEGLImpl; 1245 if (cnx->dso && cnx->egl.eglBindAPI) { 1246 res = cnx->egl.eglBindAPI(api); 1247 } 1248 return res; 1249} 1250 1251EGLenum eglQueryAPI(void) 1252{ 1253 clearError(); 1254 1255 if (egl_init_drivers() == EGL_FALSE) { 1256 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1257 } 1258 1259 egl_connection_t* const cnx = &gEGLImpl; 1260 if (cnx->dso && cnx->egl.eglQueryAPI) { 1261 return cnx->egl.eglQueryAPI(); 1262 } 1263 1264 // or, it can only be OpenGL ES 1265 return EGL_OPENGL_ES_API; 1266} 1267 1268EGLBoolean eglReleaseThread(void) 1269{ 1270 clearError(); 1271 1272#if EGL_TRACE 1273 if (getEGLDebugLevel() > 0) 1274 GLTrace_eglReleaseThread(); 1275#endif 1276 1277 // If there is context bound to the thread, release it 1278 egl_display_t::loseCurrent(get_context(getContext())); 1279 1280 egl_connection_t* const cnx = &gEGLImpl; 1281 if (cnx->dso && cnx->egl.eglReleaseThread) { 1282 cnx->egl.eglReleaseThread(); 1283 } 1284 egl_tls_t::clearTLS(); 1285 return EGL_TRUE; 1286} 1287 1288EGLSurface eglCreatePbufferFromClientBuffer( 1289 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 1290 EGLConfig config, const EGLint *attrib_list) 1291{ 1292 clearError(); 1293 1294 egl_connection_t* cnx = NULL; 1295 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 1296 if (!dp) return EGL_FALSE; 1297 if (cnx->egl.eglCreatePbufferFromClientBuffer) { 1298 return cnx->egl.eglCreatePbufferFromClientBuffer( 1299 dp->disp.dpy, buftype, buffer, config, attrib_list); 1300 } 1301 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); 1302} 1303 1304// ---------------------------------------------------------------------------- 1305// EGL_EGLEXT_VERSION 3 1306// ---------------------------------------------------------------------------- 1307 1308EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, 1309 const EGLint *attrib_list) 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.eglLockSurfaceKHR) { 1322 return s->cnx->egl.eglLockSurfaceKHR( 1323 dp->disp.dpy, s->surface, attrib_list); 1324 } 1325 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1326} 1327 1328EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) 1329{ 1330 clearError(); 1331 1332 const egl_display_ptr dp = validate_display(dpy); 1333 if (!dp) return EGL_FALSE; 1334 1335 SurfaceRef _s(dp.get(), surface); 1336 if (!_s.get()) 1337 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1338 1339 egl_surface_t const * const s = get_surface(surface); 1340 if (s->cnx->egl.eglUnlockSurfaceKHR) { 1341 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface); 1342 } 1343 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1344} 1345 1346EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1347 EGLClientBuffer buffer, const EGLint *attrib_list) 1348{ 1349 clearError(); 1350 1351 const egl_display_ptr dp = validate_display(dpy); 1352 if (!dp) return EGL_NO_IMAGE_KHR; 1353 1354 ContextRef _c(dp.get(), ctx); 1355 egl_context_t * const c = _c.get(); 1356 1357 EGLImageKHR result = EGL_NO_IMAGE_KHR; 1358 egl_connection_t* const cnx = &gEGLImpl; 1359 if (cnx->dso && cnx->egl.eglCreateImageKHR) { 1360 result = cnx->egl.eglCreateImageKHR( 1361 dp->disp.dpy, 1362 c ? c->context : EGL_NO_CONTEXT, 1363 target, buffer, attrib_list); 1364 } 1365 return result; 1366} 1367 1368EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 1369{ 1370 clearError(); 1371 1372 const egl_display_ptr dp = validate_display(dpy); 1373 if (!dp) return EGL_FALSE; 1374 1375 EGLBoolean result = EGL_FALSE; 1376 egl_connection_t* const cnx = &gEGLImpl; 1377 if (cnx->dso && cnx->egl.eglDestroyImageKHR) { 1378 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img); 1379 } 1380 return result; 1381} 1382 1383// ---------------------------------------------------------------------------- 1384// EGL_EGLEXT_VERSION 5 1385// ---------------------------------------------------------------------------- 1386 1387 1388EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) 1389{ 1390 clearError(); 1391 1392 const egl_display_ptr dp = validate_display(dpy); 1393 if (!dp) return EGL_NO_SYNC_KHR; 1394 1395 EGLSyncKHR result = EGL_NO_SYNC_KHR; 1396 egl_connection_t* const cnx = &gEGLImpl; 1397 if (cnx->dso && cnx->egl.eglCreateSyncKHR) { 1398 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list); 1399 } 1400 return result; 1401} 1402 1403EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) 1404{ 1405 clearError(); 1406 1407 const egl_display_ptr dp = validate_display(dpy); 1408 if (!dp) return EGL_FALSE; 1409 1410 EGLBoolean result = EGL_FALSE; 1411 egl_connection_t* const cnx = &gEGLImpl; 1412 if (cnx->dso && cnx->egl.eglDestroySyncKHR) { 1413 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync); 1414 } 1415 return result; 1416} 1417 1418EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) { 1419 clearError(); 1420 1421 const egl_display_ptr dp = validate_display(dpy); 1422 if (!dp) return EGL_FALSE; 1423 1424 EGLBoolean result = EGL_FALSE; 1425 egl_connection_t* const cnx = &gEGLImpl; 1426 if (cnx->dso && cnx->egl.eglSignalSyncKHR) { 1427 result = cnx->egl.eglSignalSyncKHR( 1428 dp->disp.dpy, sync, mode); 1429 } 1430 return result; 1431} 1432 1433EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, 1434 EGLint flags, EGLTimeKHR timeout) 1435{ 1436 clearError(); 1437 1438 const egl_display_ptr dp = validate_display(dpy); 1439 if (!dp) return EGL_FALSE; 1440 1441 EGLBoolean result = EGL_FALSE; 1442 egl_connection_t* const cnx = &gEGLImpl; 1443 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) { 1444 result = cnx->egl.eglClientWaitSyncKHR( 1445 dp->disp.dpy, sync, flags, timeout); 1446 } 1447 return result; 1448} 1449 1450EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, 1451 EGLint attribute, EGLint *value) 1452{ 1453 clearError(); 1454 1455 const egl_display_ptr dp = validate_display(dpy); 1456 if (!dp) return EGL_FALSE; 1457 1458 EGLBoolean result = EGL_FALSE; 1459 egl_connection_t* const cnx = &gEGLImpl; 1460 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) { 1461 result = cnx->egl.eglGetSyncAttribKHR( 1462 dp->disp.dpy, sync, attribute, value); 1463 } 1464 return result; 1465} 1466 1467// ---------------------------------------------------------------------------- 1468// EGL_EGLEXT_VERSION 15 1469// ---------------------------------------------------------------------------- 1470 1471EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) { 1472 clearError(); 1473 const egl_display_ptr dp = validate_display(dpy); 1474 if (!dp) return EGL_FALSE; 1475 EGLint result = EGL_FALSE; 1476 egl_connection_t* const cnx = &gEGLImpl; 1477 if (cnx->dso && cnx->egl.eglWaitSyncKHR) { 1478 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags); 1479 } 1480 return result; 1481} 1482 1483// ---------------------------------------------------------------------------- 1484// ANDROID extensions 1485// ---------------------------------------------------------------------------- 1486 1487EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync) 1488{ 1489 clearError(); 1490 1491 const egl_display_ptr dp = validate_display(dpy); 1492 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID; 1493 1494 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID; 1495 egl_connection_t* const cnx = &gEGLImpl; 1496 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) { 1497 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync); 1498 } 1499 return result; 1500} 1501 1502EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface, 1503 EGLnsecsANDROID time) 1504{ 1505 clearError(); 1506 1507 const egl_display_ptr dp = validate_display(dpy); 1508 if (!dp) { 1509 return EGL_FALSE; 1510 } 1511 1512 SurfaceRef _s(dp.get(), surface); 1513 if (!_s.get()) { 1514 setError(EGL_BAD_SURFACE, EGL_FALSE); 1515 return EGL_FALSE; 1516 } 1517 1518 egl_surface_t const * const s = get_surface(surface); 1519 native_window_set_buffers_timestamp(s->win.get(), time); 1520 1521 return EGL_TRUE; 1522} 1523 1524// ---------------------------------------------------------------------------- 1525// NVIDIA extensions 1526// ---------------------------------------------------------------------------- 1527EGLuint64NV eglGetSystemTimeFrequencyNV() 1528{ 1529 clearError(); 1530 1531 if (egl_init_drivers() == EGL_FALSE) { 1532 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1533 } 1534 1535 EGLuint64NV ret = 0; 1536 egl_connection_t* const cnx = &gEGLImpl; 1537 1538 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) { 1539 return cnx->egl.eglGetSystemTimeFrequencyNV(); 1540 } 1541 1542 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1543} 1544 1545EGLuint64NV eglGetSystemTimeNV() 1546{ 1547 clearError(); 1548 1549 if (egl_init_drivers() == EGL_FALSE) { 1550 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1551 } 1552 1553 EGLuint64NV ret = 0; 1554 egl_connection_t* const cnx = &gEGLImpl; 1555 1556 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) { 1557 return cnx->egl.eglGetSystemTimeNV(); 1558 } 1559 1560 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1561} 1562