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