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