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