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