Display.cpp (78477B)
1 // 2 // Copyright 2002 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // Display.cpp: Implements the egl::Display class, representing the abstract 8 // display on which graphics are drawn. Implements EGLDisplay. 9 // [EGL 1.4] section 2.1.2 page 3. 10 11 #include "libANGLE/Display.h" 12 13 #include <algorithm> 14 #include <iterator> 15 #include <sstream> 16 #include <vector> 17 18 #include <EGL/eglext.h> 19 #include <platform/PlatformMethods.h> 20 21 #include "anglebase/no_destructor.h" 22 #include "common/android_util.h" 23 #include "common/debug.h" 24 #include "common/mathutil.h" 25 #include "common/platform.h" 26 #include "common/string_utils.h" 27 #include "common/system_utils.h" 28 #include "common/tls.h" 29 #include "common/utilities.h" 30 #include "gpu_info_util/SystemInfo.h" 31 #include "libANGLE/Context.h" 32 #include "libANGLE/Device.h" 33 #include "libANGLE/EGLSync.h" 34 #include "libANGLE/Image.h" 35 #include "libANGLE/ResourceManager.h" 36 #include "libANGLE/Stream.h" 37 #include "libANGLE/Surface.h" 38 #include "libANGLE/Thread.h" 39 #include "libANGLE/capture/FrameCapture.h" 40 #include "libANGLE/histogram_macros.h" 41 #include "libANGLE/renderer/DeviceImpl.h" 42 #include "libANGLE/renderer/DisplayImpl.h" 43 #include "libANGLE/renderer/ImageImpl.h" 44 #include "libANGLE/trace.h" 45 46 #if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11) 47 # include <versionhelpers.h> 48 49 # include "libANGLE/renderer/d3d/DisplayD3D.h" 50 #endif 51 52 #if defined(ANGLE_ENABLE_OPENGL) 53 # if defined(ANGLE_PLATFORM_WINDOWS) 54 # include "libANGLE/renderer/gl/wgl/DisplayWGL.h" 55 # elif defined(ANGLE_PLATFORM_MACOS) || defined(ANGLE_PLATFORM_IOS) 56 # include "libANGLE/renderer/gl/apple/DisplayApple_api.h" 57 # elif defined(ANGLE_PLATFORM_LINUX) 58 # include "libANGLE/renderer/gl/egl/DisplayEGL.h" 59 # if defined(ANGLE_USE_GBM) 60 # include "libANGLE/renderer/gl/egl/gbm/DisplayGbm.h" 61 # endif 62 # if defined(ANGLE_USE_X11) 63 # include "libANGLE/renderer/gl/glx/DisplayGLX.h" 64 # endif 65 # elif defined(ANGLE_PLATFORM_ANDROID) 66 # include "libANGLE/renderer/gl/egl/android/DisplayAndroid.h" 67 # else 68 # error Unsupported OpenGL platform. 69 # endif 70 #endif 71 72 #if defined(ANGLE_ENABLE_NULL) 73 # include "libANGLE/renderer/null/DisplayNULL.h" 74 #endif // defined(ANGLE_ENABLE_NULL) 75 76 #if defined(ANGLE_ENABLE_VULKAN) 77 # include "libANGLE/renderer/vulkan/DisplayVk_api.h" 78 #endif // defined(ANGLE_ENABLE_VULKAN) 79 80 #if defined(ANGLE_ENABLE_METAL) 81 # include "libANGLE/renderer/metal/DisplayMtl_api.h" 82 #endif // defined(ANGLE_ENABLE_METAL) 83 84 namespace egl 85 { 86 87 namespace 88 { 89 90 constexpr angle::SubjectIndex kGPUSwitchedSubjectIndex = 0; 91 92 static constexpr size_t kWindowSurfaceMapSize = 32; 93 typedef angle::FlatUnorderedMap<EGLNativeWindowType, Surface *, kWindowSurfaceMapSize> 94 WindowSurfaceMap; 95 // Get a map of all EGL window surfaces to validate that no window has more than one EGL surface 96 // associated with it. 97 static WindowSurfaceMap *GetWindowSurfaces() 98 { 99 static angle::base::NoDestructor<WindowSurfaceMap> windowSurfaces; 100 return windowSurfaces.get(); 101 } 102 103 struct ANGLEPlatformDisplay 104 { 105 ANGLEPlatformDisplay() = default; 106 107 ANGLEPlatformDisplay(EGLNativeDisplayType nativeDisplayType) 108 : nativeDisplayType(nativeDisplayType) 109 {} 110 111 ANGLEPlatformDisplay(EGLNativeDisplayType nativeDisplayType, 112 EGLAttrib powerPreference, 113 EGLAttrib platformANGLEType, 114 EGLAttrib deviceIdHigh, 115 EGLAttrib deviceIdLow) 116 : nativeDisplayType(nativeDisplayType), 117 powerPreference(powerPreference), 118 platformANGLEType(platformANGLEType), 119 deviceIdHigh(deviceIdHigh), 120 deviceIdLow(deviceIdLow) 121 {} 122 123 auto tie() const 124 { 125 return std::tie(nativeDisplayType, powerPreference, platformANGLEType, deviceIdHigh, 126 deviceIdLow); 127 } 128 129 EGLNativeDisplayType nativeDisplayType{EGL_DEFAULT_DISPLAY}; 130 EGLAttrib powerPreference{EGL_LOW_POWER_ANGLE}; 131 EGLAttrib platformANGLEType{EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE}; 132 EGLAttrib deviceIdHigh{0}; 133 EGLAttrib deviceIdLow{0}; 134 }; 135 136 inline bool operator==(const ANGLEPlatformDisplay &a, const ANGLEPlatformDisplay &b) 137 { 138 return a.tie() == b.tie(); 139 } 140 141 static constexpr size_t kANGLEPlatformDisplayMapSize = 9; 142 typedef angle::FlatUnorderedMap<ANGLEPlatformDisplay, Display *, kANGLEPlatformDisplayMapSize> 143 ANGLEPlatformDisplayMap; 144 static ANGLEPlatformDisplayMap *GetANGLEPlatformDisplayMap() 145 { 146 static angle::base::NoDestructor<ANGLEPlatformDisplayMap> displays; 147 return displays.get(); 148 } 149 150 static constexpr size_t kDevicePlatformDisplayMapSize = 8; 151 typedef angle::FlatUnorderedMap<Device *, Display *, kDevicePlatformDisplayMapSize> 152 DevicePlatformDisplayMap; 153 static DevicePlatformDisplayMap *GetDevicePlatformDisplayMap() 154 { 155 static angle::base::NoDestructor<DevicePlatformDisplayMap> displays; 156 return displays.get(); 157 } 158 159 rx::DisplayImpl *CreateDisplayFromDevice(Device *eglDevice, const DisplayState &state) 160 { 161 rx::DisplayImpl *impl = nullptr; 162 163 switch (eglDevice->getType()) 164 { 165 #if defined(ANGLE_ENABLE_D3D11) 166 case EGL_D3D11_DEVICE_ANGLE: 167 impl = new rx::DisplayD3D(state); 168 break; 169 #endif 170 #if defined(ANGLE_ENABLE_D3D9) 171 case EGL_D3D9_DEVICE_ANGLE: 172 // Currently the only way to get EGLDeviceEXT representing a D3D9 device 173 // is to retrieve one from an already-existing EGLDisplay. 174 // When eglGetPlatformDisplayEXT is called with a D3D9 EGLDeviceEXT, 175 // the already-existing display should be returned. 176 // Therefore this codepath to create a new display from the device 177 // should never be hit. 178 UNREACHABLE(); 179 break; 180 #endif 181 default: 182 UNREACHABLE(); 183 break; 184 } 185 186 ASSERT(impl != nullptr); 187 return impl; 188 } 189 190 // On platforms with support for multiple back-ends, allow an environment variable to control 191 // the default. This is useful to run angle with benchmarks without having to modify the 192 // benchmark source. Possible values for this environment variable (ANGLE_DEFAULT_PLATFORM) 193 // are: vulkan, gl, d3d11, null. 194 EGLAttrib GetDisplayTypeFromEnvironment() 195 { 196 std::string angleDefaultEnv = angle::GetEnvironmentVar("ANGLE_DEFAULT_PLATFORM"); 197 angle::ToLower(&angleDefaultEnv); 198 199 #if defined(ANGLE_ENABLE_VULKAN) 200 if ((angleDefaultEnv == "vulkan") || (angleDefaultEnv == "vulkan-null") || 201 (angleDefaultEnv == "swiftshader")) 202 { 203 return EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE; 204 } 205 #endif 206 207 #if defined(ANGLE_ENABLE_OPENGL) 208 if (angleDefaultEnv == "gl") 209 { 210 return EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE; 211 } 212 #endif 213 214 #if defined(ANGLE_ENABLE_D3D11) 215 if (angleDefaultEnv == "d3d11") 216 { 217 return EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE; 218 } 219 #endif 220 221 #if defined(ANGLE_ENABLE_METAL) 222 if (angleDefaultEnv == "metal") 223 { 224 return EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE; 225 } 226 #endif 227 228 #if defined(ANGLE_ENABLE_NULL) 229 if (angleDefaultEnv == "null") 230 { 231 return EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE; 232 } 233 #endif 234 #if defined(ANGLE_ENABLE_METAL) 235 if (angleDefaultEnv == "metal") 236 { 237 return EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE; 238 } 239 240 #endif 241 #if defined(ANGLE_ENABLE_D3D11) 242 return EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE; 243 #elif defined(ANGLE_ENABLE_D3D9) 244 return EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE; 245 #elif defined(ANGLE_ENABLE_VULKAN) && defined(ANGLE_PLATFORM_ANDROID) 246 return EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE; 247 #elif defined(ANGLE_ENABLE_OPENGL) 248 # if defined(ANGLE_PLATFORM_ANDROID) || defined(ANGLE_USE_GBM) 249 return EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE; 250 # else 251 return EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE; 252 # endif 253 #elif defined(ANGLE_ENABLE_METAL) 254 return EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE; 255 #elif defined(ANGLE_ENABLE_VULKAN) 256 return EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE; 257 #elif defined(ANGLE_ENABLE_NULL) 258 return EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE; 259 #else 260 # error No default ANGLE platform type 261 #endif 262 } 263 264 EGLAttrib GetDeviceTypeFromEnvironment() 265 { 266 std::string angleDefaultEnv = angle::GetEnvironmentVar("ANGLE_DEFAULT_PLATFORM"); 267 angle::ToLower(&angleDefaultEnv); 268 269 #if defined(ANGLE_ENABLE_VULKAN) 270 if (angleDefaultEnv == "vulkan-null") 271 { 272 return EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE; 273 } 274 else if (angleDefaultEnv == "swiftshader") 275 { 276 return EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE; 277 } 278 #endif 279 return EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE; 280 } 281 282 EGLAttrib GetPlatformTypeFromEnvironment() 283 { 284 #if defined(ANGLE_USE_OZONE) 285 return 0; 286 #elif defined(ANGLE_USE_X11) 287 return EGL_PLATFORM_X11_EXT; 288 #elif defined(ANGLE_USE_WAYLAND) 289 return EGL_PLATFORM_WAYLAND_EXT; 290 #elif defined(ANGLE_USE_VULKAN_DISPLAY) && defined(ANGLE_VULKAN_DISPLAY_MODE_SIMPLE) 291 return EGL_PLATFORM_VULKAN_DISPLAY_MODE_SIMPLE_ANGLE; 292 #elif defined(ANGLE_USE_VULKAN_DISPLAY) && defined(ANGLE_VULKAN_DISPLAY_MODE_HEADLESS) 293 return EGL_PLATFORM_VULKAN_DISPLAY_MODE_HEADLESS_ANGLE; 294 #else 295 return 0; 296 #endif // defined(ANGLE_USE_OZONE) 297 } 298 299 rx::DisplayImpl *CreateDisplayFromAttribs(EGLAttrib displayType, 300 EGLAttrib deviceType, 301 EGLAttrib platformType, 302 const DisplayState &state) 303 { 304 ASSERT(displayType != EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE); 305 rx::DisplayImpl *impl = nullptr; 306 307 switch (displayType) 308 { 309 case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE: 310 UNREACHABLE(); 311 break; 312 313 case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE: 314 case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE: 315 #if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11) 316 impl = new rx::DisplayD3D(state); 317 break; 318 #else 319 // A D3D display was requested on a platform that doesn't support it 320 UNREACHABLE(); 321 break; 322 #endif 323 324 case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE: 325 #if defined(ANGLE_ENABLE_OPENGL) 326 # if defined(ANGLE_PLATFORM_WINDOWS) 327 impl = new rx::DisplayWGL(state); 328 break; 329 330 # elif defined(ANGLE_PLATFORM_MACOS) || defined(ANGLE_PLATFORM_IOS) 331 impl = rx::CreateDisplayCGLOrEAGL(state); 332 break; 333 334 # elif defined(ANGLE_PLATFORM_LINUX) 335 # if defined(ANGLE_USE_GBM) 336 if (platformType == 0) 337 { 338 // If platformType is unknown, use DisplayGbm now. In the future, it should use 339 // DisplayEGL letting native EGL decide what display to use. 340 impl = new rx::DisplayGbm(state); 341 break; 342 } 343 # endif 344 if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_EGL_ANGLE) 345 { 346 impl = new rx::DisplayEGL(state); 347 break; 348 } 349 # if defined(ANGLE_USE_X11) 350 if (platformType == EGL_PLATFORM_X11_EXT) 351 { 352 impl = new rx::DisplayGLX(state); 353 break; 354 } 355 # endif 356 break; 357 358 # elif defined(ANGLE_PLATFORM_ANDROID) 359 // No GL support on this platform, fail display creation. 360 impl = nullptr; 361 break; 362 363 # else 364 # error Unsupported OpenGL platform. 365 # endif 366 #else 367 // No display available 368 UNREACHABLE(); 369 break; 370 371 #endif // defined(ANGLE_ENABLE_OPENGL) 372 373 case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE: 374 #if defined(ANGLE_ENABLE_OPENGL) 375 # if defined(ANGLE_PLATFORM_WINDOWS) 376 impl = new rx::DisplayWGL(state); 377 # elif defined(ANGLE_PLATFORM_LINUX) 378 # if defined(ANGLE_USE_GBM) 379 if (platformType == 0 || 380 platformType == EGL_PLATFORM_VULKAN_DISPLAY_MODE_HEADLESS_ANGLE) 381 { 382 // If platformType is unknown, use DisplayGbm now. In the future, it should use 383 // DisplayEGL letting native EGL decide what display to use. 384 // platformType == EGL_PLATFORM_VULKAN_DISPLAY_MODE_HEADLESS_ANGLE is a hack, 385 // to allow ChromeOS GLES backend to continue functioning when Vulkan is enabled. 386 impl = new rx::DisplayGbm(state); 387 break; 388 } 389 # endif 390 if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_EGL_ANGLE) 391 { 392 impl = new rx::DisplayEGL(state); 393 break; 394 } 395 else 396 { 397 # if defined(ANGLE_USE_X11) 398 if (platformType == EGL_PLATFORM_X11_EXT) 399 { 400 impl = new rx::DisplayGLX(state); 401 break; 402 } 403 # endif 404 } 405 # elif defined(ANGLE_PLATFORM_ANDROID) 406 impl = new rx::DisplayAndroid(state); 407 # else 408 // No GLES support on this platform, fail display creation. 409 impl = nullptr; 410 # endif 411 #endif // defined(ANGLE_ENABLE_OPENGL) 412 break; 413 414 case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE: 415 #if defined(ANGLE_ENABLE_VULKAN) 416 # if defined(ANGLE_USE_VULKAN_NULL_DISPLAY) 417 if (rx::IsVulkanNullDisplayAvailable()) 418 { 419 impl = rx::CreateVulkanNullDisplay(state); 420 } 421 break; 422 # elif defined(ANGLE_PLATFORM_WINDOWS) 423 if (rx::IsVulkanWin32DisplayAvailable()) 424 { 425 impl = rx::CreateVulkanWin32Display(state); 426 } 427 break; 428 # elif defined(ANGLE_PLATFORM_LINUX) 429 # if defined(ANGLE_USE_GBM) 430 if (platformType == EGL_PLATFORM_GBM_KHR && rx::IsVulkanGbmDisplayAvailable()) 431 { 432 impl = rx::CreateVulkanGbmDisplay(state); 433 break; 434 } 435 # endif 436 # if defined(ANGLE_USE_X11) 437 if (platformType == EGL_PLATFORM_X11_EXT && rx::IsVulkanXcbDisplayAvailable()) 438 { 439 impl = rx::CreateVulkanXcbDisplay(state); 440 break; 441 } 442 # endif 443 # if defined(ANGLE_USE_WAYLAND) 444 if (platformType == EGL_PLATFORM_WAYLAND_EXT && rx::IsVulkanWaylandDisplayAvailable()) 445 { 446 impl = rx::CreateVulkanWaylandDisplay(state); 447 break; 448 } 449 # endif 450 # if defined(ANGLE_USE_VULKAN_DISPLAY) 451 if (platformType == EGL_PLATFORM_VULKAN_DISPLAY_MODE_SIMPLE_ANGLE && 452 rx::IsVulkanSimpleDisplayAvailable()) 453 { 454 impl = rx::CreateVulkanSimpleDisplay(state); 455 } 456 else if (platformType == EGL_PLATFORM_VULKAN_DISPLAY_MODE_HEADLESS_ANGLE && 457 rx::IsVulkanHeadlessDisplayAvailable()) 458 { 459 impl = rx::CreateVulkanHeadlessDisplay(state); 460 } 461 else 462 { 463 // Not supported creation type on vulkan display, fail display creation. 464 impl = nullptr; 465 } 466 # endif 467 break; 468 # elif defined(ANGLE_PLATFORM_ANDROID) 469 if (rx::IsVulkanAndroidDisplayAvailable()) 470 { 471 impl = rx::CreateVulkanAndroidDisplay(state); 472 } 473 break; 474 # elif defined(ANGLE_PLATFORM_FUCHSIA) 475 if (rx::IsVulkanFuchsiaDisplayAvailable()) 476 { 477 impl = rx::CreateVulkanFuchsiaDisplay(state); 478 } 479 break; 480 # elif defined(ANGLE_PLATFORM_GGP) 481 if (rx::IsVulkanGGPDisplayAvailable()) 482 { 483 impl = rx::CreateVulkanGGPDisplay(state); 484 } 485 break; 486 # elif defined(ANGLE_PLATFORM_APPLE) 487 if (rx::IsVulkanMacDisplayAvailable()) 488 { 489 impl = rx::CreateVulkanMacDisplay(state); 490 } 491 break; 492 # else 493 # error Unsupported Vulkan platform. 494 # endif 495 #else 496 // No display available 497 UNREACHABLE(); 498 break; 499 #endif // defined(ANGLE_ENABLE_VULKAN) 500 501 case EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE: 502 #if defined(ANGLE_ENABLE_METAL) 503 if (rx::IsMetalDisplayAvailable()) 504 { 505 impl = rx::CreateMetalDisplay(state); 506 break; 507 } 508 #endif 509 // No display available 510 UNREACHABLE(); 511 break; 512 513 case EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE: 514 #if defined(ANGLE_ENABLE_NULL) 515 impl = new rx::DisplayNULL(state); 516 break; 517 #else 518 // No display available 519 UNREACHABLE(); 520 break; 521 #endif // defined(ANGLE_ENABLE_NULL) 522 523 default: 524 UNREACHABLE(); 525 break; 526 } 527 528 return impl; 529 } 530 531 void Display_logError(angle::PlatformMethods *platform, const char *errorMessage) 532 { 533 gl::Trace(gl::LOG_ERR, errorMessage); 534 } 535 536 void Display_logWarning(angle::PlatformMethods *platform, const char *warningMessage) 537 { 538 gl::Trace(gl::LOG_WARN, warningMessage); 539 } 540 541 void Display_logInfo(angle::PlatformMethods *platform, const char *infoMessage) 542 { 543 // Uncomment to get info spam 544 #if defined(ANGLE_ENABLE_DEBUG_TRACE) 545 gl::Trace(gl::LOG_INFO, infoMessage); 546 #endif 547 } 548 549 const std::vector<std::string> EGLStringArrayToStringVector(const char **ary) 550 { 551 std::vector<std::string> vec; 552 if (ary != nullptr) 553 { 554 for (; *ary != nullptr; ary++) 555 { 556 vec.push_back(std::string(*ary)); 557 } 558 } 559 return vec; 560 } 561 562 void ANGLESetDefaultDisplayPlatform(angle::EGLDisplayType display) 563 { 564 angle::PlatformMethods *platformMethods = ANGLEPlatformCurrent(); 565 566 ANGLEResetDisplayPlatform(display); 567 platformMethods->logError = Display_logError; 568 platformMethods->logWarning = Display_logWarning; 569 platformMethods->logInfo = Display_logInfo; 570 } 571 572 void UpdateAttribsFromEnvironment(AttributeMap &attribMap) 573 { 574 EGLAttrib displayType = 575 attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE); 576 if (displayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE) 577 { 578 displayType = GetDisplayTypeFromEnvironment(); 579 attribMap.insert(EGL_PLATFORM_ANGLE_TYPE_ANGLE, displayType); 580 } 581 EGLAttrib deviceType = attribMap.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, 0); 582 if (deviceType == 0) 583 { 584 deviceType = GetDeviceTypeFromEnvironment(); 585 attribMap.insert(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, deviceType); 586 } 587 EGLAttrib platformType = attribMap.get(EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE, 0); 588 if (platformType == 0) 589 { 590 platformType = GetPlatformTypeFromEnvironment(); 591 attribMap.insert(EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE, platformType); 592 } 593 } 594 595 static constexpr uint32_t kScratchBufferLifetime = 64u; 596 597 } // anonymous namespace 598 599 // ShareGroup 600 ShareGroup::ShareGroup(rx::EGLImplFactory *factory) 601 : mRefCount(1), 602 mImplementation(factory->createShareGroup()), 603 mFrameCaptureShared(new angle::FrameCaptureShared) 604 {} 605 606 void ShareGroup::finishAllContexts() 607 { 608 for (gl::Context *shareContext : mContexts) 609 { 610 if (shareContext->hasBeenCurrent() && !shareContext->isDestroyed()) 611 { 612 shareContext->finish(); 613 } 614 } 615 } 616 617 void ShareGroup::addSharedContext(gl::Context *context) 618 { 619 mContexts.insert(context); 620 621 if (context->isRobustnessEnabled()) 622 { 623 mImplementation->onRobustContextAdd(); 624 } 625 } 626 627 void ShareGroup::removeSharedContext(gl::Context *context) 628 { 629 mContexts.erase(context); 630 } 631 632 ShareGroup::~ShareGroup() 633 { 634 SafeDelete(mImplementation); 635 } 636 637 void ShareGroup::addRef() 638 { 639 // This is protected by global lock, so no atomic is required 640 mRefCount++; 641 } 642 643 void ShareGroup::release(const Display *display) 644 { 645 if (--mRefCount == 0) 646 { 647 if (mImplementation) 648 { 649 mImplementation->onDestroy(display); 650 } 651 delete this; 652 } 653 } 654 655 // DisplayState 656 DisplayState::DisplayState(EGLNativeDisplayType nativeDisplayId) 657 : label(nullptr), featuresAllDisabled(false), displayId(nativeDisplayId) 658 {} 659 660 DisplayState::~DisplayState() {} 661 662 // Note that ANGLE support on Ozone platform is limited. Our preferred support Matrix for 663 // EGL_ANGLE_platform_angle on Linux and Ozone/Linux/Fuchsia platforms should be the following: 664 // 665 // |--------------------------------------------------------| 666 // | ANGLE type | DEVICE type | PLATFORM type | Display | 667 // |--------------------------------------------------------| 668 // | OPENGL | EGL | ANY | EGL | 669 // | OPENGL | HARDWARE | X11_EXT | GLX | 670 // | OPENGLES | HARDWARE | X11_EXT | GLX | 671 // | OPENGLES | EGL | ANY | EGL | 672 // | VULKAN | HARDWARE | X11_EXT | VkXcb | 673 // | VULKAN | SWIFTSHADER | X11_EXT | VkXcb | 674 // | OPENGLES | HARDWARE | SURFACELESS_MESA | EGL* | 675 // | OPENGLES | HARDWARE | DEVICE_EXT | EGL | 676 // | VULKAN | HARDWARE | SURFACELESS_MESA | VkBase** | 677 // | VULKAN | SWIFTSHADER | SURFACELESS_MESA | VkBase** | 678 // |--------------------------------------------------------| 679 // 680 // * No surfaceless support yet. 681 // ** Not implemented yet. 682 // 683 // |-----------------------------------------------| 684 // | OS | BUILD type | Default PLATFORM type | 685 // |-----------------------------------------------| 686 // | Linux | X11 | X11_EXT | 687 // | Linux | Ozone | SURFACELESS_MESA | 688 // | Fuchsia | Ozone | FUCHSIA*** | 689 // |-----------------------------------------------| 690 // 691 // *** Chosen implicitly. No EGLAttrib available. 692 // 693 // For more details, please refer to 694 // https://docs.google.com/document/d/1XjHiDZQISq1AMrg_l1TX1_kIKvDpU76hidn9i4cAjl8/edit?disco=AAAAJl9V_YY 695 // 696 // static 697 Display *Display::GetDisplayFromNativeDisplay(EGLenum platform, 698 EGLNativeDisplayType nativeDisplay, 699 const AttributeMap &attribMap) 700 { 701 Display *display = nullptr; 702 703 AttributeMap updatedAttribMap(attribMap); 704 UpdateAttribsFromEnvironment(updatedAttribMap); 705 706 EGLAttrib powerPreference = 707 updatedAttribMap.get(EGL_POWER_PREFERENCE_ANGLE, EGL_LOW_POWER_ANGLE); 708 EGLAttrib platformANGLEType = 709 updatedAttribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE); 710 EGLAttrib deviceIdHigh = updatedAttribMap.get(EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE, 0); 711 EGLAttrib deviceIdLow = updatedAttribMap.get(EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE, 0); 712 ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap(); 713 ANGLEPlatformDisplay displayKey(nativeDisplay, powerPreference, platformANGLEType, deviceIdHigh, 714 deviceIdLow); 715 const auto &iter = displays->find(displayKey); 716 if (iter != displays->end()) 717 { 718 display = iter->second; 719 } 720 721 if (display == nullptr) 722 { 723 // Validate the native display 724 if (!Display::isValidNativeDisplay(nativeDisplay)) 725 { 726 return nullptr; 727 } 728 729 display = new Display(platform, nativeDisplay, nullptr); 730 displays->insert(std::make_pair(displayKey, display)); 731 } 732 // Apply new attributes if the display is not initialized yet. 733 if (!display->isInitialized()) 734 { 735 display->setAttributes(updatedAttribMap); 736 737 EGLAttrib displayType = display->mAttributeMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE); 738 EGLAttrib deviceType = display->mAttributeMap.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE); 739 EGLAttrib platformType = platform; 740 if (platform == EGL_PLATFORM_ANGLE_ANGLE) 741 { 742 platformType = 743 display->mAttributeMap.get(EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE); 744 } 745 rx::DisplayImpl *impl = 746 CreateDisplayFromAttribs(displayType, deviceType, platformType, display->getState()); 747 if (impl == nullptr) 748 { 749 // No valid display implementation for these attributes 750 return nullptr; 751 } 752 753 #if defined(ANGLE_USE_ANDROID_TLS_SLOT) 754 angle::gUseAndroidOpenGLTlsSlot = displayType == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE; 755 #endif // defined(ANGLE_PLATFORM_ANDROID) 756 757 display->setupDisplayPlatform(impl); 758 } 759 760 return display; 761 } 762 763 // static 764 Display *Display::GetExistingDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay) 765 { 766 ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap(); 767 const auto &iter = displays->find(nativeDisplay); 768 769 // Check that there is a matching display 770 if (iter == displays->end()) 771 { 772 return nullptr; 773 } 774 775 return iter->second; 776 } 777 778 // static 779 Display *Display::GetDisplayFromDevice(Device *device, const AttributeMap &attribMap) 780 { 781 Display *display = nullptr; 782 783 ASSERT(Device::IsValidDevice(device)); 784 785 ANGLEPlatformDisplayMap *anglePlatformDisplays = GetANGLEPlatformDisplayMap(); 786 DevicePlatformDisplayMap *devicePlatformDisplays = GetDevicePlatformDisplayMap(); 787 788 // First see if this eglDevice is in use by a Display created using ANGLE platform 789 for (auto &displayMapEntry : *anglePlatformDisplays) 790 { 791 egl::Display *iterDisplay = displayMapEntry.second; 792 if (iterDisplay->getDevice() == device) 793 { 794 display = iterDisplay; 795 } 796 } 797 798 if (display == nullptr) 799 { 800 // See if the eglDevice is in use by a Display created using the DEVICE platform 801 const auto &iter = devicePlatformDisplays->find(device); 802 if (iter != devicePlatformDisplays->end()) 803 { 804 display = iter->second; 805 } 806 } 807 808 if (display == nullptr) 809 { 810 // Otherwise create a new Display 811 display = new Display(EGL_PLATFORM_DEVICE_EXT, 0, device); 812 devicePlatformDisplays->insert(std::make_pair(device, display)); 813 } 814 815 // Apply new attributes if the display is not initialized yet. 816 if (!display->isInitialized()) 817 { 818 display->setAttributes(attribMap); 819 rx::DisplayImpl *impl = CreateDisplayFromDevice(device, display->getState()); 820 display->setupDisplayPlatform(impl); 821 } 822 823 return display; 824 } 825 826 // static 827 Display::EglDisplaySet Display::GetEglDisplaySet() 828 { 829 Display::EglDisplaySet displays; 830 831 ANGLEPlatformDisplayMap *anglePlatformDisplays = GetANGLEPlatformDisplayMap(); 832 DevicePlatformDisplayMap *devicePlatformDisplays = GetDevicePlatformDisplayMap(); 833 834 for (auto anglePlatformDisplayMapEntry : *anglePlatformDisplays) 835 { 836 displays.insert(anglePlatformDisplayMapEntry.second); 837 } 838 839 for (auto devicePlatformDisplayMapEntry : *devicePlatformDisplays) 840 { 841 displays.insert(devicePlatformDisplayMapEntry.second); 842 } 843 844 return displays; 845 } 846 847 Display::Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice) 848 : mState(displayId), 849 mImplementation(nullptr), 850 mGPUSwitchedBinding(this, kGPUSwitchedSubjectIndex), 851 mAttributeMap(), 852 mConfigSet(), 853 mStreamSet(), 854 mInvalidContextSet(), 855 mInvalidImageSet(), 856 mInvalidStreamSet(), 857 mInvalidSurfaceSet(), 858 mInvalidSyncSet(), 859 mInitialized(false), 860 mDeviceLost(false), 861 mCaps(), 862 mDisplayExtensions(), 863 mDisplayExtensionString(), 864 mVendorString(), 865 mVersionString(), 866 mDevice(eglDevice), 867 mSurface(nullptr), 868 mPlatform(platform), 869 mTextureManager(nullptr), 870 mSemaphoreManager(nullptr), 871 mBlobCache(gl::kDefaultMaxProgramCacheMemoryBytes), 872 mMemoryProgramCache(mBlobCache), 873 mMemoryShaderCache(mBlobCache), 874 mGlobalTextureShareGroupUsers(0), 875 mGlobalSemaphoreShareGroupUsers(0), 876 mTerminatedByApi(false), 877 mActiveThreads() 878 {} 879 880 Display::~Display() 881 { 882 switch (mPlatform) 883 { 884 case EGL_PLATFORM_ANGLE_ANGLE: 885 case EGL_PLATFORM_GBM_KHR: 886 case EGL_PLATFORM_WAYLAND_EXT: 887 { 888 ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap(); 889 ANGLEPlatformDisplayMap::iterator iter = displays->find(ANGLEPlatformDisplay( 890 mState.displayId, 891 mAttributeMap.get(EGL_POWER_PREFERENCE_ANGLE, EGL_LOW_POWER_ANGLE), 892 mAttributeMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, 893 EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE), 894 mAttributeMap.get(EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE, 0), 895 mAttributeMap.get(EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE, 0))); 896 if (iter != displays->end()) 897 { 898 displays->erase(iter); 899 } 900 break; 901 } 902 case EGL_PLATFORM_DEVICE_EXT: 903 { 904 DevicePlatformDisplayMap *displays = GetDevicePlatformDisplayMap(); 905 DevicePlatformDisplayMap::iterator iter = displays->find(mDevice); 906 if (iter != displays->end()) 907 { 908 displays->erase(iter); 909 } 910 break; 911 } 912 default: 913 { 914 UNREACHABLE(); 915 } 916 } 917 918 SafeDelete(mDevice); 919 SafeDelete(mImplementation); 920 } 921 922 void Display::setLabel(EGLLabelKHR label) 923 { 924 mState.label = label; 925 } 926 927 EGLLabelKHR Display::getLabel() const 928 { 929 return mState.label; 930 } 931 932 void Display::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) 933 { 934 ASSERT(index == kGPUSwitchedSubjectIndex); 935 ASSERT(message == angle::SubjectMessage::SubjectChanged); 936 for (gl::Context *context : mState.contextSet) 937 { 938 context->onGPUSwitch(); 939 } 940 } 941 942 void Display::setupDisplayPlatform(rx::DisplayImpl *impl) 943 { 944 ASSERT(!mInitialized); 945 946 ASSERT(impl != nullptr); 947 SafeDelete(mImplementation); 948 mImplementation = impl; 949 950 // TODO(anglebug.com/7365): Remove PlatformMethods. 951 const angle::PlatformMethods *platformMethods = 952 reinterpret_cast<const angle::PlatformMethods *>( 953 mAttributeMap.get(EGL_PLATFORM_ANGLE_PLATFORM_METHODS_ANGLEX, 0)); 954 if (platformMethods != nullptr) 955 { 956 *ANGLEPlatformCurrent() = *platformMethods; 957 } 958 else 959 { 960 ANGLESetDefaultDisplayPlatform(this); 961 } 962 963 const char **featuresForceEnabled = 964 reinterpret_cast<const char **>(mAttributeMap.get(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE, 0)); 965 const char **featuresForceDisabled = 966 reinterpret_cast<const char **>(mAttributeMap.get(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE, 0)); 967 mState.featureOverridesEnabled = EGLStringArrayToStringVector(featuresForceEnabled); 968 mState.featureOverridesDisabled = EGLStringArrayToStringVector(featuresForceDisabled); 969 mState.featuresAllDisabled = 970 static_cast<bool>(mAttributeMap.get(EGL_FEATURE_ALL_DISABLED_ANGLE, 0)); 971 mImplementation->addObserver(&mGPUSwitchedBinding); 972 } 973 974 Error Display::initialize() 975 { 976 mTerminatedByApi = false; 977 978 ASSERT(mImplementation != nullptr); 979 mImplementation->setBlobCache(&mBlobCache); 980 981 // Enable shader caching if debug layers are turned on. This allows us to test that shaders are 982 // properly saved & restored on all platforms. The cache won't allocate space until it's used 983 // and will be ignored entirely if the application / system sets it's own cache functions. 984 if (rx::ShouldUseDebugLayers(mAttributeMap)) 985 { 986 mBlobCache.resize(1024 * 1024); 987 } 988 989 setGlobalDebugAnnotator(); 990 991 gl::InitializeDebugMutexIfNeeded(); 992 993 ANGLE_TRACE_EVENT0("gpu.angle", "egl::Display::initialize"); 994 995 if (isInitialized()) 996 { 997 return NoError(); 998 } 999 1000 Error error = mImplementation->initialize(this); 1001 if (error.isError()) 1002 { 1003 // Log extended error message here 1004 ERR() << "ANGLE Display::initialize error " << error.getID() << ": " << error.getMessage(); 1005 return error; 1006 } 1007 1008 mCaps = mImplementation->getCaps(); 1009 1010 mConfigSet = mImplementation->generateConfigs(); 1011 if (mConfigSet.size() == 0) 1012 { 1013 mImplementation->terminate(); 1014 return EglNotInitialized() << "No configs were generated."; 1015 } 1016 1017 // OpenGL ES1 is implemented in the frontend, explicitly add ES1 support to all configs 1018 for (auto &config : mConfigSet) 1019 { 1020 // TODO(geofflang): Enable the conformant bit once we pass enough tests 1021 // config.second.conformant |= EGL_OPENGL_ES_BIT; 1022 1023 config.second.renderableType |= EGL_OPENGL_ES_BIT; 1024 1025 // If we aren't using desktop GL entry points, remove desktop GL support from all configs 1026 #if !defined(ANGLE_ENABLE_GL_DESKTOP_FRONTEND) 1027 config.second.renderableType &= ~EGL_OPENGL_BIT; 1028 #endif 1029 } 1030 1031 if (!mState.featuresAllDisabled) 1032 { 1033 initializeFrontendFeatures(); 1034 } 1035 1036 mFeatures.clear(); 1037 mFrontendFeatures.populateFeatureList(&mFeatures); 1038 mImplementation->populateFeatureList(&mFeatures); 1039 1040 initDisplayExtensions(); 1041 initVendorString(); 1042 initVersionString(); 1043 initClientAPIString(); 1044 1045 // Populate the Display's EGLDeviceEXT if the Display wasn't created using one 1046 if (mPlatform == EGL_PLATFORM_DEVICE_EXT) 1047 { 1048 // For EGL_PLATFORM_DEVICE_EXT, mDevice should always be populated using 1049 // an external device 1050 ASSERT(mDevice != nullptr); 1051 } 1052 else if (GetClientExtensions().deviceQueryEXT) 1053 { 1054 std::unique_ptr<rx::DeviceImpl> impl(mImplementation->createDevice()); 1055 ASSERT(impl); 1056 error = impl->initialize(); 1057 if (error.isError()) 1058 { 1059 ERR() << "Failed to initialize display because device creation failed: " 1060 << error.getMessage(); 1061 mImplementation->terminate(); 1062 return error; 1063 } 1064 // Don't leak Device memory. 1065 ASSERT(mDevice == nullptr); 1066 mDevice = new Device(this, impl.release()); 1067 } 1068 else 1069 { 1070 mDevice = nullptr; 1071 } 1072 1073 mInitialized = true; 1074 1075 return NoError(); 1076 } 1077 1078 Error Display::destroyInvalidEglObjects() 1079 { 1080 // Destroy invalid EGL objects 1081 while (!mInvalidContextSet.empty()) 1082 { 1083 gl::Context *context = *mInvalidContextSet.begin(); 1084 context->setIsDestroyed(); 1085 ANGLE_TRY(releaseContextImpl(context, &mInvalidContextSet)); 1086 } 1087 1088 while (!mInvalidImageSet.empty()) 1089 { 1090 destroyImageImpl(*mInvalidImageSet.begin(), &mInvalidImageSet); 1091 } 1092 1093 while (!mInvalidStreamSet.empty()) 1094 { 1095 destroyStreamImpl(*mInvalidStreamSet.begin(), &mInvalidStreamSet); 1096 } 1097 1098 while (!mInvalidSurfaceSet.empty()) 1099 { 1100 ANGLE_TRY(destroySurfaceImpl(*mInvalidSurfaceSet.begin(), &mInvalidSurfaceSet)); 1101 } 1102 1103 while (!mInvalidSyncSet.empty()) 1104 { 1105 destroySyncImpl(*mInvalidSyncSet.begin(), &mInvalidSyncSet); 1106 } 1107 1108 return NoError(); 1109 } 1110 1111 Error Display::terminate(Thread *thread, TerminateReason terminateReason) 1112 { 1113 if (terminateReason == TerminateReason::Api) 1114 { 1115 mTerminatedByApi = true; 1116 } 1117 1118 // All subsequent calls assume the display to be valid and terminated by app. 1119 // If it is not terminated or if it isn't even initialized, early return. 1120 if (!mTerminatedByApi || !mInitialized) 1121 { 1122 return NoError(); 1123 } 1124 1125 // EGL 1.5 Specification 1126 // 3.2 Initialization 1127 // Termination marks all EGL-specific resources, such as contexts and surfaces, associated 1128 // with the specified display for deletion. Handles to all such resources are invalid as soon 1129 // as eglTerminate returns. Cache EGL objects that are no longer valid. 1130 // 1131 // It is fairly common for apps to call eglTerminate while some contexts and/or surfaces are 1132 // still current on some thread. Since objects are refCounted, trying to destroy them right away 1133 // would only result in a decRef. We instead cache such invalid objects and use other EGL 1134 // entrypoints like eglReleaseThread or thread exit events (on the Android platform) to 1135 // perform the necessary cleanup. 1136 mInvalidImageSet.insert(mImageSet.begin(), mImageSet.end()); 1137 mImageSet.clear(); 1138 1139 mInvalidStreamSet.insert(mStreamSet.begin(), mStreamSet.end()); 1140 mStreamSet.clear(); 1141 1142 mInvalidSurfaceSet.insert(mState.surfaceSet.begin(), mState.surfaceSet.end()); 1143 mState.surfaceSet.clear(); 1144 1145 mInvalidSyncSet.insert(mSyncSet.begin(), mSyncSet.end()); 1146 mSyncSet.clear(); 1147 1148 // Cache total number of contexts before invalidation. This is used as a check to verify that 1149 // no context is "lost" while being moved between the various sets. 1150 size_t contextSetSizeBeforeInvalidation = mState.contextSet.size() + mInvalidContextSet.size(); 1151 1152 // If app called eglTerminate and no active threads remain, 1153 // force realease any context that is still current. 1154 ContextSet contextsStillCurrent = {}; 1155 for (gl::Context *context : mState.contextSet) 1156 { 1157 if (context->getRefCount() > 0) 1158 { 1159 if (terminateReason == TerminateReason::NoActiveThreads) 1160 { 1161 ASSERT(mTerminatedByApi); 1162 context->release(); 1163 (void)context->unMakeCurrent(this); 1164 } 1165 else 1166 { 1167 contextsStillCurrent.emplace(context); 1168 continue; 1169 } 1170 } 1171 1172 // Add context that is not current to mInvalidContextSet for cleanup. 1173 mInvalidContextSet.emplace(context); 1174 } 1175 1176 // There are many methods that require contexts that are still current to be present in 1177 // display's contextSet like during context release or to notify of state changes in a subject. 1178 // So as to not interrupt this flow, do not remove contexts that are still current on some 1179 // thread from display's contextSet even though eglTerminate marks such contexts as invalid. 1180 // 1181 // "mState.contextSet" will now contain only those contexts that are still current on some 1182 // thread. 1183 mState.contextSet = std::move(contextsStillCurrent); 1184 1185 // Assert that the total number of contexts is the same before and after context invalidation. 1186 ASSERT(contextSetSizeBeforeInvalidation == 1187 mState.contextSet.size() + mInvalidContextSet.size()); 1188 1189 if (!mState.contextSet.empty()) 1190 { 1191 // There was atleast 1 context that was current on some thread, early return. 1192 return NoError(); 1193 } 1194 1195 mMemoryProgramCache.clear(); 1196 mMemoryShaderCache.clear(); 1197 mBlobCache.setBlobCacheFuncs(nullptr, nullptr); 1198 1199 // The global texture and semaphore managers should be deleted with the last context that uses 1200 // it. 1201 ASSERT(mGlobalTextureShareGroupUsers == 0 && mTextureManager == nullptr); 1202 ASSERT(mGlobalSemaphoreShareGroupUsers == 0 && mSemaphoreManager == nullptr); 1203 1204 // Clean up all invalid objects 1205 ANGLE_TRY(destroyInvalidEglObjects()); 1206 1207 mConfigSet.clear(); 1208 1209 if (mDevice != nullptr && mDevice->getOwningDisplay() != nullptr) 1210 { 1211 // Don't delete the device if it was created externally using eglCreateDeviceANGLE 1212 // We also shouldn't set it to null in case eglInitialize() is called again later 1213 SafeDelete(mDevice); 1214 } 1215 1216 mImplementation->terminate(); 1217 1218 mDeviceLost = false; 1219 1220 mInitialized = false; 1221 1222 gl::UninitializeDebugAnnotations(); 1223 1224 // TODO(jmadill): Store Platform in Display and deinit here. 1225 ANGLEResetDisplayPlatform(this); 1226 1227 return NoError(); 1228 } 1229 1230 Error Display::prepareForCall() 1231 { 1232 return mImplementation->prepareForCall(); 1233 } 1234 1235 Error Display::releaseThread() 1236 { 1237 ANGLE_TRY(mImplementation->releaseThread()); 1238 return destroyInvalidEglObjects(); 1239 } 1240 1241 void Display::addActiveThread(Thread *thread) 1242 { 1243 mActiveThreads.insert(thread); 1244 } 1245 1246 void Display::threadCleanup(Thread *thread) 1247 { 1248 mActiveThreads.erase(thread); 1249 const bool noActiveThreads = mActiveThreads.size() == 0; 1250 1251 (void)terminate(thread, noActiveThreads ? TerminateReason::NoActiveThreads 1252 : TerminateReason::InternalCleanup); 1253 } 1254 1255 std::vector<const Config *> Display::getConfigs(const egl::AttributeMap &attribs) const 1256 { 1257 return mConfigSet.filter(attribs); 1258 } 1259 1260 std::vector<const Config *> Display::chooseConfig(const egl::AttributeMap &attribs) const 1261 { 1262 egl::AttributeMap attribsWithDefaults = AttributeMap(); 1263 1264 // Insert default values for attributes that have either an Exact or Mask selection criteria, 1265 // and a default value that matters (e.g. isn't EGL_DONT_CARE): 1266 attribsWithDefaults.insert(EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER); 1267 attribsWithDefaults.insert(EGL_LEVEL, 0); 1268 attribsWithDefaults.insert(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT); 1269 attribsWithDefaults.insert(EGL_SURFACE_TYPE, EGL_WINDOW_BIT); 1270 attribsWithDefaults.insert(EGL_TRANSPARENT_TYPE, EGL_NONE); 1271 if (getExtensions().pixelFormatFloat) 1272 { 1273 attribsWithDefaults.insert(EGL_COLOR_COMPONENT_TYPE_EXT, 1274 EGL_COLOR_COMPONENT_TYPE_FIXED_EXT); 1275 } 1276 1277 // Add the caller-specified values (Note: the poorly-named insert() method will replace any 1278 // of the default values from above): 1279 for (auto attribIter = attribs.begin(); attribIter != attribs.end(); attribIter++) 1280 { 1281 attribsWithDefaults.insert(attribIter->first, attribIter->second); 1282 } 1283 1284 return mConfigSet.filter(attribsWithDefaults); 1285 } 1286 1287 Error Display::createWindowSurface(const Config *configuration, 1288 EGLNativeWindowType window, 1289 const AttributeMap &attribs, 1290 Surface **outSurface) 1291 { 1292 if (mImplementation->testDeviceLost()) 1293 { 1294 ANGLE_TRY(restoreLostDevice()); 1295 } 1296 1297 SurfacePointer surface(new WindowSurface(mImplementation, configuration, window, attribs, 1298 mFrontendFeatures.forceRobustResourceInit.enabled), 1299 this); 1300 ANGLE_TRY(surface->initialize(this)); 1301 1302 ASSERT(outSurface != nullptr); 1303 *outSurface = surface.release(); 1304 mState.surfaceSet.insert(*outSurface); 1305 1306 WindowSurfaceMap *windowSurfaces = GetWindowSurfaces(); 1307 ASSERT(windowSurfaces && windowSurfaces->find(window) == windowSurfaces->end()); 1308 windowSurfaces->insert(std::make_pair(window, *outSurface)); 1309 1310 mSurface = *outSurface; 1311 1312 return NoError(); 1313 } 1314 1315 Error Display::createPbufferSurface(const Config *configuration, 1316 const AttributeMap &attribs, 1317 Surface **outSurface) 1318 { 1319 ASSERT(isInitialized()); 1320 1321 if (mImplementation->testDeviceLost()) 1322 { 1323 ANGLE_TRY(restoreLostDevice()); 1324 } 1325 1326 SurfacePointer surface(new PbufferSurface(mImplementation, configuration, attribs, 1327 mFrontendFeatures.forceRobustResourceInit.enabled), 1328 this); 1329 ANGLE_TRY(surface->initialize(this)); 1330 1331 ASSERT(outSurface != nullptr); 1332 *outSurface = surface.release(); 1333 mState.surfaceSet.insert(*outSurface); 1334 1335 return NoError(); 1336 } 1337 1338 Error Display::createPbufferFromClientBuffer(const Config *configuration, 1339 EGLenum buftype, 1340 EGLClientBuffer clientBuffer, 1341 const AttributeMap &attribs, 1342 Surface **outSurface) 1343 { 1344 ASSERT(isInitialized()); 1345 1346 if (mImplementation->testDeviceLost()) 1347 { 1348 ANGLE_TRY(restoreLostDevice()); 1349 } 1350 1351 SurfacePointer surface( 1352 new PbufferSurface(mImplementation, configuration, buftype, clientBuffer, attribs, 1353 mFrontendFeatures.forceRobustResourceInit.enabled), 1354 this); 1355 ANGLE_TRY(surface->initialize(this)); 1356 1357 ASSERT(outSurface != nullptr); 1358 *outSurface = surface.release(); 1359 mState.surfaceSet.insert(*outSurface); 1360 1361 return NoError(); 1362 } 1363 1364 Error Display::createPixmapSurface(const Config *configuration, 1365 NativePixmapType nativePixmap, 1366 const AttributeMap &attribs, 1367 Surface **outSurface) 1368 { 1369 ASSERT(isInitialized()); 1370 1371 if (mImplementation->testDeviceLost()) 1372 { 1373 ANGLE_TRY(restoreLostDevice()); 1374 } 1375 1376 SurfacePointer surface(new PixmapSurface(mImplementation, configuration, nativePixmap, attribs, 1377 mFrontendFeatures.forceRobustResourceInit.enabled), 1378 this); 1379 ANGLE_TRY(surface->initialize(this)); 1380 1381 ASSERT(outSurface != nullptr); 1382 *outSurface = surface.release(); 1383 mState.surfaceSet.insert(*outSurface); 1384 1385 return NoError(); 1386 } 1387 1388 Error Display::createImage(const gl::Context *context, 1389 EGLenum target, 1390 EGLClientBuffer buffer, 1391 const AttributeMap &attribs, 1392 Image **outImage) 1393 { 1394 ASSERT(isInitialized()); 1395 1396 if (mImplementation->testDeviceLost()) 1397 { 1398 ANGLE_TRY(restoreLostDevice()); 1399 } 1400 1401 egl::ImageSibling *sibling = nullptr; 1402 if (IsTextureTarget(target)) 1403 { 1404 sibling = context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)}); 1405 } 1406 else if (IsRenderbufferTarget(target)) 1407 { 1408 sibling = context->getRenderbuffer({egl_gl::EGLClientBufferToGLObjectHandle(buffer)}); 1409 } 1410 else if (IsExternalImageTarget(target)) 1411 { 1412 sibling = new ExternalImageSibling(mImplementation, context, target, buffer, attribs); 1413 } 1414 else 1415 { 1416 UNREACHABLE(); 1417 } 1418 ASSERT(sibling != nullptr); 1419 1420 angle::UniqueObjectPointer<Image, Display> imagePtr( 1421 new Image(mImplementation, context, target, sibling, attribs), this); 1422 ANGLE_TRY(imagePtr->initialize(this)); 1423 1424 Image *image = imagePtr.release(); 1425 1426 ASSERT(outImage != nullptr); 1427 *outImage = image; 1428 1429 // Add this image to the list of all images and hold a ref to it. 1430 image->addRef(); 1431 mImageSet.insert(image); 1432 1433 return NoError(); 1434 } 1435 1436 Error Display::createStream(const AttributeMap &attribs, Stream **outStream) 1437 { 1438 ASSERT(isInitialized()); 1439 1440 Stream *stream = new Stream(this, attribs); 1441 1442 ASSERT(stream != nullptr); 1443 mStreamSet.insert(stream); 1444 1445 ASSERT(outStream != nullptr); 1446 *outStream = stream; 1447 1448 return NoError(); 1449 } 1450 1451 Error Display::createContext(const Config *configuration, 1452 gl::Context *shareContext, 1453 EGLenum clientType, 1454 const AttributeMap &attribs, 1455 gl::Context **outContext) 1456 { 1457 ASSERT(!mTerminatedByApi); 1458 ASSERT(isInitialized()); 1459 1460 if (mImplementation->testDeviceLost()) 1461 { 1462 ANGLE_TRY(restoreLostDevice()); 1463 } 1464 1465 // This display texture sharing will allow the first context to create the texture share group. 1466 bool usingDisplayTextureShareGroup = 1467 attribs.get(EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE, EGL_FALSE) == EGL_TRUE; 1468 gl::TextureManager *shareTextures = nullptr; 1469 1470 if (usingDisplayTextureShareGroup) 1471 { 1472 ASSERT((mTextureManager == nullptr) == (mGlobalTextureShareGroupUsers == 0)); 1473 if (mTextureManager == nullptr) 1474 { 1475 mTextureManager = new gl::TextureManager(); 1476 } 1477 1478 mGlobalTextureShareGroupUsers++; 1479 shareTextures = mTextureManager; 1480 } 1481 1482 // This display semaphore sharing will allow the first context to create the semaphore share 1483 // group. 1484 bool usingDisplaySemaphoreShareGroup = 1485 attribs.get(EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE, EGL_FALSE) == EGL_TRUE; 1486 gl::SemaphoreManager *shareSemaphores = nullptr; 1487 if (usingDisplaySemaphoreShareGroup) 1488 { 1489 ASSERT((mSemaphoreManager == nullptr) == (mGlobalSemaphoreShareGroupUsers == 0)); 1490 if (mSemaphoreManager == nullptr) 1491 { 1492 mSemaphoreManager = new gl::SemaphoreManager(); 1493 } 1494 1495 mGlobalSemaphoreShareGroupUsers++; 1496 shareSemaphores = mSemaphoreManager; 1497 } 1498 1499 gl::MemoryProgramCache *programCachePointer = &mMemoryProgramCache; 1500 // Check context creation attributes to see if we are using EGL_ANGLE_program_cache_control. 1501 // If not, keep caching enabled for EGL_ANDROID_blob_cache, which can have its callbacks set 1502 // at any time. 1503 bool usesProgramCacheControl = attribs.contains(EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE); 1504 if (usesProgramCacheControl) 1505 { 1506 bool programCacheControlEnabled = 1507 (attribs.get(EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE, GL_FALSE) == GL_TRUE); 1508 // A program cache size of zero indicates it should be disabled. 1509 if (!programCacheControlEnabled || mMemoryProgramCache.maxSize() == 0) 1510 { 1511 programCachePointer = nullptr; 1512 } 1513 } 1514 1515 gl::MemoryShaderCache *shaderCachePointer = &mMemoryShaderCache; 1516 // Check if shader caching frontend feature is enabled. 1517 if (!mFrontendFeatures.cacheCompiledShader.enabled) 1518 { 1519 shaderCachePointer = nullptr; 1520 } 1521 1522 gl::Context *context = new gl::Context( 1523 this, configuration, shareContext, shareTextures, shareSemaphores, programCachePointer, 1524 shaderCachePointer, clientType, attribs, mDisplayExtensions, GetClientExtensions()); 1525 Error error = context->initialize(); 1526 if (error.isError()) 1527 { 1528 delete context; 1529 return error; 1530 } 1531 1532 if (shareContext != nullptr) 1533 { 1534 shareContext->setShared(); 1535 } 1536 1537 ASSERT(context != nullptr); 1538 mState.contextSet.insert(context); 1539 1540 ASSERT(outContext != nullptr); 1541 *outContext = context; 1542 return NoError(); 1543 } 1544 1545 Error Display::createSync(const gl::Context *currentContext, 1546 EGLenum type, 1547 const AttributeMap &attribs, 1548 Sync **outSync) 1549 { 1550 ASSERT(isInitialized()); 1551 1552 if (mImplementation->testDeviceLost()) 1553 { 1554 ANGLE_TRY(restoreLostDevice()); 1555 } 1556 1557 angle::UniqueObjectPointer<egl::Sync, Display> syncPtr(new Sync(mImplementation, type, attribs), 1558 this); 1559 1560 ANGLE_TRY(syncPtr->initialize(this, currentContext)); 1561 1562 Sync *sync = syncPtr.release(); 1563 1564 sync->addRef(); 1565 mSyncSet.insert(sync); 1566 1567 *outSync = sync; 1568 return NoError(); 1569 } 1570 1571 Error Display::makeCurrent(Thread *thread, 1572 gl::Context *previousContext, 1573 egl::Surface *drawSurface, 1574 egl::Surface *readSurface, 1575 gl::Context *context) 1576 { 1577 if (!mInitialized) 1578 { 1579 return NoError(); 1580 } 1581 1582 bool contextChanged = context != previousContext; 1583 if (previousContext != nullptr && contextChanged) 1584 { 1585 previousContext->release(); 1586 thread->setCurrent(nullptr); 1587 1588 auto error = previousContext->unMakeCurrent(this); 1589 if (previousContext->getRefCount() == 0 && previousContext->isDestroyed()) 1590 { 1591 // The previous Context may have been created with a different Display. 1592 Display *previousDisplay = previousContext->getDisplay(); 1593 ANGLE_TRY(previousDisplay->releaseContext(previousContext, thread)); 1594 } 1595 ANGLE_TRY(error); 1596 } 1597 1598 thread->setCurrent(context); 1599 1600 ANGLE_TRY(mImplementation->makeCurrent(this, drawSurface, readSurface, context)); 1601 1602 if (context != nullptr) 1603 { 1604 ANGLE_TRY(context->makeCurrent(this, drawSurface, readSurface)); 1605 if (contextChanged) 1606 { 1607 context->addRef(); 1608 } 1609 } 1610 1611 // Tick all the scratch buffers to make sure they get cleaned up eventually if they stop being 1612 // used. 1613 { 1614 std::lock_guard<std::mutex> lock(mScratchBufferMutex); 1615 1616 for (angle::ScratchBuffer &scatchBuffer : mScratchBuffers) 1617 { 1618 scatchBuffer.tick(); 1619 } 1620 for (angle::ScratchBuffer &zeroFilledBuffer : mZeroFilledBuffers) 1621 { 1622 zeroFilledBuffer.tick(); 1623 } 1624 } 1625 1626 return NoError(); 1627 } 1628 1629 Error Display::restoreLostDevice() 1630 { 1631 for (ContextSet::iterator ctx = mState.contextSet.begin(); ctx != mState.contextSet.end(); 1632 ctx++) 1633 { 1634 if ((*ctx)->isResetNotificationEnabled()) 1635 { 1636 // If reset notifications have been requested, application must delete all contexts 1637 // first 1638 return EglContextLost(); 1639 } 1640 } 1641 1642 return mImplementation->restoreLostDevice(this); 1643 } 1644 1645 Error Display::destroySurfaceImpl(Surface *surface, SurfaceSet *surfaces) 1646 { 1647 if (surface->getType() == EGL_WINDOW_BIT) 1648 { 1649 WindowSurfaceMap *windowSurfaces = GetWindowSurfaces(); 1650 ASSERT(windowSurfaces); 1651 1652 bool surfaceRemoved = false; 1653 for (WindowSurfaceMap::iterator iter = windowSurfaces->begin(); 1654 iter != windowSurfaces->end(); iter++) 1655 { 1656 if (iter->second == surface) 1657 { 1658 windowSurfaces->erase(iter); 1659 surfaceRemoved = true; 1660 break; 1661 } 1662 } 1663 1664 ASSERT(surfaceRemoved); 1665 } 1666 1667 auto iter = surfaces->find(surface); 1668 ASSERT(iter != surfaces->end()); 1669 surfaces->erase(iter); 1670 ANGLE_TRY(surface->onDestroy(this)); 1671 return NoError(); 1672 } 1673 1674 void Display::destroyImageImpl(Image *image, ImageSet *images) 1675 { 1676 auto iter = images->find(image); 1677 ASSERT(iter != images->end()); 1678 (*iter)->release(this); 1679 images->erase(iter); 1680 } 1681 1682 void Display::destroyStreamImpl(Stream *stream, StreamSet *streams) 1683 { 1684 streams->erase(stream); 1685 SafeDelete(stream); 1686 } 1687 1688 // releaseContext must be called with the context being deleted as current. 1689 // To do that we can only call this in two places, Display::makeCurrent at the point where this 1690 // context is being made uncurrent and in Display::destroyContext where we make the context current 1691 // as part of destruction. 1692 Error Display::releaseContext(gl::Context *context, Thread *thread) 1693 { 1694 return releaseContextImpl(context, &mState.contextSet); 1695 } 1696 1697 Error Display::releaseContextImpl(gl::Context *context, ContextSet *contexts) 1698 { 1699 ASSERT(context->getRefCount() == 0); 1700 1701 // Use scoped_ptr to make sure the context is always freed. 1702 std::unique_ptr<gl::Context> unique_context(context); 1703 ASSERT(contexts->find(context) != contexts->end()); 1704 contexts->erase(context); 1705 1706 if (context->usingDisplayTextureShareGroup()) 1707 { 1708 ASSERT(mGlobalTextureShareGroupUsers >= 1 && mTextureManager != nullptr); 1709 if (mGlobalTextureShareGroupUsers == 1) 1710 { 1711 // If this is the last context using the global share group, destroy the global 1712 // texture manager so that the textures can be destroyed while a context still 1713 // exists 1714 mTextureManager->release(context); 1715 mTextureManager = nullptr; 1716 } 1717 mGlobalTextureShareGroupUsers--; 1718 } 1719 1720 if (context->usingDisplaySemaphoreShareGroup()) 1721 { 1722 ASSERT(mGlobalSemaphoreShareGroupUsers >= 1 && mSemaphoreManager != nullptr); 1723 if (mGlobalSemaphoreShareGroupUsers == 1) 1724 { 1725 // If this is the last context using the global share group, destroy the global 1726 // semaphore manager so that the semaphores can be destroyed while a context still 1727 // exists 1728 mSemaphoreManager->release(context); 1729 mSemaphoreManager = nullptr; 1730 } 1731 mGlobalSemaphoreShareGroupUsers--; 1732 } 1733 1734 ANGLE_TRY(context->onDestroy(this)); 1735 1736 return NoError(); 1737 } 1738 1739 Error Display::destroyContext(Thread *thread, gl::Context *context) 1740 { 1741 auto *currentContext = thread->getContext(); 1742 auto *currentDrawSurface = thread->getCurrentDrawSurface(); 1743 auto *currentReadSurface = thread->getCurrentReadSurface(); 1744 1745 context->setIsDestroyed(); 1746 1747 // If the context is still current on at least 1 thread, just return since it'll be released 1748 // once no threads have it current anymore. 1749 if (context->getRefCount() > 0) 1750 { 1751 return NoError(); 1752 } 1753 1754 // For external context, we cannot change the current native context, and the API user should 1755 // make sure the native context is current. 1756 if (context->isExternal()) 1757 { 1758 ANGLE_TRY(releaseContext(context, thread)); 1759 } 1760 else 1761 { 1762 // Keep |currentContext| alive, while releasing |context|. 1763 gl::ScopedContextRef scopedContextRef(currentContext); 1764 1765 // keep |currentDrawSurface| and |currentReadSurface| alive as well 1766 // while releasing |context|. 1767 ScopedSurfaceRef drawSurfaceRef(currentDrawSurface); 1768 ScopedSurfaceRef readSurfaceRef( 1769 currentReadSurface == currentDrawSurface ? nullptr : currentReadSurface); 1770 1771 // Make the context current, so we can release resources belong to the context, and then 1772 // when context is released from the current, it will be destroyed. 1773 // TODO(http://www.anglebug.com/6322): Don't require a Context to be current in order to 1774 // destroy it. 1775 ANGLE_TRY(makeCurrent(thread, currentContext, nullptr, nullptr, context)); 1776 ANGLE_TRY( 1777 makeCurrent(thread, context, currentDrawSurface, currentReadSurface, currentContext)); 1778 } 1779 1780 // If eglTerminate() has previously been called and this is the last Context the Display owns, 1781 // we can now fully terminate the display and release all of its resources. 1782 if (mTerminatedByApi) 1783 { 1784 for (const gl::Context *ctx : mState.contextSet) 1785 { 1786 if (ctx->getRefCount() > 0) 1787 { 1788 return NoError(); 1789 } 1790 } 1791 1792 return terminate(thread, TerminateReason::InternalCleanup); 1793 } 1794 1795 return NoError(); 1796 } 1797 1798 void Display::destroySyncImpl(Sync *sync, SyncSet *syncs) 1799 { 1800 auto iter = syncs->find(sync); 1801 ASSERT(iter != syncs->end()); 1802 (*iter)->release(this); 1803 syncs->erase(iter); 1804 } 1805 1806 void Display::destroyImage(Image *image) 1807 { 1808 return destroyImageImpl(image, &mImageSet); 1809 } 1810 1811 void Display::destroyStream(Stream *stream) 1812 { 1813 return destroyStreamImpl(stream, &mStreamSet); 1814 } 1815 1816 Error Display::destroySurface(Surface *surface) 1817 { 1818 return destroySurfaceImpl(surface, &mState.surfaceSet); 1819 } 1820 1821 void Display::destroySync(Sync *sync) 1822 { 1823 return destroySyncImpl(sync, &mSyncSet); 1824 } 1825 1826 bool Display::isDeviceLost() const 1827 { 1828 ASSERT(isInitialized()); 1829 return mDeviceLost; 1830 } 1831 1832 bool Display::testDeviceLost() 1833 { 1834 ASSERT(isInitialized()); 1835 1836 if (!mDeviceLost && mImplementation->testDeviceLost()) 1837 { 1838 notifyDeviceLost(); 1839 } 1840 1841 return mDeviceLost; 1842 } 1843 1844 void Display::notifyDeviceLost() 1845 { 1846 if (mDeviceLost) 1847 { 1848 return; 1849 } 1850 1851 for (ContextSet::iterator context = mState.contextSet.begin(); 1852 context != mState.contextSet.end(); context++) 1853 { 1854 (*context)->markContextLost(gl::GraphicsResetStatus::UnknownContextReset); 1855 } 1856 1857 mDeviceLost = true; 1858 } 1859 1860 void Display::setBlobCacheFuncs(EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get) 1861 { 1862 mBlobCache.setBlobCacheFuncs(set, get); 1863 mImplementation->setBlobCacheFuncs(set, get); 1864 } 1865 1866 // static 1867 EGLClientBuffer Display::GetNativeClientBuffer(const AHardwareBuffer *buffer) 1868 { 1869 return angle::android::AHardwareBufferToClientBuffer(buffer); 1870 } 1871 1872 // static 1873 Error Display::CreateNativeClientBuffer(const egl::AttributeMap &attribMap, 1874 EGLClientBuffer *eglClientBuffer) 1875 { 1876 int androidHardwareBufferFormat = gl::GetAndroidHardwareBufferFormatFromChannelSizes(attribMap); 1877 int width = attribMap.getAsInt(EGL_WIDTH, 0); 1878 int height = attribMap.getAsInt(EGL_HEIGHT, 0); 1879 int usage = attribMap.getAsInt(EGL_NATIVE_BUFFER_USAGE_ANDROID, 0); 1880 1881 // https://developer.android.com/ndk/reference/group/a-hardware-buffer#ahardwarebuffer_lock 1882 // for AHardwareBuffer_lock() 1883 // The passed AHardwareBuffer must have one layer, otherwise the call will fail. 1884 constexpr int kLayerCount = 1; 1885 1886 *eglClientBuffer = angle::android::CreateEGLClientBufferFromAHardwareBuffer( 1887 width, height, kLayerCount, androidHardwareBufferFormat, usage); 1888 1889 return (*eglClientBuffer == nullptr) 1890 ? egl::EglBadParameter() << "native client buffer allocation failed." 1891 : NoError(); 1892 } 1893 1894 Error Display::waitClient(const gl::Context *context) 1895 { 1896 return mImplementation->waitClient(context); 1897 } 1898 1899 Error Display::waitNative(const gl::Context *context, EGLint engine) 1900 { 1901 return mImplementation->waitNative(context, engine); 1902 } 1903 1904 const Caps &Display::getCaps() const 1905 { 1906 return mCaps; 1907 } 1908 1909 bool Display::isInitialized() const 1910 { 1911 return mInitialized; 1912 } 1913 1914 bool Display::isValidConfig(const Config *config) const 1915 { 1916 return mConfigSet.contains(config); 1917 } 1918 1919 bool Display::isValidContext(const gl::Context *context) const 1920 { 1921 return mState.contextSet.find(const_cast<gl::Context *>(context)) != mState.contextSet.end(); 1922 } 1923 1924 bool Display::isValidSurface(const Surface *surface) const 1925 { 1926 return mState.surfaceSet.find(const_cast<Surface *>(surface)) != mState.surfaceSet.end(); 1927 } 1928 1929 bool Display::isValidImage(const Image *image) const 1930 { 1931 return mImageSet.find(const_cast<Image *>(image)) != mImageSet.end(); 1932 } 1933 1934 bool Display::isValidStream(const Stream *stream) const 1935 { 1936 return mStreamSet.find(const_cast<Stream *>(stream)) != mStreamSet.end(); 1937 } 1938 1939 bool Display::isValidSync(const Sync *sync) const 1940 { 1941 return mSyncSet.find(const_cast<Sync *>(sync)) != mSyncSet.end(); 1942 } 1943 1944 bool Display::hasExistingWindowSurface(EGLNativeWindowType window) 1945 { 1946 WindowSurfaceMap *windowSurfaces = GetWindowSurfaces(); 1947 ASSERT(windowSurfaces); 1948 1949 return windowSurfaces->find(window) != windowSurfaces->end(); 1950 } 1951 1952 static ClientExtensions GenerateClientExtensions() 1953 { 1954 ClientExtensions extensions; 1955 1956 extensions.clientExtensions = true; 1957 extensions.platformBase = true; 1958 extensions.platformANGLE = true; 1959 1960 #if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11) 1961 extensions.platformANGLED3D = true; 1962 extensions.platformDevice = true; 1963 #endif 1964 1965 #if defined(ANGLE_USE_GBM) 1966 extensions.platformGbmKHR = true; 1967 #endif 1968 1969 #if defined(ANGLE_USE_WAYLAND) 1970 extensions.platformWaylandEXT = true; 1971 #endif 1972 1973 #if defined(ANGLE_ENABLE_D3D11) 1974 # if defined(ANGLE_ENABLE_WINDOWS_UWP) 1975 extensions.platformANGLED3D11ON12 = true; 1976 # else 1977 extensions.platformANGLED3D11ON12 = IsWindows10OrGreater(); 1978 # endif 1979 extensions.platformANGLEDeviceId = true; 1980 #endif 1981 1982 #if defined(ANGLE_ENABLE_OPENGL) 1983 extensions.platformANGLEOpenGL = true; 1984 #endif 1985 1986 #if defined(ANGLE_ENABLE_NULL) 1987 extensions.platformANGLENULL = true; 1988 #endif 1989 1990 #if defined(ANGLE_ENABLE_D3D11) 1991 extensions.deviceCreation = true; 1992 extensions.deviceCreationD3D11 = true; 1993 extensions.experimentalPresentPath = true; 1994 #endif 1995 1996 #if defined(ANGLE_ENABLE_VULKAN) 1997 extensions.platformANGLEVulkan = true; 1998 extensions.platformANGLEDeviceId = true; 1999 #endif 2000 2001 #if defined(ANGLE_ENABLE_SWIFTSHADER) 2002 extensions.platformANGLEDeviceTypeSwiftShader = true; 2003 #endif 2004 2005 #if defined(ANGLE_ENABLE_METAL) 2006 extensions.platformANGLEMetal = true; 2007 extensions.platformANGLEDeviceId = true; 2008 #endif 2009 2010 #if defined(ANGLE_USE_X11) 2011 extensions.x11Visual = true; 2012 #endif 2013 2014 #if defined(ANGLE_PLATFORM_LINUX) 2015 extensions.platformANGLEDeviceTypeEGLANGLE = true; 2016 #endif 2017 2018 #if (defined(ANGLE_PLATFORM_IOS) && !defined(ANGLE_PLATFORM_MACCATALYST)) || \ 2019 (defined(ANGLE_PLATFORM_MACCATALYST) && defined(ANGLE_CPU_ARM64)) 2020 extensions.platformANGLEDeviceContextVolatileEagl = true; 2021 #endif 2022 2023 #if defined(ANGLE_PLATFORM_MACOS) || defined(ANGLE_PLATFORM_MACCATALYST) 2024 extensions.platformANGLEDeviceContextVolatileCgl = true; 2025 #endif 2026 2027 #if defined(ANGLE_ENABLE_METAL) 2028 extensions.displayPowerPreferenceANGLE = true; 2029 #endif 2030 2031 extensions.clientGetAllProcAddresses = true; 2032 extensions.debug = true; 2033 extensions.featureControlANGLE = true; 2034 extensions.deviceQueryEXT = true; 2035 2036 return extensions; 2037 } 2038 2039 template <typename T> 2040 static std::string GenerateExtensionsString(const T &extensions) 2041 { 2042 std::vector<std::string> extensionsVector = extensions.getStrings(); 2043 2044 std::ostringstream stream; 2045 std::copy(extensionsVector.begin(), extensionsVector.end(), 2046 std::ostream_iterator<std::string>(stream, " ")); 2047 return stream.str(); 2048 } 2049 2050 // static 2051 const ClientExtensions &Display::GetClientExtensions() 2052 { 2053 static const ClientExtensions clientExtensions = GenerateClientExtensions(); 2054 return clientExtensions; 2055 } 2056 2057 // static 2058 const std::string &Display::GetClientExtensionString() 2059 { 2060 static const angle::base::NoDestructor<std::string> clientExtensionsString( 2061 GenerateExtensionsString(GetClientExtensions())); 2062 return *clientExtensionsString; 2063 } 2064 2065 void Display::initDisplayExtensions() 2066 { 2067 mDisplayExtensions = mImplementation->getExtensions(); 2068 2069 // Some extensions are always available because they are implemented in the EGL layer. 2070 mDisplayExtensions.createContext = true; 2071 mDisplayExtensions.createContextNoError = !mFrontendFeatures.forceGlErrorChecking.enabled; 2072 mDisplayExtensions.createContextWebGLCompatibility = true; 2073 mDisplayExtensions.createContextBindGeneratesResource = true; 2074 mDisplayExtensions.createContextClientArrays = true; 2075 mDisplayExtensions.pixelFormatFloat = true; 2076 mDisplayExtensions.reusableSyncKHR = true; 2077 2078 // Force EGL_KHR_get_all_proc_addresses on. 2079 mDisplayExtensions.getAllProcAddresses = true; 2080 2081 // Enable program cache control since it is not back-end dependent. 2082 mDisplayExtensions.programCacheControlANGLE = true; 2083 2084 // Request extension is implemented in the ANGLE frontend 2085 mDisplayExtensions.createContextExtensionsEnabled = true; 2086 2087 // Blob cache extension is provided by the ANGLE frontend 2088 mDisplayExtensions.blobCache = true; 2089 2090 // The EGL_ANDROID_recordable extension is provided by the ANGLE frontend, and will always 2091 // say that ANativeWindow is not recordable. 2092 mDisplayExtensions.recordable = true; 2093 2094 // All backends support specific context versions 2095 mDisplayExtensions.createContextBackwardsCompatible = true; 2096 2097 mDisplayExtensionString = GenerateExtensionsString(mDisplayExtensions); 2098 } 2099 2100 bool Display::isValidNativeWindow(EGLNativeWindowType window) const 2101 { 2102 return mImplementation->isValidNativeWindow(window); 2103 } 2104 2105 Error Display::validateClientBuffer(const Config *configuration, 2106 EGLenum buftype, 2107 EGLClientBuffer clientBuffer, 2108 const AttributeMap &attribs) const 2109 { 2110 return mImplementation->validateClientBuffer(configuration, buftype, clientBuffer, attribs); 2111 } 2112 2113 Error Display::validateImageClientBuffer(const gl::Context *context, 2114 EGLenum target, 2115 EGLClientBuffer clientBuffer, 2116 const egl::AttributeMap &attribs) const 2117 { 2118 return mImplementation->validateImageClientBuffer(context, target, clientBuffer, attribs); 2119 } 2120 2121 Error Display::valdiatePixmap(const Config *config, 2122 EGLNativePixmapType pixmap, 2123 const AttributeMap &attributes) const 2124 { 2125 return mImplementation->validatePixmap(config, pixmap, attributes); 2126 } 2127 2128 bool Display::isValidDisplay(const egl::Display *display) 2129 { 2130 const ANGLEPlatformDisplayMap *anglePlatformDisplayMap = GetANGLEPlatformDisplayMap(); 2131 for (const auto &displayPair : *anglePlatformDisplayMap) 2132 { 2133 if (displayPair.second == display) 2134 { 2135 return true; 2136 } 2137 } 2138 2139 const DevicePlatformDisplayMap *devicePlatformDisplayMap = GetDevicePlatformDisplayMap(); 2140 for (const auto &displayPair : *devicePlatformDisplayMap) 2141 { 2142 if (displayPair.second == display) 2143 { 2144 return true; 2145 } 2146 } 2147 2148 return false; 2149 } 2150 2151 bool Display::isValidNativeDisplay(EGLNativeDisplayType display) 2152 { 2153 // TODO(jmadill): handle this properly 2154 if (display == EGL_DEFAULT_DISPLAY) 2155 { 2156 return true; 2157 } 2158 2159 #if defined(ANGLE_PLATFORM_WINDOWS) && !defined(ANGLE_ENABLE_WINDOWS_UWP) 2160 if (display == EGL_SOFTWARE_DISPLAY_ANGLE || display == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || 2161 display == EGL_D3D11_ONLY_DISPLAY_ANGLE) 2162 { 2163 return true; 2164 } 2165 return (WindowFromDC(display) != nullptr); 2166 #else 2167 return true; 2168 #endif 2169 } 2170 2171 void Display::initVendorString() 2172 { 2173 mVendorString = "Google Inc."; 2174 std::string vendorStringImpl = mImplementation->getVendorString(); 2175 if (!vendorStringImpl.empty()) 2176 { 2177 mVendorString += " (" + vendorStringImpl + ")"; 2178 } 2179 } 2180 2181 void Display::initVersionString() 2182 { 2183 mVersionString = mImplementation->getVersionString(true); 2184 } 2185 2186 void Display::initClientAPIString() 2187 { 2188 // If the max supported desktop version is not None, we support a desktop GL frontend. 2189 if (mImplementation->getMaxSupportedDesktopVersion().valid()) 2190 { 2191 mClientAPIString = "OpenGL_ES OpenGL"; 2192 } 2193 else 2194 { 2195 mClientAPIString = "OpenGL_ES"; 2196 } 2197 } 2198 2199 void Display::initializeFrontendFeatures() 2200 { 2201 // Enable on all Impls 2202 ANGLE_FEATURE_CONDITION((&mFrontendFeatures), loseContextOnOutOfMemory, true); 2203 ANGLE_FEATURE_CONDITION((&mFrontendFeatures), allowCompressedFormats, true); 2204 2205 // No longer enable this on any Impl - crbug.com/1165751 2206 ANGLE_FEATURE_CONDITION((&mFrontendFeatures), scalarizeVecAndMatConstructorArgs, false); 2207 2208 // Disabled by default. To reduce the risk, create a feature to enable 2209 // compressing pipeline cache in multi-thread pool. 2210 ANGLE_FEATURE_CONDITION(&mFrontendFeatures, enableCompressingPipelineCacheInThreadPool, false); 2211 2212 // Disabled by default until work on the extension is complete - anglebug.com/7279. 2213 ANGLE_FEATURE_CONDITION(&mFrontendFeatures, emulatePixelLocalStorage, false); 2214 2215 mImplementation->initializeFrontendFeatures(&mFrontendFeatures); 2216 2217 rx::ApplyFeatureOverrides(&mFrontendFeatures, mState); 2218 } 2219 2220 const DisplayExtensions &Display::getExtensions() const 2221 { 2222 return mDisplayExtensions; 2223 } 2224 2225 const std::string &Display::getExtensionString() const 2226 { 2227 return mDisplayExtensionString; 2228 } 2229 2230 const std::string &Display::getVendorString() const 2231 { 2232 return mVendorString; 2233 } 2234 2235 const std::string &Display::getVersionString() const 2236 { 2237 return mVersionString; 2238 } 2239 2240 const std::string &Display::getClientAPIString() const 2241 { 2242 return mClientAPIString; 2243 } 2244 2245 std::string Display::getBackendRendererDescription() const 2246 { 2247 return mImplementation->getRendererDescription(); 2248 } 2249 2250 std::string Display::getBackendVendorString() const 2251 { 2252 return mImplementation->getVendorString(); 2253 } 2254 2255 std::string Display::getBackendVersionString(bool includeFullVersion) const 2256 { 2257 return mImplementation->getVersionString(includeFullVersion); 2258 } 2259 2260 Device *Display::getDevice() const 2261 { 2262 return mDevice; 2263 } 2264 2265 Surface *Display::getWGLSurface() const 2266 { 2267 return mSurface; 2268 } 2269 2270 gl::Version Display::getMaxSupportedESVersion() const 2271 { 2272 return mImplementation->getMaxSupportedESVersion(); 2273 } 2274 2275 EGLint Display::programCacheGetAttrib(EGLenum attrib) const 2276 { 2277 switch (attrib) 2278 { 2279 case EGL_PROGRAM_CACHE_KEY_LENGTH_ANGLE: 2280 return static_cast<EGLint>(BlobCache::kKeyLength); 2281 2282 case EGL_PROGRAM_CACHE_SIZE_ANGLE: 2283 return static_cast<EGLint>(mMemoryProgramCache.entryCount()); 2284 2285 default: 2286 UNREACHABLE(); 2287 return 0; 2288 } 2289 } 2290 2291 Error Display::programCacheQuery(EGLint index, 2292 void *key, 2293 EGLint *keysize, 2294 void *binary, 2295 EGLint *binarysize) 2296 { 2297 ASSERT(index >= 0 && index < static_cast<EGLint>(mMemoryProgramCache.entryCount())); 2298 2299 const BlobCache::Key *programHash = nullptr; 2300 BlobCache::Value programBinary; 2301 // TODO(jmadill): Make this thread-safe. 2302 bool result = 2303 mMemoryProgramCache.getAt(static_cast<size_t>(index), &programHash, &programBinary); 2304 if (!result) 2305 { 2306 return EglBadAccess() << "Program binary not accessible."; 2307 } 2308 2309 ASSERT(keysize && binarysize); 2310 2311 if (key) 2312 { 2313 ASSERT(*keysize == static_cast<EGLint>(BlobCache::kKeyLength)); 2314 memcpy(key, programHash->data(), BlobCache::kKeyLength); 2315 } 2316 2317 if (binary) 2318 { 2319 // Note: we check the size here instead of in the validation code, since we need to 2320 // access the cache as atomically as possible. It's possible that the cache contents 2321 // could change between the validation size check and the retrieval. 2322 if (programBinary.size() > static_cast<size_t>(*binarysize)) 2323 { 2324 return EglBadAccess() << "Program binary too large or changed during access."; 2325 } 2326 2327 memcpy(binary, programBinary.data(), programBinary.size()); 2328 } 2329 2330 *binarysize = static_cast<EGLint>(programBinary.size()); 2331 *keysize = static_cast<EGLint>(BlobCache::kKeyLength); 2332 2333 return NoError(); 2334 } 2335 2336 Error Display::programCachePopulate(const void *key, 2337 EGLint keysize, 2338 const void *binary, 2339 EGLint binarysize) 2340 { 2341 ASSERT(keysize == static_cast<EGLint>(BlobCache::kKeyLength)); 2342 2343 BlobCache::Key programHash; 2344 memcpy(programHash.data(), key, BlobCache::kKeyLength); 2345 2346 if (!mMemoryProgramCache.putBinary(programHash, reinterpret_cast<const uint8_t *>(binary), 2347 static_cast<size_t>(binarysize))) 2348 { 2349 return EglBadAccess() << "Failed to copy program binary into the cache."; 2350 } 2351 2352 return NoError(); 2353 } 2354 2355 EGLint Display::programCacheResize(EGLint limit, EGLenum mode) 2356 { 2357 switch (mode) 2358 { 2359 case EGL_PROGRAM_CACHE_RESIZE_ANGLE: 2360 { 2361 size_t initialSize = mMemoryProgramCache.size(); 2362 mMemoryProgramCache.resize(static_cast<size_t>(limit)); 2363 return static_cast<EGLint>(initialSize); 2364 } 2365 2366 case EGL_PROGRAM_CACHE_TRIM_ANGLE: 2367 return static_cast<EGLint>(mMemoryProgramCache.trim(static_cast<size_t>(limit))); 2368 2369 default: 2370 UNREACHABLE(); 2371 return 0; 2372 } 2373 } 2374 2375 void Display::overrideFrontendFeatures(const std::vector<std::string> &featureNames, bool enabled) 2376 { 2377 mFrontendFeatures.overrideFeatures(featureNames, enabled); 2378 } 2379 2380 const char *Display::queryStringi(const EGLint name, const EGLint index) 2381 { 2382 const char *result = nullptr; 2383 switch (name) 2384 { 2385 case EGL_FEATURE_NAME_ANGLE: 2386 result = mFeatures[index]->name; 2387 break; 2388 case EGL_FEATURE_CATEGORY_ANGLE: 2389 result = angle::FeatureCategoryToString(mFeatures[index]->category); 2390 break; 2391 case EGL_FEATURE_DESCRIPTION_ANGLE: 2392 result = mFeatures[index]->description; 2393 break; 2394 case EGL_FEATURE_BUG_ANGLE: 2395 result = mFeatures[index]->bug; 2396 break; 2397 case EGL_FEATURE_STATUS_ANGLE: 2398 result = angle::FeatureStatusToString(mFeatures[index]->enabled); 2399 break; 2400 case EGL_FEATURE_CONDITION_ANGLE: 2401 result = mFeatures[index]->condition; 2402 break; 2403 default: 2404 UNREACHABLE(); 2405 return nullptr; 2406 } 2407 return result; 2408 } 2409 2410 EGLAttrib Display::queryAttrib(const EGLint attribute) 2411 { 2412 EGLAttrib value = 0; 2413 switch (attribute) 2414 { 2415 case EGL_DEVICE_EXT: 2416 value = reinterpret_cast<EGLAttrib>(mDevice); 2417 break; 2418 2419 case EGL_FEATURE_COUNT_ANGLE: 2420 value = mFeatures.size(); 2421 break; 2422 2423 default: 2424 UNREACHABLE(); 2425 } 2426 return value; 2427 } 2428 2429 angle::ScratchBuffer Display::requestScratchBuffer() 2430 { 2431 return requestScratchBufferImpl(&mScratchBuffers); 2432 } 2433 2434 void Display::returnScratchBuffer(angle::ScratchBuffer scratchBuffer) 2435 { 2436 returnScratchBufferImpl(std::move(scratchBuffer), &mScratchBuffers); 2437 } 2438 2439 angle::ScratchBuffer Display::requestZeroFilledBuffer() 2440 { 2441 return requestScratchBufferImpl(&mZeroFilledBuffers); 2442 } 2443 2444 void Display::returnZeroFilledBuffer(angle::ScratchBuffer zeroFilledBuffer) 2445 { 2446 returnScratchBufferImpl(std::move(zeroFilledBuffer), &mZeroFilledBuffers); 2447 } 2448 2449 angle::ScratchBuffer Display::requestScratchBufferImpl( 2450 std::vector<angle::ScratchBuffer> *bufferVector) 2451 { 2452 std::lock_guard<std::mutex> lock(mScratchBufferMutex); 2453 if (!bufferVector->empty()) 2454 { 2455 angle::ScratchBuffer buffer = std::move(bufferVector->back()); 2456 bufferVector->pop_back(); 2457 return buffer; 2458 } 2459 2460 return angle::ScratchBuffer(kScratchBufferLifetime); 2461 } 2462 2463 void Display::returnScratchBufferImpl(angle::ScratchBuffer scratchBuffer, 2464 std::vector<angle::ScratchBuffer> *bufferVector) 2465 { 2466 std::lock_guard<std::mutex> lock(mScratchBufferMutex); 2467 bufferVector->push_back(std::move(scratchBuffer)); 2468 } 2469 2470 Error Display::handleGPUSwitch() 2471 { 2472 ANGLE_TRY(mImplementation->handleGPUSwitch()); 2473 initVendorString(); 2474 return NoError(); 2475 } 2476 2477 Error Display::forceGPUSwitch(EGLint gpuIDHigh, EGLint gpuIDLow) 2478 { 2479 ANGLE_TRY(mImplementation->forceGPUSwitch(gpuIDHigh, gpuIDLow)); 2480 initVendorString(); 2481 return NoError(); 2482 } 2483 2484 bool Display::supportsDmaBufFormat(EGLint format) const 2485 { 2486 return mImplementation->supportsDmaBufFormat(format); 2487 } 2488 2489 Error Display::queryDmaBufFormats(EGLint max_formats, EGLint *formats, EGLint *num_formats) 2490 { 2491 ANGLE_TRY(mImplementation->queryDmaBufFormats(max_formats, formats, num_formats)); 2492 return NoError(); 2493 } 2494 2495 Error Display::queryDmaBufModifiers(EGLint format, 2496 EGLint max_modifiers, 2497 EGLuint64KHR *modifiers, 2498 EGLBoolean *external_only, 2499 EGLint *num_modifiers) 2500 { 2501 ANGLE_TRY(mImplementation->queryDmaBufModifiers(format, max_modifiers, modifiers, external_only, 2502 num_modifiers)); 2503 return NoError(); 2504 } 2505 2506 } // namespace egl