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