gfxWindowsPlatform.cpp (59602B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #define INITGUID // set before devguid.h 8 9 #include "gfxWindowsPlatform.h" 10 11 #include "cairo.h" 12 #include "mozilla/layers/CompositorBridgeChild.h" 13 14 #include "gfxBlur.h" 15 #include "gfxImageSurface.h" 16 #include "gfxWindowsSurface.h" 17 18 #include "nsUnicharUtils.h" 19 #include "nsUnicodeProperties.h" 20 21 #include "mozilla/Preferences.h" 22 #include "mozilla/ProfilerLabels.h" 23 #include "mozilla/ProfilerMarkers.h" 24 #include "mozilla/ProfilerThreadSleep.h" 25 #include "mozilla/Components.h" 26 #include "mozilla/Sprintf.h" 27 #include "mozilla/WindowsVersion.h" 28 #include "nsIGfxInfo.h" 29 #include "nsServiceManagerUtils.h" 30 #include "nsTArray.h" 31 #include "nsThreadUtils.h" 32 #include "mozilla/glean/GfxMetrics.h" 33 34 #include "plbase64.h" 35 #include "nsIXULRuntime.h" 36 #include "imgLoader.h" 37 38 #include "nsIGfxInfo.h" 39 40 #include "gfxCrashReporterUtils.h" 41 42 #include "mozilla/layers/CanvasChild.h" 43 #include "mozilla/layers/CompositorThread.h" 44 45 #include "gfxDWriteFontList.h" 46 #include "gfxDWriteFonts.h" 47 #include "gfxDWriteCommon.h" 48 #include <dwrite.h> 49 50 #include "gfxTextRun.h" 51 #include "gfxUserFontSet.h" 52 #include "nsWindowsHelpers.h" 53 #include "gfx2DGlue.h" 54 55 #include <d3d10_1.h> 56 57 #include "mozilla/gfx/2D.h" 58 #include "mozilla/gfx/gfxVars.h" 59 60 #include <dwmapi.h> 61 #include <d3d11.h> 62 #include <d2d1_1.h> 63 64 #include "nsIMemoryReporter.h" 65 #include <winternl.h> 66 #include "d3dkmtQueryStatistics.h" 67 68 #include "base/thread.h" 69 #include "mozilla/StaticPrefs_gfx.h" 70 #ifdef MOZ_WMF_CDM 71 # include "mozilla/StaticPrefs_media.h" 72 #endif 73 #include "mozilla/StaticPrefs_layers.h" 74 #include "gfxConfig.h" 75 #include "VsyncSource.h" 76 #include "DriverCrashGuard.h" 77 #include "mozilla/dom/ContentChild.h" 78 #include "mozilla/gfx/DeviceManagerDx.h" 79 #include "mozilla/gfx/DisplayConfigWindows.h" 80 #include "mozilla/gfx/GPUProcessManager.h" 81 #include "mozilla/layers/DeviceAttachmentsD3D11.h" 82 #include "mozilla/WindowsProcessMitigations.h" 83 #include "D3D11Checks.h" 84 #include "mozilla/ScreenHelperWin.h" 85 86 using namespace mozilla; 87 using namespace mozilla::gfx; 88 using namespace mozilla::layers; 89 using namespace mozilla::widget; 90 using namespace mozilla::image; 91 using namespace mozilla::unicode; 92 93 DCForMetrics::DCForMetrics() { 94 // Get the whole screen DC: 95 mDC = GetDC(nullptr); 96 SetGraphicsMode(mDC, GM_ADVANCED); 97 } 98 99 class GPUAdapterReporter final : public nsIMemoryReporter { 100 // Callers must Release the DXGIAdapter after use or risk mem-leak 101 static bool GetDXGIAdapter(IDXGIAdapter** aDXGIAdapter) { 102 RefPtr<ID3D11Device> d3d11Device; 103 RefPtr<IDXGIDevice> dxgiDevice; 104 bool result = false; 105 106 if ((d3d11Device = mozilla::gfx::Factory::GetDirect3D11Device())) { 107 if (d3d11Device->QueryInterface(__uuidof(IDXGIDevice), 108 getter_AddRefs(dxgiDevice)) == S_OK) { 109 result = (dxgiDevice->GetAdapter(aDXGIAdapter) == S_OK); 110 } 111 } 112 113 return result; 114 } 115 116 ~GPUAdapterReporter() {} 117 118 public: 119 NS_DECL_ISUPPORTS 120 121 NS_IMETHOD 122 CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData, 123 bool aAnonymize) override { 124 HANDLE ProcessHandle = GetCurrentProcess(); 125 126 int64_t dedicatedBytesUsed = 0; 127 int64_t sharedBytesUsed = 0; 128 int64_t committedBytesUsed = 0; 129 IDXGIAdapter* DXGIAdapter; 130 131 HMODULE gdi32Handle; 132 PFND3DKMTQS queryD3DKMTStatistics = nullptr; 133 134 if ((gdi32Handle = LoadLibrary(TEXT("gdi32.dll")))) 135 queryD3DKMTStatistics = 136 (PFND3DKMTQS)GetProcAddress(gdi32Handle, "D3DKMTQueryStatistics"); 137 138 if (queryD3DKMTStatistics && GetDXGIAdapter(&DXGIAdapter)) { 139 // Most of this block is understood thanks to wj32's work on Process 140 // Hacker 141 142 DXGI_ADAPTER_DESC adapterDesc; 143 D3DKMTQS queryStatistics; 144 145 DXGIAdapter->GetDesc(&adapterDesc); 146 DXGIAdapter->Release(); 147 148 memset(&queryStatistics, 0, sizeof(D3DKMTQS)); 149 queryStatistics.Type = D3DKMTQS_PROCESS; 150 queryStatistics.AdapterLuid = adapterDesc.AdapterLuid; 151 queryStatistics.hProcess = ProcessHandle; 152 if (NT_SUCCESS(queryD3DKMTStatistics(&queryStatistics))) { 153 committedBytesUsed = 154 queryStatistics.QueryResult.ProcessInfo.SystemMemory.BytesAllocated; 155 } 156 157 memset(&queryStatistics, 0, sizeof(D3DKMTQS)); 158 queryStatistics.Type = D3DKMTQS_ADAPTER; 159 queryStatistics.AdapterLuid = adapterDesc.AdapterLuid; 160 if (NT_SUCCESS(queryD3DKMTStatistics(&queryStatistics))) { 161 ULONG i; 162 ULONG segmentCount = queryStatistics.QueryResult.AdapterInfo.NbSegments; 163 164 for (i = 0; i < segmentCount; i++) { 165 memset(&queryStatistics, 0, sizeof(D3DKMTQS)); 166 queryStatistics.Type = D3DKMTQS_SEGMENT; 167 queryStatistics.AdapterLuid = adapterDesc.AdapterLuid; 168 queryStatistics.QuerySegment.SegmentId = i; 169 170 if (NT_SUCCESS(queryD3DKMTStatistics(&queryStatistics))) { 171 bool aperture = queryStatistics.QueryResult.SegmentInfo.Aperture; 172 memset(&queryStatistics, 0, sizeof(D3DKMTQS)); 173 queryStatistics.Type = D3DKMTQS_PROCESS_SEGMENT; 174 queryStatistics.AdapterLuid = adapterDesc.AdapterLuid; 175 queryStatistics.hProcess = ProcessHandle; 176 queryStatistics.QueryProcessSegment.SegmentId = i; 177 if (NT_SUCCESS(queryD3DKMTStatistics(&queryStatistics))) { 178 ULONGLONG bytesCommitted = 179 queryStatistics.QueryResult.ProcessSegmentInfo.BytesCommitted; 180 if (aperture) 181 sharedBytesUsed += bytesCommitted; 182 else 183 dedicatedBytesUsed += bytesCommitted; 184 } 185 } 186 } 187 } 188 } 189 190 FreeLibrary(gdi32Handle); 191 192 MOZ_COLLECT_REPORT("gpu-committed", KIND_OTHER, UNITS_BYTES, 193 committedBytesUsed, 194 "Memory committed by the Windows graphics system."); 195 196 MOZ_COLLECT_REPORT( 197 "gpu-dedicated", KIND_OTHER, UNITS_BYTES, dedicatedBytesUsed, 198 "Out-of-process memory allocated for this process in a physical " 199 "GPU adapter's memory."); 200 201 MOZ_COLLECT_REPORT("gpu-shared", KIND_OTHER, UNITS_BYTES, sharedBytesUsed, 202 "In-process memory that is shared with the GPU."); 203 204 return NS_OK; 205 } 206 }; 207 208 NS_IMPL_ISUPPORTS(GPUAdapterReporter, nsIMemoryReporter) 209 210 Atomic<size_t> gfxWindowsPlatform::sD3D11SharedTextures; 211 Atomic<size_t> gfxWindowsPlatform::sD3D9SharedTextures; 212 213 class D3DSharedTexturesReporter final : public nsIMemoryReporter { 214 ~D3DSharedTexturesReporter() {} 215 216 public: 217 NS_DECL_ISUPPORTS 218 219 NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport, 220 nsISupports* aData, bool aAnonymize) override { 221 if (gfxWindowsPlatform::sD3D11SharedTextures > 0) { 222 MOZ_COLLECT_REPORT("d3d11-shared-textures", KIND_OTHER, UNITS_BYTES, 223 gfxWindowsPlatform::sD3D11SharedTextures, 224 "D3D11 shared textures."); 225 } 226 227 if (gfxWindowsPlatform::sD3D9SharedTextures > 0) { 228 MOZ_COLLECT_REPORT("d3d9-shared-textures", KIND_OTHER, UNITS_BYTES, 229 gfxWindowsPlatform::sD3D9SharedTextures, 230 "D3D9 shared textures."); 231 } 232 233 return NS_OK; 234 } 235 }; 236 237 NS_IMPL_ISUPPORTS(D3DSharedTexturesReporter, nsIMemoryReporter) 238 239 gfxWindowsPlatform::gfxWindowsPlatform() { 240 // If win32k is locked down then we can't use COM STA and shouldn't need it. 241 // Also, we won't be using any GPU memory in this process. 242 if (!IsWin32kLockedDown()) { 243 /* 244 * Initialize COM 245 */ 246 CoInitialize(nullptr); 247 248 RegisterStrongMemoryReporter(new GPUAdapterReporter()); 249 RegisterStrongMemoryReporter(new D3DSharedTexturesReporter()); 250 } 251 } 252 253 gfxWindowsPlatform::~gfxWindowsPlatform() { 254 DeviceManagerDx::Shutdown(); 255 256 // We don't initialize COM when win32k is locked down. 257 if (!IsWin32kLockedDown()) { 258 /* 259 * Uninitialize COM 260 */ 261 CoUninitialize(); 262 } 263 } 264 265 /* static */ 266 void gfxWindowsPlatform::InitMemoryReportersForGPUProcess() { 267 MOZ_RELEASE_ASSERT(XRE_IsGPUProcess()); 268 269 RegisterStrongMemoryReporter(new GPUAdapterReporter()); 270 RegisterStrongMemoryReporter(new D3DSharedTexturesReporter()); 271 } 272 273 /* static */ 274 nsresult gfxWindowsPlatform::GetGpuTimeSinceProcessStartInMs( 275 uint64_t* aResult) { 276 // If win32k is locked down then we should not have any GPU processing and 277 // cannot use these APIs either way. 278 if (IsWin32kLockedDown()) { 279 *aResult = 0; 280 return NS_OK; 281 } 282 283 nsModuleHandle module(LoadLibrary(L"gdi32.dll")); 284 if (!module) { 285 return NS_ERROR_NOT_AVAILABLE; 286 } 287 288 PFND3DKMTQS queryD3DKMTStatistics = 289 (PFND3DKMTQS)GetProcAddress(module, "D3DKMTQueryStatistics"); 290 if (!queryD3DKMTStatistics) { 291 return NS_ERROR_NOT_AVAILABLE; 292 } 293 294 gfx::DeviceManagerDx* dm = DeviceManagerDx::Get(); 295 if (!dm) { 296 return NS_ERROR_NOT_AVAILABLE; 297 } 298 299 D3D11DeviceStatus status; 300 if (!dm->ExportDeviceInfo(&status)) { 301 // Assume that we used 0ms of GPU time if the device manager 302 // doesn't know the device status. 303 *aResult = 0; 304 return NS_OK; 305 } 306 307 const DxgiAdapterDesc& adapterDesc = status.adapter(); 308 309 D3DKMTQS queryStatistics; 310 memset(&queryStatistics, 0, sizeof(D3DKMTQS)); 311 queryStatistics.Type = D3DKMTQS_ADAPTER; 312 queryStatistics.AdapterLuid = adapterDesc.AdapterLuid; 313 if (!NT_SUCCESS(queryD3DKMTStatistics(&queryStatistics))) { 314 return NS_ERROR_FAILURE; 315 } 316 317 uint64_t result = 0; 318 ULONG nodeCount = queryStatistics.QueryResult.AdapterInfo.NodeCount; 319 for (ULONG i = 0; i < nodeCount; ++i) { 320 memset(&queryStatistics, 0, sizeof(D3DKMTQS)); 321 queryStatistics.Type = D3DKMTQS_PROCESS_NODE; 322 queryStatistics.AdapterLuid = adapterDesc.AdapterLuid; 323 queryStatistics.hProcess = GetCurrentProcess(); 324 queryStatistics.QueryProcessNode.NodeId = i; 325 if (NT_SUCCESS(queryD3DKMTStatistics(&queryStatistics))) { 326 result += queryStatistics.QueryResult.ProcessNodeInformation.RunningTime 327 .QuadPart * 328 100 / PR_NSEC_PER_MSEC; 329 } 330 } 331 332 *aResult = result; 333 return NS_OK; 334 } 335 336 static void UpdateANGLEConfig() { 337 if (!gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) { 338 gfxConfig::Disable(Feature::D3D11_HW_ANGLE, FeatureStatus::Disabled, 339 "D3D11 compositing is disabled", 340 "FEATURE_FAILURE_HW_ANGLE_D3D11_DISABLED"_ns); 341 } 342 } 343 344 void gfxWindowsPlatform::InitAcceleration() { 345 gfxPlatform::InitAcceleration(); 346 347 DeviceManagerDx::Init(); 348 349 InitializeConfig(); 350 // Ensure devices initialization. SharedSurfaceANGLE and 351 // SharedSurfaceD3D11Interop use them. The devices are lazily initialized 352 // with WebRender to reduce memory usage. 353 // Initialize them now when running non-e10s. 354 if (!BrowserTabsRemoteAutostart()) { 355 EnsureDevicesInitialized(); 356 } 357 UpdateANGLEConfig(); 358 UpdateRenderMode(); 359 360 // If we have Skia and we didn't init dwrite already, do it now. 361 if (!DWriteEnabled() && GetDefaultContentBackend() == BackendType::SKIA) { 362 InitDWriteSupport(); 363 } 364 // We need to listen for font setting changes even if DWrite is not used. 365 Factory::SetSystemTextQuality(gfxVars::SystemTextQuality()); 366 gfxVars::SetSystemTextQualityListener( 367 gfxDWriteFont::SystemTextQualityChanged); 368 369 // Our ScreenHelperWin also depends on DeviceManagerDx state. 370 if (XRE_IsParentProcess() && !gfxPlatform::IsHeadless()) { 371 ScreenHelperWin::RefreshScreens(); 372 } 373 374 RecordStartupTelemetry(); 375 } 376 377 void gfxWindowsPlatform::InitWebRenderConfig() { 378 gfxPlatform::InitWebRenderConfig(); 379 UpdateBackendPrefs(); 380 } 381 382 void gfxWindowsPlatform::InitPlatformHardwareVideoConfig() { 383 FeatureState& featureDec = 384 gfxConfig::GetFeature(Feature::HARDWARE_VIDEO_DECODING); 385 FeatureState& featureEnc = 386 gfxConfig::GetFeature(Feature::HARDWARE_VIDEO_ENCODING); 387 388 DeviceManagerDx* dm = DeviceManagerDx::Get(); 389 if (!dm) { 390 featureDec.ForceDisable(FeatureStatus::Unavailable, 391 "Requires DeviceManagerDx", 392 "FEATURE_FAILURE_NO_DEVICE_MANAGER_DX"_ns); 393 featureEnc.ForceDisable(FeatureStatus::Unavailable, 394 "Requires DeviceManagerDx", 395 "FEATURE_FAILURE_NO_DEVICE_MANAGER_DX"_ns); 396 } else if (!dm->TextureSharingWorks()) { 397 featureDec.ForceDisable(FeatureStatus::Unavailable, 398 "Requires texture sharing", 399 "FEATURE_FAILURE_BROKEN_TEXTURE_SHARING"_ns); 400 featureEnc.ForceDisable(FeatureStatus::Unavailable, 401 "Requires texture sharing", 402 "FEATURE_FAILURE_BROKEN_TEXTURE_SHARING"_ns); 403 } else if (dm->IsWARP()) { 404 featureDec.ForceDisable(FeatureStatus::Unavailable, "Cannot use with WARP", 405 "FEATURE_FAILURE_D3D11_WARP_DEVICE"_ns); 406 featureEnc.ForceDisable(FeatureStatus::Unavailable, "Cannot use with WARP", 407 "FEATURE_FAILURE_D3D11_WARP_DEVICE"_ns); 408 } 409 } 410 411 #ifdef MOZ_WMF_CDM 412 void gfxWindowsPlatform::InitPlatformHardwarDRMConfig() { 413 nsCString message, failureId; 414 FeatureState& featureHWDRM = gfxConfig::GetFeature(Feature::WMF_HW_DRM); 415 featureHWDRM.Reset(); 416 featureHWDRM.EnableByDefault(); 417 if (StaticPrefs::media_wmf_media_engine_enabled() != 1 && 418 StaticPrefs::media_wmf_media_engine_enabled() != 2) { 419 featureHWDRM.UserDisable( 420 "Force disabled by 'media.wmf.media-engine.enabled'", 421 "FEATURE_FAILURE_USER_FORCE_DISABLED"_ns); 422 } else if (StaticPrefs::media_wmf_media_engine_bypass_gfx_blocklist()) { 423 featureHWDRM.UserForceEnable( 424 "Force enabled by " 425 "'media.wmf.media-engine.bypass-gfx-blocklist'"); 426 } 427 if (!IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_WMF_HW_DRM, &message, 428 failureId)) { 429 featureHWDRM.Disable(FeatureStatus::Blocklisted, message.get(), failureId); 430 } 431 if (Preferences::GetBool("media.eme.hwdrm.failed", false)) { 432 featureHWDRM.ForceDisable(FeatureStatus::Unavailable, 433 "Force disabled by failed to find a descryptor", 434 "FEATURE_FAILURE_NO_DESCRYPTOR_FAILED"_ns); 435 } 436 gfxVars::SetUseWMFHWDWM(featureHWDRM.IsEnabled()); 437 } 438 #endif 439 440 bool gfxWindowsPlatform::InitDWriteSupport() { 441 mozilla::ScopedGfxFeatureReporter reporter("DWrite"); 442 if (!gfxDWriteFont::InitDWriteSupport()) { 443 return false; 444 } 445 446 reporter.SetSuccessful(); 447 return true; 448 } 449 450 bool gfxWindowsPlatform::HandleDeviceReset() { 451 mozilla::gfx::DeviceResetReason resetReason = 452 mozilla::gfx::DeviceResetReason::OK; 453 if (!DidRenderingDeviceReset(&resetReason)) { 454 return false; 455 } 456 457 if (resetReason != mozilla::gfx::DeviceResetReason::FORCED_RESET) { 458 glean::gfx::device_reset_reason.AccumulateSingleSample( 459 uint32_t(resetReason)); 460 } 461 462 // Remove devices and adapters. 463 DeviceManagerDx::Get()->ResetDevices(); 464 465 imgLoader::NormalLoader()->ClearCache(Nothing()); 466 imgLoader::PrivateBrowsingLoader()->ClearCache(Nothing()); 467 gfxGaussianBlur::ShutdownBlurCache(); 468 469 gfxConfig::Reset(Feature::D3D11_COMPOSITING); 470 gfxConfig::Reset(Feature::D3D11_HW_ANGLE); 471 472 InitializeConfig(); 473 // XXX Add InitWebRenderConfig() calling. 474 if (mInitializedDevices) { 475 InitializeDevices(); 476 } 477 UpdateANGLEConfig(); 478 return true; 479 } 480 481 BackendPrefsData gfxWindowsPlatform::GetBackendPrefs() const { 482 BackendPrefsData data; 483 484 data.mCanvasBitmask = BackendTypeBit(BackendType::SKIA); 485 data.mContentBitmask = BackendTypeBit(BackendType::SKIA); 486 data.mCanvasDefault = BackendType::SKIA; 487 data.mContentDefault = BackendType::SKIA; 488 489 return data; 490 } 491 492 void gfxWindowsPlatform::UpdateBackendPrefs() { 493 BackendPrefsData data = GetBackendPrefs(); 494 InitBackendPrefs(std::move(data)); 495 } 496 497 void gfxWindowsPlatform::UpdateRenderMode() { 498 bool didReset = HandleDeviceReset(); 499 500 UpdateBackendPrefs(); 501 502 if (didReset) { 503 mScreenReferenceDrawTarget = CreateOffscreenContentDrawTarget( 504 IntSize(1, 1), SurfaceFormat::B8G8R8A8); 505 if (!mScreenReferenceDrawTarget) { 506 gfxCriticalNote 507 << "Failed to update reference draw target after device reset" 508 << ", D3D11 device:" << hexa(Factory::GetDirect3D11Device().get()) 509 << ", D3D11 status:" 510 << FeatureStatusToString( 511 gfxConfig::GetValue(Feature::D3D11_COMPOSITING)) 512 << ", content:" << int(GetDefaultContentBackend()) 513 << ", compositor:" << int(GetCompositorBackend()); 514 MOZ_CRASH( 515 "GFX: Failed to update reference draw target after device reset"); 516 } 517 } 518 } 519 520 mozilla::gfx::BackendType gfxWindowsPlatform::GetContentBackendFor( 521 mozilla::layers::LayersBackend aLayers) { 522 return gfxPlatform::GetDefaultContentBackend(); 523 } 524 525 mozilla::gfx::BackendType gfxWindowsPlatform::GetPreferredCanvasBackend() { 526 return gfxPlatform::GetPreferredCanvasBackend(); 527 } 528 529 bool gfxWindowsPlatform::CreatePlatformFontList() { 530 return gfxPlatformFontList::Initialize(new gfxDWriteFontList); 531 } 532 533 already_AddRefed<gfxASurface> gfxWindowsPlatform::CreateOffscreenSurface( 534 const IntSize& aSize, gfxImageFormat aFormat) { 535 if (!Factory::AllowedSurfaceSize(aSize)) { 536 return nullptr; 537 } 538 539 RefPtr<gfxASurface> surf = nullptr; 540 541 #ifdef CAIRO_HAS_WIN32_SURFACE 542 if (!XRE_IsContentProcess()) { 543 surf = new gfxWindowsSurface(aSize, aFormat); 544 } 545 #endif 546 547 if (!surf || surf->CairoStatus()) { 548 surf = new gfxImageSurface(aSize, aFormat); 549 } 550 551 return surf.forget(); 552 } 553 554 void gfxWindowsPlatform::GetCommonFallbackFonts( 555 uint32_t aCh, Script aRunScript, FontPresentation aPresentation, 556 nsTArray<const char*>& aFontList) { 557 if (PrefersColor(aPresentation)) { 558 aFontList.AppendElement("Segoe UI Emoji"); 559 aFontList.AppendElement("Twemoji Mozilla"); 560 } 561 562 switch (aRunScript) { 563 case Script::INVALID: 564 case Script::NUM_SCRIPT_CODES: 565 // Ensure the switch covers all the Script enum values. 566 MOZ_ASSERT_UNREACHABLE("bad script code"); 567 break; 568 569 case Script::COMMON: 570 case Script::INHERITED: 571 // In most cases, COMMON and INHERITED characters will be merged into 572 // their context, but if they occur without context, we'll just treat 573 // them like Latin, etc. 574 case Script::LATIN: 575 case Script::CYRILLIC: 576 case Script::GREEK: 577 case Script::ARMENIAN: 578 case Script::HEBREW: 579 // We always append Arial below, so no need to add it here. 580 // aFontList.AppendElement("Arial"); 581 break; 582 583 case Script::MATHEMATICAL_NOTATION: 584 case Script::SYMBOLS: 585 case Script::SYMBOLS_EMOJI: 586 // Not currently returned by script run resolution (but some symbols may 587 // be handled below). 588 break; 589 590 // CJK-related script codes are a bit troublesome because of unification; 591 // we'll probably just get HAN much of the time, so the choice of which 592 // language font to try for fallback is rather arbitrary. Usually, though, 593 // we hope that font prefs will have handled this earlier. 594 case Script::BOPOMOFO: 595 case Script::HAN_WITH_BOPOMOFO: 596 case Script::SIMPLIFIED_HAN: 597 case Script::HAN: 598 aFontList.AppendElement("SimSun"); 599 if (aCh > 0xFFFF) { 600 aFontList.AppendElement("SimSun-ExtB"); 601 } 602 break; 603 // Currently, we don't resolve script runs to this value, but we may do so 604 // in future if we get better at handling things like `lang=zh-Hant`, not 605 // just resolving based on the Unicode text. 606 case Script::TRADITIONAL_HAN: 607 case Script::TRADITIONAL_HAN_WITH_LATIN: 608 aFontList.AppendElement("MingLiU"); 609 if (aCh > 0xFFFF) { 610 aFontList.AppendElement("MingLiU-ExtB"); 611 } 612 break; 613 case Script::HIRAGANA: 614 case Script::KATAKANA: 615 case Script::KATAKANA_OR_HIRAGANA: 616 case Script::JAPANESE: 617 aFontList.AppendElement("Yu Gothic"); 618 aFontList.AppendElement("MS PGothic"); 619 break; 620 case Script::HANGUL: 621 case Script::JAMO: 622 case Script::KOREAN: 623 aFontList.AppendElement("Malgun Gothic"); 624 break; 625 626 case Script::YI: 627 aFontList.AppendElement("Microsoft Yi Baiti"); 628 break; 629 case Script::MONGOLIAN: 630 aFontList.AppendElement("Mongolian Baiti"); 631 break; 632 case Script::TIBETAN: 633 aFontList.AppendElement("Microsoft Himalaya"); 634 break; 635 case Script::PHAGS_PA: 636 aFontList.AppendElement("Microsoft PhagsPa"); 637 break; 638 639 case Script::ARABIC: 640 // Default to Arial (added unconditionally below) for Arabic script. 641 break; 642 case Script::ARABIC_NASTALIQ: 643 aFontList.AppendElement("Urdu Typesetting"); 644 break; 645 case Script::SYRIAC: 646 case Script::ESTRANGELO_SYRIAC: 647 aFontList.AppendElement("Estrangelo Edessa"); 648 break; 649 case Script::THAANA: 650 aFontList.AppendElement("MV Boli"); 651 break; 652 653 case Script::BENGALI: 654 aFontList.AppendElement("Vrinda"); 655 aFontList.AppendElement("Nirmala UI"); 656 break; 657 case Script::DEVANAGARI: 658 aFontList.AppendElement("Kokila"); 659 aFontList.AppendElement("Nirmala UI"); 660 break; 661 case Script::GUJARATI: 662 aFontList.AppendElement("Shruti"); 663 aFontList.AppendElement("Nirmala UI"); 664 break; 665 case Script::GURMUKHI: 666 aFontList.AppendElement("Raavi"); 667 aFontList.AppendElement("Nirmala UI"); 668 break; 669 case Script::KANNADA: 670 aFontList.AppendElement("Tunga"); 671 aFontList.AppendElement("Nirmala UI"); 672 break; 673 case Script::MALAYALAM: 674 aFontList.AppendElement("Kartika"); 675 aFontList.AppendElement("Nirmala UI"); 676 break; 677 case Script::ORIYA: 678 aFontList.AppendElement("Kalinga"); 679 aFontList.AppendElement("Nirmala UI"); 680 break; 681 case Script::TAMIL: 682 aFontList.AppendElement("Latha"); 683 aFontList.AppendElement("Nirmala UI"); 684 break; 685 case Script::TELUGU: 686 aFontList.AppendElement("Gautami"); 687 aFontList.AppendElement("Nirmala UI"); 688 break; 689 case Script::SINHALA: 690 aFontList.AppendElement("Iskoola Pota"); 691 aFontList.AppendElement("Nirmala UI"); 692 break; 693 694 case Script::CHAKMA: 695 case Script::MEETEI_MAYEK: 696 case Script::OL_CHIKI: 697 case Script::SORA_SOMPENG: 698 aFontList.AppendElement("Nirmala UI"); 699 break; 700 701 case Script::MYANMAR: 702 aFontList.AppendElement("Myanmar Text"); 703 break; 704 case Script::KHMER: 705 aFontList.AppendElement("Khmer UI"); 706 break; 707 case Script::LAO: 708 aFontList.AppendElement("Lao UI"); 709 break; 710 case Script::THAI: 711 aFontList.AppendElement("Tahoma"); 712 aFontList.AppendElement("Leelawadee UI"); 713 break; 714 case Script::TAI_LE: 715 aFontList.AppendElement("Microsoft Tai Le"); 716 break; 717 case Script::BUGINESE: 718 aFontList.AppendElement("Leelawadee UI"); 719 break; 720 case Script::NEW_TAI_LUE: 721 aFontList.AppendElement("Microsoft New Tai Lue"); 722 break; 723 case Script::JAVANESE: 724 aFontList.AppendElement("Javanese Text"); 725 break; 726 727 case Script::GEORGIAN: 728 case Script::KHUTSURI: 729 case Script::LISU: 730 aFontList.AppendElement("Segoe UI"); 731 break; 732 733 case Script::ETHIOPIC: 734 aFontList.AppendElement("Nyala"); 735 aFontList.AppendElement("Ebrima"); 736 break; 737 738 case Script::ADLAM: 739 case Script::NKO: 740 case Script::OSMANYA: 741 case Script::TIFINAGH: 742 case Script::VAI: 743 aFontList.AppendElement("Ebrima"); 744 break; 745 746 case Script::CANADIAN_ABORIGINAL: 747 aFontList.AppendElement("Euphemia"); 748 break; 749 750 case Script::CHEROKEE: 751 case Script::OSAGE: 752 aFontList.AppendElement("Gadugi"); 753 break; 754 755 case Script::BRAILLE: 756 case Script::DESERET: 757 aFontList.AppendElement("Segoe UI Symbol"); 758 break; 759 760 case Script::BRAHMI: 761 case Script::CARIAN: 762 case Script::CUNEIFORM: 763 case Script::CYPRIOT: 764 case Script::EGYPTIAN_HIEROGLYPHS: 765 case Script::GLAGOLITIC: 766 case Script::GOTHIC: 767 case Script::IMPERIAL_ARAMAIC: 768 case Script::INSCRIPTIONAL_PAHLAVI: 769 case Script::INSCRIPTIONAL_PARTHIAN: 770 case Script::KHAROSHTHI: 771 case Script::LYCIAN: 772 case Script::LYDIAN: 773 case Script::MEROITIC_CURSIVE: 774 case Script::OGHAM: 775 case Script::OLD_ITALIC: 776 case Script::OLD_PERSIAN: 777 case Script::OLD_SOUTH_ARABIAN: 778 case Script::OLD_TURKIC: 779 case Script::PHOENICIAN: 780 case Script::RUNIC: 781 case Script::SHAVIAN: 782 case Script::UGARITIC: 783 aFontList.AppendElement("Segoe UI Historic"); 784 break; 785 786 // For some scripts where Windows doesn't supply a font by default, 787 // there are Noto fonts that users might have installed: 788 case Script::AHOM: 789 aFontList.AppendElement("Noto Serif Ahom"); 790 break; 791 case Script::AVESTAN: 792 aFontList.AppendElement("Noto Sans Avestan"); 793 break; 794 case Script::BALINESE: 795 aFontList.AppendElement("Noto Sans Balinese"); 796 break; 797 case Script::BAMUM: 798 aFontList.AppendElement("Noto Sans Bamum"); 799 break; 800 case Script::BASSA_VAH: 801 aFontList.AppendElement("Noto Sans Bassa Vah"); 802 break; 803 case Script::BATAK: 804 aFontList.AppendElement("Noto Sans Batak"); 805 break; 806 case Script::BHAIKSUKI: 807 aFontList.AppendElement("Noto Sans Bhaiksuki"); 808 break; 809 case Script::BUHID: 810 aFontList.AppendElement("Noto Sans Buhid"); 811 break; 812 case Script::CAUCASIAN_ALBANIAN: 813 aFontList.AppendElement("Noto Sans Caucasian Albanian"); 814 break; 815 case Script::CHAM: 816 aFontList.AppendElement("Noto Sans Cham"); 817 break; 818 case Script::COPTIC: 819 aFontList.AppendElement("Noto Sans Coptic"); 820 break; 821 case Script::DUPLOYAN: 822 aFontList.AppendElement("Noto Sans Duployan"); 823 break; 824 case Script::ELBASAN: 825 aFontList.AppendElement("Noto Sans Elbasan"); 826 break; 827 case Script::GRANTHA: 828 aFontList.AppendElement("Noto Sans Grantha"); 829 break; 830 case Script::HANIFI_ROHINGYA: 831 aFontList.AppendElement("Noto Sans Hanifi Rohingya"); 832 break; 833 case Script::HANUNOO: 834 aFontList.AppendElement("Noto Sans Hanunoo"); 835 break; 836 case Script::HATRAN: 837 aFontList.AppendElement("Noto Sans Hatran"); 838 break; 839 case Script::KAITHI: 840 aFontList.AppendElement("Noto Sans Kaithi"); 841 break; 842 case Script::KAYAH_LI: 843 aFontList.AppendElement("Noto Sans Kayah Li"); 844 break; 845 case Script::KHOJKI: 846 aFontList.AppendElement("Noto Sans Khojki"); 847 break; 848 case Script::KHUDAWADI: 849 aFontList.AppendElement("Noto Sans Khudawadi"); 850 break; 851 case Script::LEPCHA: 852 aFontList.AppendElement("Noto Sans Lepcha"); 853 break; 854 case Script::LIMBU: 855 aFontList.AppendElement("Noto Sans Limbu"); 856 break; 857 case Script::LINEAR_A: 858 aFontList.AppendElement("Noto Sans Linear A"); 859 break; 860 case Script::LINEAR_B: 861 aFontList.AppendElement("Noto Sans Linear B"); 862 break; 863 case Script::MAHAJANI: 864 aFontList.AppendElement("Noto Sans Mahajani"); 865 break; 866 case Script::MANDAIC: 867 aFontList.AppendElement("Noto Sans Mandaic"); 868 break; 869 case Script::MANICHAEAN: 870 aFontList.AppendElement("Noto Sans Manichaean"); 871 break; 872 case Script::MARCHEN: 873 aFontList.AppendElement("Noto Sans Marchen"); 874 break; 875 case Script::MENDE_KIKAKUI: 876 aFontList.AppendElement("Noto Sans Mende Kikakui"); 877 break; 878 case Script::MEROITIC_HIEROGLYPHS: 879 aFontList.AppendElement("Noto Sans Meroitic"); 880 break; 881 case Script::MIAO: 882 aFontList.AppendElement("Noto Sans Miao"); 883 break; 884 case Script::MODI: 885 aFontList.AppendElement("Noto Sans Modi"); 886 break; 887 case Script::MRO: 888 aFontList.AppendElement("Noto Sans Mro"); 889 break; 890 case Script::MULTANI: 891 aFontList.AppendElement("Noto Sans Multani"); 892 break; 893 case Script::NABATAEAN: 894 aFontList.AppendElement("Noto Sans Nabataean"); 895 break; 896 case Script::NEWA: 897 aFontList.AppendElement("Noto Sans Newa"); 898 break; 899 case Script::OLD_HUNGARIAN: 900 aFontList.AppendElement("Noto Sans Old Hungarian"); 901 break; 902 case Script::OLD_NORTH_ARABIAN: 903 aFontList.AppendElement("Noto Sans Old North Arabian"); 904 break; 905 case Script::OLD_PERMIC: 906 aFontList.AppendElement("Noto Sans Old Permic"); 907 break; 908 case Script::PAHAWH_HMONG: 909 aFontList.AppendElement("Noto Sans Pahawh Hmong"); 910 break; 911 case Script::PALMYRENE: 912 aFontList.AppendElement("Noto Sans Palmyrene"); 913 break; 914 case Script::PAU_CIN_HAU: 915 aFontList.AppendElement("Noto Sans Pau Cin Hau"); 916 break; 917 case Script::PSALTER_PAHLAVI: 918 aFontList.AppendElement("Noto Sans Psalter Pahlavi"); 919 break; 920 case Script::REJANG: 921 aFontList.AppendElement("Noto Sans Rejang"); 922 break; 923 case Script::SAMARITAN: 924 aFontList.AppendElement("Noto Sans Samaritan"); 925 break; 926 case Script::SAURASHTRA: 927 aFontList.AppendElement("Noto Sans Saurashtra"); 928 break; 929 case Script::SHARADA: 930 aFontList.AppendElement("Noto Sans Sharada"); 931 break; 932 case Script::SIDDHAM: 933 aFontList.AppendElement("Noto Sans Siddham"); 934 break; 935 case Script::SUNDANESE: 936 aFontList.AppendElement("Noto Sans Sundanese"); 937 break; 938 case Script::SYLOTI_NAGRI: 939 aFontList.AppendElement("Noto Sans Syloti Nagri"); 940 break; 941 case Script::TAGALOG: 942 aFontList.AppendElement("Noto Sans Tagalog"); 943 break; 944 case Script::TAGBANWA: 945 aFontList.AppendElement("Noto Sans Tagbanwa"); 946 break; 947 case Script::TAI_THAM: 948 aFontList.AppendElement("Noto Sans Tai Tham"); 949 break; 950 case Script::TAI_VIET: 951 aFontList.AppendElement("Noto Sans Tai Viet"); 952 break; 953 case Script::TAKRI: 954 aFontList.AppendElement("Noto Sans Takri"); 955 break; 956 case Script::TIRHUTA: 957 aFontList.AppendElement("Noto Sans Tirhuta"); 958 break; 959 case Script::WANCHO: 960 aFontList.AppendElement("Noto Sans Wancho"); 961 break; 962 case Script::WARANG_CITI: 963 aFontList.AppendElement("Noto Sans Warang Citi"); 964 break; 965 966 case Script::AFAKA: 967 case Script::ANATOLIAN_HIEROGLYPHS: 968 case Script::BERIA_ERFE: 969 case Script::BLISSYMBOLS: 970 case Script::BOOK_PAHLAVI: 971 case Script::CHORASMIAN: 972 case Script::CIRTH: 973 case Script::CYPRO_MINOAN: 974 case Script::DEMOTIC_EGYPTIAN: 975 case Script::DIVES_AKURU: 976 case Script::DOGRA: 977 case Script::EASTERN_SYRIAC: 978 case Script::ELYMAIC: 979 case Script::GARAY: 980 case Script::GUNJALA_GONDI: 981 case Script::GURUNG_KHEMA: 982 case Script::HARAPPAN_INDUS: 983 case Script::HIERATIC_EGYPTIAN: 984 case Script::JURCHEN: 985 case Script::KAWI: 986 case Script::KHITAN_SMALL_SCRIPT: 987 case Script::KIRAT_RAI: 988 case Script::KPELLE: 989 case Script::LATIN_FRAKTUR: 990 case Script::LATIN_GAELIC: 991 case Script::LOMA: 992 case Script::MAKASAR: 993 case Script::MASARAM_GONDI: 994 case Script::MAYAN_HIEROGLYPHS: 995 case Script::MEDEFAIDRIN: 996 case Script::MOON: 997 case Script::NAG_MUNDARI: 998 case Script::NAKHI_GEBA: 999 case Script::NANDINAGARI: 1000 case Script::NUSHU: 1001 case Script::NYIAKENG_PUACHUE_HMONG: 1002 case Script::OL_ONAL: 1003 case Script::OLD_CHURCH_SLAVONIC_CYRILLIC: 1004 case Script::OLD_SOGDIAN: 1005 case Script::OLD_UYGHUR: 1006 case Script::RONGORONGO: 1007 case Script::SARATI: 1008 case Script::SIDETIC: 1009 case Script::SIGNWRITING: 1010 case Script::SOGDIAN: 1011 case Script::SOYOMBO: 1012 case Script::SUNUWAR: 1013 case Script::TAI_YO: 1014 case Script::TANGSA: 1015 case Script::TANGUT: 1016 case Script::TENGWAR: 1017 case Script::TODHRI: 1018 case Script::TOLONG_SIKI: 1019 case Script::TOTO: 1020 case Script::TULU_TIGALARI: 1021 case Script::UNKNOWN: 1022 case Script::UNWRITTEN_LANGUAGES: 1023 case Script::VISIBLE_SPEECH: 1024 case Script::VITHKUQI: 1025 case Script::WESTERN_SYRIAC: 1026 case Script::WOLEAI: 1027 case Script::YEZIDI: 1028 case Script::ZANABAZAR_SQUARE: 1029 break; 1030 } 1031 1032 // Arial is used as default fallback for system fallback, so always try that. 1033 aFontList.AppendElement("Arial"); 1034 1035 // Symbols/dingbats are generally Script=COMMON but may be resolved to any 1036 // surrounding script run. So we'll always append a couple of likely fonts 1037 // for such characters. 1038 const uint32_t b = aCh >> 8; 1039 if (aRunScript == Script::COMMON || // Stray COMMON chars not resolved 1040 (b >= 0x20 && b <= 0x2b) || b == 0x2e || // BMP symbols/punctuation/etc 1041 GetGenCategory(aCh) == nsUGenCategory::kSymbol || 1042 GetGenCategory(aCh) == nsUGenCategory::kPunctuation) { 1043 // Segoe UI handles some punctuation/symbols that are missing from many text 1044 // fonts. 1045 aFontList.AppendElement("Segoe UI"); 1046 aFontList.AppendElement("Segoe UI Symbol"); 1047 aFontList.AppendElement("Cambria Math"); 1048 } 1049 1050 // Arial Unicode MS also has lots of glyphs for obscure characters; try it as 1051 // a last resort, if available. 1052 aFontList.AppendElement("Arial Unicode MS"); 1053 1054 // If we didn't begin with the color-emoji fonts, include them here 1055 // so that they'll be preferred over user-installed (and possibly 1056 // broken) fonts in the global fallback path. 1057 if (!PrefersColor(aPresentation)) { 1058 aFontList.AppendElement("Segoe UI Emoji"); 1059 aFontList.AppendElement("Twemoji Mozilla"); 1060 } 1061 } 1062 1063 bool gfxWindowsPlatform::DidRenderingDeviceReset( 1064 mozilla::gfx::DeviceResetReason* aResetReason) { 1065 DeviceManagerDx* dm = DeviceManagerDx::Get(); 1066 if (!dm) { 1067 return false; 1068 } 1069 return dm->HasDeviceReset(aResetReason); 1070 } 1071 1072 void gfxWindowsPlatform::CompositorUpdated() { 1073 DeviceManagerDx::Get()->ForceDeviceReset( 1074 mozilla::gfx::ForcedDeviceResetReason::COMPOSITOR_UPDATED); 1075 UpdateRenderMode(); 1076 } 1077 1078 BOOL CALLBACK InvalidateWindowForDeviceReset(HWND aWnd, LPARAM aMsg) { 1079 RedrawWindow(aWnd, nullptr, nullptr, 1080 RDW_INVALIDATE | RDW_INTERNALPAINT | RDW_FRAME); 1081 return TRUE; 1082 } 1083 1084 void gfxWindowsPlatform::SchedulePaintIfDeviceReset() { 1085 AUTO_PROFILER_LABEL("gfxWindowsPlatform::SchedulePaintIfDeviceReset", OTHER); 1086 1087 mozilla::gfx::DeviceResetReason resetReason = 1088 mozilla::gfx::DeviceResetReason::OK; 1089 if (!DidRenderingDeviceReset(&resetReason)) { 1090 return; 1091 } 1092 1093 gfxCriticalNote << "(gfxWindowsPlatform) Detected device reset: " 1094 << (int)resetReason; 1095 1096 if (XRE_IsParentProcess()) { 1097 // Trigger an ::OnPaint for each window. 1098 ::EnumThreadWindows(GetCurrentThreadId(), InvalidateWindowForDeviceReset, 1099 0); 1100 } else { 1101 NS_DispatchToMainThread(NS_NewRunnableFunction( 1102 "gfx::gfxWindowsPlatform::SchedulePaintIfDeviceReset", []() -> void { 1103 gfxWindowsPlatform::GetPlatform()->CheckForContentOnlyDeviceReset(); 1104 })); 1105 } 1106 1107 gfxCriticalNote << "(gfxWindowsPlatform) scheduled device update."; 1108 } 1109 1110 void gfxWindowsPlatform::CheckForContentOnlyDeviceReset() { 1111 if (!DidRenderingDeviceReset()) { 1112 return; 1113 } 1114 1115 bool isContentOnlyTDR; 1116 D3D11DeviceStatus status; 1117 1118 DeviceManagerDx::Get()->ExportDeviceInfo(&status); 1119 CompositorBridgeChild::Get()->SendCheckContentOnlyTDR(status.sequenceNumber(), 1120 &isContentOnlyTDR); 1121 1122 // The parent process doesn't know about the reset yet, or the reset is 1123 // local to our device. 1124 if (isContentOnlyTDR) { 1125 gfxCriticalNote << "A content-only TDR is detected."; 1126 dom::ContentChild* cc = dom::ContentChild::GetSingleton(); 1127 cc->RecvReinitRenderingForDeviceReset(); 1128 } 1129 } 1130 1131 nsTArray<uint8_t> gfxWindowsPlatform::GetPlatformCMSOutputProfileData() { 1132 if (XRE_IsContentProcess()) { 1133 auto& cmsOutputProfileData = GetCMSOutputProfileData(); 1134 // We should have set our profile data when we received our initial 1135 // ContentDeviceData. 1136 MOZ_ASSERT(cmsOutputProfileData.isSome(), 1137 "Should have created output profile data when we received " 1138 "initial content device data."); 1139 1140 // If we have data, it should not be empty. 1141 MOZ_ASSERT_IF(cmsOutputProfileData.isSome(), 1142 !cmsOutputProfileData->IsEmpty()); 1143 1144 if (cmsOutputProfileData.isSome()) { 1145 return cmsOutputProfileData.ref().Clone(); 1146 } 1147 return nsTArray<uint8_t>(); 1148 } 1149 1150 return GetPlatformCMSOutputProfileData_Impl(); 1151 } 1152 1153 nsTArray<uint8_t> gfxWindowsPlatform::GetPlatformCMSOutputProfileData_Impl() { 1154 static nsTArray<uint8_t> sCached = [&] { 1155 // Check override pref first: 1156 nsTArray<uint8_t> prefProfileData = 1157 gfxPlatform::GetPrefCMSOutputProfileData(); 1158 if (!prefProfileData.IsEmpty()) { 1159 return prefProfileData; 1160 } 1161 1162 // - 1163 // Otherwise, create a dummy DC and pull from that. 1164 1165 HDC dc = ::GetDC(nullptr); 1166 if (!dc) { 1167 return nsTArray<uint8_t>(); 1168 } 1169 1170 WCHAR profilePath[MAX_PATH]; 1171 DWORD profilePathLen = MAX_PATH; 1172 1173 bool getProfileResult = ::GetICMProfileW(dc, &profilePathLen, profilePath); 1174 1175 ::ReleaseDC(nullptr, dc); 1176 1177 if (!getProfileResult) { 1178 return nsTArray<uint8_t>(); 1179 } 1180 1181 void* mem = nullptr; 1182 size_t size = 0; 1183 1184 qcms_data_from_unicode_path(profilePath, &mem, &size); 1185 if (!mem) { 1186 return nsTArray<uint8_t>(); 1187 } 1188 1189 nsTArray<uint8_t> result; 1190 result.AppendElements(static_cast<uint8_t*>(mem), size); 1191 1192 free(mem); 1193 1194 return result; 1195 }(); 1196 1197 return sCached.Clone(); 1198 } 1199 1200 void gfxWindowsPlatform::GetDLLVersion(char16ptr_t aDLLPath, 1201 nsAString& aVersion) { 1202 DWORD versInfoSize, vers[4] = {0}; 1203 // version info not available case 1204 aVersion.AssignLiteral(u"0.0.0.0"); 1205 versInfoSize = GetFileVersionInfoSizeW(aDLLPath, nullptr); 1206 AutoTArray<BYTE, 512> versionInfo; 1207 1208 if (versInfoSize == 0) { 1209 return; 1210 } 1211 1212 // XXX(Bug 1631371) Check if this should use a fallible operation as it 1213 // pretended earlier. 1214 versionInfo.AppendElements(uint32_t(versInfoSize)); 1215 1216 if (!GetFileVersionInfoW(aDLLPath, 0, versInfoSize, 1217 LPBYTE(versionInfo.Elements()))) { 1218 return; 1219 } 1220 1221 UINT len = 0; 1222 VS_FIXEDFILEINFO* fileInfo = nullptr; 1223 if (!VerQueryValue(LPBYTE(versionInfo.Elements()), TEXT("\\"), 1224 (LPVOID*)&fileInfo, &len) || 1225 len == 0 || fileInfo == nullptr) { 1226 return; 1227 } 1228 1229 DWORD fileVersMS = fileInfo->dwFileVersionMS; 1230 DWORD fileVersLS = fileInfo->dwFileVersionLS; 1231 1232 vers[0] = HIWORD(fileVersMS); 1233 vers[1] = LOWORD(fileVersMS); 1234 vers[2] = HIWORD(fileVersLS); 1235 vers[3] = LOWORD(fileVersLS); 1236 1237 char buf[256]; 1238 SprintfLiteral(buf, "%lu.%lu.%lu.%lu", vers[0], vers[1], vers[2], vers[3]); 1239 aVersion.Assign(NS_ConvertUTF8toUTF16(buf)); 1240 } 1241 1242 static BOOL CALLBACK AppendClearTypeParams(HMONITOR aMonitor, HDC, LPRECT, 1243 LPARAM aContext) { 1244 MONITORINFOEXW monitorInfo; 1245 monitorInfo.cbSize = sizeof(MONITORINFOEXW); 1246 if (!GetMonitorInfoW(aMonitor, &monitorInfo)) { 1247 return TRUE; 1248 } 1249 1250 ClearTypeParameterInfo ctinfo; 1251 ctinfo.displayName.Assign(monitorInfo.szDevice); 1252 1253 RefPtr<IDWriteRenderingParams> renderingParams; 1254 HRESULT hr = Factory::GetDWriteFactory()->CreateMonitorRenderingParams( 1255 aMonitor, getter_AddRefs(renderingParams)); 1256 if (FAILED(hr)) { 1257 return TRUE; 1258 } 1259 1260 ctinfo.gamma = renderingParams->GetGamma() * 1000; 1261 ctinfo.pixelStructure = renderingParams->GetPixelGeometry(); 1262 ctinfo.clearTypeLevel = renderingParams->GetClearTypeLevel() * 100; 1263 ctinfo.enhancedContrast = renderingParams->GetEnhancedContrast() * 100; 1264 1265 auto* params = reinterpret_cast<nsTArray<ClearTypeParameterInfo>*>(aContext); 1266 params->AppendElement(ctinfo); 1267 return TRUE; 1268 } 1269 1270 void gfxWindowsPlatform::GetCleartypeParams( 1271 nsTArray<ClearTypeParameterInfo>& aParams) { 1272 aParams.Clear(); 1273 if (!DWriteEnabled()) { 1274 return; 1275 } 1276 EnumDisplayMonitors(nullptr, nullptr, AppendClearTypeParams, 1277 reinterpret_cast<LPARAM>(&aParams)); 1278 } 1279 1280 void gfxWindowsPlatform::FontsPrefsChanged(const char* aPref) { 1281 bool clearTextFontCaches = true; 1282 1283 gfxPlatform::FontsPrefsChanged(aPref); 1284 1285 if (aPref && 1286 !strncmp(GFX_CLEARTYPE_PARAMS, aPref, strlen(GFX_CLEARTYPE_PARAMS))) { 1287 gfxDWriteFont::UpdateClearTypeVars(); 1288 } else { 1289 clearTextFontCaches = false; 1290 } 1291 1292 if (clearTextFontCaches) { 1293 gfxFontCache* fc = gfxFontCache::GetCache(); 1294 if (fc) { 1295 fc->Flush(); 1296 } 1297 } 1298 } 1299 1300 bool gfxWindowsPlatform::IsOptimus() { 1301 static int knowIsOptimus = -1; 1302 if (knowIsOptimus == -1) { 1303 // other potential optimus -- nvd3d9wrapx.dll & nvdxgiwrap.dll 1304 if (GetModuleHandleA("nvumdshim.dll") || 1305 GetModuleHandleA("nvumdshimx.dll")) { 1306 knowIsOptimus = 1; 1307 } else { 1308 knowIsOptimus = 0; 1309 } 1310 } 1311 return knowIsOptimus; 1312 } 1313 1314 static void InitializeANGLEConfig() { 1315 FeatureState& d3d11ANGLE = gfxConfig::GetFeature(Feature::D3D11_HW_ANGLE); 1316 1317 if (!gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) { 1318 d3d11ANGLE.DisableByDefault(FeatureStatus::Unavailable, 1319 "D3D11 compositing is disabled", 1320 "FEATURE_FAILURE_HW_ANGLE_D3D11_DISABLED"_ns); 1321 return; 1322 } 1323 1324 d3d11ANGLE.EnableByDefault(); 1325 1326 nsCString message; 1327 nsCString failureId; 1328 if (!gfxPlatform::IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_DIRECT3D_11_ANGLE, 1329 &message, failureId)) { 1330 d3d11ANGLE.Disable(FeatureStatus::Blocklisted, message.get(), failureId); 1331 } 1332 } 1333 1334 void gfxWindowsPlatform::InitializeDirectDrawConfig() { 1335 MOZ_ASSERT(XRE_IsParentProcess()); 1336 1337 FeatureState& ddraw = gfxConfig::GetFeature(Feature::DIRECT_DRAW); 1338 ddraw.EnableByDefault(); 1339 } 1340 1341 void gfxWindowsPlatform::InitializeConfig() { 1342 if (XRE_IsParentProcess()) { 1343 // The parent process first determines which features can be attempted. 1344 // This information is relayed to content processes and the GPU process. 1345 InitializeD3D11Config(); 1346 InitializeANGLEConfig(); 1347 } else { 1348 ImportCachedContentDeviceData(); 1349 InitializeANGLEConfig(); 1350 } 1351 } 1352 1353 void gfxWindowsPlatform::InitializeD3D11Config() { 1354 MOZ_ASSERT(XRE_IsParentProcess()); 1355 1356 FeatureState& d3d11 = gfxConfig::GetFeature(Feature::D3D11_COMPOSITING); 1357 1358 if (!gfxConfig::IsEnabled(Feature::HW_COMPOSITING)) { 1359 d3d11.DisableByDefault(FeatureStatus::Unavailable, 1360 "Hardware compositing is disabled", 1361 "FEATURE_FAILURE_D3D11_NEED_HWCOMP"_ns); 1362 return; 1363 } 1364 1365 d3d11.EnableByDefault(); 1366 1367 // Check if the user really, really wants WARP. 1368 if (StaticPrefs::layers_d3d11_force_warp_AtStartup()) { 1369 // Force D3D11 on even if we disabled it. 1370 d3d11.UserForceEnable("User force-enabled WARP"); 1371 } 1372 1373 nsCString message; 1374 nsCString failureId; 1375 if (StaticPrefs::layers_d3d11_enable_blacklist_AtStartup() && 1376 !gfxPlatform::IsGfxInfoStatusOkay(nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS, 1377 &message, failureId)) { 1378 d3d11.Disable(FeatureStatus::Blocklisted, message.get(), failureId); 1379 } 1380 } 1381 1382 /* static */ 1383 void gfxWindowsPlatform::RecordContentDeviceFailure( 1384 TelemetryDeviceCode aDevice) { 1385 // If the parent process fails to acquire a device, we record this 1386 // normally as part of the environment. The exceptional case we're 1387 // looking for here is when the parent process successfully acquires 1388 // a device, but the content process fails to acquire the same device. 1389 // This would not normally be displayed in about:support. 1390 if (!XRE_IsContentProcess()) { 1391 return; 1392 } 1393 glean::gfx::content_failed_to_acquire_device.AccumulateSingleSample( 1394 uint32_t(aDevice)); 1395 } 1396 1397 void gfxWindowsPlatform::RecordStartupTelemetry() { 1398 if (!XRE_IsParentProcess()) { 1399 return; 1400 } 1401 1402 DeviceManagerDx* dx = DeviceManagerDx::Get(); 1403 nsTArray<DXGI_OUTPUT_DESC1> outputs = dx->EnumerateOutputs(); 1404 1405 uint32_t allSupportedColorSpaces = 0; 1406 for (auto& output : outputs) { 1407 uint32_t colorSpace = 1 << output.ColorSpace; 1408 allSupportedColorSpaces |= colorSpace; 1409 } 1410 1411 glean::gfx_hdr::windows_display_colorspace_bitfield.Set( 1412 allSupportedColorSpaces); 1413 } 1414 1415 // Supports lazy device initialization on Windows, so that WebRender can avoid 1416 // initializing GPU state and allocating swap chains for most non-GPU processes. 1417 void gfxWindowsPlatform::EnsureDevicesInitialized() { 1418 MOZ_DIAGNOSTIC_ASSERT(!IsWin32kLockedDown()); 1419 1420 if (!mInitializedDevices) { 1421 mInitializedDevices = true; 1422 InitializeDevices(); 1423 UpdateBackendPrefs(); 1424 } 1425 } 1426 1427 bool gfxWindowsPlatform::DevicesInitialized() { return mInitializedDevices; } 1428 1429 void gfxWindowsPlatform::InitializeDevices() { 1430 MOZ_ASSERT(NS_IsMainThread()); 1431 1432 if (XRE_IsParentProcess()) { 1433 // If we're the UI process, and the GPU process is enabled, then we don't 1434 // initialize any DirectX devices. We do leave them enabled in gfxConfig 1435 // though. If the GPU process fails to create these devices it will send 1436 // a message back and we'll update their status. 1437 if (gfxConfig::IsEnabled(Feature::GPU_PROCESS)) { 1438 return; 1439 } 1440 1441 // No GPU process, continue initializing devices as normal. 1442 } 1443 1444 // If acceleration is disabled, we refuse to initialize anything. 1445 if (!gfxConfig::IsEnabled(Feature::HW_COMPOSITING)) { 1446 return; 1447 } 1448 1449 // If we previously crashed initializing devices, bail out now. 1450 D3D11LayersCrashGuard detectCrashes; 1451 if (detectCrashes.Crashed()) { 1452 gfxConfig::SetFailed(Feature::HW_COMPOSITING, 1453 FeatureStatus::CrashedOnStartup, 1454 "Crashed during startup in a previous session"); 1455 gfxConfig::SetFailed( 1456 Feature::D3D11_COMPOSITING, FeatureStatus::CrashedOnStartup, 1457 "Harware acceleration crashed during startup in a previous session"); 1458 return; 1459 } 1460 1461 // First, initialize D3D11. 1462 InitializeD3D11(); 1463 } 1464 1465 void gfxWindowsPlatform::InitializeD3D11() { 1466 // This function attempts to initialize our D3D11 devices, if the hardware 1467 // is not blocklisted for D3D11 layers. This first attempt will try to create 1468 // a hardware accelerated device. If this creation fails or the hardware is 1469 // blocklisted, then this function will abort if WARP is disabled, causing us 1470 // to fallback to Basic layers. If WARP is not disabled it will use a WARP 1471 // device which should always be available on Windows 7 and higher. 1472 if (!gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) { 1473 return; 1474 } 1475 1476 DeviceManagerDx* dm = DeviceManagerDx::Get(); 1477 if (XRE_IsParentProcess()) { 1478 if (!dm->CreateCompositorDevices()) { 1479 return; 1480 } 1481 } 1482 1483 dm->CreateContentDevices(); 1484 1485 // Content process failed to create the d3d11 device while parent process 1486 // succeed. 1487 if (XRE_IsContentProcess() && 1488 !gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) { 1489 gfxCriticalError() 1490 << "[D3D11] Failed to create the D3D11 device in content \ 1491 process."; 1492 } 1493 } 1494 1495 class D3DVsyncSource final : public VsyncSource { 1496 public: 1497 D3DVsyncSource() 1498 : mPrevVsync(TimeStamp::Now()), 1499 mVsyncEnabled(false), 1500 mWaitVBlankMonitor(NULL) { 1501 mVsyncThread = new base::Thread("WindowsVsyncThread"); 1502 MOZ_RELEASE_ASSERT(mVsyncThread->Start(), 1503 "GFX: Could not start Windows vsync thread"); 1504 SetVsyncRate(); 1505 } 1506 1507 void SetVsyncRate() { 1508 DWM_TIMING_INFO vblankTime; 1509 // Make sure to init the cbSize, otherwise GetCompositionTiming will fail 1510 vblankTime.cbSize = sizeof(DWM_TIMING_INFO); 1511 HRESULT hr = DwmGetCompositionTimingInfo(0, &vblankTime); 1512 if (SUCCEEDED(hr)) { 1513 UNSIGNED_RATIO refreshRate = vblankTime.rateRefresh; 1514 // We get the rate in hertz / time, but we want the rate in ms. 1515 float rate = 1516 ((float)refreshRate.uiDenominator / (float)refreshRate.uiNumerator) * 1517 1000; 1518 mVsyncRate = TimeDuration::FromMilliseconds(rate); 1519 } else { 1520 mVsyncRate = TimeDuration::FromMilliseconds(1000.0 / 60.0); 1521 } 1522 } 1523 1524 virtual void Shutdown() override { 1525 MOZ_ASSERT(NS_IsMainThread()); 1526 DisableVsync(); 1527 mVsyncThread->Stop(); 1528 delete mVsyncThread; 1529 } 1530 1531 virtual void EnableVsync() override { 1532 MOZ_ASSERT(NS_IsMainThread()); 1533 MOZ_ASSERT(mVsyncThread->IsRunning()); 1534 { // scope lock 1535 if (mVsyncEnabled) { 1536 return; 1537 } 1538 mVsyncEnabled = true; 1539 } 1540 1541 mVsyncThread->message_loop()->PostTask(NewRunnableMethod( 1542 "D3DVsyncSource::VBlankLoop", this, &D3DVsyncSource::VBlankLoop)); 1543 } 1544 1545 virtual void DisableVsync() override { 1546 MOZ_ASSERT(NS_IsMainThread()); 1547 MOZ_ASSERT(mVsyncThread->IsRunning()); 1548 if (!mVsyncEnabled) { 1549 return; 1550 } 1551 mVsyncEnabled = false; 1552 } 1553 1554 virtual bool IsVsyncEnabled() override { 1555 MOZ_ASSERT(NS_IsMainThread()); 1556 return mVsyncEnabled; 1557 } 1558 1559 virtual TimeDuration GetVsyncRate() override { return mVsyncRate; } 1560 1561 void ScheduleSoftwareVsync(TimeStamp aVsyncTimestamp) { 1562 MOZ_ASSERT(IsInVsyncThread()); 1563 NS_WARNING( 1564 "DwmComposition dynamically disabled, falling back to software " 1565 "timers"); 1566 1567 TimeStamp nextVsync = aVsyncTimestamp + mVsyncRate; 1568 TimeDuration delay = nextVsync - TimeStamp::Now(); 1569 if (delay.ToMilliseconds() < 0) { 1570 delay = mozilla::TimeDuration::FromMilliseconds(0); 1571 } 1572 1573 mVsyncThread->message_loop()->PostDelayedTask( 1574 NewRunnableMethod("D3DVsyncSource::VBlankLoop", this, 1575 &D3DVsyncSource::VBlankLoop), 1576 delay.ToMilliseconds()); 1577 } 1578 1579 // Returns the timestamp for the just happened vsync 1580 TimeStamp GetVBlankTime() { 1581 TimeStamp vsync = TimeStamp::Now(); 1582 TimeStamp now = vsync; 1583 1584 DWM_TIMING_INFO vblankTime; 1585 // Make sure to init the cbSize, otherwise 1586 // GetCompositionTiming will fail 1587 vblankTime.cbSize = sizeof(DWM_TIMING_INFO); 1588 HRESULT hr = DwmGetCompositionTimingInfo(0, &vblankTime); 1589 if (!SUCCEEDED(hr)) { 1590 return vsync; 1591 } 1592 1593 LARGE_INTEGER frequency; 1594 QueryPerformanceFrequency(&frequency); 1595 1596 LARGE_INTEGER qpcNow; 1597 QueryPerformanceCounter(&qpcNow); 1598 1599 const int microseconds = 1000000; 1600 int64_t adjust = qpcNow.QuadPart - vblankTime.qpcVBlank; 1601 int64_t usAdjust = (adjust * microseconds) / frequency.QuadPart; 1602 vsync -= TimeDuration::FromMicroseconds((double)usAdjust); 1603 1604 // On Windows 10 and on, DWMGetCompositionTimingInfo, mostly 1605 // reports the upcoming vsync time, which is in the future. 1606 // It can also sometimes report a vblank time in the past. 1607 // Since large parts of Gecko assume TimeStamps can't be in future, 1608 // use the previous vsync. 1609 1610 // Windows 10 and Intel HD vsync timestamps are messy and 1611 // all over the place once in a while. Most of the time, 1612 // it reports the upcoming vsync. Sometimes, that upcoming 1613 // vsync is in the past. Sometimes that upcoming vsync is before 1614 // the previously seen vsync. 1615 // In these error cases, normalize to Now(); 1616 if (vsync >= now) { 1617 vsync = vsync - mVsyncRate; 1618 } 1619 1620 // On Windows 7 and 8, DwmFlush wakes up AFTER qpcVBlankTime 1621 // from DWMGetCompositionTimingInfo. We can return the adjusted vsync. 1622 if (vsync >= now) { 1623 vsync = now; 1624 } 1625 1626 // Our vsync time is some time very far in the past, adjust to Now. 1627 // 4 ms is arbitrary, so feel free to pick something else if this isn't 1628 // working. See the comment above. 1629 if ((now - vsync).ToMilliseconds() > 4.0) { 1630 vsync = now; 1631 } 1632 1633 return vsync; 1634 } 1635 1636 void VBlankLoop() { 1637 MOZ_ASSERT(IsInVsyncThread()); 1638 MOZ_ASSERT(sizeof(int64_t) == sizeof(QPC_TIME)); 1639 1640 TimeStamp vsync = TimeStamp::Now(); 1641 mPrevVsync = TimeStamp(); 1642 TimeStamp flushTime = TimeStamp::Now(); 1643 TimeDuration longVBlank = mVsyncRate * 2; 1644 1645 for (;;) { 1646 { // scope lock 1647 if (!mVsyncEnabled) return; 1648 } 1649 1650 // Large parts of gecko assume that the refresh driver timestamp 1651 // must be <= Now() and cannot be in the future. 1652 MOZ_ASSERT(vsync <= TimeStamp::Now()); 1653 NotifyVsync(vsync, vsync + mVsyncRate); 1654 1655 HRESULT hr = E_FAIL; 1656 if (!StaticPrefs::gfx_vsync_force_disable_waitforvblank()) { 1657 UpdateVBlankOutput(); 1658 if (mWaitVBlankOutput) { 1659 const TimeStamp vblank_begin_wait = TimeStamp::Now(); 1660 { 1661 AUTO_PROFILER_THREAD_SLEEP; 1662 AUTO_PROFILER_MARKER_UNTYPED("WaitForVBlank", GRAPHICS_VSync, {}); 1663 hr = mWaitVBlankOutput->WaitForVBlank(); 1664 } 1665 if (SUCCEEDED(hr)) { 1666 // vblank might return instantly when running headless, 1667 // monitor powering off, etc. Since we're on a dedicated 1668 // thread, instant-return should not happen in the normal 1669 // case, so catch any odd behavior with a time cutoff: 1670 TimeDuration vblank_wait = TimeStamp::Now() - vblank_begin_wait; 1671 if (vblank_wait.ToMilliseconds() < 1.0) { 1672 hr = E_FAIL; // fall back on old behavior 1673 } 1674 } 1675 } 1676 } else { 1677 // To mitigate bug 1924932 we only want to use DwmFlush if WaitForVBlank 1678 // is disabled, WaitForVBlank is the standard since Vista so we should 1679 // probably remove this option entirely. 1680 AUTO_PROFILER_MARKER_UNTYPED("DwmFlush", GRAPHICS_VSync, {}); 1681 hr = DwmFlush(); 1682 } 1683 if (!SUCCEEDED(hr)) { 1684 // DWMFlush isn't working, fallback to software vsync. 1685 AUTO_PROFILER_MARKER_UNTYPED("SoftwareVsync", GRAPHICS_VSync, {}); 1686 ScheduleSoftwareVsync(TimeStamp::Now()); 1687 return; 1688 } 1689 1690 TimeStamp now = TimeStamp::Now(); 1691 TimeDuration flushDiff = now - flushTime; 1692 flushTime = now; 1693 if ((flushDiff > longVBlank) || mPrevVsync.IsNull()) { 1694 // Our vblank took longer than 2 intervals, readjust our timestamps 1695 PROFILER_MARKER_UNTYPED("LongVBlank", GRAPHICS_VSync); 1696 vsync = GetVBlankTime(); 1697 mPrevVsync = vsync; 1698 } else { 1699 // Instead of giving the actual vsync time, a constant interval 1700 // between vblanks instead of the noise generated via hardware 1701 // is actually what we want. Most apps just care about the diff 1702 // between vblanks to animate, so a clean constant interval is 1703 // smoother. 1704 vsync = mPrevVsync + mVsyncRate; 1705 if (vsync > now) { 1706 // DWMFlush woke up very early, so readjust our times again 1707 PROFILER_MARKER_UNTYPED("EarlyWake", GRAPHICS_VSync); 1708 vsync = GetVBlankTime(); 1709 } 1710 1711 if (vsync <= mPrevVsync) { 1712 PROFILER_MARKER_UNTYPED("TimeSteppedBack", GRAPHICS_VSync); 1713 vsync = TimeStamp::Now(); 1714 } 1715 1716 if ((now - vsync).ToMilliseconds() > 2.0) { 1717 // Account for time drift here where vsync never quite catches up to 1718 // Now and we'd fall ever so slightly further behind Now(). 1719 PROFILER_MARKER_UNTYPED("TimeFellBehind2ms", GRAPHICS_VSync); 1720 vsync = GetVBlankTime(); 1721 } 1722 1723 mPrevVsync = vsync; 1724 } 1725 } // end for 1726 } 1727 virtual ~D3DVsyncSource() { MOZ_ASSERT(NS_IsMainThread()); } 1728 1729 private: 1730 bool IsInVsyncThread() { 1731 return mVsyncThread->thread_id() == PlatformThread::CurrentId(); 1732 } 1733 1734 void UpdateVBlankOutput() { 1735 HMONITOR primary_monitor = 1736 MonitorFromWindow(nullptr, MONITOR_DEFAULTTOPRIMARY); 1737 if (primary_monitor == mWaitVBlankMonitor && mWaitVBlankOutput) { 1738 return; 1739 } 1740 1741 mWaitVBlankMonitor = primary_monitor; 1742 1743 RefPtr<IDXGIOutput> output = nullptr; 1744 if (DeviceManagerDx* dx = DeviceManagerDx::Get()) { 1745 if (dx->GetOutputFromMonitor(mWaitVBlankMonitor, &output)) { 1746 mWaitVBlankOutput = output; 1747 return; 1748 } 1749 } 1750 1751 // failed to convert a monitor to an output so keep trying 1752 mWaitVBlankOutput = nullptr; 1753 } 1754 1755 TimeStamp mPrevVsync; 1756 base::Thread* mVsyncThread; 1757 TimeDuration mVsyncRate; 1758 Atomic<bool> mVsyncEnabled; 1759 1760 HMONITOR mWaitVBlankMonitor; 1761 RefPtr<IDXGIOutput> mWaitVBlankOutput; 1762 }; // D3DVsyncSource 1763 1764 already_AddRefed<mozilla::gfx::VsyncSource> 1765 gfxWindowsPlatform::CreateGlobalHardwareVsyncSource() { 1766 MOZ_RELEASE_ASSERT(NS_IsMainThread(), "GFX: Not in main thread."); 1767 1768 RefPtr<VsyncSource> d3dVsyncSource = new D3DVsyncSource(); 1769 return d3dVsyncSource.forget(); 1770 } 1771 1772 void gfxWindowsPlatform::ImportGPUDeviceData( 1773 const mozilla::gfx::GPUDeviceData& aData) { 1774 MOZ_ASSERT(XRE_IsParentProcess()); 1775 1776 gfxPlatform::ImportGPUDeviceData(aData); 1777 1778 gfxConfig::ImportChange(Feature::D3D11_COMPOSITING, aData.d3d11Compositing()); 1779 1780 DeviceManagerDx* dm = DeviceManagerDx::Get(); 1781 if (gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) { 1782 dm->ImportDeviceInfo(aData.gpuDevice().ref()); 1783 } else { 1784 // There should be no devices, so this just takes away the device status. 1785 dm->ResetDevices(); 1786 } 1787 1788 // Hardware video decoding depends on d3d11 state, so update the cache. 1789 InitHardwareVideoConfig(); 1790 1791 // For completeness (and messaging in about:support). Content recomputes this 1792 // on its own, and we won't use ANGLE in the UI process if we're using a GPU 1793 // process. 1794 UpdateANGLEConfig(); 1795 } 1796 1797 void gfxWindowsPlatform::ImportContentDeviceData( 1798 const mozilla::gfx::ContentDeviceData& aData) { 1799 MOZ_ASSERT(XRE_IsContentProcess()); 1800 1801 gfxPlatform::ImportContentDeviceData(aData); 1802 1803 const DevicePrefs& prefs = aData.prefs(); 1804 gfxConfig::Inherit(Feature::D3D11_COMPOSITING, prefs.d3d11Compositing()); 1805 1806 if (gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) { 1807 DeviceManagerDx* dm = DeviceManagerDx::Get(); 1808 dm->ImportDeviceInfo(aData.d3d11()); 1809 } 1810 } 1811 1812 void gfxWindowsPlatform::BuildContentDeviceData(ContentDeviceData* aOut) { 1813 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED 1814 // D3D11_COMPOSITING may be updated by the GPU process in DeviceManagerDx. 1815 if (auto* gpm = GPUProcessManager::Get()) { 1816 MOZ_DIAGNOSTIC_ASSERT(gpm->IsGPUReady()); 1817 } 1818 #endif 1819 1820 // Check for device resets before giving back new graphics information. 1821 UpdateRenderMode(); 1822 1823 gfxPlatform::BuildContentDeviceData(aOut); 1824 1825 const FeatureState& d3d11 = gfxConfig::GetFeature(Feature::D3D11_COMPOSITING); 1826 aOut->prefs().d3d11Compositing() = d3d11.GetValue(); 1827 1828 if (d3d11.IsEnabled()) { 1829 DeviceManagerDx* dm = DeviceManagerDx::Get(); 1830 dm->ExportDeviceInfo(&aOut->d3d11()); 1831 } 1832 1833 aOut->cmsOutputProfileData() = 1834 gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfileData(); 1835 } 1836 1837 bool gfxWindowsPlatform::CheckVariationFontSupport() { 1838 // Variation font support is only available on Fall Creators Update or later. 1839 return IsWin10FallCreatorsUpdateOrLater(); 1840 } 1841 1842 void gfxWindowsPlatform::GetPlatformDisplayInfo( 1843 mozilla::widget::InfoObject& aObj) { 1844 HwStretchingSupport stretch; 1845 DeviceManagerDx::Get()->CheckHardwareStretchingSupport(stretch); 1846 1847 nsPrintfCString stretchValue( 1848 "both=%u window-only=%u full-screen-only=%u none=%u error=%u", 1849 stretch.mBoth, stretch.mWindowOnly, stretch.mFullScreenOnly, 1850 stretch.mNone, stretch.mError); 1851 aObj.DefineProperty("HardwareStretching", stretchValue.get()); 1852 1853 ScaledResolutionSet scaled; 1854 GetScaledResolutions(scaled); 1855 if (scaled.IsEmpty()) { 1856 return; 1857 } 1858 1859 aObj.DefineProperty("ScaledResolutionCount", scaled.Length()); 1860 for (size_t i = 0; i < scaled.Length(); ++i) { 1861 auto& s = scaled[i]; 1862 nsPrintfCString name("ScaledResolution%zu", i); 1863 nsPrintfCString value("source %dx%d, target %dx%d", s.first.width, 1864 s.first.height, s.second.width, s.second.height); 1865 aObj.DefineProperty(name.get(), value.get()); 1866 } 1867 }