eglApi.cpp revision 63108c34ec181e923b68ee840bb7960f205466a7
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 egl_connection_t* const cnx = &gEGLImpl; 749 result = setError(cnx->egl.eglGetError(), EGL_FALSE); 750 } 751 return result; 752} 753 754 755EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, 756 EGLint attribute, EGLint *value) 757{ 758 clearError(); 759 760 const egl_display_ptr dp = validate_display(dpy); 761 if (!dp) return EGL_FALSE; 762 763 ContextRef _c(dp.get(), ctx); 764 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 765 766 egl_context_t * const c = get_context(ctx); 767 return c->cnx->egl.eglQueryContext( 768 dp->disp.dpy, c->context, attribute, value); 769 770} 771 772EGLContext eglGetCurrentContext(void) 773{ 774 // could be called before eglInitialize(), but we wouldn't have a context 775 // then, and this function would correctly return EGL_NO_CONTEXT. 776 777 clearError(); 778 779 EGLContext ctx = getContext(); 780 return ctx; 781} 782 783EGLSurface eglGetCurrentSurface(EGLint readdraw) 784{ 785 // could be called before eglInitialize(), but we wouldn't have a context 786 // then, and this function would correctly return EGL_NO_SURFACE. 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 switch (readdraw) { 795 case EGL_READ: return c->read; 796 case EGL_DRAW: return c->draw; 797 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 798 } 799 } 800 return EGL_NO_SURFACE; 801} 802 803EGLDisplay eglGetCurrentDisplay(void) 804{ 805 // could be called before eglInitialize(), but we wouldn't have a context 806 // then, and this function would correctly return EGL_NO_DISPLAY. 807 808 clearError(); 809 810 EGLContext ctx = getContext(); 811 if (ctx) { 812 egl_context_t const * const c = get_context(ctx); 813 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 814 return c->dpy; 815 } 816 return EGL_NO_DISPLAY; 817} 818 819EGLBoolean eglWaitGL(void) 820{ 821 clearError(); 822 823 egl_connection_t* const cnx = &gEGLImpl; 824 if (!cnx->dso) 825 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 826 827 return cnx->egl.eglWaitGL(); 828} 829 830EGLBoolean eglWaitNative(EGLint engine) 831{ 832 clearError(); 833 834 egl_connection_t* const cnx = &gEGLImpl; 835 if (!cnx->dso) 836 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 837 838 return cnx->egl.eglWaitNative(engine); 839} 840 841EGLint eglGetError(void) 842{ 843 EGLint err = EGL_SUCCESS; 844 egl_connection_t* const cnx = &gEGLImpl; 845 if (cnx->dso) { 846 err = cnx->egl.eglGetError(); 847 } 848 if (err == EGL_SUCCESS) { 849 err = egl_tls_t::getError(); 850 } 851 return err; 852} 853 854static __eglMustCastToProperFunctionPointerType findBuiltinGLWrapper( 855 const char* procname) { 856 const egl_connection_t* cnx = &gEGLImpl; 857 void* proc = NULL; 858 859 proc = dlsym(cnx->libGles2, procname); 860 if (proc) return (__eglMustCastToProperFunctionPointerType)proc; 861 862 proc = dlsym(cnx->libGles1, procname); 863 if (proc) return (__eglMustCastToProperFunctionPointerType)proc; 864 865 return NULL; 866} 867 868__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) 869{ 870 // eglGetProcAddress() could be the very first function called 871 // in which case we must make sure we've initialized ourselves, this 872 // happens the first time egl_get_display() is called. 873 874 clearError(); 875 876 if (egl_init_drivers() == EGL_FALSE) { 877 setError(EGL_BAD_PARAMETER, NULL); 878 return NULL; 879 } 880 881 if (FILTER_EXTENSIONS(procname)) { 882 return NULL; 883 } 884 885 __eglMustCastToProperFunctionPointerType addr; 886 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap)); 887 if (addr) return addr; 888 889 addr = findBuiltinGLWrapper(procname); 890 if (addr) return addr; 891 892 // this protects accesses to sGLExtentionMap and sGLExtentionSlot 893 pthread_mutex_lock(&sExtensionMapMutex); 894 895 /* 896 * Since eglGetProcAddress() is not associated to anything, it needs 897 * to return a function pointer that "works" regardless of what 898 * the current context is. 899 * 900 * For this reason, we return a "forwarder", a small stub that takes 901 * care of calling the function associated with the context 902 * currently bound. 903 * 904 * We first look for extensions we've already resolved, if we're seeing 905 * this extension for the first time, we go through all our 906 * implementations and call eglGetProcAddress() and record the 907 * result in the appropriate implementation hooks and return the 908 * address of the forwarder corresponding to that hook set. 909 * 910 */ 911 912 const String8 name(procname); 913 addr = sGLExtentionMap.valueFor(name); 914 const int slot = sGLExtentionSlot; 915 916 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS, 917 "no more slots for eglGetProcAddress(\"%s\")", 918 procname); 919 920#if EGL_TRACE 921 gl_hooks_t *debugHooks = GLTrace_getGLHooks(); 922#endif 923 924 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) { 925 bool found = false; 926 927 egl_connection_t* const cnx = &gEGLImpl; 928 if (cnx->dso && cnx->egl.eglGetProcAddress) { 929 // Extensions are independent of the bound context 930 addr = 931 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] = 932 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] = 933#if EGL_TRACE 934 debugHooks->ext.extensions[slot] = 935 gHooksTrace.ext.extensions[slot] = 936#endif 937 cnx->egl.eglGetProcAddress(procname); 938 if (addr) found = true; 939 } 940 941 if (found) { 942 addr = gExtensionForwarders[slot]; 943 sGLExtentionMap.add(name, addr); 944 sGLExtentionSlot++; 945 } 946 } 947 948 pthread_mutex_unlock(&sExtensionMapMutex); 949 return addr; 950} 951 952class FrameCompletionThread : public Thread { 953public: 954 955 static void queueSync(EGLSyncKHR sync) { 956 static sp<FrameCompletionThread> thread(new FrameCompletionThread); 957 static bool running = false; 958 if (!running) { 959 thread->run("GPUFrameCompletion"); 960 running = true; 961 } 962 { 963 Mutex::Autolock lock(thread->mMutex); 964 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d", 965 thread->mFramesQueued).string()); 966 thread->mQueue.push_back(sync); 967 thread->mCondition.signal(); 968 thread->mFramesQueued++; 969 ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size()); 970 } 971 } 972 973private: 974 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {} 975 976 virtual bool threadLoop() { 977 EGLSyncKHR sync; 978 uint32_t frameNum; 979 { 980 Mutex::Autolock lock(mMutex); 981 while (mQueue.isEmpty()) { 982 mCondition.wait(mMutex); 983 } 984 sync = mQueue[0]; 985 frameNum = mFramesCompleted; 986 } 987 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); 988 { 989 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d", 990 frameNum).string()); 991 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR); 992 if (result == EGL_FALSE) { 993 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError()); 994 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { 995 ALOGE("FrameCompletion: timeout waiting for fence"); 996 } 997 eglDestroySyncKHR(dpy, sync); 998 } 999 { 1000 Mutex::Autolock lock(mMutex); 1001 mQueue.removeAt(0); 1002 mFramesCompleted++; 1003 ATRACE_INT("GPU Frames Outstanding", mQueue.size()); 1004 } 1005 return true; 1006 } 1007 1008 uint32_t mFramesQueued; 1009 uint32_t mFramesCompleted; 1010 Vector<EGLSyncKHR> mQueue; 1011 Condition mCondition; 1012 Mutex mMutex; 1013}; 1014 1015EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) 1016{ 1017 ATRACE_CALL(); 1018 clearError(); 1019 1020 const egl_display_ptr dp = validate_display(dpy); 1021 if (!dp) return EGL_FALSE; 1022 1023 SurfaceRef _s(dp.get(), draw); 1024 if (!_s.get()) 1025 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1026 1027#if EGL_TRACE 1028 gl_hooks_t const *trace_hooks = getGLTraceThreadSpecific(); 1029 if (getEGLDebugLevel() > 0) { 1030 if (trace_hooks == NULL) { 1031 if (GLTrace_start() < 0) { 1032 ALOGE("Disabling Tracer for OpenGL ES"); 1033 setEGLDebugLevel(0); 1034 } else { 1035 // switch over to the trace version of hooks 1036 EGLContext ctx = egl_tls_t::getContext(); 1037 egl_context_t * const c = get_context(ctx); 1038 if (c) { 1039 setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 1040 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx); 1041 } 1042 } 1043 } 1044 1045 GLTrace_eglSwapBuffers(dpy, draw); 1046 } else if (trace_hooks != NULL) { 1047 // tracing is now disabled, so switch back to the non trace version 1048 EGLContext ctx = egl_tls_t::getContext(); 1049 egl_context_t * const c = get_context(ctx); 1050 if (c) setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 1051 GLTrace_stop(); 1052 } 1053#endif 1054 1055 egl_surface_t const * const s = get_surface(draw); 1056 1057 if (CC_UNLIKELY(dp->traceGpuCompletion)) { 1058 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL); 1059 if (sync != EGL_NO_SYNC_KHR) { 1060 FrameCompletionThread::queueSync(sync); 1061 } 1062 } 1063 1064 if (CC_UNLIKELY(dp->finishOnSwap)) { 1065 uint32_t pixel; 1066 egl_context_t * const c = get_context( egl_tls_t::getContext() ); 1067 if (c) { 1068 // glReadPixels() ensures that the frame is complete 1069 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1, 1070 GL_RGBA,GL_UNSIGNED_BYTE,&pixel); 1071 } 1072 } 1073 1074 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface); 1075} 1076 1077EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, 1078 NativePixmapType target) 1079{ 1080 clearError(); 1081 1082 const egl_display_ptr dp = validate_display(dpy); 1083 if (!dp) return EGL_FALSE; 1084 1085 SurfaceRef _s(dp.get(), surface); 1086 if (!_s.get()) 1087 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1088 1089 egl_surface_t const * const s = get_surface(surface); 1090 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target); 1091} 1092 1093const char* eglQueryString(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->getVendorString(); 1103 case EGL_VERSION: 1104 return dp->getVersionString(); 1105 case EGL_EXTENSIONS: 1106 return dp->getExtensionString(); 1107 case EGL_CLIENT_APIS: 1108 return dp->getClientApiString(); 1109 } 1110 return setError(EGL_BAD_PARAMETER, (const char *)0); 1111} 1112 1113EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name) 1114{ 1115 clearError(); 1116 1117 const egl_display_ptr dp = validate_display(dpy); 1118 if (!dp) return (const char *) NULL; 1119 1120 switch (name) { 1121 case EGL_VENDOR: 1122 return dp->disp.queryString.vendor; 1123 case EGL_VERSION: 1124 return dp->disp.queryString.version; 1125 case EGL_EXTENSIONS: 1126 return dp->disp.queryString.extensions; 1127 case EGL_CLIENT_APIS: 1128 return dp->disp.queryString.clientApi; 1129 } 1130 return setError(EGL_BAD_PARAMETER, (const char *)0); 1131} 1132 1133// ---------------------------------------------------------------------------- 1134// EGL 1.1 1135// ---------------------------------------------------------------------------- 1136 1137EGLBoolean eglSurfaceAttrib( 1138 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 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.eglSurfaceAttrib) { 1151 return s->cnx->egl.eglSurfaceAttrib( 1152 dp->disp.dpy, s->surface, attribute, value); 1153 } 1154 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1155} 1156 1157EGLBoolean eglBindTexImage( 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.eglBindTexImage) { 1171 return s->cnx->egl.eglBindTexImage( 1172 dp->disp.dpy, s->surface, buffer); 1173 } 1174 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1175} 1176 1177EGLBoolean eglReleaseTexImage( 1178 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1179{ 1180 clearError(); 1181 1182 const egl_display_ptr dp = validate_display(dpy); 1183 if (!dp) return EGL_FALSE; 1184 1185 SurfaceRef _s(dp.get(), surface); 1186 if (!_s.get()) 1187 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1188 1189 egl_surface_t const * const s = get_surface(surface); 1190 if (s->cnx->egl.eglReleaseTexImage) { 1191 return s->cnx->egl.eglReleaseTexImage( 1192 dp->disp.dpy, s->surface, buffer); 1193 } 1194 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1195} 1196 1197EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 1198{ 1199 clearError(); 1200 1201 const egl_display_ptr dp = validate_display(dpy); 1202 if (!dp) return EGL_FALSE; 1203 1204 EGLBoolean res = EGL_TRUE; 1205 egl_connection_t* const cnx = &gEGLImpl; 1206 if (cnx->dso && cnx->egl.eglSwapInterval) { 1207 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval); 1208 } 1209 1210 return res; 1211} 1212 1213 1214// ---------------------------------------------------------------------------- 1215// EGL 1.2 1216// ---------------------------------------------------------------------------- 1217 1218EGLBoolean eglWaitClient(void) 1219{ 1220 clearError(); 1221 1222 egl_connection_t* const cnx = &gEGLImpl; 1223 if (!cnx->dso) 1224 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1225 1226 EGLBoolean res; 1227 if (cnx->egl.eglWaitClient) { 1228 res = cnx->egl.eglWaitClient(); 1229 } else { 1230 res = cnx->egl.eglWaitGL(); 1231 } 1232 return res; 1233} 1234 1235EGLBoolean eglBindAPI(EGLenum api) 1236{ 1237 clearError(); 1238 1239 if (egl_init_drivers() == EGL_FALSE) { 1240 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1241 } 1242 1243 // bind this API on all EGLs 1244 EGLBoolean res = EGL_TRUE; 1245 egl_connection_t* const cnx = &gEGLImpl; 1246 if (cnx->dso && cnx->egl.eglBindAPI) { 1247 res = cnx->egl.eglBindAPI(api); 1248 } 1249 return res; 1250} 1251 1252EGLenum eglQueryAPI(void) 1253{ 1254 clearError(); 1255 1256 if (egl_init_drivers() == EGL_FALSE) { 1257 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1258 } 1259 1260 egl_connection_t* const cnx = &gEGLImpl; 1261 if (cnx->dso && cnx->egl.eglQueryAPI) { 1262 return cnx->egl.eglQueryAPI(); 1263 } 1264 1265 // or, it can only be OpenGL ES 1266 return EGL_OPENGL_ES_API; 1267} 1268 1269EGLBoolean eglReleaseThread(void) 1270{ 1271 clearError(); 1272 1273#if EGL_TRACE 1274 if (getEGLDebugLevel() > 0) 1275 GLTrace_eglReleaseThread(); 1276#endif 1277 1278 // If there is context bound to the thread, release it 1279 egl_display_t::loseCurrent(get_context(getContext())); 1280 1281 egl_connection_t* const cnx = &gEGLImpl; 1282 if (cnx->dso && cnx->egl.eglReleaseThread) { 1283 cnx->egl.eglReleaseThread(); 1284 } 1285 egl_tls_t::clearTLS(); 1286 return EGL_TRUE; 1287} 1288 1289EGLSurface eglCreatePbufferFromClientBuffer( 1290 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 1291 EGLConfig config, const EGLint *attrib_list) 1292{ 1293 clearError(); 1294 1295 egl_connection_t* cnx = NULL; 1296 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 1297 if (!dp) return EGL_FALSE; 1298 if (cnx->egl.eglCreatePbufferFromClientBuffer) { 1299 return cnx->egl.eglCreatePbufferFromClientBuffer( 1300 dp->disp.dpy, buftype, buffer, config, attrib_list); 1301 } 1302 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); 1303} 1304 1305// ---------------------------------------------------------------------------- 1306// EGL_EGLEXT_VERSION 3 1307// ---------------------------------------------------------------------------- 1308 1309EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, 1310 const EGLint *attrib_list) 1311{ 1312 clearError(); 1313 1314 const egl_display_ptr dp = validate_display(dpy); 1315 if (!dp) return EGL_FALSE; 1316 1317 SurfaceRef _s(dp.get(), surface); 1318 if (!_s.get()) 1319 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1320 1321 egl_surface_t const * const s = get_surface(surface); 1322 if (s->cnx->egl.eglLockSurfaceKHR) { 1323 return s->cnx->egl.eglLockSurfaceKHR( 1324 dp->disp.dpy, s->surface, attrib_list); 1325 } 1326 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1327} 1328 1329EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) 1330{ 1331 clearError(); 1332 1333 const egl_display_ptr dp = validate_display(dpy); 1334 if (!dp) return EGL_FALSE; 1335 1336 SurfaceRef _s(dp.get(), surface); 1337 if (!_s.get()) 1338 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1339 1340 egl_surface_t const * const s = get_surface(surface); 1341 if (s->cnx->egl.eglUnlockSurfaceKHR) { 1342 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface); 1343 } 1344 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1345} 1346 1347EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1348 EGLClientBuffer buffer, const EGLint *attrib_list) 1349{ 1350 clearError(); 1351 1352 const egl_display_ptr dp = validate_display(dpy); 1353 if (!dp) return EGL_NO_IMAGE_KHR; 1354 1355 ContextRef _c(dp.get(), ctx); 1356 egl_context_t * const c = _c.get(); 1357 1358 EGLImageKHR result = EGL_NO_IMAGE_KHR; 1359 egl_connection_t* const cnx = &gEGLImpl; 1360 if (cnx->dso && cnx->egl.eglCreateImageKHR) { 1361 result = cnx->egl.eglCreateImageKHR( 1362 dp->disp.dpy, 1363 c ? c->context : EGL_NO_CONTEXT, 1364 target, buffer, attrib_list); 1365 } 1366 return result; 1367} 1368 1369EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 1370{ 1371 clearError(); 1372 1373 const egl_display_ptr dp = validate_display(dpy); 1374 if (!dp) return EGL_FALSE; 1375 1376 EGLBoolean result = EGL_FALSE; 1377 egl_connection_t* const cnx = &gEGLImpl; 1378 if (cnx->dso && cnx->egl.eglDestroyImageKHR) { 1379 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img); 1380 } 1381 return result; 1382} 1383 1384// ---------------------------------------------------------------------------- 1385// EGL_EGLEXT_VERSION 5 1386// ---------------------------------------------------------------------------- 1387 1388 1389EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) 1390{ 1391 clearError(); 1392 1393 const egl_display_ptr dp = validate_display(dpy); 1394 if (!dp) return EGL_NO_SYNC_KHR; 1395 1396 EGLSyncKHR result = EGL_NO_SYNC_KHR; 1397 egl_connection_t* const cnx = &gEGLImpl; 1398 if (cnx->dso && cnx->egl.eglCreateSyncKHR) { 1399 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list); 1400 } 1401 return result; 1402} 1403 1404EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) 1405{ 1406 clearError(); 1407 1408 const egl_display_ptr dp = validate_display(dpy); 1409 if (!dp) return EGL_FALSE; 1410 1411 EGLBoolean result = EGL_FALSE; 1412 egl_connection_t* const cnx = &gEGLImpl; 1413 if (cnx->dso && cnx->egl.eglDestroySyncKHR) { 1414 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync); 1415 } 1416 return result; 1417} 1418 1419EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) { 1420 clearError(); 1421 1422 const egl_display_ptr dp = validate_display(dpy); 1423 if (!dp) return EGL_FALSE; 1424 1425 EGLBoolean result = EGL_FALSE; 1426 egl_connection_t* const cnx = &gEGLImpl; 1427 if (cnx->dso && cnx->egl.eglSignalSyncKHR) { 1428 result = cnx->egl.eglSignalSyncKHR( 1429 dp->disp.dpy, sync, mode); 1430 } 1431 return result; 1432} 1433 1434EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, 1435 EGLint flags, EGLTimeKHR timeout) 1436{ 1437 clearError(); 1438 1439 const egl_display_ptr dp = validate_display(dpy); 1440 if (!dp) return EGL_FALSE; 1441 1442 EGLBoolean result = EGL_FALSE; 1443 egl_connection_t* const cnx = &gEGLImpl; 1444 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) { 1445 result = cnx->egl.eglClientWaitSyncKHR( 1446 dp->disp.dpy, sync, flags, timeout); 1447 } 1448 return result; 1449} 1450 1451EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, 1452 EGLint attribute, EGLint *value) 1453{ 1454 clearError(); 1455 1456 const egl_display_ptr dp = validate_display(dpy); 1457 if (!dp) return EGL_FALSE; 1458 1459 EGLBoolean result = EGL_FALSE; 1460 egl_connection_t* const cnx = &gEGLImpl; 1461 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) { 1462 result = cnx->egl.eglGetSyncAttribKHR( 1463 dp->disp.dpy, sync, attribute, value); 1464 } 1465 return result; 1466} 1467 1468// ---------------------------------------------------------------------------- 1469// EGL_EGLEXT_VERSION 15 1470// ---------------------------------------------------------------------------- 1471 1472EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) { 1473 clearError(); 1474 const egl_display_ptr dp = validate_display(dpy); 1475 if (!dp) return EGL_FALSE; 1476 EGLint result = EGL_FALSE; 1477 egl_connection_t* const cnx = &gEGLImpl; 1478 if (cnx->dso && cnx->egl.eglWaitSyncKHR) { 1479 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags); 1480 } 1481 return result; 1482} 1483 1484// ---------------------------------------------------------------------------- 1485// ANDROID extensions 1486// ---------------------------------------------------------------------------- 1487 1488EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync) 1489{ 1490 clearError(); 1491 1492 const egl_display_ptr dp = validate_display(dpy); 1493 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID; 1494 1495 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID; 1496 egl_connection_t* const cnx = &gEGLImpl; 1497 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) { 1498 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync); 1499 } 1500 return result; 1501} 1502 1503EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface, 1504 EGLnsecsANDROID time) 1505{ 1506 clearError(); 1507 1508 const egl_display_ptr dp = validate_display(dpy); 1509 if (!dp) { 1510 return EGL_FALSE; 1511 } 1512 1513 SurfaceRef _s(dp.get(), surface); 1514 if (!_s.get()) { 1515 setError(EGL_BAD_SURFACE, EGL_FALSE); 1516 return EGL_FALSE; 1517 } 1518 1519 egl_surface_t const * const s = get_surface(surface); 1520 native_window_set_buffers_timestamp(s->win.get(), time); 1521 1522 return EGL_TRUE; 1523} 1524 1525// ---------------------------------------------------------------------------- 1526// NVIDIA extensions 1527// ---------------------------------------------------------------------------- 1528EGLuint64NV eglGetSystemTimeFrequencyNV() 1529{ 1530 clearError(); 1531 1532 if (egl_init_drivers() == EGL_FALSE) { 1533 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1534 } 1535 1536 EGLuint64NV ret = 0; 1537 egl_connection_t* const cnx = &gEGLImpl; 1538 1539 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) { 1540 return cnx->egl.eglGetSystemTimeFrequencyNV(); 1541 } 1542 1543 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1544} 1545 1546EGLuint64NV eglGetSystemTimeNV() 1547{ 1548 clearError(); 1549 1550 if (egl_init_drivers() == EGL_FALSE) { 1551 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1552 } 1553 1554 EGLuint64NV ret = 0; 1555 egl_connection_t* const cnx = &gEGLImpl; 1556 1557 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) { 1558 return cnx->egl.eglGetSystemTimeNV(); 1559 } 1560 1561 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1562} 1563