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