eglApi.cpp revision 5bf6f3b5bf06e04a742bde8d40409d3c9e434c05
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 "../hooks.h" 43 44#include "egl_display.h" 45#include "egl_object.h" 46#include "egl_tls.h" 47#include "egldefs.h" 48 49using namespace android; 50 51// This extension has not been ratified yet, so can't be shipped. 52// Implementation is incomplete and untested. 53#define ENABLE_EGL_KHR_GL_COLORSPACE 0 54 55// ---------------------------------------------------------------------------- 56 57namespace android { 58 59struct extention_map_t { 60 const char* name; 61 __eglMustCastToProperFunctionPointerType address; 62}; 63 64/* 65 * This is the list of EGL extensions exposed to applications. 66 * 67 * Some of them (gBuiltinExtensionString) are implemented entirely in this EGL 68 * wrapper and are always available. 69 * 70 * The rest (gExtensionString) depend on support in the EGL driver, and are 71 * only available if the driver supports them. However, some of these must be 72 * supported because they are used by the Android system itself; these are 73 * listd as mandatory below and are required by the CDD. The system *assumes* 74 * the mandatory extensions are present and may not function properly if some 75 * are missing. 76 * 77 * NOTE: Both strings MUST have a single space as the last character. 78 */ 79extern char const * const gBuiltinExtensionString = 80 "EGL_KHR_get_all_proc_addresses " 81 "EGL_ANDROID_presentation_time " 82 "EGL_KHR_swap_buffers_with_damage " 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_3D_image " 94 "EGL_KHR_gl_texture_cubemap_image " 95 "EGL_KHR_gl_renderbuffer_image " 96 "EGL_KHR_reusable_sync " 97 "EGL_KHR_fence_sync " 98 "EGL_KHR_create_context " 99 "EGL_KHR_config_attribs " 100 "EGL_KHR_surfaceless_context " 101 "EGL_KHR_stream " 102 "EGL_KHR_stream_fifo " 103 "EGL_KHR_stream_producer_eglsurface " 104 "EGL_KHR_stream_consumer_gltexture " 105 "EGL_KHR_stream_cross_process_fd " 106 "EGL_EXT_create_context_robustness " 107 "EGL_NV_system_time " 108 "EGL_ANDROID_image_native_buffer " // mandatory 109 "EGL_KHR_wait_sync " // strongly recommended 110 "EGL_ANDROID_recordable " // mandatory 111 "EGL_KHR_partial_update " // strongly recommended 112 "EGL_EXT_buffer_age " // strongly recommended with partial_update 113 "EGL_KHR_create_context_no_error " 114 ; 115 116// extensions not exposed to applications but used by the ANDROID system 117// "EGL_ANDROID_blob_cache " // strongly recommended 118// "EGL_IMG_hibernate_process " // optional 119// "EGL_ANDROID_native_fence_sync " // strongly recommended 120// "EGL_ANDROID_framebuffer_target " // mandatory for HWC 1.1 121// "EGL_ANDROID_image_crop " // optional 122 123/* 124 * EGL Extensions entry-points exposed to 3rd party applications 125 * (keep in sync with gExtensionString above) 126 * 127 */ 128static const extention_map_t sExtensionMap[] = { 129 // EGL_KHR_lock_surface 130 { "eglLockSurfaceKHR", 131 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR }, 132 { "eglUnlockSurfaceKHR", 133 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR }, 134 135 // EGL_KHR_image, EGL_KHR_image_base 136 { "eglCreateImageKHR", 137 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, 138 { "eglDestroyImageKHR", 139 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, 140 141 // EGL_KHR_reusable_sync, EGL_KHR_fence_sync 142 { "eglCreateSyncKHR", 143 (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR }, 144 { "eglDestroySyncKHR", 145 (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR }, 146 { "eglClientWaitSyncKHR", 147 (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR }, 148 { "eglSignalSyncKHR", 149 (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR }, 150 { "eglGetSyncAttribKHR", 151 (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR }, 152 153 // EGL_NV_system_time 154 { "eglGetSystemTimeFrequencyNV", 155 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV }, 156 { "eglGetSystemTimeNV", 157 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV }, 158 159 // EGL_KHR_wait_sync 160 { "eglWaitSyncKHR", 161 (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR }, 162 163 // EGL_ANDROID_presentation_time 164 { "eglPresentationTimeANDROID", 165 (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID }, 166 167 // EGL_KHR_swap_buffers_with_damage 168 { "eglSwapBuffersWithDamageKHR", 169 (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR }, 170 171 // EGL_KHR_partial_update 172 { "eglSetDamageRegionKHR", 173 (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR }, 174 175 { "eglCreateStreamKHR", 176 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamKHR }, 177 { "eglDestroyStreamKHR", 178 (__eglMustCastToProperFunctionPointerType)&eglDestroyStreamKHR }, 179 { "eglStreamAttribKHR", 180 (__eglMustCastToProperFunctionPointerType)&eglStreamAttribKHR }, 181 { "eglQueryStreamKHR", 182 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamKHR }, 183 { "eglQueryStreamu64KHR", 184 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamu64KHR }, 185 { "eglQueryStreamTimeKHR", 186 (__eglMustCastToProperFunctionPointerType)&eglQueryStreamTimeKHR }, 187 { "eglCreateStreamProducerSurfaceKHR", 188 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamProducerSurfaceKHR }, 189 { "eglStreamConsumerGLTextureExternalKHR", 190 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerGLTextureExternalKHR }, 191 { "eglStreamConsumerAcquireKHR", 192 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerAcquireKHR }, 193 { "eglStreamConsumerReleaseKHR", 194 (__eglMustCastToProperFunctionPointerType)&eglStreamConsumerReleaseKHR }, 195 { "eglGetStreamFileDescriptorKHR", 196 (__eglMustCastToProperFunctionPointerType)&eglGetStreamFileDescriptorKHR }, 197 { "eglCreateStreamFromFileDescriptorKHR", 198 (__eglMustCastToProperFunctionPointerType)&eglCreateStreamFromFileDescriptorKHR }, 199}; 200 201/* 202 * These extensions entry-points should not be exposed to applications. 203 * They're used internally by the Android EGL layer. 204 */ 205#define FILTER_EXTENSIONS(procname) \ 206 (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") || \ 207 !strcmp((procname), "eglHibernateProcessIMG") || \ 208 !strcmp((procname), "eglAwakenProcessIMG") || \ 209 !strcmp((procname), "eglDupNativeFenceFDANDROID")) 210 211 212 213// accesses protected by sExtensionMapMutex 214static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap; 215static int sGLExtentionSlot = 0; 216static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER; 217 218static void(*findProcAddress(const char* name, 219 const extention_map_t* map, size_t n))() { 220 for (uint32_t i=0 ; i<n ; i++) { 221 if (!strcmp(name, map[i].name)) { 222 return map[i].address; 223 } 224 } 225 return NULL; 226} 227 228// ---------------------------------------------------------------------------- 229 230extern void setGLHooksThreadSpecific(gl_hooks_t const *value); 231extern EGLBoolean egl_init_drivers(); 232extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS]; 233extern gl_hooks_t gHooksTrace; 234 235} // namespace android; 236 237 238// ---------------------------------------------------------------------------- 239 240static inline void clearError() { egl_tls_t::clearError(); } 241static inline EGLContext getContext() { return egl_tls_t::getContext(); } 242 243// ---------------------------------------------------------------------------- 244 245EGLDisplay eglGetDisplay(EGLNativeDisplayType display) 246{ 247 clearError(); 248 249 uintptr_t index = reinterpret_cast<uintptr_t>(display); 250 if (index >= NUM_DISPLAYS) { 251 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 252 } 253 254 if (egl_init_drivers() == EGL_FALSE) { 255 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 256 } 257 258 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display); 259 return dpy; 260} 261 262// ---------------------------------------------------------------------------- 263// Initialization 264// ---------------------------------------------------------------------------- 265 266EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) 267{ 268 clearError(); 269 270 egl_display_ptr dp = get_display(dpy); 271 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 272 273 EGLBoolean res = dp->initialize(major, minor); 274 275 return res; 276} 277 278EGLBoolean eglTerminate(EGLDisplay dpy) 279{ 280 // NOTE: don't unload the drivers b/c some APIs can be called 281 // after eglTerminate() has been called. eglTerminate() only 282 // terminates an EGLDisplay, not a EGL itself. 283 284 clearError(); 285 286 egl_display_ptr dp = get_display(dpy); 287 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 288 289 EGLBoolean res = dp->terminate(); 290 291 return res; 292} 293 294// ---------------------------------------------------------------------------- 295// configuration 296// ---------------------------------------------------------------------------- 297 298EGLBoolean eglGetConfigs( EGLDisplay dpy, 299 EGLConfig *configs, 300 EGLint config_size, EGLint *num_config) 301{ 302 clearError(); 303 304 const egl_display_ptr dp = validate_display(dpy); 305 if (!dp) return EGL_FALSE; 306 307 if (num_config==0) { 308 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 309 } 310 311 EGLBoolean res = EGL_FALSE; 312 *num_config = 0; 313 314 egl_connection_t* const cnx = &gEGLImpl; 315 if (cnx->dso) { 316 res = cnx->egl.eglGetConfigs( 317 dp->disp.dpy, configs, config_size, num_config); 318 } 319 320 return res; 321} 322 323EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, 324 EGLConfig *configs, EGLint config_size, 325 EGLint *num_config) 326{ 327 clearError(); 328 329 const egl_display_ptr dp = validate_display(dpy); 330 if (!dp) return EGL_FALSE; 331 332 if (num_config==0) { 333 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 334 } 335 336 EGLBoolean res = EGL_FALSE; 337 *num_config = 0; 338 339 egl_connection_t* const cnx = &gEGLImpl; 340 if (cnx->dso) { 341 if (attrib_list) { 342 char value[PROPERTY_VALUE_MAX]; 343 property_get("debug.egl.force_msaa", value, "false"); 344 345 if (!strcmp(value, "true")) { 346 size_t attribCount = 0; 347 EGLint attrib = attrib_list[0]; 348 349 // Only enable MSAA if the context is OpenGL ES 2.0 and 350 // if no caveat is requested 351 const EGLint *attribRendererable = NULL; 352 const EGLint *attribCaveat = NULL; 353 354 // Count the number of attributes and look for 355 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT 356 while (attrib != EGL_NONE) { 357 attrib = attrib_list[attribCount]; 358 switch (attrib) { 359 case EGL_RENDERABLE_TYPE: 360 attribRendererable = &attrib_list[attribCount]; 361 break; 362 case EGL_CONFIG_CAVEAT: 363 attribCaveat = &attrib_list[attribCount]; 364 break; 365 } 366 attribCount++; 367 } 368 369 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT && 370 (!attribCaveat || attribCaveat[1] != EGL_NONE)) { 371 372 // Insert 2 extra attributes to force-enable MSAA 4x 373 EGLint aaAttribs[attribCount + 4]; 374 aaAttribs[0] = EGL_SAMPLE_BUFFERS; 375 aaAttribs[1] = 1; 376 aaAttribs[2] = EGL_SAMPLES; 377 aaAttribs[3] = 4; 378 379 memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint)); 380 381 EGLint numConfigAA; 382 EGLBoolean resAA = cnx->egl.eglChooseConfig( 383 dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA); 384 385 if (resAA == EGL_TRUE && numConfigAA > 0) { 386 ALOGD("Enabling MSAA 4x"); 387 *num_config = numConfigAA; 388 return resAA; 389 } 390 } 391 } 392 } 393 394 res = cnx->egl.eglChooseConfig( 395 dp->disp.dpy, attrib_list, configs, config_size, num_config); 396 } 397 return res; 398} 399 400EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, 401 EGLint attribute, EGLint *value) 402{ 403 clearError(); 404 405 egl_connection_t* cnx = NULL; 406 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 407 if (!dp) return EGL_FALSE; 408 409 return cnx->egl.eglGetConfigAttrib( 410 dp->disp.dpy, config, attribute, value); 411} 412 413// ---------------------------------------------------------------------------- 414// surfaces 415// ---------------------------------------------------------------------------- 416 417// The EGL_KHR_gl_colorspace spec hasn't been ratified yet, so these haven't 418// been added to the Khronos egl.h. 419#define EGL_GL_COLORSPACE_KHR EGL_VG_COLORSPACE 420#define EGL_GL_COLORSPACE_SRGB_KHR EGL_VG_COLORSPACE_sRGB 421#define EGL_GL_COLORSPACE_LINEAR_KHR EGL_VG_COLORSPACE_LINEAR 422 423// Turn linear formats into corresponding sRGB formats when colorspace is 424// EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear 425// formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where 426// the modification isn't possible, the original dataSpace is returned. 427static android_dataspace modifyBufferDataspace( android_dataspace dataSpace, 428 EGLint colorspace) { 429 if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) { 430 return HAL_DATASPACE_SRGB_LINEAR; 431 } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) { 432 return HAL_DATASPACE_SRGB; 433 } 434 return dataSpace; 435} 436 437EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, 438 NativeWindowType window, 439 const EGLint *attrib_list) 440{ 441 clearError(); 442 443 egl_connection_t* cnx = NULL; 444 egl_display_ptr dp = validate_display_connection(dpy, cnx); 445 if (dp) { 446 EGLDisplay iDpy = dp->disp.dpy; 447 448 int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL); 449 if (result != OK) { 450 ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) " 451 "failed (%#x) (already connected to another API?)", 452 window, result); 453 return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE); 454 } 455 456 // Set the native window's buffers format to match what this config requests. 457 // Whether to use sRGB gamma is not part of the EGLconfig, but is part 458 // of our native format. So if sRGB gamma is requested, we have to 459 // modify the EGLconfig's format before setting the native window's 460 // format. 461 462 // by default, just pick RGBA_8888 463 EGLint format = HAL_PIXEL_FORMAT_RGBA_8888; 464 android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN; 465 466 EGLint a = 0; 467 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a); 468 if (a > 0) { 469 // alpha-channel requested, there's really only one suitable format 470 format = HAL_PIXEL_FORMAT_RGBA_8888; 471 } else { 472 EGLint r, g, b; 473 r = g = b = 0; 474 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE, &r); 475 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g); 476 cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE, &b); 477 EGLint colorDepth = r + g + b; 478 if (colorDepth <= 16) { 479 format = HAL_PIXEL_FORMAT_RGB_565; 480 } else { 481 format = HAL_PIXEL_FORMAT_RGBX_8888; 482 } 483 } 484 485 // now select a corresponding sRGB format if needed 486 if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) { 487 for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) { 488 if (*attr == EGL_GL_COLORSPACE_KHR) { 489 if (ENABLE_EGL_KHR_GL_COLORSPACE) { 490 dataSpace = modifyBufferDataspace(dataSpace, *(attr+1)); 491 } else { 492 // Normally we'd pass through unhandled attributes to 493 // the driver. But in case the driver implements this 494 // extension but we're disabling it, we want to prevent 495 // it getting through -- support will be broken without 496 // our help. 497 ALOGE("sRGB window surfaces not supported"); 498 return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); 499 } 500 } 501 } 502 } 503 504 if (format != 0) { 505 int err = native_window_set_buffers_format(window, format); 506 if (err != 0) { 507 ALOGE("error setting native window pixel format: %s (%d)", 508 strerror(-err), err); 509 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 510 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 511 } 512 } 513 514 if (dataSpace != 0) { 515 int err = native_window_set_buffers_data_space(window, dataSpace); 516 if (err != 0) { 517 ALOGE("error setting native window pixel dataSpace: %s (%d)", 518 strerror(-err), err); 519 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 520 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 521 } 522 } 523 524 // the EGL spec requires that a new EGLSurface default to swap interval 525 // 1, so explicitly set that on the window here. 526 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window); 527 anw->setSwapInterval(anw, 1); 528 529 EGLSurface surface = cnx->egl.eglCreateWindowSurface( 530 iDpy, config, window, attrib_list); 531 if (surface != EGL_NO_SURFACE) { 532 egl_surface_t* s = new egl_surface_t(dp.get(), config, window, 533 surface, cnx); 534 return s; 535 } 536 537 // EGLSurface creation failed 538 native_window_set_buffers_format(window, 0); 539 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 540 } 541 return EGL_NO_SURFACE; 542} 543 544EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, 545 NativePixmapType pixmap, 546 const EGLint *attrib_list) 547{ 548 clearError(); 549 550 egl_connection_t* cnx = NULL; 551 egl_display_ptr dp = validate_display_connection(dpy, cnx); 552 if (dp) { 553 EGLSurface surface = cnx->egl.eglCreatePixmapSurface( 554 dp->disp.dpy, config, pixmap, attrib_list); 555 if (surface != EGL_NO_SURFACE) { 556 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, 557 surface, cnx); 558 return s; 559 } 560 } 561 return EGL_NO_SURFACE; 562} 563 564EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, 565 const EGLint *attrib_list) 566{ 567 clearError(); 568 569 egl_connection_t* cnx = NULL; 570 egl_display_ptr dp = validate_display_connection(dpy, cnx); 571 if (dp) { 572 EGLSurface surface = cnx->egl.eglCreatePbufferSurface( 573 dp->disp.dpy, config, attrib_list); 574 if (surface != EGL_NO_SURFACE) { 575 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, 576 surface, cnx); 577 return s; 578 } 579 } 580 return EGL_NO_SURFACE; 581} 582 583EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) 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 s = get_surface(surface); 595 ANativeWindow* window = s->win.get(); 596 if (window) { 597 int result = native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 598 if (result != OK) { 599 ALOGE("eglDestroySurface: native_window_api_disconnect (win=%p) " 600 "failed (%#x)", 601 window, result); 602 } 603 } 604 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface); 605 if (result == EGL_TRUE) { 606 _s.terminate(); 607 } 608 return result; 609} 610 611EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface, 612 EGLint attribute, EGLint *value) 613{ 614 clearError(); 615 616 const egl_display_ptr dp = validate_display(dpy); 617 if (!dp) return EGL_FALSE; 618 619 SurfaceRef _s(dp.get(), surface); 620 if (!_s.get()) 621 return setError(EGL_BAD_SURFACE, EGL_FALSE); 622 623 egl_surface_t const * const s = get_surface(surface); 624 return s->cnx->egl.eglQuerySurface( 625 dp->disp.dpy, s->surface, attribute, value); 626} 627 628void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) { 629 ATRACE_CALL(); 630 clearError(); 631 632 const egl_display_ptr dp = validate_display(dpy); 633 if (!dp) { 634 return; 635 } 636 637 SurfaceRef _s(dp.get(), surface); 638 if (!_s.get()) { 639 setError(EGL_BAD_SURFACE, EGL_FALSE); 640 return; 641 } 642} 643 644// ---------------------------------------------------------------------------- 645// Contexts 646// ---------------------------------------------------------------------------- 647 648EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, 649 EGLContext share_list, const EGLint *attrib_list) 650{ 651 clearError(); 652 653 egl_connection_t* cnx = NULL; 654 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 655 if (dp) { 656 if (share_list != EGL_NO_CONTEXT) { 657 if (!ContextRef(dp.get(), share_list).get()) { 658 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT); 659 } 660 egl_context_t* const c = get_context(share_list); 661 share_list = c->context; 662 } 663 EGLContext context = cnx->egl.eglCreateContext( 664 dp->disp.dpy, config, share_list, attrib_list); 665 if (context != EGL_NO_CONTEXT) { 666 // figure out if it's a GLESv1 or GLESv2 667 int version = 0; 668 if (attrib_list) { 669 while (*attrib_list != EGL_NONE) { 670 GLint attr = *attrib_list++; 671 GLint value = *attrib_list++; 672 if (attr == EGL_CONTEXT_CLIENT_VERSION) { 673 if (value == 1) { 674 version = egl_connection_t::GLESv1_INDEX; 675 } else if (value == 2 || value == 3) { 676 version = egl_connection_t::GLESv2_INDEX; 677 } 678 } 679 }; 680 } 681 egl_context_t* c = new egl_context_t(dpy, context, config, cnx, 682 version); 683 return c; 684 } 685 } 686 return EGL_NO_CONTEXT; 687} 688 689EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) 690{ 691 clearError(); 692 693 const egl_display_ptr dp = validate_display(dpy); 694 if (!dp) 695 return EGL_FALSE; 696 697 ContextRef _c(dp.get(), ctx); 698 if (!_c.get()) 699 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 700 701 egl_context_t * const c = get_context(ctx); 702 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context); 703 if (result == EGL_TRUE) { 704 _c.terminate(); 705 } 706 return result; 707} 708 709EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, 710 EGLSurface read, EGLContext ctx) 711{ 712 clearError(); 713 714 egl_display_ptr dp = validate_display(dpy); 715 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 716 717 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not 718 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is 719 // a valid but uninitialized display. 720 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) || 721 (draw != EGL_NO_SURFACE) ) { 722 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE); 723 } 724 725 // get a reference to the object passed in 726 ContextRef _c(dp.get(), ctx); 727 SurfaceRef _d(dp.get(), draw); 728 SurfaceRef _r(dp.get(), read); 729 730 // validate the context (if not EGL_NO_CONTEXT) 731 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) { 732 // EGL_NO_CONTEXT is valid 733 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 734 } 735 736 // these are the underlying implementation's object 737 EGLContext impl_ctx = EGL_NO_CONTEXT; 738 EGLSurface impl_draw = EGL_NO_SURFACE; 739 EGLSurface impl_read = EGL_NO_SURFACE; 740 741 // these are our objects structs passed in 742 egl_context_t * c = NULL; 743 egl_surface_t const * d = NULL; 744 egl_surface_t const * r = NULL; 745 746 // these are the current objects structs 747 egl_context_t * cur_c = get_context(getContext()); 748 749 if (ctx != EGL_NO_CONTEXT) { 750 c = get_context(ctx); 751 impl_ctx = c->context; 752 } else { 753 // no context given, use the implementation of the current context 754 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) { 755 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT); 756 return setError(EGL_BAD_MATCH, EGL_FALSE); 757 } 758 if (cur_c == NULL) { 759 // no current context 760 // not an error, there is just no current context. 761 return EGL_TRUE; 762 } 763 } 764 765 // retrieve the underlying implementation's draw EGLSurface 766 if (draw != EGL_NO_SURFACE) { 767 if (!_d.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 768 d = get_surface(draw); 769 impl_draw = d->surface; 770 } 771 772 // retrieve the underlying implementation's read EGLSurface 773 if (read != EGL_NO_SURFACE) { 774 if (!_r.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE); 775 r = get_surface(read); 776 impl_read = r->surface; 777 } 778 779 780 EGLBoolean result = dp->makeCurrent(c, cur_c, 781 draw, read, ctx, 782 impl_draw, impl_read, impl_ctx); 783 784 if (result == EGL_TRUE) { 785 if (c) { 786 setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 787 egl_tls_t::setContext(ctx); 788 _c.acquire(); 789 _r.acquire(); 790 _d.acquire(); 791 } else { 792 setGLHooksThreadSpecific(&gHooksNoContext); 793 egl_tls_t::setContext(EGL_NO_CONTEXT); 794 } 795 } else { 796 // this will ALOGE the error 797 egl_connection_t* const cnx = &gEGLImpl; 798 result = setError(cnx->egl.eglGetError(), EGL_FALSE); 799 } 800 return result; 801} 802 803 804EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, 805 EGLint attribute, EGLint *value) 806{ 807 clearError(); 808 809 const egl_display_ptr dp = validate_display(dpy); 810 if (!dp) return EGL_FALSE; 811 812 ContextRef _c(dp.get(), ctx); 813 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 814 815 egl_context_t * const c = get_context(ctx); 816 return c->cnx->egl.eglQueryContext( 817 dp->disp.dpy, c->context, attribute, value); 818 819} 820 821EGLContext eglGetCurrentContext(void) 822{ 823 // could be called before eglInitialize(), but we wouldn't have a context 824 // then, and this function would correctly return EGL_NO_CONTEXT. 825 826 clearError(); 827 828 EGLContext ctx = getContext(); 829 return ctx; 830} 831 832EGLSurface eglGetCurrentSurface(EGLint readdraw) 833{ 834 // could be called before eglInitialize(), but we wouldn't have a context 835 // then, and this function would correctly return EGL_NO_SURFACE. 836 837 clearError(); 838 839 EGLContext ctx = getContext(); 840 if (ctx) { 841 egl_context_t const * const c = get_context(ctx); 842 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 843 switch (readdraw) { 844 case EGL_READ: return c->read; 845 case EGL_DRAW: return c->draw; 846 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 847 } 848 } 849 return EGL_NO_SURFACE; 850} 851 852EGLDisplay eglGetCurrentDisplay(void) 853{ 854 // could be called before eglInitialize(), but we wouldn't have a context 855 // then, and this function would correctly return EGL_NO_DISPLAY. 856 857 clearError(); 858 859 EGLContext ctx = getContext(); 860 if (ctx) { 861 egl_context_t const * const c = get_context(ctx); 862 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 863 return c->dpy; 864 } 865 return EGL_NO_DISPLAY; 866} 867 868EGLBoolean eglWaitGL(void) 869{ 870 clearError(); 871 872 egl_connection_t* const cnx = &gEGLImpl; 873 if (!cnx->dso) 874 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 875 876 return cnx->egl.eglWaitGL(); 877} 878 879EGLBoolean eglWaitNative(EGLint engine) 880{ 881 clearError(); 882 883 egl_connection_t* const cnx = &gEGLImpl; 884 if (!cnx->dso) 885 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 886 887 return cnx->egl.eglWaitNative(engine); 888} 889 890EGLint eglGetError(void) 891{ 892 EGLint err = EGL_SUCCESS; 893 egl_connection_t* const cnx = &gEGLImpl; 894 if (cnx->dso) { 895 err = cnx->egl.eglGetError(); 896 } 897 if (err == EGL_SUCCESS) { 898 err = egl_tls_t::getError(); 899 } 900 return err; 901} 902 903static __eglMustCastToProperFunctionPointerType findBuiltinWrapper( 904 const char* procname) { 905 const egl_connection_t* cnx = &gEGLImpl; 906 void* proc = NULL; 907 908 proc = dlsym(cnx->libEgl, procname); 909 if (proc) return (__eglMustCastToProperFunctionPointerType)proc; 910 911 proc = dlsym(cnx->libGles2, procname); 912 if (proc) return (__eglMustCastToProperFunctionPointerType)proc; 913 914 proc = dlsym(cnx->libGles1, procname); 915 if (proc) return (__eglMustCastToProperFunctionPointerType)proc; 916 917 return NULL; 918} 919 920__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) 921{ 922 // eglGetProcAddress() could be the very first function called 923 // in which case we must make sure we've initialized ourselves, this 924 // happens the first time egl_get_display() is called. 925 926 clearError(); 927 928 if (egl_init_drivers() == EGL_FALSE) { 929 setError(EGL_BAD_PARAMETER, NULL); 930 return NULL; 931 } 932 933 if (FILTER_EXTENSIONS(procname)) { 934 return NULL; 935 } 936 937 __eglMustCastToProperFunctionPointerType addr; 938 addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap)); 939 if (addr) return addr; 940 941 addr = findBuiltinWrapper(procname); 942 if (addr) return addr; 943 944 // this protects accesses to sGLExtentionMap and sGLExtentionSlot 945 pthread_mutex_lock(&sExtensionMapMutex); 946 947 /* 948 * Since eglGetProcAddress() is not associated to anything, it needs 949 * to return a function pointer that "works" regardless of what 950 * the current context is. 951 * 952 * For this reason, we return a "forwarder", a small stub that takes 953 * care of calling the function associated with the context 954 * currently bound. 955 * 956 * We first look for extensions we've already resolved, if we're seeing 957 * this extension for the first time, we go through all our 958 * implementations and call eglGetProcAddress() and record the 959 * result in the appropriate implementation hooks and return the 960 * address of the forwarder corresponding to that hook set. 961 * 962 */ 963 964 const String8 name(procname); 965 addr = sGLExtentionMap.valueFor(name); 966 const int slot = sGLExtentionSlot; 967 968 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS, 969 "no more slots for eglGetProcAddress(\"%s\")", 970 procname); 971 972 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) { 973 bool found = false; 974 975 egl_connection_t* const cnx = &gEGLImpl; 976 if (cnx->dso && cnx->egl.eglGetProcAddress) { 977 // Extensions are independent of the bound context 978 addr = 979 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] = 980 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] = 981 cnx->egl.eglGetProcAddress(procname); 982 if (addr) found = true; 983 } 984 985 if (found) { 986 addr = gExtensionForwarders[slot]; 987 sGLExtentionMap.add(name, addr); 988 sGLExtentionSlot++; 989 } 990 } 991 992 pthread_mutex_unlock(&sExtensionMapMutex); 993 return addr; 994} 995 996class FrameCompletionThread : public Thread { 997public: 998 999 static void queueSync(EGLSyncKHR sync) { 1000 static sp<FrameCompletionThread> thread(new FrameCompletionThread); 1001 static bool running = false; 1002 if (!running) { 1003 thread->run("GPUFrameCompletion"); 1004 running = true; 1005 } 1006 { 1007 Mutex::Autolock lock(thread->mMutex); 1008 ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d", 1009 thread->mFramesQueued).string()); 1010 thread->mQueue.push_back(sync); 1011 thread->mCondition.signal(); 1012 thread->mFramesQueued++; 1013 ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size()); 1014 } 1015 } 1016 1017private: 1018 FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {} 1019 1020 virtual bool threadLoop() { 1021 EGLSyncKHR sync; 1022 uint32_t frameNum; 1023 { 1024 Mutex::Autolock lock(mMutex); 1025 while (mQueue.isEmpty()) { 1026 mCondition.wait(mMutex); 1027 } 1028 sync = mQueue[0]; 1029 frameNum = mFramesCompleted; 1030 } 1031 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); 1032 { 1033 ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d", 1034 frameNum).string()); 1035 EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR); 1036 if (result == EGL_FALSE) { 1037 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError()); 1038 } else if (result == EGL_TIMEOUT_EXPIRED_KHR) { 1039 ALOGE("FrameCompletion: timeout waiting for fence"); 1040 } 1041 eglDestroySyncKHR(dpy, sync); 1042 } 1043 { 1044 Mutex::Autolock lock(mMutex); 1045 mQueue.removeAt(0); 1046 mFramesCompleted++; 1047 ATRACE_INT("GPU Frames Outstanding", mQueue.size()); 1048 } 1049 return true; 1050 } 1051 1052 uint32_t mFramesQueued; 1053 uint32_t mFramesCompleted; 1054 Vector<EGLSyncKHR> mQueue; 1055 Condition mCondition; 1056 Mutex mMutex; 1057}; 1058 1059EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw, 1060 EGLint *rects, EGLint n_rects) 1061{ 1062 ATRACE_CALL(); 1063 clearError(); 1064 1065 const egl_display_ptr dp = validate_display(dpy); 1066 if (!dp) return EGL_FALSE; 1067 1068 SurfaceRef _s(dp.get(), draw); 1069 if (!_s.get()) 1070 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1071 1072 egl_surface_t const * const s = get_surface(draw); 1073 1074 if (CC_UNLIKELY(dp->traceGpuCompletion)) { 1075 EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL); 1076 if (sync != EGL_NO_SYNC_KHR) { 1077 FrameCompletionThread::queueSync(sync); 1078 } 1079 } 1080 1081 if (CC_UNLIKELY(dp->finishOnSwap)) { 1082 uint32_t pixel; 1083 egl_context_t * const c = get_context( egl_tls_t::getContext() ); 1084 if (c) { 1085 // glReadPixels() ensures that the frame is complete 1086 s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1, 1087 GL_RGBA,GL_UNSIGNED_BYTE,&pixel); 1088 } 1089 } 1090 1091 if (n_rects == 0) { 1092 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface); 1093 } 1094 1095 Vector<android_native_rect_t> androidRects; 1096 for (int r = 0; r < n_rects; ++r) { 1097 int offset = r * 4; 1098 int x = rects[offset]; 1099 int y = rects[offset + 1]; 1100 int width = rects[offset + 2]; 1101 int height = rects[offset + 3]; 1102 android_native_rect_t androidRect; 1103 androidRect.left = x; 1104 androidRect.top = y + height; 1105 androidRect.right = x + width; 1106 androidRect.bottom = y; 1107 androidRects.push_back(androidRect); 1108 } 1109 native_window_set_surface_damage(s->win.get(), androidRects.array(), 1110 androidRects.size()); 1111 1112 if (s->cnx->egl.eglSwapBuffersWithDamageKHR) { 1113 return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface, 1114 rects, n_rects); 1115 } else { 1116 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface); 1117 } 1118} 1119 1120EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) 1121{ 1122 return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0); 1123} 1124 1125EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, 1126 NativePixmapType target) 1127{ 1128 clearError(); 1129 1130 const egl_display_ptr dp = validate_display(dpy); 1131 if (!dp) return EGL_FALSE; 1132 1133 SurfaceRef _s(dp.get(), surface); 1134 if (!_s.get()) 1135 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1136 1137 egl_surface_t const * const s = get_surface(surface); 1138 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target); 1139} 1140 1141const char* eglQueryString(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->getVendorString(); 1151 case EGL_VERSION: 1152 return dp->getVersionString(); 1153 case EGL_EXTENSIONS: 1154 return dp->getExtensionString(); 1155 case EGL_CLIENT_APIS: 1156 return dp->getClientApiString(); 1157 } 1158 return setError(EGL_BAD_PARAMETER, (const char *)0); 1159} 1160 1161EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name) 1162{ 1163 clearError(); 1164 1165 const egl_display_ptr dp = validate_display(dpy); 1166 if (!dp) return (const char *) NULL; 1167 1168 switch (name) { 1169 case EGL_VENDOR: 1170 return dp->disp.queryString.vendor; 1171 case EGL_VERSION: 1172 return dp->disp.queryString.version; 1173 case EGL_EXTENSIONS: 1174 return dp->disp.queryString.extensions; 1175 case EGL_CLIENT_APIS: 1176 return dp->disp.queryString.clientApi; 1177 } 1178 return setError(EGL_BAD_PARAMETER, (const char *)0); 1179} 1180 1181// ---------------------------------------------------------------------------- 1182// EGL 1.1 1183// ---------------------------------------------------------------------------- 1184 1185EGLBoolean eglSurfaceAttrib( 1186 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 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.eglSurfaceAttrib) { 1199 return s->cnx->egl.eglSurfaceAttrib( 1200 dp->disp.dpy, s->surface, attribute, value); 1201 } 1202 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1203} 1204 1205EGLBoolean eglBindTexImage( 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.eglBindTexImage) { 1219 return s->cnx->egl.eglBindTexImage( 1220 dp->disp.dpy, s->surface, buffer); 1221 } 1222 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1223} 1224 1225EGLBoolean eglReleaseTexImage( 1226 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1227{ 1228 clearError(); 1229 1230 const egl_display_ptr dp = validate_display(dpy); 1231 if (!dp) return EGL_FALSE; 1232 1233 SurfaceRef _s(dp.get(), surface); 1234 if (!_s.get()) 1235 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1236 1237 egl_surface_t const * const s = get_surface(surface); 1238 if (s->cnx->egl.eglReleaseTexImage) { 1239 return s->cnx->egl.eglReleaseTexImage( 1240 dp->disp.dpy, s->surface, buffer); 1241 } 1242 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1243} 1244 1245EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 1246{ 1247 clearError(); 1248 1249 const egl_display_ptr dp = validate_display(dpy); 1250 if (!dp) return EGL_FALSE; 1251 1252 EGLBoolean res = EGL_TRUE; 1253 egl_connection_t* const cnx = &gEGLImpl; 1254 if (cnx->dso && cnx->egl.eglSwapInterval) { 1255 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval); 1256 } 1257 1258 return res; 1259} 1260 1261 1262// ---------------------------------------------------------------------------- 1263// EGL 1.2 1264// ---------------------------------------------------------------------------- 1265 1266EGLBoolean eglWaitClient(void) 1267{ 1268 clearError(); 1269 1270 egl_connection_t* const cnx = &gEGLImpl; 1271 if (!cnx->dso) 1272 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 1273 1274 EGLBoolean res; 1275 if (cnx->egl.eglWaitClient) { 1276 res = cnx->egl.eglWaitClient(); 1277 } else { 1278 res = cnx->egl.eglWaitGL(); 1279 } 1280 return res; 1281} 1282 1283EGLBoolean eglBindAPI(EGLenum api) 1284{ 1285 clearError(); 1286 1287 if (egl_init_drivers() == EGL_FALSE) { 1288 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1289 } 1290 1291 // bind this API on all EGLs 1292 EGLBoolean res = EGL_TRUE; 1293 egl_connection_t* const cnx = &gEGLImpl; 1294 if (cnx->dso && cnx->egl.eglBindAPI) { 1295 res = cnx->egl.eglBindAPI(api); 1296 } 1297 return res; 1298} 1299 1300EGLenum eglQueryAPI(void) 1301{ 1302 clearError(); 1303 1304 if (egl_init_drivers() == EGL_FALSE) { 1305 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1306 } 1307 1308 egl_connection_t* const cnx = &gEGLImpl; 1309 if (cnx->dso && cnx->egl.eglQueryAPI) { 1310 return cnx->egl.eglQueryAPI(); 1311 } 1312 1313 // or, it can only be OpenGL ES 1314 return EGL_OPENGL_ES_API; 1315} 1316 1317EGLBoolean eglReleaseThread(void) 1318{ 1319 clearError(); 1320 1321 // If there is context bound to the thread, release it 1322 egl_display_t::loseCurrent(get_context(getContext())); 1323 1324 egl_connection_t* const cnx = &gEGLImpl; 1325 if (cnx->dso && cnx->egl.eglReleaseThread) { 1326 cnx->egl.eglReleaseThread(); 1327 } 1328 egl_tls_t::clearTLS(); 1329 return EGL_TRUE; 1330} 1331 1332EGLSurface eglCreatePbufferFromClientBuffer( 1333 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 1334 EGLConfig config, const EGLint *attrib_list) 1335{ 1336 clearError(); 1337 1338 egl_connection_t* cnx = NULL; 1339 const egl_display_ptr dp = validate_display_connection(dpy, cnx); 1340 if (!dp) return EGL_FALSE; 1341 if (cnx->egl.eglCreatePbufferFromClientBuffer) { 1342 return cnx->egl.eglCreatePbufferFromClientBuffer( 1343 dp->disp.dpy, buftype, buffer, config, attrib_list); 1344 } 1345 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); 1346} 1347 1348// ---------------------------------------------------------------------------- 1349// EGL_EGLEXT_VERSION 3 1350// ---------------------------------------------------------------------------- 1351 1352EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, 1353 const EGLint *attrib_list) 1354{ 1355 clearError(); 1356 1357 const egl_display_ptr dp = validate_display(dpy); 1358 if (!dp) return EGL_FALSE; 1359 1360 SurfaceRef _s(dp.get(), surface); 1361 if (!_s.get()) 1362 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1363 1364 egl_surface_t const * const s = get_surface(surface); 1365 if (s->cnx->egl.eglLockSurfaceKHR) { 1366 return s->cnx->egl.eglLockSurfaceKHR( 1367 dp->disp.dpy, s->surface, attrib_list); 1368 } 1369 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1370} 1371 1372EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) 1373{ 1374 clearError(); 1375 1376 const egl_display_ptr dp = validate_display(dpy); 1377 if (!dp) return EGL_FALSE; 1378 1379 SurfaceRef _s(dp.get(), surface); 1380 if (!_s.get()) 1381 return setError(EGL_BAD_SURFACE, EGL_FALSE); 1382 1383 egl_surface_t const * const s = get_surface(surface); 1384 if (s->cnx->egl.eglUnlockSurfaceKHR) { 1385 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface); 1386 } 1387 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 1388} 1389 1390EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1391 EGLClientBuffer buffer, const EGLint *attrib_list) 1392{ 1393 clearError(); 1394 1395 const egl_display_ptr dp = validate_display(dpy); 1396 if (!dp) return EGL_NO_IMAGE_KHR; 1397 1398 ContextRef _c(dp.get(), ctx); 1399 egl_context_t * const c = _c.get(); 1400 1401 EGLImageKHR result = EGL_NO_IMAGE_KHR; 1402 egl_connection_t* const cnx = &gEGLImpl; 1403 if (cnx->dso && cnx->egl.eglCreateImageKHR) { 1404 result = cnx->egl.eglCreateImageKHR( 1405 dp->disp.dpy, 1406 c ? c->context : EGL_NO_CONTEXT, 1407 target, buffer, attrib_list); 1408 } 1409 return result; 1410} 1411 1412EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 1413{ 1414 clearError(); 1415 1416 const egl_display_ptr dp = validate_display(dpy); 1417 if (!dp) return EGL_FALSE; 1418 1419 EGLBoolean result = EGL_FALSE; 1420 egl_connection_t* const cnx = &gEGLImpl; 1421 if (cnx->dso && cnx->egl.eglDestroyImageKHR) { 1422 result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img); 1423 } 1424 return result; 1425} 1426 1427// ---------------------------------------------------------------------------- 1428// EGL_EGLEXT_VERSION 5 1429// ---------------------------------------------------------------------------- 1430 1431 1432EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) 1433{ 1434 clearError(); 1435 1436 const egl_display_ptr dp = validate_display(dpy); 1437 if (!dp) return EGL_NO_SYNC_KHR; 1438 1439 EGLSyncKHR result = EGL_NO_SYNC_KHR; 1440 egl_connection_t* const cnx = &gEGLImpl; 1441 if (cnx->dso && cnx->egl.eglCreateSyncKHR) { 1442 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list); 1443 } 1444 return result; 1445} 1446 1447EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) 1448{ 1449 clearError(); 1450 1451 const egl_display_ptr dp = validate_display(dpy); 1452 if (!dp) return EGL_FALSE; 1453 1454 EGLBoolean result = EGL_FALSE; 1455 egl_connection_t* const cnx = &gEGLImpl; 1456 if (cnx->dso && cnx->egl.eglDestroySyncKHR) { 1457 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync); 1458 } 1459 return result; 1460} 1461 1462EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) { 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.eglSignalSyncKHR) { 1471 result = cnx->egl.eglSignalSyncKHR( 1472 dp->disp.dpy, sync, mode); 1473 } 1474 return result; 1475} 1476 1477EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, 1478 EGLint flags, EGLTimeKHR timeout) 1479{ 1480 clearError(); 1481 1482 const egl_display_ptr dp = validate_display(dpy); 1483 if (!dp) return EGL_FALSE; 1484 1485 EGLBoolean result = EGL_FALSE; 1486 egl_connection_t* const cnx = &gEGLImpl; 1487 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) { 1488 result = cnx->egl.eglClientWaitSyncKHR( 1489 dp->disp.dpy, sync, flags, timeout); 1490 } 1491 return result; 1492} 1493 1494EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, 1495 EGLint attribute, EGLint *value) 1496{ 1497 clearError(); 1498 1499 const egl_display_ptr dp = validate_display(dpy); 1500 if (!dp) return EGL_FALSE; 1501 1502 EGLBoolean result = EGL_FALSE; 1503 egl_connection_t* const cnx = &gEGLImpl; 1504 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) { 1505 result = cnx->egl.eglGetSyncAttribKHR( 1506 dp->disp.dpy, sync, attribute, value); 1507 } 1508 return result; 1509} 1510 1511EGLStreamKHR eglCreateStreamKHR(EGLDisplay dpy, const EGLint *attrib_list) 1512{ 1513 clearError(); 1514 1515 const egl_display_ptr dp = validate_display(dpy); 1516 if (!dp) return EGL_NO_STREAM_KHR; 1517 1518 EGLStreamKHR result = EGL_NO_STREAM_KHR; 1519 egl_connection_t* const cnx = &gEGLImpl; 1520 if (cnx->dso && cnx->egl.eglCreateStreamKHR) { 1521 result = cnx->egl.eglCreateStreamKHR( 1522 dp->disp.dpy, attrib_list); 1523 } 1524 return result; 1525} 1526 1527EGLBoolean eglDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream) 1528{ 1529 clearError(); 1530 1531 const egl_display_ptr dp = validate_display(dpy); 1532 if (!dp) return EGL_FALSE; 1533 1534 EGLBoolean result = EGL_FALSE; 1535 egl_connection_t* const cnx = &gEGLImpl; 1536 if (cnx->dso && cnx->egl.eglDestroyStreamKHR) { 1537 result = cnx->egl.eglDestroyStreamKHR( 1538 dp->disp.dpy, stream); 1539 } 1540 return result; 1541} 1542 1543EGLBoolean eglStreamAttribKHR(EGLDisplay dpy, EGLStreamKHR stream, 1544 EGLenum attribute, EGLint value) 1545{ 1546 clearError(); 1547 1548 const egl_display_ptr dp = validate_display(dpy); 1549 if (!dp) return EGL_FALSE; 1550 1551 EGLBoolean result = EGL_FALSE; 1552 egl_connection_t* const cnx = &gEGLImpl; 1553 if (cnx->dso && cnx->egl.eglStreamAttribKHR) { 1554 result = cnx->egl.eglStreamAttribKHR( 1555 dp->disp.dpy, stream, attribute, value); 1556 } 1557 return result; 1558} 1559 1560EGLBoolean eglQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream, 1561 EGLenum attribute, EGLint *value) 1562{ 1563 clearError(); 1564 1565 const egl_display_ptr dp = validate_display(dpy); 1566 if (!dp) return EGL_FALSE; 1567 1568 EGLBoolean result = EGL_FALSE; 1569 egl_connection_t* const cnx = &gEGLImpl; 1570 if (cnx->dso && cnx->egl.eglQueryStreamKHR) { 1571 result = cnx->egl.eglQueryStreamKHR( 1572 dp->disp.dpy, stream, attribute, value); 1573 } 1574 return result; 1575} 1576 1577EGLBoolean eglQueryStreamu64KHR(EGLDisplay dpy, EGLStreamKHR stream, 1578 EGLenum attribute, EGLuint64KHR *value) 1579{ 1580 clearError(); 1581 1582 const egl_display_ptr dp = validate_display(dpy); 1583 if (!dp) return EGL_FALSE; 1584 1585 EGLBoolean result = EGL_FALSE; 1586 egl_connection_t* const cnx = &gEGLImpl; 1587 if (cnx->dso && cnx->egl.eglQueryStreamu64KHR) { 1588 result = cnx->egl.eglQueryStreamu64KHR( 1589 dp->disp.dpy, stream, attribute, value); 1590 } 1591 return result; 1592} 1593 1594EGLBoolean eglQueryStreamTimeKHR(EGLDisplay dpy, EGLStreamKHR stream, 1595 EGLenum attribute, EGLTimeKHR *value) 1596{ 1597 clearError(); 1598 1599 const egl_display_ptr dp = validate_display(dpy); 1600 if (!dp) return EGL_FALSE; 1601 1602 EGLBoolean result = EGL_FALSE; 1603 egl_connection_t* const cnx = &gEGLImpl; 1604 if (cnx->dso && cnx->egl.eglQueryStreamTimeKHR) { 1605 result = cnx->egl.eglQueryStreamTimeKHR( 1606 dp->disp.dpy, stream, attribute, value); 1607 } 1608 return result; 1609} 1610 1611EGLSurface eglCreateStreamProducerSurfaceKHR(EGLDisplay dpy, EGLConfig config, 1612 EGLStreamKHR stream, const EGLint *attrib_list) 1613{ 1614 clearError(); 1615 1616 egl_display_ptr dp = validate_display(dpy); 1617 if (!dp) return EGL_NO_SURFACE; 1618 1619 egl_connection_t* const cnx = &gEGLImpl; 1620 if (cnx->dso && cnx->egl.eglCreateStreamProducerSurfaceKHR) { 1621 EGLSurface surface = cnx->egl.eglCreateStreamProducerSurfaceKHR( 1622 dp->disp.dpy, config, stream, attrib_list); 1623 if (surface != EGL_NO_SURFACE) { 1624 egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL, 1625 surface, cnx); 1626 return s; 1627 } 1628 } 1629 return EGL_NO_SURFACE; 1630} 1631 1632EGLBoolean eglStreamConsumerGLTextureExternalKHR(EGLDisplay dpy, 1633 EGLStreamKHR stream) 1634{ 1635 clearError(); 1636 1637 const egl_display_ptr dp = validate_display(dpy); 1638 if (!dp) return EGL_FALSE; 1639 1640 EGLBoolean result = EGL_FALSE; 1641 egl_connection_t* const cnx = &gEGLImpl; 1642 if (cnx->dso && cnx->egl.eglStreamConsumerGLTextureExternalKHR) { 1643 result = cnx->egl.eglStreamConsumerGLTextureExternalKHR( 1644 dp->disp.dpy, stream); 1645 } 1646 return result; 1647} 1648 1649EGLBoolean eglStreamConsumerAcquireKHR(EGLDisplay dpy, 1650 EGLStreamKHR stream) 1651{ 1652 clearError(); 1653 1654 const egl_display_ptr dp = validate_display(dpy); 1655 if (!dp) return EGL_FALSE; 1656 1657 EGLBoolean result = EGL_FALSE; 1658 egl_connection_t* const cnx = &gEGLImpl; 1659 if (cnx->dso && cnx->egl.eglStreamConsumerAcquireKHR) { 1660 result = cnx->egl.eglStreamConsumerAcquireKHR( 1661 dp->disp.dpy, stream); 1662 } 1663 return result; 1664} 1665 1666EGLBoolean eglStreamConsumerReleaseKHR(EGLDisplay dpy, 1667 EGLStreamKHR stream) 1668{ 1669 clearError(); 1670 1671 const egl_display_ptr dp = validate_display(dpy); 1672 if (!dp) return EGL_FALSE; 1673 1674 EGLBoolean result = EGL_FALSE; 1675 egl_connection_t* const cnx = &gEGLImpl; 1676 if (cnx->dso && cnx->egl.eglStreamConsumerReleaseKHR) { 1677 result = cnx->egl.eglStreamConsumerReleaseKHR( 1678 dp->disp.dpy, stream); 1679 } 1680 return result; 1681} 1682 1683EGLNativeFileDescriptorKHR eglGetStreamFileDescriptorKHR( 1684 EGLDisplay dpy, EGLStreamKHR stream) 1685{ 1686 clearError(); 1687 1688 const egl_display_ptr dp = validate_display(dpy); 1689 if (!dp) return EGL_NO_FILE_DESCRIPTOR_KHR; 1690 1691 EGLNativeFileDescriptorKHR result = EGL_NO_FILE_DESCRIPTOR_KHR; 1692 egl_connection_t* const cnx = &gEGLImpl; 1693 if (cnx->dso && cnx->egl.eglGetStreamFileDescriptorKHR) { 1694 result = cnx->egl.eglGetStreamFileDescriptorKHR( 1695 dp->disp.dpy, stream); 1696 } 1697 return result; 1698} 1699 1700EGLStreamKHR eglCreateStreamFromFileDescriptorKHR( 1701 EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor) 1702{ 1703 clearError(); 1704 1705 const egl_display_ptr dp = validate_display(dpy); 1706 if (!dp) return EGL_NO_STREAM_KHR; 1707 1708 EGLStreamKHR result = EGL_NO_STREAM_KHR; 1709 egl_connection_t* const cnx = &gEGLImpl; 1710 if (cnx->dso && cnx->egl.eglCreateStreamFromFileDescriptorKHR) { 1711 result = cnx->egl.eglCreateStreamFromFileDescriptorKHR( 1712 dp->disp.dpy, file_descriptor); 1713 } 1714 return result; 1715} 1716 1717// ---------------------------------------------------------------------------- 1718// EGL_EGLEXT_VERSION 15 1719// ---------------------------------------------------------------------------- 1720 1721EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) { 1722 clearError(); 1723 const egl_display_ptr dp = validate_display(dpy); 1724 if (!dp) return EGL_FALSE; 1725 EGLint result = EGL_FALSE; 1726 egl_connection_t* const cnx = &gEGLImpl; 1727 if (cnx->dso && cnx->egl.eglWaitSyncKHR) { 1728 result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags); 1729 } 1730 return result; 1731} 1732 1733// ---------------------------------------------------------------------------- 1734// ANDROID extensions 1735// ---------------------------------------------------------------------------- 1736 1737EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync) 1738{ 1739 clearError(); 1740 1741 const egl_display_ptr dp = validate_display(dpy); 1742 if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID; 1743 1744 EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID; 1745 egl_connection_t* const cnx = &gEGLImpl; 1746 if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) { 1747 result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync); 1748 } 1749 return result; 1750} 1751 1752EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface, 1753 EGLnsecsANDROID time) 1754{ 1755 clearError(); 1756 1757 const egl_display_ptr dp = validate_display(dpy); 1758 if (!dp) { 1759 return EGL_FALSE; 1760 } 1761 1762 SurfaceRef _s(dp.get(), surface); 1763 if (!_s.get()) { 1764 setError(EGL_BAD_SURFACE, EGL_FALSE); 1765 return EGL_FALSE; 1766 } 1767 1768 egl_surface_t const * const s = get_surface(surface); 1769 native_window_set_buffers_timestamp(s->win.get(), time); 1770 1771 return EGL_TRUE; 1772} 1773 1774// ---------------------------------------------------------------------------- 1775// NVIDIA extensions 1776// ---------------------------------------------------------------------------- 1777EGLuint64NV eglGetSystemTimeFrequencyNV() 1778{ 1779 clearError(); 1780 1781 if (egl_init_drivers() == EGL_FALSE) { 1782 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1783 } 1784 1785 EGLuint64NV ret = 0; 1786 egl_connection_t* const cnx = &gEGLImpl; 1787 1788 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) { 1789 return cnx->egl.eglGetSystemTimeFrequencyNV(); 1790 } 1791 1792 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1793} 1794 1795EGLuint64NV eglGetSystemTimeNV() 1796{ 1797 clearError(); 1798 1799 if (egl_init_drivers() == EGL_FALSE) { 1800 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1801 } 1802 1803 EGLuint64NV ret = 0; 1804 egl_connection_t* const cnx = &gEGLImpl; 1805 1806 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) { 1807 return cnx->egl.eglGetSystemTimeNV(); 1808 } 1809 1810 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1811} 1812 1813// ---------------------------------------------------------------------------- 1814// Partial update extension 1815// ---------------------------------------------------------------------------- 1816EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface, 1817 EGLint *rects, EGLint n_rects) 1818{ 1819 clearError(); 1820 1821 const egl_display_ptr dp = validate_display(dpy); 1822 if (!dp) { 1823 setError(EGL_BAD_DISPLAY, EGL_FALSE); 1824 return EGL_FALSE; 1825 } 1826 1827 SurfaceRef _s(dp.get(), surface); 1828 if (!_s.get()) { 1829 setError(EGL_BAD_SURFACE, EGL_FALSE); 1830 return EGL_FALSE; 1831 } 1832 1833 egl_surface_t const * const s = get_surface(surface); 1834 if (s->cnx->egl.eglSetDamageRegionKHR) { 1835 return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface, 1836 rects, n_rects); 1837 } 1838 1839 return EGL_FALSE; 1840} 1841