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 __STDC_LIMIT_MACROS 1 18 #define ATRACE_TAG ATRACE_TAG_GRAPHICS 19 20 #include "egl_display.h" 21 22 #include "../egl_impl.h" 23 24 #include <EGL/eglext_angle.h> 25 #include <private/EGL/display.h> 26 27 #include <cutils/properties.h> 28 #include "Loader.h" 29 #include "egl_angle_platform.h" 30 #include "egl_cache.h" 31 #include "egl_object.h" 32 #include "egl_tls.h" 33 34 #include <android/dlext.h> 35 #include <dlfcn.h> 36 #include <graphicsenv/GraphicsEnv.h> 37 38 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h> 39 #include <configstore/Utils.h> 40 41 using namespace android::hardware::configstore; 42 using namespace android::hardware::configstore::V1_0; 43 44 // ---------------------------------------------------------------------------- 45 namespace android { 46 // ---------------------------------------------------------------------------- 47 48 static char const * const sVendorString = "Android"; 49 static char const* const sVersionString14 = "1.4 Android META-EGL"; 50 static char const* const sVersionString15 = "1.5 Android META-EGL"; 51 static char const * const sClientApiString = "OpenGL_ES"; 52 53 extern char const * const gBuiltinExtensionString; 54 extern char const * const gExtensionString; 55 56 extern void setGLHooksThreadSpecific(gl_hooks_t const *value); 57 58 // ---------------------------------------------------------------------------- 59 60 bool findExtension(const char* exts, const char* name, size_t nameLen) { 61 if (exts) { 62 if (!nameLen) { 63 nameLen = strlen(name); 64 } 65 for (const char* match = strstr(exts, name); match; match = strstr(match + nameLen, name)) { 66 if (match[nameLen] == '\0' || match[nameLen] == ' ') { 67 return true; 68 } 69 } 70 } 71 return false; 72 } 73 74 bool needsAndroidPEglMitigation() { 75 static const int32_t vndk_version = property_get_int32("ro.vndk.version", -1); 76 return vndk_version <= 28; 77 } 78 79 int egl_get_init_count(EGLDisplay dpy) { 80 egl_display_t* eglDisplay = egl_display_t::get(dpy); 81 return eglDisplay ? eglDisplay->getRefsCount() : 0; 82 } 83 84 egl_display_t egl_display_t::sDisplay[NUM_DISPLAYS]; 85 86 egl_display_t::egl_display_t() : 87 magic('_dpy'), finishOnSwap(false), traceGpuCompletion(false), refs(0), eglIsInitialized(false) { 88 } 89 90 egl_display_t::~egl_display_t() { 91 magic = 0; 92 egl_cache_t::get()->terminate(); 93 } 94 95 egl_display_t* egl_display_t::get(EGLDisplay dpy) { 96 if (uintptr_t(dpy) == 0) { 97 return nullptr; 98 } 99 100 uintptr_t index = uintptr_t(dpy)-1U; 101 if (index >= NUM_DISPLAYS || !sDisplay[index].isValid()) { 102 return nullptr; 103 } 104 return &sDisplay[index]; 105 } 106 107 void egl_display_t::addObject(egl_object_t* object) { 108 std::lock_guard<std::mutex> _l(lock); 109 objects.insert(object); 110 } 111 112 void egl_display_t::removeObject(egl_object_t* object) { 113 std::lock_guard<std::mutex> _l(lock); 114 objects.erase(object); 115 } 116 117 bool egl_display_t::getObject(egl_object_t* object) const { 118 std::lock_guard<std::mutex> _l(lock); 119 if (objects.find(object) != objects.end()) { 120 if (object->getDisplay() == this) { 121 object->incRef(); 122 return true; 123 } 124 } 125 return false; 126 } 127 128 EGLDisplay egl_display_t::getFromNativeDisplay(EGLNativeDisplayType disp, 129 const EGLAttrib* attrib_list) { 130 if (uintptr_t(disp) >= NUM_DISPLAYS) 131 return nullptr; 132 133 return sDisplay[uintptr_t(disp)].getPlatformDisplay(disp, attrib_list); 134 } 135 136 static bool addAnglePlatformAttributes(egl_connection_t* const cnx, 137 std::vector<EGLAttrib>& attrs) { 138 intptr_t vendorEGL = (intptr_t)cnx->vendorEGL; 139 140 attrs.reserve(4 * 2); 141 142 attrs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE); 143 attrs.push_back(cnx->angleBackend); 144 145 switch (cnx->angleBackend) { 146 case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE: 147 ALOGV("%s: Requesting Vulkan ANGLE back-end", __FUNCTION__); 148 char prop[PROPERTY_VALUE_MAX]; 149 property_get("debug.angle.validation", prop, "0"); 150 attrs.push_back(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE); 151 attrs.push_back(atoi(prop)); 152 break; 153 case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE: 154 ALOGV("%s: Requesting Default ANGLE back-end", __FUNCTION__); 155 break; 156 case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE: 157 ALOGV("%s: Requesting OpenGL ES ANGLE back-end", __FUNCTION__); 158 // NOTE: This is only valid if the backend is OpenGL 159 attrs.push_back(EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE); 160 attrs.push_back(vendorEGL); 161 break; 162 default: 163 ALOGV("%s: Requesting Unknown (%d) ANGLE back-end", __FUNCTION__, cnx->angleBackend); 164 break; 165 } 166 attrs.push_back(EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE); 167 attrs.push_back(EGL_FALSE); 168 169 return true; 170 } 171 172 static EGLDisplay getPlatformDisplayAngle(EGLNativeDisplayType display, egl_connection_t* const cnx, 173 const EGLAttrib* attrib_list, EGLint* error) { 174 EGLDisplay dpy = EGL_NO_DISPLAY; 175 *error = EGL_NONE; 176 177 if (cnx->egl.eglGetPlatformDisplay) { 178 std::vector<EGLAttrib> attrs; 179 if (attrib_list) { 180 for (const EGLAttrib* attr = attrib_list; *attr != EGL_NONE; attr += 2) { 181 attrs.push_back(attr[0]); 182 attrs.push_back(attr[1]); 183 } 184 } 185 186 if (!addAnglePlatformAttributes(cnx, attrs)) { 187 ALOGE("eglGetDisplay(%p) failed: Mismatch display request", display); 188 *error = EGL_BAD_PARAMETER; 189 return EGL_NO_DISPLAY; 190 } 191 attrs.push_back(EGL_NONE); 192 193 dpy = cnx->egl.eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE, 194 reinterpret_cast<void*>(EGL_DEFAULT_DISPLAY), 195 attrs.data()); 196 if (dpy == EGL_NO_DISPLAY) { 197 ALOGE("eglGetPlatformDisplay failed!"); 198 } else { 199 if (!angle::initializeAnglePlatform(dpy)) { 200 ALOGE("initializeAnglePlatform failed!"); 201 } 202 } 203 } else { 204 ALOGE("eglGetDisplay(%p) failed: Unable to look up eglGetPlatformDisplay from ANGLE", 205 display); 206 } 207 208 return dpy; 209 } 210 211 EGLDisplay egl_display_t::getPlatformDisplay(EGLNativeDisplayType display, 212 const EGLAttrib* attrib_list) { 213 std::lock_guard<std::mutex> _l(lock); 214 ATRACE_CALL(); 215 216 // get our driver loader 217 Loader& loader(Loader::getInstance()); 218 219 egl_connection_t* const cnx = &gEGLImpl; 220 if (cnx->dso) { 221 EGLDisplay dpy = EGL_NO_DISPLAY; 222 223 if (cnx->useAngle) { 224 EGLint error; 225 dpy = getPlatformDisplayAngle(display, cnx, attrib_list, &error); 226 if (error != EGL_NONE) { 227 return setError(error, dpy); 228 } 229 } 230 if (dpy == EGL_NO_DISPLAY) { 231 // NOTE: eglGetPlatformDisplay with a empty attribute list 232 // behaves the same as eglGetDisplay 233 if (cnx->egl.eglGetPlatformDisplay) { 234 dpy = cnx->egl.eglGetPlatformDisplay(EGL_PLATFORM_ANDROID_KHR, display, 235 attrib_list); 236 } 237 238 // It is possible that eglGetPlatformDisplay does not have a 239 // working implementation for Android platform; in that case, 240 // one last fallback to eglGetDisplay 241 if(dpy == EGL_NO_DISPLAY) { 242 if (attrib_list) { 243 ALOGW("getPlatformDisplay: unexpected attribute list, attributes ignored"); 244 } 245 dpy = cnx->egl.eglGetDisplay(display); 246 } 247 } 248 249 disp.dpy = dpy; 250 if (dpy == EGL_NO_DISPLAY) { 251 loader.close(cnx); 252 } 253 } 254 255 return EGLDisplay(uintptr_t(display) + 1U); 256 } 257 258 EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) { 259 260 { // scope for refLock 261 std::unique_lock<std::mutex> _l(refLock); 262 refs++; 263 if (refs > 1) { 264 // We don't know what to report until we know what the 265 // driver supports. Make sure we are initialized before 266 // returning the version info. 267 while(!eglIsInitialized) { 268 refCond.wait(_l); 269 } 270 egl_connection_t* const cnx = &gEGLImpl; 271 272 // TODO: If device doesn't provide 1.4 or 1.5 then we'll be 273 // changing the behavior from the past where we always advertise 274 // version 1.4. May need to check that revision is valid 275 // before using cnx->major & cnx->minor 276 if (major != nullptr) *major = cnx->major; 277 if (minor != nullptr) *minor = cnx->minor; 278 return EGL_TRUE; 279 } 280 while(eglIsInitialized) { 281 refCond.wait(_l); 282 } 283 } 284 285 { // scope for lock 286 std::lock_guard<std::mutex> _l(lock); 287 288 setGLHooksThreadSpecific(&gHooksNoContext); 289 290 // initialize each EGL and 291 // build our own extension string first, based on the extension we know 292 // and the extension supported by our client implementation 293 294 egl_connection_t* const cnx = &gEGLImpl; 295 cnx->major = -1; 296 cnx->minor = -1; 297 if (cnx->dso) { 298 EGLDisplay idpy = disp.dpy; 299 if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) { 300 //ALOGD("initialized dpy=%p, ver=%d.%d, cnx=%p", 301 // idpy, cnx->major, cnx->minor, cnx); 302 303 // display is now initialized 304 disp.state = egl_display_t::INITIALIZED; 305 306 // get the query-strings for this display for each implementation 307 disp.queryString.vendor = cnx->egl.eglQueryString(idpy, 308 EGL_VENDOR); 309 disp.queryString.version = cnx->egl.eglQueryString(idpy, 310 EGL_VERSION); 311 disp.queryString.extensions = cnx->egl.eglQueryString(idpy, 312 EGL_EXTENSIONS); 313 disp.queryString.clientApi = cnx->egl.eglQueryString(idpy, 314 EGL_CLIENT_APIS); 315 316 } else { 317 ALOGW("eglInitialize(%p) failed (%s)", idpy, 318 egl_tls_t::egl_strerror(cnx->egl.eglGetError())); 319 } 320 } 321 322 if (cnx->minor == 5) { 323 // full list in egl_entries.in 324 if (!cnx->egl.eglCreateImage || 325 !cnx->egl.eglDestroyImage || 326 !cnx->egl.eglGetPlatformDisplay || 327 !cnx->egl.eglCreatePlatformWindowSurface || 328 !cnx->egl.eglCreatePlatformPixmapSurface || 329 !cnx->egl.eglCreateSync || 330 !cnx->egl.eglDestroySync || 331 !cnx->egl.eglClientWaitSync || 332 !cnx->egl.eglGetSyncAttrib || 333 !cnx->egl.eglWaitSync) { 334 ALOGE("Driver indicates EGL 1.5 support, but does not have " 335 "a critical API"); 336 cnx->minor = 4; 337 } 338 } 339 340 // the query strings are per-display 341 mVendorString = sVendorString; 342 mVersionString.clear(); 343 cnx->driverVersion = EGL_MAKE_VERSION(1, 4, 0); 344 mVersionString = sVersionString14; 345 if ((cnx->major == 1) && (cnx->minor == 5)) { 346 mVersionString = sVersionString15; 347 cnx->driverVersion = EGL_MAKE_VERSION(1, 5, 0); 348 } 349 if (mVersionString.empty()) { 350 ALOGW("Unexpected driver version: %d.%d, want 1.4 or 1.5", cnx->major, cnx->minor); 351 mVersionString = sVersionString14; 352 } 353 mClientApiString = sClientApiString; 354 355 mExtensionString = gBuiltinExtensionString; 356 357 hasColorSpaceSupport = findExtension(disp.queryString.extensions, "EGL_KHR_gl_colorspace"); 358 359 // Note: CDD requires that devices supporting wide color and/or HDR color also support 360 // the EGL_KHR_gl_colorspace extension. 361 bool wideColorBoardConfig = 362 getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>( 363 false); 364 365 // Add wide-color extensions if device can support wide-color 366 if (wideColorBoardConfig && hasColorSpaceSupport) { 367 mExtensionString.append( 368 "EGL_EXT_gl_colorspace_scrgb EGL_EXT_gl_colorspace_scrgb_linear " 369 "EGL_EXT_gl_colorspace_display_p3_linear EGL_EXT_gl_colorspace_display_p3 " 370 "EGL_EXT_gl_colorspace_display_p3_passthrough "); 371 } 372 373 bool hasHdrBoardConfig = 374 getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasHDRDisplay>(false); 375 376 if (hasHdrBoardConfig && hasColorSpaceSupport) { 377 // hasHDRBoardConfig indicates the system is capable of supporting HDR content. 378 // Typically that means there is an HDR capable display attached, but could be 379 // support for attaching an HDR display. In either case, advertise support for 380 // HDR color spaces. 381 mExtensionString.append( 382 "EGL_EXT_gl_colorspace_bt2020_linear EGL_EXT_gl_colorspace_bt2020_pq "); 383 } 384 385 char const* start = gExtensionString; 386 do { 387 // length of the extension name 388 size_t len = strcspn(start, " "); 389 if (len) { 390 // NOTE: we could avoid the copy if we had strnstr. 391 const std::string ext(start, len); 392 // Mitigation for Android P vendor partitions: Adreno 530 driver shipped on 393 // some Android P vendor partitions this extension under the draft KHR name, 394 // but during Khronos review it was decided to demote it to EXT. 395 if (needsAndroidPEglMitigation() && ext == "EGL_EXT_image_gl_colorspace" && 396 findExtension(disp.queryString.extensions, "EGL_KHR_image_gl_colorspace")) { 397 mExtensionString.append("EGL_EXT_image_gl_colorspace "); 398 } 399 if (findExtension(disp.queryString.extensions, ext.c_str(), len)) { 400 mExtensionString.append(ext + " "); 401 } 402 // advance to the next extension name, skipping the space. 403 start += len; 404 start += (*start == ' ') ? 1 : 0; 405 } 406 } while (*start != '\0'); 407 408 egl_cache_t::get()->initialize(this); 409 410 char value[PROPERTY_VALUE_MAX]; 411 property_get("debug.egl.finish", value, "0"); 412 if (atoi(value)) { 413 finishOnSwap = true; 414 } 415 416 property_get("debug.egl.traceGpuCompletion", value, "0"); 417 if (atoi(value)) { 418 traceGpuCompletion = true; 419 } 420 421 // TODO: If device doesn't provide 1.4 or 1.5 then we'll be 422 // changing the behavior from the past where we always advertise 423 // version 1.4. May need to check that revision is valid 424 // before using cnx->major & cnx->minor 425 if (major != nullptr) *major = cnx->major; 426 if (minor != nullptr) *minor = cnx->minor; 427 } 428 429 { // scope for refLock 430 std::unique_lock<std::mutex> _l(refLock); 431 eglIsInitialized = true; 432 refCond.notify_all(); 433 } 434 435 return EGL_TRUE; 436 } 437 438 EGLBoolean egl_display_t::terminate() { 439 440 { // scope for refLock 441 std::unique_lock<std::mutex> _rl(refLock); 442 if (refs == 0) { 443 /* 444 * From the EGL spec (3.2): 445 * "Termination of a display that has already been terminated, 446 * (...), is allowed, but the only effect of such a call is 447 * to return EGL_TRUE (...) 448 */ 449 return EGL_TRUE; 450 } 451 452 // this is specific to Android, display termination is ref-counted. 453 refs--; 454 if (refs > 0) { 455 return EGL_TRUE; 456 } 457 } 458 459 EGLBoolean res = EGL_FALSE; 460 461 { // scope for lock 462 std::lock_guard<std::mutex> _l(lock); 463 464 egl_connection_t* const cnx = &gEGLImpl; 465 if (cnx->dso && disp.state == egl_display_t::INITIALIZED) { 466 // If we're using ANGLE reset any custom DisplayPlatform 467 if (cnx->useAngle) { 468 angle::resetAnglePlatform(disp.dpy); 469 } 470 if (cnx->egl.eglTerminate(disp.dpy) == EGL_FALSE) { 471 ALOGW("eglTerminate(%p) failed (%s)", disp.dpy, 472 egl_tls_t::egl_strerror(cnx->egl.eglGetError())); 473 } 474 // REVISIT: it's unclear what to do if eglTerminate() fails 475 disp.state = egl_display_t::TERMINATED; 476 res = EGL_TRUE; 477 } 478 479 // Reset the extension string since it will be regenerated if we get 480 // reinitialized. 481 mExtensionString.clear(); 482 483 // Mark all objects remaining in the list as terminated, unless 484 // there are no reference to them, it which case, we're free to 485 // delete them. 486 size_t count = objects.size(); 487 ALOGW_IF(count, "eglTerminate() called w/ %zu objects remaining", count); 488 for (auto o : objects) { 489 o->destroy(); 490 } 491 492 // this marks all object handles are "terminated" 493 objects.clear(); 494 } 495 496 { // scope for refLock 497 std::unique_lock<std::mutex> _rl(refLock); 498 eglIsInitialized = false; 499 refCond.notify_all(); 500 } 501 502 return res; 503 } 504 505 void egl_display_t::loseCurrent(egl_context_t * cur_c) 506 { 507 if (cur_c) { 508 egl_display_t* display = cur_c->getDisplay(); 509 if (display) { 510 display->loseCurrentImpl(cur_c); 511 } 512 } 513 } 514 515 void egl_display_t::loseCurrentImpl(egl_context_t * cur_c) 516 { 517 // by construction, these are either 0 or valid (possibly terminated) 518 // it should be impossible for these to be invalid 519 ContextRef _cur_c(cur_c); 520 SurfaceRef _cur_r(cur_c ? get_surface(cur_c->read) : nullptr); 521 SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : nullptr); 522 523 { // scope for the lock 524 std::lock_guard<std::mutex> _l(lock); 525 cur_c->onLooseCurrent(); 526 527 } 528 529 // This cannot be called with the lock held because it might end-up 530 // calling back into EGL (in particular when a surface is destroyed 531 // it calls ANativeWindow::disconnect 532 _cur_c.release(); 533 _cur_r.release(); 534 _cur_d.release(); 535 } 536 537 EGLBoolean egl_display_t::makeCurrent(egl_context_t* c, egl_context_t* cur_c, 538 EGLSurface draw, EGLSurface read, EGLContext /*ctx*/, 539 EGLSurface impl_draw, EGLSurface impl_read, EGLContext impl_ctx) 540 { 541 EGLBoolean result; 542 543 // by construction, these are either 0 or valid (possibly terminated) 544 // it should be impossible for these to be invalid 545 ContextRef _cur_c(cur_c); 546 SurfaceRef _cur_r(cur_c ? get_surface(cur_c->read) : nullptr); 547 SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : nullptr); 548 549 { // scope for the lock 550 std::lock_guard<std::mutex> _l(lock); 551 if (c) { 552 result = c->cnx->egl.eglMakeCurrent( 553 disp.dpy, impl_draw, impl_read, impl_ctx); 554 if (result == EGL_TRUE) { 555 c->onMakeCurrent(draw, read); 556 } 557 } else { 558 result = cur_c->cnx->egl.eglMakeCurrent( 559 disp.dpy, impl_draw, impl_read, impl_ctx); 560 if (result == EGL_TRUE) { 561 cur_c->onLooseCurrent(); 562 } 563 } 564 } 565 566 if (result == EGL_TRUE) { 567 // This cannot be called with the lock held because it might end-up 568 // calling back into EGL (in particular when a surface is destroyed 569 // it calls ANativeWindow::disconnect 570 _cur_c.release(); 571 _cur_r.release(); 572 _cur_d.release(); 573 } 574 575 return result; 576 } 577 578 bool egl_display_t::haveExtension(const char* name, size_t nameLen) const { 579 if (!nameLen) { 580 nameLen = strlen(name); 581 } 582 return findExtension(mExtensionString.c_str(), name, nameLen); 583 } 584 585 // ---------------------------------------------------------------------------- 586 }; // namespace android 587 // ---------------------------------------------------------------------------- 588