1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "DeviceManagerDx.h"
7 #include "D3D11Checks.h"
9 #include "GfxDriverInfo.h"
10 #include "gfxWindowsPlatform.h"
11 #include "mozilla/D3DMessageUtils.h"
12 #include "mozilla/StaticPrefs_gfx.h"
13 #include "mozilla/StaticPrefs_layers.h"
14 #include "mozilla/Telemetry.h"
15 #include "mozilla/WindowsVersion.h"
16 #include "mozilla/gfx/GPUParent.h"
17 #include "mozilla/gfx/GPUProcessManager.h"
18 #include "mozilla/gfx/GraphicsMessages.h"
19 #include "mozilla/gfx/Logging.h"
20 #include "mozilla/gfx/gfxVars.h"
21 #include "mozilla/layers/CompositorBridgeChild.h"
22 #include "mozilla/layers/CompositorThread.h"
23 #include "mozilla/layers/DeviceAttachmentsD3D11.h"
24 #include "mozilla/Preferences.h"
25 #include "nsPrintfCString.h"
30 #include "mozilla/gfx/AllOfDcomp.h"
38 using namespace mozilla::widget
;
39 using namespace mozilla::layers
;
41 StaticAutoPtr
<DeviceManagerDx
> DeviceManagerDx::sInstance
;
43 // We don't have access to the D3D11CreateDevice type in gfxWindowsPlatform.h,
44 // since it doesn't include d3d11.h, so we use a static here. It should only
45 // be used within InitializeD3D11.
46 decltype(D3D11CreateDevice
)* sD3D11CreateDeviceFn
= nullptr;
48 // It should only be used within CreateDirectCompositionDevice.
49 decltype(DCompositionCreateDevice2
)* sDcompCreateDevice2Fn
= nullptr;
50 decltype(DCompositionCreateDevice3
)* sDcompCreateDevice3Fn
= nullptr;
52 // It should only be used within CreateDCompSurfaceHandle
53 decltype(DCompositionCreateSurfaceHandle
)* sDcompCreateSurfaceHandleFn
=
56 // We don't have access to the DirectDrawCreateEx type in gfxWindowsPlatform.h,
57 // since it doesn't include ddraw.h, so we use a static here. It should only
58 // be used within InitializeDirectDrawConfig.
59 decltype(DirectDrawCreateEx
)* sDirectDrawCreateExFn
= nullptr;
62 void DeviceManagerDx::Init() { sInstance
= new DeviceManagerDx(); }
65 void DeviceManagerDx::Shutdown() { sInstance
= nullptr; }
67 DeviceManagerDx::DeviceManagerDx()
68 : mDeviceLock("gfxWindowsPlatform.mDeviceLock"),
69 mCompositorDeviceSupportsVideo(false) {
70 // Set up the D3D11 feature levels we can ask for.
71 if (IsWin8OrLater()) {
72 mFeatureLevels
.AppendElement(D3D_FEATURE_LEVEL_11_1
);
74 mFeatureLevels
.AppendElement(D3D_FEATURE_LEVEL_11_0
);
75 mFeatureLevels
.AppendElement(D3D_FEATURE_LEVEL_10_1
);
76 mFeatureLevels
.AppendElement(D3D_FEATURE_LEVEL_10_0
);
77 MOZ_COUNT_CTOR(DeviceManagerDx
);
80 DeviceManagerDx::~DeviceManagerDx() { MOZ_COUNT_DTOR(DeviceManagerDx
); }
82 bool DeviceManagerDx::LoadD3D11() {
83 FeatureState
& d3d11
= gfxConfig::GetFeature(Feature::D3D11_COMPOSITING
);
84 MOZ_ASSERT(d3d11
.IsEnabled());
86 if (sD3D11CreateDeviceFn
) {
90 nsModuleHandle
module(LoadLibrarySystem32(L
"d3d11.dll"));
92 d3d11
.SetFailed(FeatureStatus::Unavailable
,
93 "Direct3D11 not available on this computer",
94 "FEATURE_FAILURE_D3D11_LIB"_ns
);
98 sD3D11CreateDeviceFn
=
99 (decltype(D3D11CreateDevice
)*)GetProcAddress(module
, "D3D11CreateDevice");
100 if (!sD3D11CreateDeviceFn
) {
101 // We should just be on Windows Vista or XP in this case.
102 d3d11
.SetFailed(FeatureStatus::Unavailable
,
103 "Direct3D11 not available on this computer",
104 "FEATURE_FAILURE_D3D11_FUNCPTR"_ns
);
108 mD3D11Module
.steal(module
);
112 bool DeviceManagerDx::LoadDcomp() {
113 MOZ_ASSERT(gfxConfig::GetFeature(Feature::D3D11_COMPOSITING
).IsEnabled());
114 MOZ_ASSERT(gfxVars::UseWebRenderANGLE());
115 MOZ_ASSERT(gfxVars::UseWebRenderDCompWin());
117 if (sDcompCreateDevice2Fn
) {
118 return true; // Already loaded.
121 nsModuleHandle
module(LoadLibrarySystem32(L
"dcomp.dll"));
126 sDcompCreateDevice2Fn
= (decltype(DCompositionCreateDevice2
)*)GetProcAddress(
127 module
, "DCompositionCreateDevice2");
128 sDcompCreateDevice3Fn
= (decltype(DCompositionCreateDevice3
)*)GetProcAddress(
129 module
, "DCompositionCreateDevice3");
130 if (!sDcompCreateDevice2Fn
) {
134 // Load optional API for external compositing
135 sDcompCreateSurfaceHandleFn
=
136 (decltype(DCompositionCreateSurfaceHandle
)*)::GetProcAddress(
137 module
, "DCompositionCreateSurfaceHandle");
139 mDcompModule
.steal(module
);
143 void DeviceManagerDx::ReleaseD3D11() {
144 MOZ_ASSERT(!mCompositorDevice
);
145 MOZ_ASSERT(!mContentDevice
);
146 MOZ_ASSERT(!mVRDevice
);
147 MOZ_ASSERT(!mDecoderDevice
);
149 mD3D11Module
.reset();
150 sD3D11CreateDeviceFn
= nullptr;
153 nsTArray
<DXGI_OUTPUT_DESC1
> DeviceManagerDx::EnumerateOutputs() {
154 RefPtr
<IDXGIAdapter
> adapter
= GetDXGIAdapter();
157 NS_WARNING("Failed to acquire a DXGI adapter for enumerating outputs.");
158 return nsTArray
<DXGI_OUTPUT_DESC1
>();
161 nsTArray
<DXGI_OUTPUT_DESC1
> outputs
;
162 for (UINT i
= 0;; ++i
) {
163 RefPtr
<IDXGIOutput
> output
= nullptr;
164 if (FAILED(adapter
->EnumOutputs(i
, getter_AddRefs(output
)))) {
168 RefPtr
<IDXGIOutput6
> output6
= nullptr;
169 if (FAILED(output
->QueryInterface(__uuidof(IDXGIOutput6
),
170 getter_AddRefs(output6
)))) {
174 DXGI_OUTPUT_DESC1 desc
;
175 if (FAILED(output6
->GetDesc1(&desc
))) {
179 outputs
.AppendElement(desc
);
184 bool DeviceManagerDx::GetOutputFromMonitor(HMONITOR monitor
,
185 RefPtr
<IDXGIOutput
>* aOutOutput
) {
186 RefPtr
<IDXGIAdapter
> adapter
= GetDXGIAdapter();
189 NS_WARNING("Failed to acquire a DXGI adapter for GetOutputFromMonitor.");
193 for (UINT i
= 0;; ++i
) {
194 RefPtr
<IDXGIOutput
> output
= nullptr;
195 if (FAILED(adapter
->EnumOutputs(i
, getter_AddRefs(output
)))) {
199 DXGI_OUTPUT_DESC desc
;
200 if (FAILED(output
->GetDesc(&desc
))) {
204 if (desc
.Monitor
== monitor
) {
205 *aOutOutput
= output
;
212 void DeviceManagerDx::CheckHardwareStretchingSupport(HwStretchingSupport
& aRv
) {
213 RefPtr
<IDXGIAdapter
> adapter
= GetDXGIAdapter();
217 "Failed to acquire a DXGI adapter for checking hardware stretching "
223 for (UINT i
= 0;; ++i
) {
224 RefPtr
<IDXGIOutput
> output
= nullptr;
225 HRESULT result
= adapter
->EnumOutputs(i
, getter_AddRefs(output
));
226 if (result
== DXGI_ERROR_NOT_FOUND
) {
227 // No more outputs to check.
231 if (FAILED(result
)) {
236 RefPtr
<IDXGIOutput6
> output6
= nullptr;
237 if (FAILED(output
->QueryInterface(__uuidof(IDXGIOutput6
),
238 getter_AddRefs(output6
)))) {
244 if (FAILED(output6
->CheckHardwareCompositionSupport(&flags
))) {
249 bool fullScreen
= flags
& DXGI_HARDWARE_COMPOSITION_SUPPORT_FLAG_FULLSCREEN
;
250 bool window
= flags
& DXGI_HARDWARE_COMPOSITION_SUPPORT_FLAG_WINDOWED
;
251 if (fullScreen
&& window
) {
253 } else if (fullScreen
) {
254 ++aRv
.mFullScreenOnly
;
264 static inline bool ProcessOwnsCompositor() {
265 return XRE_GetProcessType() == GeckoProcessType_GPU
||
266 XRE_GetProcessType() == GeckoProcessType_VR
||
267 (XRE_IsParentProcess() && !gfxConfig::IsEnabled(Feature::GPU_PROCESS
));
271 bool DeviceManagerDx::CreateCompositorDevices() {
272 MutexAutoLock
lock(mDeviceLock
);
273 return CreateCompositorDevicesLocked();
276 bool DeviceManagerDx::CreateCompositorDevicesLocked() {
277 MOZ_ASSERT(ProcessOwnsCompositor());
279 FeatureState
& d3d11
= gfxConfig::GetFeature(Feature::D3D11_COMPOSITING
);
280 MOZ_ASSERT(d3d11
.IsEnabled());
282 if (int32_t sleepSec
=
283 StaticPrefs::gfx_direct3d11_sleep_on_create_device_AtStartup()) {
284 printf_stderr("Attach to PID: %lu\n", GetCurrentProcessId());
285 Sleep(sleepSec
* 1000);
292 CreateCompositorDevice(d3d11
);
294 if (!d3d11
.IsEnabled()) {
295 MOZ_ASSERT(!mCompositorDevice
);
301 // We leak these everywhere and we need them our entire runtime anyway, let's
302 // leak it here as well. We keep the pointer to sD3D11CreateDeviceFn around
303 // as well for D2D1 and device resets.
304 mD3D11Module
.disown();
306 MOZ_ASSERT(mCompositorDevice
);
307 if (!d3d11
.IsEnabled()) {
311 // When WR is used, do not preload attachments for D3D11 Non-WR compositor.
313 // Fallback from WR to D3D11 Non-WR compositor without re-creating gpu process
314 // could happen when WR causes error. In this case, the attachments are loaded
316 if (gfx::gfxVars::UseSoftwareWebRender()) {
317 PreloadAttachmentsOnCompositorThread();
323 bool DeviceManagerDx::CreateVRDevice() {
324 MOZ_ASSERT(ProcessOwnsCompositor());
330 if (!gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING
)) {
331 NS_WARNING("Direct3D11 Compositing required for VR");
339 RefPtr
<IDXGIAdapter1
> adapter
= GetDXGIAdapterLocked();
341 NS_WARNING("Failed to acquire a DXGI adapter for VR");
345 UINT flags
= D3D11_CREATE_DEVICE_BGRA_SUPPORT
;
348 if (!CreateDevice(adapter
, D3D_DRIVER_TYPE_UNKNOWN
, flags
, hr
, mVRDevice
)) {
349 gfxCriticalError() << "Crash during D3D11 device creation for VR";
353 if (FAILED(hr
) || !mVRDevice
) {
354 NS_WARNING("Failed to acquire a D3D11 device for VR");
361 bool DeviceManagerDx::CreateCanvasDevice() {
362 MutexAutoLock
lock(mDeviceLock
);
363 return CreateCanvasDeviceLocked();
366 bool DeviceManagerDx::CreateCanvasDeviceLocked() {
367 MOZ_ASSERT(ProcessOwnsCompositor());
377 RefPtr
<IDXGIAdapter1
> adapter
= GetDXGIAdapterLocked();
379 NS_WARNING("Failed to acquire a DXGI adapter for Canvas");
383 UINT flags
= D3D11_CREATE_DEVICE_BGRA_SUPPORT
;
386 if (!CreateDevice(adapter
, D3D_DRIVER_TYPE_UNKNOWN
, flags
, hr
,
388 gfxCriticalError() << "Crash during D3D11 device creation for Canvas";
393 gfx_direct2d_target_independent_rasterization_disabled_AtStartup()) {
394 int creationFlags
= 0x2; // disable target independent rasterization
395 const GUID D2D_INTERNAL_DEVICE_CREATION_OPTIONS
= {
399 {0x84, 0x42, 0x40, 0x43, 0xe0, 0xb0, 0x94, 0x95}};
400 mCanvasDevice
->SetPrivateData(D2D_INTERNAL_DEVICE_CREATION_OPTIONS
,
401 sizeof(creationFlags
), &creationFlags
);
404 if (FAILED(hr
) || !mCanvasDevice
) {
405 NS_WARNING("Failed to acquire a D3D11 device for Canvas");
409 if (!D3D11Checks::DoesTextureSharingWork(mCanvasDevice
)) {
410 mCanvasDevice
= nullptr;
414 if (XRE_IsGPUProcess()) {
415 Factory::SetDirect3D11Device(mCanvasDevice
);
421 void DeviceManagerDx::CreateDirectCompositionDevice() {
422 MutexAutoLock
lock(mDeviceLock
);
423 CreateDirectCompositionDeviceLocked();
426 void DeviceManagerDx::CreateDirectCompositionDeviceLocked() {
427 if (!gfxVars::UseWebRenderDCompWin()) {
431 if (!mCompositorDevice
) {
439 RefPtr
<IDXGIDevice
> dxgiDevice
;
440 if (mCompositorDevice
->QueryInterface(
441 IID_PPV_ARGS((IDXGIDevice
**)getter_AddRefs(dxgiDevice
))) != S_OK
) {
446 RefPtr
<IDCompositionDesktopDevice
> desktopDevice
;
448 hr
= sDcompCreateDevice3Fn(
451 (IDCompositionDesktopDevice
**)getter_AddRefs(desktopDevice
)));
452 if (!desktopDevice
) {
453 hr
= sDcompCreateDevice2Fn(
456 (IDCompositionDesktopDevice
**)getter_AddRefs(desktopDevice
)));
459 MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) { return; }
461 if (!SUCCEEDED(hr
)) {
465 RefPtr
<IDCompositionDevice2
> compositionDevice
;
466 if (desktopDevice
->QueryInterface(IID_PPV_ARGS(
467 (IDCompositionDevice2
**)getter_AddRefs(compositionDevice
))) != S_OK
) {
471 mDirectCompositionDevice
= compositionDevice
;
475 HANDLE
DeviceManagerDx::CreateDCompSurfaceHandle() {
476 if (!sDcompCreateSurfaceHandleFn
) {
481 HRESULT hr
= sDcompCreateSurfaceHandleFn(COMPOSITIONOBJECT_ALL_ACCESS
,
490 void DeviceManagerDx::ImportDeviceInfo(const D3D11DeviceStatus
& aDeviceStatus
) {
491 MOZ_ASSERT(!ProcessOwnsCompositor());
493 MutexAutoLock
lock(mDeviceLock
);
494 mDeviceStatus
= Some(aDeviceStatus
);
497 bool DeviceManagerDx::ExportDeviceInfo(D3D11DeviceStatus
* aOut
) {
498 MutexAutoLock
lock(mDeviceLock
);
500 *aOut
= mDeviceStatus
.value();
507 void DeviceManagerDx::CreateContentDevices() {
508 MutexAutoLock
lock(mDeviceLock
);
509 CreateContentDevicesLocked();
512 void DeviceManagerDx::CreateContentDevicesLocked() {
513 MOZ_ASSERT(gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING
));
519 // We should have been assigned a DeviceStatus from the parent process,
520 // GPU process, or the same process if using in-process compositing.
521 MOZ_ASSERT(mDeviceStatus
);
523 if (CreateContentDevice() == FeatureStatus::CrashedInHandler
) {
524 DisableD3D11AfterCrash();
528 already_AddRefed
<IDXGIAdapter1
> DeviceManagerDx::GetDXGIAdapter() {
529 MutexAutoLock
lock(mDeviceLock
);
530 return do_AddRef(GetDXGIAdapterLocked());
533 IDXGIAdapter1
* DeviceManagerDx::GetDXGIAdapterLocked() {
538 nsModuleHandle
dxgiModule(LoadLibrarySystem32(L
"dxgi.dll"));
539 decltype(CreateDXGIFactory1
)* createDXGIFactory1
=
540 (decltype(CreateDXGIFactory1
)*)GetProcAddress(dxgiModule
,
541 "CreateDXGIFactory1");
542 if (!createDXGIFactory1
) {
545 static const auto fCreateDXGIFactory2
=
546 (decltype(CreateDXGIFactory2
)*)GetProcAddress(dxgiModule
,
547 "CreateDXGIFactory2");
549 // Try to use a DXGI 1.1 adapter in order to share resources
551 RefPtr
<IDXGIFactory1
> factory1
;
552 if (StaticPrefs::gfx_direct3d11_enable_debug_layer_AtStartup()) {
553 RefPtr
<IDXGIFactory2
> factory2
;
554 if (fCreateDXGIFactory2
) {
555 auto hr
= fCreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG
,
556 __uuidof(IDXGIFactory2
),
557 getter_AddRefs(factory2
));
558 MOZ_ALWAYS_TRUE(!FAILED(hr
));
561 "fCreateDXGIFactory2 not loaded, cannot create debug IDXGIFactory2.");
567 createDXGIFactory1(__uuidof(IDXGIFactory1
), getter_AddRefs(factory1
));
568 if (FAILED(hr
) || !factory1
) {
569 // This seems to happen with some people running the iZ3D driver.
570 // They won't get acceleration.
575 if (!mDeviceStatus
) {
576 // If we haven't created a device yet, and have no existing device status,
577 // then this must be the compositor device. Pick the first adapter we can.
578 if (FAILED(factory1
->EnumAdapters1(0, getter_AddRefs(mAdapter
)))) {
582 // In the UI and GPU process, we clear mDeviceStatus on device reset, so we
583 // should never reach here. Furthermore, the UI process does not create
584 // devices when using a GPU process.
586 // So, this should only ever get called on the content process or RDD
588 MOZ_ASSERT(XRE_IsContentProcess() || XRE_IsRDDProcess());
590 // In the child process, we search for the adapter that matches the parent
591 // process. The first adapter can be mismatched on dual-GPU systems.
592 for (UINT index
= 0;; index
++) {
593 RefPtr
<IDXGIAdapter1
> adapter
;
594 if (FAILED(factory1
->EnumAdapters1(index
, getter_AddRefs(adapter
)))) {
598 const DxgiAdapterDesc
& preferred
= mDeviceStatus
->adapter();
600 DXGI_ADAPTER_DESC desc
;
601 if (SUCCEEDED(adapter
->GetDesc(&desc
)) &&
602 desc
.AdapterLuid
.HighPart
== preferred
.AdapterLuid
.HighPart
&&
603 desc
.AdapterLuid
.LowPart
== preferred
.AdapterLuid
.LowPart
&&
604 desc
.VendorId
== preferred
.VendorId
&&
605 desc
.DeviceId
== preferred
.DeviceId
) {
606 mAdapter
= adapter
.forget();
616 // We leak this module everywhere, we might as well do so here as well.
621 bool DeviceManagerDx::CreateCompositorDeviceHelper(
622 FeatureState
& aD3d11
, IDXGIAdapter1
* aAdapter
, bool aAttemptVideoSupport
,
623 RefPtr
<ID3D11Device
>& aOutDevice
) {
624 // Check if a failure was injected for testing.
625 if (StaticPrefs::gfx_testing_device_fail()) {
626 aD3d11
.SetFailed(FeatureStatus::Failed
,
627 "Direct3D11 device failure simulated by preference",
628 "FEATURE_FAILURE_D3D11_SIM"_ns
);
632 UINT flags
= D3D11_CREATE_DEVICE_BGRA_SUPPORT
;
634 DXGI_ADAPTER_DESC desc
;
635 aAdapter
->GetDesc(&desc
);
636 if (desc
.VendorId
!= 0x1414) {
637 // 0x1414 is Microsoft (e.g. WARP)
638 // When not using WARP, use
639 // D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS to prevent
640 // bug 1092260. IE 11 also uses this flag.
641 flags
|= D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
;
644 if (aAttemptVideoSupport
) {
645 flags
|= D3D11_CREATE_DEVICE_VIDEO_SUPPORT
;
649 RefPtr
<ID3D11Device
> device
;
650 if (!CreateDevice(aAdapter
, D3D_DRIVER_TYPE_UNKNOWN
, flags
, hr
, device
)) {
651 if (!aAttemptVideoSupport
) {
652 gfxCriticalError() << "Crash during D3D11 device creation";
653 aD3d11
.SetFailed(FeatureStatus::CrashedInHandler
,
654 "Crashed trying to acquire a D3D11 device",
655 "FEATURE_FAILURE_D3D11_DEVICE1"_ns
);
660 if (FAILED(hr
) || !device
) {
661 if (!aAttemptVideoSupport
) {
662 aD3d11
.SetFailed(FeatureStatus::Failed
,
663 "Failed to acquire a D3D11 device",
664 "FEATURE_FAILURE_D3D11_DEVICE2"_ns
);
668 if (!D3D11Checks::DoesDeviceWork()) {
669 if (!aAttemptVideoSupport
) {
670 aD3d11
.SetFailed(FeatureStatus::Broken
,
671 "Direct3D11 device was determined to be broken",
672 "FEATURE_FAILURE_D3D11_BROKEN"_ns
);
681 // Note that it's enough for us to just use a counter for a unique ID,
682 // even though the counter isn't synchronized between processes. If we
683 // start in the GPU process and wind up in the parent process, the
684 // whole graphics stack is blown away anyway. But just in case, we
685 // make gpu process IDs negative and parent process IDs positive.
686 static inline int32_t GetNextDeviceCounter() {
687 static int32_t sDeviceCounter
= 0;
688 return XRE_IsGPUProcess() ? --sDeviceCounter
: ++sDeviceCounter
;
691 void DeviceManagerDx::CreateCompositorDevice(FeatureState
& d3d11
) {
692 if (StaticPrefs::layers_d3d11_force_warp_AtStartup()) {
693 CreateWARPCompositorDevice();
697 RefPtr
<IDXGIAdapter1
> adapter
= GetDXGIAdapterLocked();
699 d3d11
.SetFailed(FeatureStatus::Unavailable
,
700 "Failed to acquire a DXGI adapter",
701 "FEATURE_FAILURE_D3D11_DXGI"_ns
);
705 if (XRE_IsGPUProcess() && !D3D11Checks::DoesRemotePresentWork(adapter
)) {
706 d3d11
.SetFailed(FeatureStatus::Unavailable
,
707 "DXGI does not support out-of-process presentation",
708 "FEATURE_FAILURE_D3D11_REMOTE_PRESENT"_ns
);
712 RefPtr
<ID3D11Device
> device
;
713 if (!CreateCompositorDeviceHelper(d3d11
, adapter
, true, device
)) {
714 // Try again without video support and record that it failed.
715 mCompositorDeviceSupportsVideo
= false;
716 if (!CreateCompositorDeviceHelper(d3d11
, adapter
, false, device
)) {
720 mCompositorDeviceSupportsVideo
= true;
723 // Only test this when not using WARP since it can fail and cause
724 // GetDeviceRemovedReason to return weird values.
725 bool textureSharingWorks
= D3D11Checks::DoesTextureSharingWork(device
);
727 DXGI_ADAPTER_DESC desc
;
729 adapter
->GetDesc(&desc
);
731 if (!textureSharingWorks
) {
732 gfxConfig::SetFailed(Feature::D3D11_HW_ANGLE
, FeatureStatus::Broken
,
733 "Texture sharing doesn't work",
734 "FEATURE_FAILURE_HW_ANGLE_NEEDS_TEXTURE_SHARING"_ns
);
736 if (D3D11Checks::DoesRenderTargetViewNeedRecreating(device
)) {
737 gfxConfig::SetFailed(Feature::D3D11_HW_ANGLE
, FeatureStatus::Broken
,
738 "RenderTargetViews need recreating",
739 "FEATURE_FAILURE_HW_ANGLE_NEEDS_RTV_RECREATION"_ns
);
741 if (XRE_IsParentProcess()) {
742 // It seems like this may only happen when we're using the NVIDIA gpu
743 D3D11Checks::WarnOnAdapterMismatch(device
);
746 uint32_t featureLevel
= device
->GetFeatureLevel();
747 auto formatOptions
= D3D11Checks::FormatOptions(device
);
748 mCompositorDevice
= device
;
750 int32_t sequenceNumber
= GetNextDeviceCounter();
751 mDeviceStatus
= Some(D3D11DeviceStatus(
752 false, textureSharingWorks
, featureLevel
, DxgiAdapterDesc::From(desc
),
753 sequenceNumber
, formatOptions
));
754 mCompositorDevice
->SetExceptionMode(0);
757 bool DeviceManagerDx::CreateDevice(IDXGIAdapter
* aAdapter
,
758 D3D_DRIVER_TYPE aDriverType
, UINT aFlags
,
760 RefPtr
<ID3D11Device
>& aOutDevice
) {
761 if (StaticPrefs::gfx_direct3d11_enable_debug_layer_AtStartup() ||
762 StaticPrefs::gfx_direct3d11_break_on_error_AtStartup()) {
763 aFlags
|= D3D11_CREATE_DEVICE_DEBUG
;
767 aResOut
= sD3D11CreateDeviceFn(
768 aAdapter
, aDriverType
, nullptr, aFlags
, mFeatureLevels
.Elements(),
769 mFeatureLevels
.Length(), D3D11_SDK_VERSION
, getter_AddRefs(aOutDevice
),
772 MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) { return false; }
774 if (StaticPrefs::gfx_direct3d11_break_on_error_AtStartup()) {
776 if (!aOutDevice
) break;
778 RefPtr
<ID3D11Debug
> debug
;
779 if (!SUCCEEDED(aOutDevice
->QueryInterface(__uuidof(ID3D11Debug
),
780 getter_AddRefs(debug
))))
783 RefPtr
<ID3D11InfoQueue
> infoQueue
;
784 if (!SUCCEEDED(debug
->QueryInterface(__uuidof(ID3D11InfoQueue
),
785 getter_AddRefs(infoQueue
))))
788 D3D11_INFO_QUEUE_FILTER filter
;
791 // Disable warnings caused by Advanced Layers that are known and not
793 D3D11_MESSAGE_ID blockIDs
[] = {
794 D3D11_MESSAGE_ID_DEVICE_DRAW_CONSTANT_BUFFER_TOO_SMALL
};
795 filter
.DenyList
.NumIDs
= MOZ_ARRAY_LENGTH(blockIDs
);
796 filter
.DenyList
.pIDList
= blockIDs
;
797 infoQueue
->PushStorageFilter(&filter
);
799 infoQueue
->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION
, true);
800 infoQueue
->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR
, true);
801 infoQueue
->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_WARNING
, true);
808 void DeviceManagerDx::CreateWARPCompositorDevice() {
809 ScopedGfxFeatureReporter
reporterWARP(
810 "D3D11-WARP", StaticPrefs::layers_d3d11_force_warp_AtStartup());
811 FeatureState
& d3d11
= gfxConfig::GetFeature(Feature::D3D11_COMPOSITING
);
814 RefPtr
<ID3D11Device
> device
;
816 // Use D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
817 // to prevent bug 1092260. IE 11 also uses this flag.
818 UINT flags
= D3D11_CREATE_DEVICE_BGRA_SUPPORT
;
819 if (!CreateDevice(nullptr, D3D_DRIVER_TYPE_WARP
, flags
, hr
, device
)) {
820 gfxCriticalError() << "Exception occurred initializing WARP D3D11 device!";
821 d3d11
.SetFailed(FeatureStatus::CrashedInHandler
,
822 "Crashed creating a D3D11 WARP device",
823 "FEATURE_FAILURE_D3D11_WARP_DEVICE"_ns
);
826 if (FAILED(hr
) || !device
) {
827 // This should always succeed... in theory.
828 gfxCriticalError() << "Failed to initialize WARP D3D11 device! "
830 d3d11
.SetFailed(FeatureStatus::Failed
,
831 "Failed to create a D3D11 WARP device",
832 "FEATURE_FAILURE_D3D11_WARP_DEVICE2"_ns
);
836 // Only test for texture sharing on Windows 8 since it puts the device into
837 // an unusable state if used on Windows 7
838 bool textureSharingWorks
= false;
839 if (IsWin8OrLater()) {
840 textureSharingWorks
= D3D11Checks::DoesTextureSharingWork(device
);
843 DXGI_ADAPTER_DESC desc
;
844 D3D11Checks::GetDxgiDesc(device
, &desc
);
846 int featureLevel
= device
->GetFeatureLevel();
848 auto formatOptions
= D3D11Checks::FormatOptions(device
);
849 mCompositorDevice
= device
;
851 int32_t sequenceNumber
= GetNextDeviceCounter();
852 mDeviceStatus
= Some(D3D11DeviceStatus(
853 true, textureSharingWorks
, featureLevel
, DxgiAdapterDesc::From(desc
),
854 sequenceNumber
, formatOptions
));
855 mCompositorDevice
->SetExceptionMode(0);
857 reporterWARP
.SetSuccessful();
860 FeatureStatus
DeviceManagerDx::CreateContentDevice() {
861 RefPtr
<IDXGIAdapter1
> adapter
;
862 if (!mDeviceStatus
->isWARP()) {
863 adapter
= GetDXGIAdapterLocked();
865 gfxCriticalNote
<< "Could not get a DXGI adapter";
866 return FeatureStatus::Unavailable
;
871 RefPtr
<ID3D11Device
> device
;
873 UINT flags
= D3D11_CREATE_DEVICE_BGRA_SUPPORT
;
874 D3D_DRIVER_TYPE type
=
875 mDeviceStatus
->isWARP() ? D3D_DRIVER_TYPE_WARP
: D3D_DRIVER_TYPE_UNKNOWN
;
876 if (!CreateDevice(adapter
, type
, flags
, hr
, device
)) {
878 << "Recovered from crash while creating a D3D11 content device";
879 gfxWindowsPlatform::RecordContentDeviceFailure(
880 TelemetryDeviceCode::Content
);
881 return FeatureStatus::CrashedInHandler
;
884 if (FAILED(hr
) || !device
) {
885 gfxCriticalNote
<< "Failed to create a D3D11 content device: " << hexa(hr
);
886 gfxWindowsPlatform::RecordContentDeviceFailure(
887 TelemetryDeviceCode::Content
);
888 return FeatureStatus::Failed
;
891 // InitializeD2D() will abort early if the compositor device did not support
892 // texture sharing. If we're in the content process, we can't rely on the
893 // parent device alone: some systems have dual GPUs that are capable of
894 // binding the parent and child processes to different GPUs. As a safety net,
895 // we re-check texture sharing against the newly created D3D11 content device.
896 // If it fails, we won't use Direct2D.
897 if (XRE_IsContentProcess()) {
898 if (!D3D11Checks::DoesTextureSharingWork(device
)) {
899 return FeatureStatus::Failed
;
902 DebugOnly
<bool> ok
= ContentAdapterIsParentAdapter(device
);
906 mContentDevice
= device
;
907 mContentDevice
->SetExceptionMode(0);
909 RefPtr
<ID3D10Multithread
> multi
;
910 hr
= mContentDevice
->QueryInterface(__uuidof(ID3D10Multithread
),
911 getter_AddRefs(multi
));
912 if (SUCCEEDED(hr
) && multi
) {
913 multi
->SetMultithreadProtected(TRUE
);
915 return FeatureStatus::Available
;
918 RefPtr
<ID3D11Device
> DeviceManagerDx::CreateDecoderDevice(
919 bool aHardwareWebRender
) {
920 MutexAutoLock
lock(mDeviceLock
);
922 if (!mDeviceStatus
) {
926 bool isAMD
= mDeviceStatus
->adapter().VendorId
== 0x1002;
927 bool reuseDevice
= false;
928 if (gfxVars::ReuseDecoderDevice()) {
932 gfxCriticalNoteOnce
<< "Always have to reuse decoder device on AMD";
936 // Use mCompositorDevice for decoder device only for hardware WebRender.
937 if (aHardwareWebRender
&& mCompositorDevice
&&
938 mCompositorDeviceSupportsVideo
&& !mDecoderDevice
) {
939 mDecoderDevice
= mCompositorDevice
;
941 RefPtr
<ID3D10Multithread
> multi
;
942 mDecoderDevice
->QueryInterface(__uuidof(ID3D10Multithread
),
943 getter_AddRefs(multi
));
945 multi
->SetMultithreadProtected(TRUE
);
949 if (mDecoderDevice
) {
950 RefPtr
<ID3D11Device
> dev
= mDecoderDevice
;
955 if (!sD3D11CreateDeviceFn
) {
956 // We should just be on Windows Vista or XP in this case.
960 RefPtr
<IDXGIAdapter1
> adapter
= GetDXGIAdapterLocked();
966 RefPtr
<ID3D11Device
> device
;
968 UINT flags
= D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
|
969 D3D11_CREATE_DEVICE_VIDEO_SUPPORT
;
970 if (!CreateDevice(adapter
, D3D_DRIVER_TYPE_UNKNOWN
, flags
, hr
, device
)) {
973 if (FAILED(hr
) || !device
|| !D3D11Checks::DoesDeviceWork()) {
977 RefPtr
<ID3D10Multithread
> multi
;
978 device
->QueryInterface(__uuidof(ID3D10Multithread
), getter_AddRefs(multi
));
980 multi
->SetMultithreadProtected(TRUE
);
983 mDecoderDevice
= device
;
988 // ID3D11DeviceChild, IDXGIObject and ID3D11Device implement SetPrivateData with
989 // the exact same parameters.
990 template <typename T
>
991 static HRESULT
SetDebugName(T
* d3d11Object
, const char* debugString
) {
992 return d3d11Object
->SetPrivateData(WKPDID_D3DDebugObjectName
,
993 strlen(debugString
), debugString
);
996 RefPtr
<ID3D11Device
> DeviceManagerDx::CreateMediaEngineDevice() {
997 MutexAutoLock
lock(mDeviceLock
);
1003 RefPtr
<ID3D11Device
> device
;
1004 UINT flags
= D3D11_CREATE_DEVICE_VIDEO_SUPPORT
|
1005 D3D11_CREATE_DEVICE_BGRA_SUPPORT
|
1006 D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
;
1007 if (!CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE
, flags
, hr
, device
)) {
1010 if (FAILED(hr
) || !device
|| !D3D11Checks::DoesDeviceWork()) {
1013 Unused
<< SetDebugName(device
.get(), "MFMediaEngineDevice");
1015 RefPtr
<ID3D10Multithread
> multi
;
1016 device
->QueryInterface(__uuidof(ID3D10Multithread
), getter_AddRefs(multi
));
1018 multi
->SetMultithreadProtected(TRUE
);
1023 void DeviceManagerDx::ResetDevices() {
1024 MutexAutoLock
lock(mDeviceLock
);
1025 ResetDevicesLocked();
1028 void DeviceManagerDx::ResetDevicesLocked() {
1030 mCompositorAttachments
= nullptr;
1031 mCompositorDevice
= nullptr;
1032 mContentDevice
= nullptr;
1033 mCanvasDevice
= nullptr;
1034 mImageDevice
= nullptr;
1035 mVRDevice
= nullptr;
1036 mDecoderDevice
= nullptr;
1037 mDirectCompositionDevice
= nullptr;
1038 mDeviceStatus
= Nothing();
1039 mDeviceResetReason
= Nothing();
1040 Factory::SetDirect3D11Device(nullptr);
1043 bool DeviceManagerDx::MaybeResetAndReacquireDevices() {
1044 MutexAutoLock
lock(mDeviceLock
);
1046 DeviceResetReason resetReason
;
1047 if (!HasDeviceResetLocked(&resetReason
)) {
1051 GPUProcessManager::RecordDeviceReset(resetReason
);
1053 bool createCompositorDevice
= !!mCompositorDevice
;
1054 bool createContentDevice
= !!mContentDevice
;
1055 bool createCanvasDevice
= !!mCanvasDevice
;
1056 bool createDirectCompositionDevice
= !!mDirectCompositionDevice
;
1058 ResetDevicesLocked();
1060 if (createCompositorDevice
&& !CreateCompositorDevicesLocked()) {
1061 // Just stop, don't try anything more
1064 if (createContentDevice
) {
1065 CreateContentDevicesLocked();
1067 if (createCanvasDevice
) {
1068 CreateCanvasDeviceLocked();
1070 if (createDirectCompositionDevice
) {
1071 CreateDirectCompositionDeviceLocked();
1077 bool DeviceManagerDx::ContentAdapterIsParentAdapter(ID3D11Device
* device
) {
1078 DXGI_ADAPTER_DESC desc
;
1079 if (!D3D11Checks::GetDxgiDesc(device
, &desc
)) {
1080 gfxCriticalNote
<< "Could not query device DXGI adapter info";
1084 const DxgiAdapterDesc
& preferred
= mDeviceStatus
->adapter();
1086 if (desc
.VendorId
!= preferred
.VendorId
||
1087 desc
.DeviceId
!= preferred
.DeviceId
||
1088 desc
.SubSysId
!= preferred
.SubSysId
||
1089 desc
.AdapterLuid
.HighPart
!= preferred
.AdapterLuid
.HighPart
||
1090 desc
.AdapterLuid
.LowPart
!= preferred
.AdapterLuid
.LowPart
) {
1091 gfxCriticalNote
<< "VendorIDMismatch P " << hexa(preferred
.VendorId
) << " "
1092 << hexa(desc
.VendorId
);
1099 static DeviceResetReason
HResultToResetReason(HRESULT hr
) {
1101 case DXGI_ERROR_DEVICE_HUNG
:
1102 return DeviceResetReason::HUNG
;
1103 case DXGI_ERROR_DEVICE_REMOVED
:
1104 return DeviceResetReason::REMOVED
;
1105 case DXGI_ERROR_DEVICE_RESET
:
1106 return DeviceResetReason::RESET
;
1107 case DXGI_ERROR_DRIVER_INTERNAL_ERROR
:
1108 return DeviceResetReason::DRIVER_ERROR
;
1109 case DXGI_ERROR_INVALID_CALL
:
1110 return DeviceResetReason::INVALID_CALL
;
1112 return DeviceResetReason::OUT_OF_MEMORY
;
1116 return DeviceResetReason::OTHER
;
1119 bool DeviceManagerDx::HasDeviceReset(DeviceResetReason
* aOutReason
) {
1120 MutexAutoLock
lock(mDeviceLock
);
1121 return HasDeviceResetLocked(aOutReason
);
1124 bool DeviceManagerDx::HasDeviceResetLocked(DeviceResetReason
* aOutReason
) {
1125 if (mDeviceResetReason
) {
1127 *aOutReason
= mDeviceResetReason
.value();
1132 DeviceResetReason reason
;
1133 if (GetAnyDeviceRemovedReason(&reason
)) {
1134 mDeviceResetReason
= Some(reason
);
1136 *aOutReason
= reason
;
1144 static inline bool DidDeviceReset(const RefPtr
<ID3D11Device
>& aDevice
,
1145 DeviceResetReason
* aOutReason
) {
1149 HRESULT hr
= aDevice
->GetDeviceRemovedReason();
1154 *aOutReason
= HResultToResetReason(hr
);
1158 bool DeviceManagerDx::GetAnyDeviceRemovedReason(DeviceResetReason
* aOutReason
) {
1159 if (DidDeviceReset(mCompositorDevice
, aOutReason
) ||
1160 DidDeviceReset(mContentDevice
, aOutReason
) ||
1161 DidDeviceReset(mCanvasDevice
, aOutReason
)) {
1165 if (XRE_IsParentProcess() && NS_IsMainThread() &&
1166 StaticPrefs::gfx_testing_device_reset()) {
1167 Preferences::SetInt("gfx.testing.device-reset", 0);
1168 *aOutReason
= DeviceResetReason::FORCED_RESET
;
1175 void DeviceManagerDx::ForceDeviceReset(ForcedDeviceResetReason aReason
) {
1176 Telemetry::Accumulate(Telemetry::FORCED_DEVICE_RESET_REASON
,
1179 MutexAutoLock
lock(mDeviceLock
);
1180 if (!mDeviceResetReason
) {
1181 mDeviceResetReason
= Some(DeviceResetReason::FORCED_RESET
);
1186 void DeviceManagerDx::DisableD3D11AfterCrash() {
1187 gfxConfig::Disable(Feature::D3D11_COMPOSITING
,
1188 FeatureStatus::CrashedInHandler
,
1189 "Crashed while acquiring a Direct3D11 device",
1190 "FEATURE_FAILURE_D3D11_CRASH"_ns
);
1194 RefPtr
<ID3D11Device
> DeviceManagerDx::GetCompositorDevice() {
1195 MutexAutoLock
lock(mDeviceLock
);
1196 return mCompositorDevice
;
1199 RefPtr
<ID3D11Device
> DeviceManagerDx::GetContentDevice() {
1200 MOZ_ASSERT(XRE_IsGPUProcess() ||
1201 gfxPlatform::GetPlatform()->DevicesInitialized());
1203 MutexAutoLock
lock(mDeviceLock
);
1204 return mContentDevice
;
1207 RefPtr
<ID3D11Device
> DeviceManagerDx::GetImageDevice() {
1208 MutexAutoLock
lock(mDeviceLock
);
1210 return mImageDevice
;
1213 RefPtr
<ID3D11Device
> device
= mContentDevice
;
1215 device
= mCompositorDevice
;
1222 RefPtr
<ID3D10Multithread
> multi
;
1224 device
->QueryInterface((ID3D10Multithread
**)getter_AddRefs(multi
));
1225 if (FAILED(hr
) || !multi
) {
1226 gfxWarning() << "Multithread safety interface not supported. " << hr
;
1229 multi
->SetMultithreadProtected(TRUE
);
1231 mImageDevice
= device
;
1233 return mImageDevice
;
1236 RefPtr
<ID3D11Device
> DeviceManagerDx::GetVRDevice() {
1237 MutexAutoLock
lock(mDeviceLock
);
1244 RefPtr
<ID3D11Device
> DeviceManagerDx::GetCanvasDevice() {
1245 MutexAutoLock
lock(mDeviceLock
);
1246 return mCanvasDevice
;
1249 RefPtr
<IDCompositionDevice2
> DeviceManagerDx::GetDirectCompositionDevice() {
1250 MutexAutoLock
lock(mDeviceLock
);
1251 return mDirectCompositionDevice
;
1254 unsigned DeviceManagerDx::GetCompositorFeatureLevel() const {
1255 MutexAutoLock
lock(mDeviceLock
);
1256 if (!mDeviceStatus
) {
1259 return mDeviceStatus
->featureLevel();
1262 bool DeviceManagerDx::TextureSharingWorks() {
1263 MutexAutoLock
lock(mDeviceLock
);
1264 if (!mDeviceStatus
) {
1267 return mDeviceStatus
->textureSharingWorks();
1270 bool DeviceManagerDx::CanInitializeKeyedMutexTextures() {
1271 MutexAutoLock
lock(mDeviceLock
);
1272 return mDeviceStatus
&& StaticPrefs::gfx_direct3d11_allow_keyed_mutex() &&
1273 gfxVars::AllowD3D11KeyedMutex();
1276 bool DeviceManagerDx::HasCrashyInitData() {
1277 MutexAutoLock
lock(mDeviceLock
);
1278 if (!mDeviceStatus
) {
1282 return (mDeviceStatus
->adapter().VendorId
== 0x8086 && !IsWin10OrLater());
1285 bool DeviceManagerDx::CheckRemotePresentSupport() {
1286 MOZ_ASSERT(XRE_IsParentProcess());
1288 RefPtr
<IDXGIAdapter1
> adapter
= GetDXGIAdapter();
1292 if (!D3D11Checks::DoesRemotePresentWork(adapter
)) {
1298 bool DeviceManagerDx::IsWARP() {
1299 MutexAutoLock
lock(mDeviceLock
);
1300 if (!mDeviceStatus
) {
1303 return mDeviceStatus
->isWARP();
1306 bool DeviceManagerDx::CanUseNV12() {
1307 MutexAutoLock
lock(mDeviceLock
);
1308 if (!mDeviceStatus
) {
1311 return mDeviceStatus
->formatOptions().contains(
1312 D3D11Checks::VideoFormatOption::NV12
);
1315 bool DeviceManagerDx::CanUseP010() {
1316 MutexAutoLock
lock(mDeviceLock
);
1317 if (!mDeviceStatus
) {
1320 return mDeviceStatus
->formatOptions().contains(
1321 D3D11Checks::VideoFormatOption::P010
);
1324 bool DeviceManagerDx::CanUseP016() {
1325 MutexAutoLock
lock(mDeviceLock
);
1326 if (!mDeviceStatus
) {
1329 return mDeviceStatus
->formatOptions().contains(
1330 D3D11Checks::VideoFormatOption::P016
);
1333 bool DeviceManagerDx::CanUseDComp() {
1334 MutexAutoLock
lock(mDeviceLock
);
1335 return !!mDirectCompositionDevice
;
1338 void DeviceManagerDx::InitializeDirectDraw() {
1339 MOZ_ASSERT(layers::CompositorThreadHolder::IsInCompositorThread());
1342 // Already initialized.
1346 FeatureState
& ddraw
= gfxConfig::GetFeature(Feature::DIRECT_DRAW
);
1347 if (!ddraw
.IsEnabled()) {
1351 // Check if DirectDraw is available on this system.
1352 mDirectDrawDLL
.own(LoadLibrarySystem32(L
"ddraw.dll"));
1353 if (!mDirectDrawDLL
) {
1354 ddraw
.SetFailed(FeatureStatus::Unavailable
,
1355 "DirectDraw not available on this computer",
1356 "FEATURE_FAILURE_DDRAW_LIB"_ns
);
1360 sDirectDrawCreateExFn
= (decltype(DirectDrawCreateEx
)*)GetProcAddress(
1361 mDirectDrawDLL
, "DirectDrawCreateEx");
1362 if (!sDirectDrawCreateExFn
) {
1363 ddraw
.SetFailed(FeatureStatus::Unavailable
,
1364 "DirectDraw not available on this computer",
1365 "FEATURE_FAILURE_DDRAW_LIB"_ns
);
1371 hr
= sDirectDrawCreateExFn(nullptr, getter_AddRefs(mDirectDraw
),
1372 IID_IDirectDraw7
, nullptr);
1374 MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
1375 ddraw
.SetFailed(FeatureStatus::Failed
, "Failed to create DirectDraw",
1376 "FEATURE_FAILURE_DDRAW_LIB"_ns
);
1377 gfxCriticalNote
<< "DoesCreatingDirectDrawFailed";
1381 ddraw
.SetFailed(FeatureStatus::Failed
, "Failed to create DirectDraw",
1382 "FEATURE_FAILURE_DDRAW_LIB"_ns
);
1383 gfxCriticalNote
<< "DoesCreatingDirectDrawFailed " << hexa(hr
);
1388 IDirectDraw7
* DeviceManagerDx::GetDirectDraw() { return mDirectDraw
; }
1390 void DeviceManagerDx::GetCompositorDevices(
1391 RefPtr
<ID3D11Device
>* aOutDevice
,
1392 RefPtr
<layers::DeviceAttachmentsD3D11
>* aOutAttachments
) {
1393 RefPtr
<ID3D11Device
> device
;
1395 MutexAutoLock
lock(mDeviceLock
);
1396 if (!mCompositorDevice
) {
1399 if (mCompositorAttachments
) {
1400 *aOutDevice
= mCompositorDevice
;
1401 *aOutAttachments
= mCompositorAttachments
;
1405 // Otherwise, we'll try to create attachments outside the lock.
1406 device
= mCompositorDevice
;
1409 // We save the attachments object even if it fails to initialize, so the
1410 // compositor can grab the failure ID.
1411 RefPtr
<layers::DeviceAttachmentsD3D11
> attachments
=
1412 layers::DeviceAttachmentsD3D11::Create(device
);
1414 MutexAutoLock
lock(mDeviceLock
);
1415 if (device
!= mCompositorDevice
) {
1418 mCompositorAttachments
= attachments
;
1421 *aOutDevice
= device
;
1422 *aOutAttachments
= attachments
;
1426 void DeviceManagerDx::PreloadAttachmentsOnCompositorThread() {
1427 if (!CompositorThread()) {
1431 RefPtr
<Runnable
> task
= NS_NewRunnableFunction(
1432 "DeviceManagerDx::PreloadAttachmentsOnCompositorThread", []() -> void {
1433 if (DeviceManagerDx
* dm
= DeviceManagerDx::Get()) {
1434 RefPtr
<ID3D11Device
> device
;
1435 RefPtr
<layers::DeviceAttachmentsD3D11
> attachments
;
1436 dm
->GetCompositorDevices(&device
, &attachments
);
1439 CompositorThread()->Dispatch(task
.forget());
1443 } // namespace mozilla