eglApi.cpp revision 733a80754786d39cdc0fee09509b194472c320bc
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// This extension has not been ratified yet, so can't be shipped. 53// Implementation is incomplete and untested. 54#define ENABLE_EGL_KHR_GL_COLORSPACE 0 55 56// ---------------------------------------------------------------------------- 57 58namespace android { 59 60struct extention_map_t { 61 const char* name; 62 __eglMustCastToProperFunctionPointerType address; 63}; 64 65/* 66 * This is the list of EGL extensions exposed to applications. 67 * 68 * Some of them (gBuiltinExtensionString) are implemented entirely in this EGL 69 * wrapper and are always available. 70 * 71 * The rest (gExtensionString) depend on support in the EGL driver, and are 72 * only available if the driver supports them. However, some of these must be 73 * supported because they are used by the Android system itself; these are 74 * listd as mandatory below and are required by the CDD. The system *assumes* 75 * the mandatory extensions are present and may not function properly if some 76 * are missing. 77 * 78 * NOTE: Both strings MUST have a single space as the last character. 79 */ 80extern char const * const gBuiltinExtensionString = 81 "EGL_KHR_get_all_proc_addresses " 82 "EGL_ANDROID_presentation_time " 83 ; 84extern char const * const gExtensionString = 85 "EGL_KHR_image " // mandatory 86 "EGL_KHR_image_base " // mandatory 87 "EGL_KHR_image_pixmap " 88 "EGL_KHR_lock_surface " 89#if (ENABLE_EGL_KHR_GL_COLORSPACE != 0) 90 "EGL_KHR_gl_colorspace " 91#endif 92 "EGL_KHR_gl_texture_2D_image " 93 "EGL_KHR_gl_texture_cubemap_image " 94 "EGL_KHR_gl_renderbuffer_image " 95 "EGL_KHR_reusable_sync " 96 "EGL_KHR_fence_sync " 97 "EGL_KHR_create_context " 98 "EGL_EXT_create_context_robustness " 99 "EGL_NV_system_time " 100 "EGL_ANDROID_image_native_buffer " // mandatory 101 "EGL_KHR_wait_sync " // strongly recommended 102 "EGL_ANDROID_recordable " // mandatory 103 ; 104 105// extensions not exposed to applications but used by the ANDROID system 106// "EGL_ANDROID_blob_cache " // strongly recommended 107// "EGL_IMG_hibernate_process " // optional 108// "EGL_ANDROID_native_fence_sync " // strongly recommended 109// "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1 110// "EGL_ANDROID_image_crop " // optional 111 112/* 113 * EGL Extensions entry-points exposed to 3rd party applications 114 * (keep in sync with gExtensionString above) 115 * 116 */ 117static const extention_map_t sExtensionMap[] = { 118 // EGL_KHR_lock_surface 119 { "eglLockSurfaceKHR", 120 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR }, 121 { "eglUnlockSurfaceKHR", 122 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR }, 123 124 // EGL_KHR_image, EGL_KHR_image_base 125 { "eglCreateImageKHR", 126 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, 127 { "eglDestroyImageKHR", 128 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, 129 130 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync 131 { "eglCreateSyncKHR", 132 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR }, 133 { "eglDestroySyncKHR", 134 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR }, 135 { "eglClientWaitSyncKHR", 136 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR }, 137 { "eglSignalSyncKHR", 138 (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR }, 139 { "eglGetSyncAttribKHR", 140 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR }, 141 142 // EGL_NV_system_time 143 { "eglGetSystemTimeFrequencyNV", 144 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV }, 145 { "eglGetSystemTimeNV", 146 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV }, 147 148 // EGL_KHR_wait_sync 149 { "eglWaitSyncKHR", 150 (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR }, 151 152 // EGL_ANDROID_presentation_time 153 { "eglPresentationTimeANDROID", 154 (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID }, 155}; 156 157/* 158 * These extensions entry-points should not be exposed to applications. 159 * They're used internally by the Android EGL layer. 160 */ 161#define FILTER_EXTENSIONS(procname) \ 162 (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \ 163 !strcmp((procname), "eglHibernateProcessIMG") || \ 164 !strcmp((procname), "eglAwakenProcessIMG") || \ 165 !strcmp((procname), "eglDupNativeFenceFDANDROID")) 166 167 168 169// accesses protected by sExtensionMapMutex 170static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap; 171static int sGLExtentionSlot = 0; 172static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER; 173 174static void(*findProcAddress(const char* name, 175 const extention_map_t* map, size_t n))() { 176 for (uint32_t i=0 ; i<n ; i++) { 177 if (!strcmp(name, map[i].name)) { 178 return map[i].address; 179 } 180 } 181 return NULL; 182} 183 184// ---------------------------------------------------------------------------- 185 186extern void setGLHooksThreadSpecific(gl_hooks_t const *value); 187extern EGLBoolean egl_init_drivers(); 188extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS]; 189extern int getEGLDebugLevel(); 190extern void setEGLDebugLevel(int level); 191extern gl_hooks_t gHooksTrace; 192 193} // namespace android; 194 195 196// ---------------------------------------------------------------------------- 197 198static inline void clearError() { egl_tls_t::clearError(); } 199static inline EGLContext getContext() { return egl_tls_t::getContext(); } 200 201// ---------------------------------------------------------------------------- 202 203EGLDisplay eglGetDisplay(EGLNativeDisplayType display) 204{ 205 clearError(); 206 207 uintptr_t index = reinterpret_cast<uintptr_t>(display); 208 if (index >= NUM_DISPLAYS) { 209 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 210 } 211 212 if (egl_init_drivers() == EGL_FALSE) { 213 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 214 } 215 216 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display); 217 return dpy; 218} 219 220// ---------------------------------------------------------------------------- 221// Initialization 222// ---------------------------------------------------------------------------- 223 224EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) 225{ 226 clearError(); 227 228 egl_display_ptr dp = get_display(dpy); 229 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 230 231 EGLBoolean res = dp->initialize(major, minor); 232 233 return res; 234} 235 236EGLBoolean eglTerminate(EGLDisplay dpy) 237{ 238 // NOTE: don't unload the drivers b/c some APIs can be called 239 // after eglTerminate() has been called. eglTerminate() only 240 // terminates an EGLDisplay, not a EGL itself. 241 242 clearError(); 243 244 egl_display_ptr dp = get_display(dpy); 245 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 246 247 EGLBoolean res = dp->terminate(); 248 249 return res; 250} 251 252// ---------------------------------------------------------------------------- 253// configuration 254// ---------------------------------------------------------------------------- 255 256EGLBoolean eglGetConfigs( EGLDisplay dpy, 257 EGLConfig *configs, 258 EGLint config_size, EGLint *num_config) 259{ 260 clearError(); 261 262 const egl_display_ptr dp = validate_display(dpy); 263 if (!dp) return EGL_FALSE; 264 265 if (num_config==0) { 266 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 267 } 268 269 EGLBoolean res = EGL_FALSE; 270 *num_config = 0; 271 272 egl_connection_t* const cnx = &gEGLImpl; 273 if (cnx->dso) { 274 res = cnx->egl.eglGetConfigs( 275 dp->disp.dpy, configs, config_size, num_config); 276 } 277 278 return res; 279} 280 281EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, 282 EGLConfig *configs, EGLint config_size, 283 EGLint *num_config) 284{ 285 clearError(); 286 287 const egl_display_ptr dp = validate_display(dpy); 288 if (!dp) return EGL_FALSE; 289 290 if (num_config==0) { 291 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 292 } 293 294 EGLBoolean res = EGL_FALSE; 295 *num_config = 0; 296 297 egl_connection_t* const cnx = &gEGLImpl; 298 if (cnx->dso) { 299 if (attrib_list) { 300 char value[PROPERTY_VALUE_MAX]; 301 property_get("debug.egl.force_msaa", value, "false"); 302 303 if (!strcmp(value, "true")) { 304 size_t attribCount = 0; 305 EGLint attrib = attrib_list[0]; 306 307 // Only enable MSAA if the context is OpenGL ES 2.0 and 308 // if no caveat is requested 309 const EGLint *attribRendererable = NULL; 310 const EGLint *attribCaveat = NULL; 311 312 // Count the number of attributes and look for 313 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT 314 while (attrib != EGL_NONE) { 315 attrib = attrib_list[attribCount]; 316 switch (attrib) { 317 case EGL_RENDERABLE_TYPE: 318 attribRendererable = &attrib_list[attribCount]; 319 break; 320 case EGL_CONFIG_CAVEAT: 321 attribCaveat = &attrib_list[attribCount]; 322 break; 323 } 324 attribCount++; 325 } 326 327 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT && 328 (!attribCaveat || attribCaveat[1] != EGL_NONE)) { 329 330 // Insert 2 extra attributes to force-enable MSAA 4x 331 EGLint aaAttribs[attribCount + 4]; 332 aaAttribs[0] = EGL_SAMPLE_BUFFERS; 333 aaAttribs[1] = 1; 334 aaAttribs[2] = EGL_SAMPLES; 335 aaAttribs[3] = 4; 336 337 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint)); 338 339 EGLint numConfigAA; 340 EGLBoolean resAA = cnx->egl.eglChooseConfig( 341 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA); 342 343 if (resAA == EGL_TRUE && numConfigAA > 0) { 344 ALOGD("Enabling MSAA 4x"); 345 *num_config = numConfigAA; 346 return resAA; 347 } 348 } 349 } 350 } 351 352 res = cnx->egl.eglChooseConfig( 353 dp->disp.dpy, attrib_list, configs, config_size, num_config); 354 } 355 return res; 356} 357 358EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, 359 EGLint attribute, EGLint *value) 360{ 361 clearError(); 362 363 egl_connection_t* cnx = NULL; 364 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 365 if (!dp) return EGL_FALSE; 366 367 return cnx->egl.eglGetConfigAttrib( 368 dp->disp.dpy, config, attribute, value); 369} 370 371// ---------------------------------------------------------------------------- 372// surfaces 373// ---------------------------------------------------------------------------- 374 375// The EGL_KHR_gl_colorspace spec hasn't been ratified yet, so these haven't 376// been added to the Khronos egl.h. 377#define EGL_GL_COLORSPACE_KHR EGL_VG_COLORSPACE 378#define EGL_GL_COLORSPACE_SRGB_KHR EGL_VG_COLORSPACE_sRGB 379#define EGL_GL_COLORSPACE_LINEAR_KHR EGL_VG_COLORSPACE_LINEAR 380 381// Turn linear formats into corresponding sRGB formats when colorspace is 382// EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear 383// formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where 384// the modification isn't possible, the original format is returned. 385static int modifyFormatColorspace(int fmt, EGLint colorspace) { 386 if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) { 387 switch (fmt) { 388 case HAL_PIXEL_FORMAT_sRGB_A_8888: return HAL_PIXEL_FORMAT_RGBA_8888; 389 case HAL_PIXEL_FORMAT_sRGB_X_8888: return HAL_PIXEL_FORMAT_RGBX_8888; 390 } 391 } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) { 392 switch (fmt) { 393 case HAL_PIXEL_FORMAT_RGBA_8888: return HAL_PIXEL_FORMAT_sRGB_A_8888; 394 case HAL_PIXEL_FORMAT_RGBX_8888: return HAL_PIXEL_FORMAT_sRGB_X_8888; 395 } 396 } 397 return fmt; 398} 399 400EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, 401 NativeWindowType window, 402 const EGLint *attrib_list) 403{ 404 clearError(); 405 406 egl_connection_t* cnx = NULL; 407 egl_display_ptr dp = validate_display_connection(dpy, cnx); 408 if (dp) { 409 EGLDisplay iDpy = dp->disp.dpy; 410 411 int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL); 412 if (result != OK) { 413 ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) " 414 "failed (%#x) (already connected to another API?)", 415 window, result); 416 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); 417 } 418 419 // Set the native window's buffers format to match what this config requests. 420 // Whether to use sRGB gamma is not part of the EGLconfig, but is part 421 // of our native format. So if sRGB gamma is requested, we have to 422 // modify the EGLconfig's format before setting the native window's 423 // format. 424 425 // by default, just pick RGBA_8888 426 EGLint format = HAL_PIXEL_FORMAT_RGBA_8888; 427 428 EGLint a = 0; 429 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a); 430 if (a > 0) { 431 // alpha-channel requested, there's really only one suitable format 432 format = HAL_PIXEL_FORMAT_RGBA_8888; 433 } else { 434 EGLint r, g, b; 435 r = g = b = 0; 436 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE, &r); 437 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g); 438 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE, &b); 439 EGLint colorDepth = r + g + b; 440 if (colorDepth <= 16) { 441 format = HAL_PIXEL_FORMAT_RGB_565; 442 } else { 443 format = HAL_PIXEL_FORMAT_RGBX_8888; 444 } 445 } 446 447 // now select a corresponding sRGB format if needed 448 if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) { 449 for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) { 450 if (*attr == EGL_GL_COLORSPACE_KHR) { 451 if (ENABLE_EGL_KHR_GL_COLORSPACE) { 452 format = modifyFormatColorspace(format, *(attr+1)); 453 } else { 454 // Normally we'd pass through unhandled attributes to 455 // the driver. But in case the driver implements this 456 // extension but we're disabling it, we want to prevent 457 // it getting through -- support will be broken without 458 // our help. 459 ALOGE("sRGB window surfaces not supported"); 460 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); 461 } 462 } 463 } 464 } 465 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 findBuiltinWrapper( 855 const char* procname) { 856 const egl_connection_t* cnx = &gEGLImpl; 857 void* proc = NULL; 858 859 proc = dlsym(cnx->libEgl, procname); 860 if (proc) return (__eglMustCastToProperFunctionPointerType)proc; 861 862 proc = dlsym(cnx->libGles2, procname); 863 if (proc) return (__eglMustCastToProperFunctionPointerType)proc; 864 865 proc = dlsym(cnx->libGles1, procname); 866 if (proc) return (__eglMustCastToProperFunctionPointerType)proc; 867 868 return NULL; 869} 870 871__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) 872{ 873 // eglGetProcAddress() could be the very first function called 874 // in which case we must make sure we've initialized ourselves, this 875 // happens the first time egl_get_display() is called. 876 877 clearError(); 878 879 if (egl_init_drivers() == EGL_FALSE) { 880 setError(EGL_BAD_PARAMETER, NULL); 881 return NULL; 882 } 883 884 if (FILTER_EXTENSIONS(procname)) { 885 return NULL; 886 } 887 888 __eglMustCastToProperFunctionPointerType addr; 889 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap)); 890 if (addr) return addr; 891 892 addr = findBuiltinWrapper(procname); 893 if (addr) return addr; 894 895 // this protects accesses to sGLExtentionMap and sGLExtentionSlot 896 pthread_mutex_lock(&sExtensionMapMutex); 897 898 /* 899 * Since eglGetProcAddress() is not associated to anything, it needs 900 * to return a function pointer that "works" regardless of what 901 * the current context is. 902 * 903 * For this reason, we return a "forwarder", a small stub that takes 904 * care of calling the function associated with the context 905 * currently bound. 906 * 907 * We first look for extensions we've already resolved, if we're seeing 908 * this extension for the first time, we go through all our 909 * implementations and call eglGetProcAddress() and record the 910 * result in the appropriate implementation hooks and return the 911 * address of the forwarder corresponding to that hook set. 912 * 913 */ 914 915 const String8 name(procname); 916 addr = sGLExtentionMap.valueFor(name); 917 const int slot = sGLExtentionSlot; 918 919 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS, 920 "no more slots for eglGetProcAddress(\"%s\")", 921 procname); 922 923#if EGL_TRACE 924 gl_hooks_t *debugHooks = GLTrace_getGLHooks(); 925#endif 926 927 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) { 928 bool found = false; 929 930 egl_connection_t* const cnx = &gEGLImpl; 931 if (cnx->dso && cnx->egl.eglGetProcAddress) { 932 // Extensions are independent of the bound context 933 addr = 934 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] = 935 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] = 936#if EGL_TRACE 937 debugHooks->ext.extensions[slot] = 938 gHooksTrace.ext.extensions[slot] = 939#endif 940 cnx->egl.eglGetProcAddress(procname); 941 if (addr) found = true; 942 } 943 944 if (found) { 945 addr = gExtensionForwarders[slot]; 946 sGLExtentionMap.add(name, addr); 947 sGLExtentionSlot++; 948 } 949 } 950 951 pthread_mutex_unlock(&sExtensionMapMutex); 952 return addr; 953} 954 955class FrameCompletionThread : public Thread { 956public: 957 958 static void queueSync(EGLSyncKHR sync) { 959 static sp<FrameCompletionThread> thread(new FrameCompletionThread); 960 static bool running = false; 961 if (!running) { 962 thread->run("GPUFrameCompletion"); 963 running = true; 964 } 965 { 966 Mutex::Autolock lock(thread->mMutex); 967 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d", 968 thread->mFramesQueued).string()); 969 thread->mQueue.push_back(sync); 970 thread->mCondition.signal(); 971 thread->mFramesQueued++; 972 ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size()); 973 } 974 } 975 976private: 977 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {} 978 979 virtual bool threadLoop() { 980 EGLSyncKHR sync; 981 uint32_t frameNum; 982 { 983 Mutex::Autolock lock(mMutex); 984 while (mQueue.isEmpty()) { 985 mCondition.wait(mMutex); 986 } 987 sync = mQueue[0]; 988 frameNum = mFramesCompleted; 989 } 990 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); 991 { 992 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d", 993 frameNum).string()); 994 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR); 995 if (result == EGL_FALSE) { 996 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError()); 997 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { 998 ALOGE("FrameCompletion: timeout waiting for fence"); 999 } 1000 eglDestroySyncKHR(dpy, sync); 1001 } 1002 { 1003 Mutex::Autolock lock(mMutex); 1004 mQueue.removeAt(0); 1005 mFramesCompleted++; 1006 ATRACE_INT("GPU Frames Outstanding", mQueue.size()); 1007 } 1008 return true; 1009 } 1010 1011 uint32_t mFramesQueued; 1012 uint32_t mFramesCompleted; 1013 Vector<EGLSyncKHR> mQueue; 1014 Condition mCondition; 1015 Mutex mMutex; 1016}; 1017 1018EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) 1019{ 1020 ATRACE_CALL(); 1021 clearError(); 1022 1023 const egl_display_ptr dp = validate_display(dpy); 1024 if (!dp) return EGL_FALSE; 1025 1026 SurfaceRef _s(dp.get(), draw); 1027 if (!_s.get()) 1028 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1029 1030#if EGL_TRACE 1031 gl_hooks_t const *trace_hooks = getGLTraceThreadSpecific(); 1032 if (getEGLDebugLevel() > 0) { 1033 if (trace_hooks == NULL) { 1034 if (GLTrace_start() < 0) { 1035 ALOGE("Disabling Tracer for OpenGL ES"); 1036 setEGLDebugLevel(0); 1037 } else { 1038 // switch over to the trace version of hooks 1039 EGLContext ctx = egl_tls_t::getContext(); 1040 egl_context_t * const c = get_context(ctx); 1041 if (c) { 1042 setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 1043 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx); 1044 } 1045 } 1046 } 1047 1048 GLTrace_eglSwapBuffers(dpy, draw); 1049 } else if (trace_hooks != NULL) { 1050 // tracing is now disabled, so switch back to the non trace version 1051 EGLContext ctx = egl_tls_t::getContext(); 1052 egl_context_t * const c = get_context(ctx); 1053 if (c) setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 1054 GLTrace_stop(); 1055 } 1056#endif 1057 1058 egl_surface_t const * const s = get_surface(draw); 1059 1060 if (CC_UNLIKELY(dp->traceGpuCompletion)) { 1061 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL); 1062 if (sync != EGL_NO_SYNC_KHR) { 1063 FrameCompletionThread::queueSync(sync); 1064 } 1065 } 1066 1067 if (CC_UNLIKELY(dp->finishOnSwap)) { 1068 uint32_t pixel; 1069 egl_context_t * const c = get_context( egl_tls_t::getContext() ); 1070 if (c) { 1071 // glReadPixels() ensures that the frame is complete 1072 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1, 1073 GL_RGBA,GL_UNSIGNED_BYTE,&pixel); 1074 } 1075 } 1076 1077 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface); 1078} 1079 1080EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, 1081 NativePixmapType target) 1082{ 1083 clearError(); 1084 1085 const egl_display_ptr dp = validate_display(dpy); 1086 if (!dp) return EGL_FALSE; 1087 1088 SurfaceRef _s(dp.get(), surface); 1089 if (!_s.get()) 1090 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1091 1092 egl_surface_t const * const s = get_surface(surface); 1093 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target); 1094} 1095 1096const char* eglQueryString(EGLDisplay dpy, EGLint name) 1097{ 1098 clearError(); 1099 1100 const egl_display_ptr dp = validate_display(dpy); 1101 if (!dp) return (const char *) NULL; 1102 1103 switch (name) { 1104 case EGL_VENDOR: 1105 return dp->getVendorString(); 1106 case EGL_VERSION: 1107 return dp->getVersionString(); 1108 case EGL_EXTENSIONS: 1109 return dp->getExtensionString(); 1110 case EGL_CLIENT_APIS: 1111 return dp->getClientApiString(); 1112 } 1113 return setError(EGL_BAD_PARAMETER, (const char *)0); 1114} 1115 1116EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name) 1117{ 1118 clearError(); 1119 1120 const egl_display_ptr dp = validate_display(dpy); 1121 if (!dp) return (const char *) NULL; 1122 1123 switch (name) { 1124 case EGL_VENDOR: 1125 return dp->disp.queryString.vendor; 1126 case EGL_VERSION: 1127 return dp->disp.queryString.version; 1128 case EGL_EXTENSIONS: 1129 return dp->disp.queryString.extensions; 1130 case EGL_CLIENT_APIS: 1131 return dp->disp.queryString.clientApi; 1132 } 1133 return setError(EGL_BAD_PARAMETER, (const char *)0); 1134} 1135 1136// ---------------------------------------------------------------------------- 1137// EGL 1.1 1138// ---------------------------------------------------------------------------- 1139 1140EGLBoolean eglSurfaceAttrib( 1141 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 1142{ 1143 clearError(); 1144 1145 const egl_display_ptr dp = validate_display(dpy); 1146 if (!dp) return EGL_FALSE; 1147 1148 SurfaceRef _s(dp.get(), surface); 1149 if (!_s.get()) 1150 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1151 1152 egl_surface_t const * const s = get_surface(surface); 1153 if (s->cnx->egl.eglSurfaceAttrib) { 1154 return s->cnx->egl.eglSurfaceAttrib( 1155 dp->disp.dpy, s->surface, attribute, value); 1156 } 1157 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1158} 1159 1160EGLBoolean eglBindTexImage( 1161 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1162{ 1163 clearError(); 1164 1165 const egl_display_ptr dp = validate_display(dpy); 1166 if (!dp) return EGL_FALSE; 1167 1168 SurfaceRef _s(dp.get(), surface); 1169 if (!_s.get()) 1170 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1171 1172 egl_surface_t const * const s = get_surface(surface); 1173 if (s->cnx->egl.eglBindTexImage) { 1174 return s->cnx->egl.eglBindTexImage( 1175 dp->disp.dpy, s->surface, buffer); 1176 } 1177 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1178} 1179 1180EGLBoolean eglReleaseTexImage( 1181 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1182{ 1183 clearError(); 1184 1185 const egl_display_ptr dp = validate_display(dpy); 1186 if (!dp) return EGL_FALSE; 1187 1188 SurfaceRef _s(dp.get(), surface); 1189 if (!_s.get()) 1190 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1191 1192 egl_surface_t const * const s = get_surface(surface); 1193 if (s->cnx->egl.eglReleaseTexImage) { 1194 return s->cnx->egl.eglReleaseTexImage( 1195 dp->disp.dpy, s->surface, buffer); 1196 } 1197 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1198} 1199 1200EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 1201{ 1202 clearError(); 1203 1204 const egl_display_ptr dp = validate_display(dpy); 1205 if (!dp) return EGL_FALSE; 1206 1207 EGLBoolean res = EGL_TRUE; 1208 egl_connection_t* const cnx = &gEGLImpl; 1209 if (cnx->dso && cnx->egl.eglSwapInterval) { 1210 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval); 1211 } 1212 1213 return res; 1214} 1215 1216 1217// ---------------------------------------------------------------------------- 1218// EGL 1.2 1219// ---------------------------------------------------------------------------- 1220 1221EGLBoolean eglWaitClient(void) 1222{ 1223 clearError(); 1224 1225 egl_connection_t* const cnx = &gEGLImpl; 1226 if (!cnx->dso) 1227 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1228 1229 EGLBoolean res; 1230 if (cnx->egl.eglWaitClient) { 1231 res = cnx->egl.eglWaitClient(); 1232 } else { 1233 res = cnx->egl.eglWaitGL(); 1234 } 1235 return res; 1236} 1237 1238EGLBoolean eglBindAPI(EGLenum api) 1239{ 1240 clearError(); 1241 1242 if (egl_init_drivers() == EGL_FALSE) { 1243 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1244 } 1245 1246 // bind this API on all EGLs 1247 EGLBoolean res = EGL_TRUE; 1248 egl_connection_t* const cnx = &gEGLImpl; 1249 if (cnx->dso && cnx->egl.eglBindAPI) { 1250 res = cnx->egl.eglBindAPI(api); 1251 } 1252 return res; 1253} 1254 1255EGLenum eglQueryAPI(void) 1256{ 1257 clearError(); 1258 1259 if (egl_init_drivers() == EGL_FALSE) { 1260 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1261 } 1262 1263 egl_connection_t* const cnx = &gEGLImpl; 1264 if (cnx->dso && cnx->egl.eglQueryAPI) { 1265 return cnx->egl.eglQueryAPI(); 1266 } 1267 1268 // or, it can only be OpenGL ES 1269 return EGL_OPENGL_ES_API; 1270} 1271 1272EGLBoolean eglReleaseThread(void) 1273{ 1274 clearError(); 1275 1276#if EGL_TRACE 1277 if (getEGLDebugLevel() > 0) 1278 GLTrace_eglReleaseThread(); 1279#endif 1280 1281 // If there is context bound to the thread, release it 1282 egl_display_t::loseCurrent(get_context(getContext())); 1283 1284 egl_connection_t* const cnx = &gEGLImpl; 1285 if (cnx->dso && cnx->egl.eglReleaseThread) { 1286 cnx->egl.eglReleaseThread(); 1287 } 1288 egl_tls_t::clearTLS(); 1289 return EGL_TRUE; 1290} 1291 1292EGLSurface eglCreatePbufferFromClientBuffer( 1293 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 1294 EGLConfig config, const EGLint *attrib_list) 1295{ 1296 clearError(); 1297 1298 egl_connection_t* cnx = NULL; 1299 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 1300 if (!dp) return EGL_FALSE; 1301 if (cnx->egl.eglCreatePbufferFromClientBuffer) { 1302 return cnx->egl.eglCreatePbufferFromClientBuffer( 1303 dp->disp.dpy, buftype, buffer, config, attrib_list); 1304 } 1305 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); 1306} 1307 1308// ---------------------------------------------------------------------------- 1309// EGL_EGLEXT_VERSION 3 1310// ---------------------------------------------------------------------------- 1311 1312EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, 1313 const EGLint *attrib_list) 1314{ 1315 clearError(); 1316 1317 const egl_display_ptr dp = validate_display(dpy); 1318 if (!dp) return EGL_FALSE; 1319 1320 SurfaceRef _s(dp.get(), surface); 1321 if (!_s.get()) 1322 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1323 1324 egl_surface_t const * const s = get_surface(surface); 1325 if (s->cnx->egl.eglLockSurfaceKHR) { 1326 return s->cnx->egl.eglLockSurfaceKHR( 1327 dp->disp.dpy, s->surface, attrib_list); 1328 } 1329 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1330} 1331 1332EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) 1333{ 1334 clearError(); 1335 1336 const egl_display_ptr dp = validate_display(dpy); 1337 if (!dp) return EGL_FALSE; 1338 1339 SurfaceRef _s(dp.get(), surface); 1340 if (!_s.get()) 1341 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1342 1343 egl_surface_t const * const s = get_surface(surface); 1344 if (s->cnx->egl.eglUnlockSurfaceKHR) { 1345 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface); 1346 } 1347 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1348} 1349 1350EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1351 EGLClientBuffer buffer, const EGLint *attrib_list) 1352{ 1353 clearError(); 1354 1355 const egl_display_ptr dp = validate_display(dpy); 1356 if (!dp) return EGL_NO_IMAGE_KHR; 1357 1358 ContextRef _c(dp.get(), ctx); 1359 egl_context_t * const c = _c.get(); 1360 1361 EGLImageKHR result = EGL_NO_IMAGE_KHR; 1362 egl_connection_t* const cnx = &gEGLImpl; 1363 if (cnx->dso && cnx->egl.eglCreateImageKHR) { 1364 result = cnx->egl.eglCreateImageKHR( 1365 dp->disp.dpy, 1366 c ? c->context : EGL_NO_CONTEXT, 1367 target, buffer, attrib_list); 1368 } 1369 return result; 1370} 1371 1372EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 1373{ 1374 clearError(); 1375 1376 const egl_display_ptr dp = validate_display(dpy); 1377 if (!dp) return EGL_FALSE; 1378 1379 EGLBoolean result = EGL_FALSE; 1380 egl_connection_t* const cnx = &gEGLImpl; 1381 if (cnx->dso && cnx->egl.eglDestroyImageKHR) { 1382 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img); 1383 } 1384 return result; 1385} 1386 1387// ---------------------------------------------------------------------------- 1388// EGL_EGLEXT_VERSION 5 1389// ---------------------------------------------------------------------------- 1390 1391 1392EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) 1393{ 1394 clearError(); 1395 1396 const egl_display_ptr dp = validate_display(dpy); 1397 if (!dp) return EGL_NO_SYNC_KHR; 1398 1399 EGLSyncKHR result = EGL_NO_SYNC_KHR; 1400 egl_connection_t* const cnx = &gEGLImpl; 1401 if (cnx->dso && cnx->egl.eglCreateSyncKHR) { 1402 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list); 1403 } 1404 return result; 1405} 1406 1407EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) 1408{ 1409 clearError(); 1410 1411 const egl_display_ptr dp = validate_display(dpy); 1412 if (!dp) return EGL_FALSE; 1413 1414 EGLBoolean result = EGL_FALSE; 1415 egl_connection_t* const cnx = &gEGLImpl; 1416 if (cnx->dso && cnx->egl.eglDestroySyncKHR) { 1417 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync); 1418 } 1419 return result; 1420} 1421 1422EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) { 1423 clearError(); 1424 1425 const egl_display_ptr dp = validate_display(dpy); 1426 if (!dp) return EGL_FALSE; 1427 1428 EGLBoolean result = EGL_FALSE; 1429 egl_connection_t* const cnx = &gEGLImpl; 1430 if (cnx->dso && cnx->egl.eglSignalSyncKHR) { 1431 result = cnx->egl.eglSignalSyncKHR( 1432 dp->disp.dpy, sync, mode); 1433 } 1434 return result; 1435} 1436 1437EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, 1438 EGLint flags, EGLTimeKHR timeout) 1439{ 1440 clearError(); 1441 1442 const egl_display_ptr dp = validate_display(dpy); 1443 if (!dp) return EGL_FALSE; 1444 1445 EGLBoolean result = EGL_FALSE; 1446 egl_connection_t* const cnx = &gEGLImpl; 1447 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) { 1448 result = cnx->egl.eglClientWaitSyncKHR( 1449 dp->disp.dpy, sync, flags, timeout); 1450 } 1451 return result; 1452} 1453 1454EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, 1455 EGLint attribute, EGLint *value) 1456{ 1457 clearError(); 1458 1459 const egl_display_ptr dp = validate_display(dpy); 1460 if (!dp) return EGL_FALSE; 1461 1462 EGLBoolean result = EGL_FALSE; 1463 egl_connection_t* const cnx = &gEGLImpl; 1464 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) { 1465 result = cnx->egl.eglGetSyncAttribKHR( 1466 dp->disp.dpy, sync, attribute, value); 1467 } 1468 return result; 1469} 1470 1471// ---------------------------------------------------------------------------- 1472// EGL_EGLEXT_VERSION 15 1473// ---------------------------------------------------------------------------- 1474 1475EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) { 1476 clearError(); 1477 const egl_display_ptr dp = validate_display(dpy); 1478 if (!dp) return EGL_FALSE; 1479 EGLint result = EGL_FALSE; 1480 egl_connection_t* const cnx = &gEGLImpl; 1481 if (cnx->dso && cnx->egl.eglWaitSyncKHR) { 1482 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags); 1483 } 1484 return result; 1485} 1486 1487// ---------------------------------------------------------------------------- 1488// ANDROID extensions 1489// ---------------------------------------------------------------------------- 1490 1491EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync) 1492{ 1493 clearError(); 1494 1495 const egl_display_ptr dp = validate_display(dpy); 1496 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID; 1497 1498 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID; 1499 egl_connection_t* const cnx = &gEGLImpl; 1500 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) { 1501 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync); 1502 } 1503 return result; 1504} 1505 1506EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface, 1507 EGLnsecsANDROID time) 1508{ 1509 clearError(); 1510 1511 const egl_display_ptr dp = validate_display(dpy); 1512 if (!dp) { 1513 return EGL_FALSE; 1514 } 1515 1516 SurfaceRef _s(dp.get(), surface); 1517 if (!_s.get()) { 1518 setError(EGL_BAD_SURFACE, EGL_FALSE); 1519 return EGL_FALSE; 1520 } 1521 1522 egl_surface_t const * const s = get_surface(surface); 1523 native_window_set_buffers_timestamp(s->win.get(), time); 1524 1525 return EGL_TRUE; 1526} 1527 1528// ---------------------------------------------------------------------------- 1529// NVIDIA extensions 1530// ---------------------------------------------------------------------------- 1531EGLuint64NV eglGetSystemTimeFrequencyNV() 1532{ 1533 clearError(); 1534 1535 if (egl_init_drivers() == EGL_FALSE) { 1536 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1537 } 1538 1539 EGLuint64NV ret = 0; 1540 egl_connection_t* const cnx = &gEGLImpl; 1541 1542 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) { 1543 return cnx->egl.eglGetSystemTimeFrequencyNV(); 1544 } 1545 1546 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1547} 1548 1549EGLuint64NV eglGetSystemTimeNV() 1550{ 1551 clearError(); 1552 1553 if (egl_init_drivers() == EGL_FALSE) { 1554 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1555 } 1556 1557 EGLuint64NV ret = 0; 1558 egl_connection_t* const cnx = &gEGLImpl; 1559 1560 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) { 1561 return cnx->egl.eglGetSystemTimeNV(); 1562 } 1563 1564 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1565} 1566