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/gfx/GPUParent.h"
16 #include "mozilla/gfx/GPUProcessManager.h"
17 #include "mozilla/gfx/GraphicsMessages.h"
18 #include "mozilla/gfx/Logging.h"
19 #include "mozilla/gfx/gfxVars.h"
20 #include "mozilla/layers/CompositorBridgeChild.h"
21 #include "mozilla/layers/CompositorThread.h"
22 #include "mozilla/layers/DeviceAttachmentsD3D11.h"
23 #include "mozilla/Preferences.h"
24 #include "nsPrintfCString.h"
37 using namespace mozilla::widget
;
38 using namespace mozilla::layers
;
40 StaticAutoPtr
<DeviceManagerDx
> DeviceManagerDx::sInstance
;
42 // We don't have access to the D3D11CreateDevice type in gfxWindowsPlatform.h,
43 // since it doesn't include d3d11.h, so we use a static here. It should only
44 // be used within InitializeD3D11.
45 decltype(D3D11CreateDevice
)* sD3D11CreateDeviceFn
= nullptr;
47 // It should only be used within CreateDirectCompositionDevice.
48 decltype(DCompositionCreateDevice2
)* sDcompCreateDevice2Fn
= nullptr;
49 decltype(DCompositionCreateDevice3
)* sDcompCreateDevice3Fn
= nullptr;
51 // It should only be used within CreateDCompSurfaceHandle
52 decltype(DCompositionCreateSurfaceHandle
)* sDcompCreateSurfaceHandleFn
=
55 // We don't have access to the DirectDrawCreateEx type in gfxWindowsPlatform.h,
56 // since it doesn't include ddraw.h, so we use a static here. It should only
57 // be used within InitializeDirectDrawConfig.
58 decltype(DirectDrawCreateEx
)* sDirectDrawCreateExFn
= nullptr;
61 void DeviceManagerDx::Init() { sInstance
= new DeviceManagerDx(); }
64 void DeviceManagerDx::Shutdown() { sInstance
= nullptr; }
66 DeviceManagerDx::DeviceManagerDx()
67 : mDeviceLock("gfxWindowsPlatform.mDeviceLock"),
68 mCompositorDeviceSupportsVideo(false) {
69 // Set up the D3D11 feature levels we can ask for.
70 mFeatureLevels
.AppendElement(D3D_FEATURE_LEVEL_11_1
);
71 mFeatureLevels
.AppendElement(D3D_FEATURE_LEVEL_11_0
);
72 mFeatureLevels
.AppendElement(D3D_FEATURE_LEVEL_10_1
);
73 mFeatureLevels
.AppendElement(D3D_FEATURE_LEVEL_10_0
);
74 MOZ_COUNT_CTOR(DeviceManagerDx
);
77 DeviceManagerDx::~DeviceManagerDx() { MOZ_COUNT_DTOR(DeviceManagerDx
); }
79 bool DeviceManagerDx::LoadD3D11() {
80 FeatureState
& d3d11
= gfxConfig::GetFeature(Feature::D3D11_COMPOSITING
);
81 MOZ_ASSERT(d3d11
.IsEnabled());
83 if (sD3D11CreateDeviceFn
) {
87 nsModuleHandle
module(LoadLibrarySystem32(L
"d3d11.dll"));
89 d3d11
.SetFailed(FeatureStatus::Unavailable
,
90 "Direct3D11 not available on this computer",
91 "FEATURE_FAILURE_D3D11_LIB"_ns
);
95 sD3D11CreateDeviceFn
=
96 (decltype(D3D11CreateDevice
)*)GetProcAddress(module
, "D3D11CreateDevice");
97 if (!sD3D11CreateDeviceFn
) {
98 // We should just be on Windows Vista or XP in this case.
99 d3d11
.SetFailed(FeatureStatus::Unavailable
,
100 "Direct3D11 not available on this computer",
101 "FEATURE_FAILURE_D3D11_FUNCPTR"_ns
);
105 mD3D11Module
.steal(module
);
109 bool DeviceManagerDx::LoadDcomp() {
110 MOZ_ASSERT(gfxConfig::GetFeature(Feature::D3D11_COMPOSITING
).IsEnabled());
111 MOZ_ASSERT(gfxVars::UseWebRenderANGLE());
112 MOZ_ASSERT(gfxVars::UseWebRenderDCompWin());
114 if (sDcompCreateDevice2Fn
) {
115 return true; // Already loaded.
118 nsModuleHandle
module(LoadLibrarySystem32(L
"dcomp.dll"));
123 sDcompCreateDevice2Fn
= (decltype(DCompositionCreateDevice2
)*)GetProcAddress(
124 module
, "DCompositionCreateDevice2");
125 sDcompCreateDevice3Fn
= (decltype(DCompositionCreateDevice3
)*)GetProcAddress(
126 module
, "DCompositionCreateDevice3");
127 if (!sDcompCreateDevice2Fn
) {
131 // Load optional API for external compositing
132 sDcompCreateSurfaceHandleFn
=
133 (decltype(DCompositionCreateSurfaceHandle
)*)::GetProcAddress(
134 module
, "DCompositionCreateSurfaceHandle");
136 mDcompModule
.steal(module
);
140 void DeviceManagerDx::ReleaseD3D11() {
141 MOZ_ASSERT(!mCompositorDevice
);
142 MOZ_ASSERT(!mContentDevice
);
143 MOZ_ASSERT(!mVRDevice
);
144 MOZ_ASSERT(!mDecoderDevice
);
146 mD3D11Module
.reset();
147 sD3D11CreateDeviceFn
= nullptr;
150 nsTArray
<DXGI_OUTPUT_DESC1
> DeviceManagerDx::EnumerateOutputs() {
151 RefPtr
<IDXGIAdapter
> adapter
= GetDXGIAdapter();
154 NS_WARNING("Failed to acquire a DXGI adapter for enumerating outputs.");
155 return nsTArray
<DXGI_OUTPUT_DESC1
>();
158 nsTArray
<DXGI_OUTPUT_DESC1
> outputs
;
159 for (UINT i
= 0;; ++i
) {
160 RefPtr
<IDXGIOutput
> output
= nullptr;
161 if (FAILED(adapter
->EnumOutputs(i
, getter_AddRefs(output
)))) {
165 RefPtr
<IDXGIOutput6
> output6
= nullptr;
166 if (FAILED(output
->QueryInterface(__uuidof(IDXGIOutput6
),
167 getter_AddRefs(output6
)))) {
171 DXGI_OUTPUT_DESC1 desc
;
172 if (FAILED(output6
->GetDesc1(&desc
))) {
176 outputs
.AppendElement(desc
);
181 bool DeviceManagerDx::GetOutputFromMonitor(HMONITOR monitor
,
182 RefPtr
<IDXGIOutput
>* aOutOutput
) {
183 RefPtr
<IDXGIAdapter
> adapter
= GetDXGIAdapter();
186 NS_WARNING("Failed to acquire a DXGI adapter for GetOutputFromMonitor.");
190 for (UINT i
= 0;; ++i
) {
191 RefPtr
<IDXGIOutput
> output
= nullptr;
192 if (FAILED(adapter
->EnumOutputs(i
, getter_AddRefs(output
)))) {
196 DXGI_OUTPUT_DESC desc
;
197 if (FAILED(output
->GetDesc(&desc
))) {
201 if (desc
.Monitor
== monitor
) {
202 *aOutOutput
= output
;
209 void DeviceManagerDx::CheckHardwareStretchingSupport(HwStretchingSupport
& aRv
) {
210 RefPtr
<IDXGIAdapter
> adapter
= GetDXGIAdapter();
214 "Failed to acquire a DXGI adapter for checking hardware stretching "
220 for (UINT i
= 0;; ++i
) {
221 RefPtr
<IDXGIOutput
> output
= nullptr;
222 HRESULT result
= adapter
->EnumOutputs(i
, getter_AddRefs(output
));
223 if (result
== DXGI_ERROR_NOT_FOUND
) {
224 // No more outputs to check.
228 if (FAILED(result
)) {
233 RefPtr
<IDXGIOutput6
> output6
= nullptr;
234 if (FAILED(output
->QueryInterface(__uuidof(IDXGIOutput6
),
235 getter_AddRefs(output6
)))) {
241 if (FAILED(output6
->CheckHardwareCompositionSupport(&flags
))) {
246 bool fullScreen
= flags
& DXGI_HARDWARE_COMPOSITION_SUPPORT_FLAG_FULLSCREEN
;
247 bool window
= flags
& DXGI_HARDWARE_COMPOSITION_SUPPORT_FLAG_WINDOWED
;
248 if (fullScreen
&& window
) {
250 } else if (fullScreen
) {
251 ++aRv
.mFullScreenOnly
;
261 static inline bool ProcessOwnsCompositor() {
262 return XRE_GetProcessType() == GeckoProcessType_GPU
||
263 XRE_GetProcessType() == GeckoProcessType_VR
||
264 (XRE_IsParentProcess() && !gfxConfig::IsEnabled(Feature::GPU_PROCESS
));
268 bool DeviceManagerDx::CreateCompositorDevices() {
269 MutexAutoLock
lock(mDeviceLock
);
270 return CreateCompositorDevicesLocked();
273 bool DeviceManagerDx::CreateCompositorDevicesLocked() {
274 MOZ_ASSERT(ProcessOwnsCompositor());
276 FeatureState
& d3d11
= gfxConfig::GetFeature(Feature::D3D11_COMPOSITING
);
277 MOZ_ASSERT(d3d11
.IsEnabled());
279 if (int32_t sleepSec
=
280 StaticPrefs::gfx_direct3d11_sleep_on_create_device_AtStartup()) {
281 printf_stderr("Attach to PID: %lu\n", GetCurrentProcessId());
282 Sleep(sleepSec
* 1000);
289 CreateCompositorDevice(d3d11
);
291 if (!d3d11
.IsEnabled()) {
292 MOZ_ASSERT(!mCompositorDevice
);
298 // We leak these everywhere and we need them our entire runtime anyway, let's
299 // leak it here as well. We keep the pointer to sD3D11CreateDeviceFn around
300 // as well for D2D1 and device resets.
301 mD3D11Module
.disown();
303 MOZ_ASSERT(mCompositorDevice
);
304 if (!d3d11
.IsEnabled()) {
308 // When WR is used, do not preload attachments for D3D11 Non-WR compositor.
310 // Fallback from WR to D3D11 Non-WR compositor without re-creating gpu process
311 // could happen when WR causes error. In this case, the attachments are loaded
313 if (gfx::gfxVars::UseSoftwareWebRender()) {
314 PreloadAttachmentsOnCompositorThread();
320 bool DeviceManagerDx::CreateVRDevice() {
321 MOZ_ASSERT(ProcessOwnsCompositor());
327 if (!gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING
)) {
328 NS_WARNING("Direct3D11 Compositing required for VR");
336 RefPtr
<IDXGIAdapter1
> adapter
= GetDXGIAdapterLocked();
338 NS_WARNING("Failed to acquire a DXGI adapter for VR");
342 UINT flags
= D3D11_CREATE_DEVICE_BGRA_SUPPORT
;
345 if (!CreateDevice(adapter
, D3D_DRIVER_TYPE_UNKNOWN
, flags
, hr
, mVRDevice
)) {
346 gfxCriticalError() << "Crash during D3D11 device creation for VR";
350 if (FAILED(hr
) || !mVRDevice
) {
351 NS_WARNING("Failed to acquire a D3D11 device for VR");
358 bool DeviceManagerDx::CreateCanvasDevice() {
359 MutexAutoLock
lock(mDeviceLock
);
360 return CreateCanvasDeviceLocked();
363 bool DeviceManagerDx::CreateCanvasDeviceLocked() {
364 MOZ_ASSERT(ProcessOwnsCompositor());
374 RefPtr
<IDXGIAdapter1
> adapter
= GetDXGIAdapterLocked();
376 NS_WARNING("Failed to acquire a DXGI adapter for Canvas");
380 UINT flags
= D3D11_CREATE_DEVICE_BGRA_SUPPORT
;
383 if (!CreateDevice(adapter
, D3D_DRIVER_TYPE_UNKNOWN
, flags
, hr
,
385 gfxCriticalError() << "Crash during D3D11 device creation for Canvas";
390 gfx_direct2d_target_independent_rasterization_disabled_AtStartup()) {
391 int creationFlags
= 0x2; // disable target independent rasterization
392 const GUID D2D_INTERNAL_DEVICE_CREATION_OPTIONS
= {
396 {0x84, 0x42, 0x40, 0x43, 0xe0, 0xb0, 0x94, 0x95}};
397 mCanvasDevice
->SetPrivateData(D2D_INTERNAL_DEVICE_CREATION_OPTIONS
,
398 sizeof(creationFlags
), &creationFlags
);
401 if (FAILED(hr
) || !mCanvasDevice
) {
402 NS_WARNING("Failed to acquire a D3D11 device for Canvas");
406 if (!D3D11Checks::DoesTextureSharingWork(mCanvasDevice
)) {
407 mCanvasDevice
= nullptr;
411 if (XRE_IsGPUProcess()) {
412 Factory::SetDirect3D11Device(mCanvasDevice
);
418 void DeviceManagerDx::CreateDirectCompositionDevice() {
419 MutexAutoLock
lock(mDeviceLock
);
420 CreateDirectCompositionDeviceLocked();
423 void DeviceManagerDx::CreateDirectCompositionDeviceLocked() {
424 if (!gfxVars::UseWebRenderDCompWin()) {
428 if (!mCompositorDevice
) {
436 RefPtr
<IDXGIDevice
> dxgiDevice
;
437 if (mCompositorDevice
->QueryInterface(
438 IID_PPV_ARGS((IDXGIDevice
**)getter_AddRefs(dxgiDevice
))) != S_OK
) {
443 RefPtr
<IDCompositionDesktopDevice
> desktopDevice
;
445 hr
= sDcompCreateDevice3Fn(
448 (IDCompositionDesktopDevice
**)getter_AddRefs(desktopDevice
)));
449 if (!desktopDevice
) {
450 hr
= sDcompCreateDevice2Fn(
453 (IDCompositionDesktopDevice
**)getter_AddRefs(desktopDevice
)));
456 MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) { return; }
458 if (!SUCCEEDED(hr
)) {
462 RefPtr
<IDCompositionDevice2
> compositionDevice
;
463 if (desktopDevice
->QueryInterface(IID_PPV_ARGS(
464 (IDCompositionDevice2
**)getter_AddRefs(compositionDevice
))) != S_OK
) {
468 mDirectCompositionDevice
= compositionDevice
;
472 HANDLE
DeviceManagerDx::CreateDCompSurfaceHandle() {
473 if (!sDcompCreateSurfaceHandleFn
) {
478 HRESULT hr
= sDcompCreateSurfaceHandleFn(COMPOSITIONOBJECT_ALL_ACCESS
,
487 void DeviceManagerDx::ImportDeviceInfo(const D3D11DeviceStatus
& aDeviceStatus
) {
488 MOZ_ASSERT(!ProcessOwnsCompositor());
490 MutexAutoLock
lock(mDeviceLock
);
491 mDeviceStatus
= Some(aDeviceStatus
);
494 bool DeviceManagerDx::ExportDeviceInfo(D3D11DeviceStatus
* aOut
) {
495 MutexAutoLock
lock(mDeviceLock
);
497 *aOut
= mDeviceStatus
.value();
504 void DeviceManagerDx::CreateContentDevices() {
505 MutexAutoLock
lock(mDeviceLock
);
506 CreateContentDevicesLocked();
509 void DeviceManagerDx::CreateContentDevicesLocked() {
510 MOZ_ASSERT(gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING
));
516 // We should have been assigned a DeviceStatus from the parent process,
517 // GPU process, or the same process if using in-process compositing.
518 MOZ_ASSERT(mDeviceStatus
);
520 if (CreateContentDevice() == FeatureStatus::CrashedInHandler
) {
521 DisableD3D11AfterCrash();
525 already_AddRefed
<IDXGIAdapter1
> DeviceManagerDx::GetDXGIAdapter() {
526 MutexAutoLock
lock(mDeviceLock
);
527 return do_AddRef(GetDXGIAdapterLocked());
530 IDXGIAdapter1
* DeviceManagerDx::GetDXGIAdapterLocked() {
535 nsModuleHandle
dxgiModule(LoadLibrarySystem32(L
"dxgi.dll"));
536 decltype(CreateDXGIFactory1
)* createDXGIFactory1
=
537 (decltype(CreateDXGIFactory1
)*)GetProcAddress(dxgiModule
,
538 "CreateDXGIFactory1");
539 if (!createDXGIFactory1
) {
542 static const auto fCreateDXGIFactory2
=
543 (decltype(CreateDXGIFactory2
)*)GetProcAddress(dxgiModule
,
544 "CreateDXGIFactory2");
546 // Try to use a DXGI 1.1 adapter in order to share resources
548 RefPtr
<IDXGIFactory1
> factory1
;
549 if (StaticPrefs::gfx_direct3d11_enable_debug_layer_AtStartup()) {
550 RefPtr
<IDXGIFactory2
> factory2
;
551 if (fCreateDXGIFactory2
) {
552 auto hr
= fCreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG
,
553 __uuidof(IDXGIFactory2
),
554 getter_AddRefs(factory2
));
555 MOZ_ALWAYS_TRUE(!FAILED(hr
));
558 "fCreateDXGIFactory2 not loaded, cannot create debug IDXGIFactory2.");
564 createDXGIFactory1(__uuidof(IDXGIFactory1
), getter_AddRefs(factory1
));
565 if (FAILED(hr
) || !factory1
) {
566 // This seems to happen with some people running the iZ3D driver.
567 // They won't get acceleration.
572 if (!mDeviceStatus
) {
573 // If we haven't created a device yet, and have no existing device status,
574 // then this must be the compositor device. Pick the first adapter we can.
575 if (FAILED(factory1
->EnumAdapters1(0, getter_AddRefs(mAdapter
)))) {
579 // In the UI and GPU process, we clear mDeviceStatus on device reset, so we
580 // should never reach here. Furthermore, the UI process does not create
581 // devices when using a GPU process.
583 // So, this should only ever get called on the content process or RDD
585 MOZ_ASSERT(XRE_IsContentProcess() || XRE_IsRDDProcess());
587 // In the child process, we search for the adapter that matches the parent
588 // process. The first adapter can be mismatched on dual-GPU systems.
589 for (UINT index
= 0;; index
++) {
590 RefPtr
<IDXGIAdapter1
> adapter
;
591 if (FAILED(factory1
->EnumAdapters1(index
, getter_AddRefs(adapter
)))) {
595 const DxgiAdapterDesc
& preferred
= mDeviceStatus
->adapter();
597 DXGI_ADAPTER_DESC desc
;
598 if (SUCCEEDED(adapter
->GetDesc(&desc
)) &&
599 desc
.AdapterLuid
.HighPart
== preferred
.AdapterLuid
.HighPart
&&
600 desc
.AdapterLuid
.LowPart
== preferred
.AdapterLuid
.LowPart
&&
601 desc
.VendorId
== preferred
.VendorId
&&
602 desc
.DeviceId
== preferred
.DeviceId
) {
603 mAdapter
= adapter
.forget();
613 // We leak this module everywhere, we might as well do so here as well.
618 bool DeviceManagerDx::CreateCompositorDeviceHelper(
619 FeatureState
& aD3d11
, IDXGIAdapter1
* aAdapter
, bool aAttemptVideoSupport
,
620 RefPtr
<ID3D11Device
>& aOutDevice
) {
621 // Check if a failure was injected for testing.
622 if (StaticPrefs::gfx_testing_device_fail()) {
623 aD3d11
.SetFailed(FeatureStatus::Failed
,
624 "Direct3D11 device failure simulated by preference",
625 "FEATURE_FAILURE_D3D11_SIM"_ns
);
629 UINT flags
= D3D11_CREATE_DEVICE_BGRA_SUPPORT
;
631 DXGI_ADAPTER_DESC desc
;
632 aAdapter
->GetDesc(&desc
);
633 if (desc
.VendorId
!= 0x1414) {
634 // 0x1414 is Microsoft (e.g. WARP)
635 // When not using WARP, use
636 // D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS to prevent
637 // bug 1092260. IE 11 also uses this flag.
638 flags
|= D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
;
641 if (aAttemptVideoSupport
) {
642 flags
|= D3D11_CREATE_DEVICE_VIDEO_SUPPORT
;
646 RefPtr
<ID3D11Device
> device
;
647 if (!CreateDevice(aAdapter
, D3D_DRIVER_TYPE_UNKNOWN
, flags
, hr
, device
)) {
648 if (!aAttemptVideoSupport
) {
649 gfxCriticalError() << "Crash during D3D11 device creation";
650 aD3d11
.SetFailed(FeatureStatus::CrashedInHandler
,
651 "Crashed trying to acquire a D3D11 device",
652 "FEATURE_FAILURE_D3D11_DEVICE1"_ns
);
657 if (FAILED(hr
) || !device
) {
658 if (!aAttemptVideoSupport
) {
659 aD3d11
.SetFailed(FeatureStatus::Failed
,
660 "Failed to acquire a D3D11 device",
661 "FEATURE_FAILURE_D3D11_DEVICE2"_ns
);
665 if (!D3D11Checks::DoesDeviceWork()) {
666 if (!aAttemptVideoSupport
) {
667 aD3d11
.SetFailed(FeatureStatus::Broken
,
668 "Direct3D11 device was determined to be broken",
669 "FEATURE_FAILURE_D3D11_BROKEN"_ns
);
678 // Note that it's enough for us to just use a counter for a unique ID,
679 // even though the counter isn't synchronized between processes. If we
680 // start in the GPU process and wind up in the parent process, the
681 // whole graphics stack is blown away anyway. But just in case, we
682 // make gpu process IDs negative and parent process IDs positive.
683 static inline int32_t GetNextDeviceCounter() {
684 static int32_t sDeviceCounter
= 0;
685 return XRE_IsGPUProcess() ? --sDeviceCounter
: ++sDeviceCounter
;
688 void DeviceManagerDx::CreateCompositorDevice(FeatureState
& d3d11
) {
689 if (StaticPrefs::layers_d3d11_force_warp_AtStartup()) {
690 CreateWARPCompositorDevice();
694 RefPtr
<IDXGIAdapter1
> adapter
= GetDXGIAdapterLocked();
696 d3d11
.SetFailed(FeatureStatus::Unavailable
,
697 "Failed to acquire a DXGI adapter",
698 "FEATURE_FAILURE_D3D11_DXGI"_ns
);
702 if (XRE_IsGPUProcess() && !D3D11Checks::DoesRemotePresentWork(adapter
)) {
703 d3d11
.SetFailed(FeatureStatus::Unavailable
,
704 "DXGI does not support out-of-process presentation",
705 "FEATURE_FAILURE_D3D11_REMOTE_PRESENT"_ns
);
709 RefPtr
<ID3D11Device
> device
;
710 if (!CreateCompositorDeviceHelper(d3d11
, adapter
, true, device
)) {
711 // Try again without video support and record that it failed.
712 mCompositorDeviceSupportsVideo
= false;
713 if (!CreateCompositorDeviceHelper(d3d11
, adapter
, false, device
)) {
717 mCompositorDeviceSupportsVideo
= true;
720 // Only test this when not using WARP since it can fail and cause
721 // GetDeviceRemovedReason to return weird values.
722 bool textureSharingWorks
= D3D11Checks::DoesTextureSharingWork(device
);
724 DXGI_ADAPTER_DESC desc
;
726 adapter
->GetDesc(&desc
);
728 if (!textureSharingWorks
) {
729 gfxConfig::SetFailed(Feature::D3D11_HW_ANGLE
, FeatureStatus::Broken
,
730 "Texture sharing doesn't work",
731 "FEATURE_FAILURE_HW_ANGLE_NEEDS_TEXTURE_SHARING"_ns
);
733 if (D3D11Checks::DoesRenderTargetViewNeedRecreating(device
)) {
734 gfxConfig::SetFailed(Feature::D3D11_HW_ANGLE
, FeatureStatus::Broken
,
735 "RenderTargetViews need recreating",
736 "FEATURE_FAILURE_HW_ANGLE_NEEDS_RTV_RECREATION"_ns
);
738 if (XRE_IsParentProcess()) {
739 // It seems like this may only happen when we're using the NVIDIA gpu
740 D3D11Checks::WarnOnAdapterMismatch(device
);
743 RefPtr
<ID3D10Multithread
> multi
;
744 HRESULT hr
= device
->QueryInterface(__uuidof(ID3D10Multithread
),
745 getter_AddRefs(multi
));
746 if (SUCCEEDED(hr
) && multi
) {
747 multi
->SetMultithreadProtected(TRUE
);
750 uint32_t featureLevel
= device
->GetFeatureLevel();
751 auto formatOptions
= D3D11Checks::FormatOptions(device
);
752 mCompositorDevice
= device
;
754 int32_t sequenceNumber
= GetNextDeviceCounter();
755 mDeviceStatus
= Some(D3D11DeviceStatus(
756 false, textureSharingWorks
, featureLevel
, DxgiAdapterDesc::From(desc
),
757 sequenceNumber
, formatOptions
));
758 mCompositorDevice
->SetExceptionMode(0);
761 bool DeviceManagerDx::CreateDevice(IDXGIAdapter
* aAdapter
,
762 D3D_DRIVER_TYPE aDriverType
, UINT aFlags
,
764 RefPtr
<ID3D11Device
>& aOutDevice
) {
765 if (StaticPrefs::gfx_direct3d11_enable_debug_layer_AtStartup() ||
766 StaticPrefs::gfx_direct3d11_break_on_error_AtStartup()) {
767 aFlags
|= D3D11_CREATE_DEVICE_DEBUG
;
771 aResOut
= sD3D11CreateDeviceFn(
772 aAdapter
, aDriverType
, nullptr, aFlags
, mFeatureLevels
.Elements(),
773 mFeatureLevels
.Length(), D3D11_SDK_VERSION
, getter_AddRefs(aOutDevice
),
776 MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) { return false; }
778 if (StaticPrefs::gfx_direct3d11_break_on_error_AtStartup()) {
780 if (!aOutDevice
) break;
782 RefPtr
<ID3D11Debug
> debug
;
783 if (!SUCCEEDED(aOutDevice
->QueryInterface(__uuidof(ID3D11Debug
),
784 getter_AddRefs(debug
))))
787 RefPtr
<ID3D11InfoQueue
> infoQueue
;
788 if (!SUCCEEDED(debug
->QueryInterface(__uuidof(ID3D11InfoQueue
),
789 getter_AddRefs(infoQueue
))))
792 D3D11_INFO_QUEUE_FILTER filter
;
795 // Disable warnings caused by Advanced Layers that are known and not
797 D3D11_MESSAGE_ID blockIDs
[] = {
798 D3D11_MESSAGE_ID_DEVICE_DRAW_CONSTANT_BUFFER_TOO_SMALL
};
799 filter
.DenyList
.NumIDs
= MOZ_ARRAY_LENGTH(blockIDs
);
800 filter
.DenyList
.pIDList
= blockIDs
;
801 infoQueue
->PushStorageFilter(&filter
);
803 infoQueue
->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION
, true);
804 infoQueue
->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR
, true);
805 infoQueue
->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_WARNING
, true);
812 void DeviceManagerDx::CreateWARPCompositorDevice() {
813 ScopedGfxFeatureReporter
reporterWARP(
814 "D3D11-WARP", StaticPrefs::layers_d3d11_force_warp_AtStartup());
815 FeatureState
& d3d11
= gfxConfig::GetFeature(Feature::D3D11_COMPOSITING
);
818 RefPtr
<ID3D11Device
> device
;
820 // Use D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
821 // to prevent bug 1092260. IE 11 also uses this flag.
822 UINT flags
= D3D11_CREATE_DEVICE_BGRA_SUPPORT
;
823 if (!CreateDevice(nullptr, D3D_DRIVER_TYPE_WARP
, flags
, hr
, device
)) {
824 gfxCriticalError() << "Exception occurred initializing WARP D3D11 device!";
825 d3d11
.SetFailed(FeatureStatus::CrashedInHandler
,
826 "Crashed creating a D3D11 WARP device",
827 "FEATURE_FAILURE_D3D11_WARP_DEVICE"_ns
);
830 if (FAILED(hr
) || !device
) {
831 // This should always succeed... in theory.
832 gfxCriticalError() << "Failed to initialize WARP D3D11 device! "
834 d3d11
.SetFailed(FeatureStatus::Failed
,
835 "Failed to create a D3D11 WARP device",
836 "FEATURE_FAILURE_D3D11_WARP_DEVICE2"_ns
);
840 bool textureSharingWorks
= D3D11Checks::DoesTextureSharingWork(device
);
842 RefPtr
<ID3D10Multithread
> multi
;
843 hr
= device
->QueryInterface(__uuidof(ID3D10Multithread
),
844 getter_AddRefs(multi
));
845 if (SUCCEEDED(hr
) && multi
) {
846 multi
->SetMultithreadProtected(TRUE
);
849 DXGI_ADAPTER_DESC desc
;
850 D3D11Checks::GetDxgiDesc(device
, &desc
);
852 int featureLevel
= device
->GetFeatureLevel();
854 auto formatOptions
= D3D11Checks::FormatOptions(device
);
855 mCompositorDevice
= device
;
857 int32_t sequenceNumber
= GetNextDeviceCounter();
858 mDeviceStatus
= Some(D3D11DeviceStatus(
859 true, textureSharingWorks
, featureLevel
, DxgiAdapterDesc::From(desc
),
860 sequenceNumber
, formatOptions
));
861 mCompositorDevice
->SetExceptionMode(0);
863 reporterWARP
.SetSuccessful();
866 FeatureStatus
DeviceManagerDx::CreateContentDevice() {
867 RefPtr
<IDXGIAdapter1
> adapter
;
868 if (!mDeviceStatus
->isWARP()) {
869 adapter
= GetDXGIAdapterLocked();
871 gfxCriticalNote
<< "Could not get a DXGI adapter";
872 return FeatureStatus::Unavailable
;
877 RefPtr
<ID3D11Device
> device
;
879 UINT flags
= D3D11_CREATE_DEVICE_BGRA_SUPPORT
;
880 D3D_DRIVER_TYPE type
=
881 mDeviceStatus
->isWARP() ? D3D_DRIVER_TYPE_WARP
: D3D_DRIVER_TYPE_UNKNOWN
;
882 if (!CreateDevice(adapter
, type
, flags
, hr
, device
)) {
884 << "Recovered from crash while creating a D3D11 content device";
885 gfxWindowsPlatform::RecordContentDeviceFailure(
886 TelemetryDeviceCode::Content
);
887 return FeatureStatus::CrashedInHandler
;
890 if (FAILED(hr
) || !device
) {
891 gfxCriticalNote
<< "Failed to create a D3D11 content device: " << hexa(hr
);
892 gfxWindowsPlatform::RecordContentDeviceFailure(
893 TelemetryDeviceCode::Content
);
894 return FeatureStatus::Failed
;
897 // InitializeD2D() will abort early if the compositor device did not support
898 // texture sharing. If we're in the content process, we can't rely on the
899 // parent device alone: some systems have dual GPUs that are capable of
900 // binding the parent and child processes to different GPUs. As a safety net,
901 // we re-check texture sharing against the newly created D3D11 content device.
902 // If it fails, we won't use Direct2D.
903 if (XRE_IsContentProcess()) {
904 if (!D3D11Checks::DoesTextureSharingWork(device
)) {
905 return FeatureStatus::Failed
;
908 DebugOnly
<bool> ok
= ContentAdapterIsParentAdapter(device
);
912 mContentDevice
= device
;
913 mContentDevice
->SetExceptionMode(0);
915 RefPtr
<ID3D10Multithread
> multi
;
916 hr
= mContentDevice
->QueryInterface(__uuidof(ID3D10Multithread
),
917 getter_AddRefs(multi
));
918 if (SUCCEEDED(hr
) && multi
) {
919 multi
->SetMultithreadProtected(TRUE
);
921 return FeatureStatus::Available
;
924 RefPtr
<ID3D11Device
> DeviceManagerDx::CreateDecoderDevice(
925 bool aHardwareWebRender
) {
926 MutexAutoLock
lock(mDeviceLock
);
928 if (!mDeviceStatus
) {
932 bool isAMD
= mDeviceStatus
->adapter().VendorId
== 0x1002;
933 bool reuseDevice
= false;
934 if (gfxVars::ReuseDecoderDevice()) {
938 gfxCriticalNoteOnce
<< "Always have to reuse decoder device on AMD";
942 // Use mCompositorDevice for decoder device only for hardware WebRender.
943 if (aHardwareWebRender
&& mCompositorDevice
&&
944 mCompositorDeviceSupportsVideo
&& !mDecoderDevice
) {
945 mDecoderDevice
= mCompositorDevice
;
947 RefPtr
<ID3D10Multithread
> multi
;
948 mDecoderDevice
->QueryInterface(__uuidof(ID3D10Multithread
),
949 getter_AddRefs(multi
));
951 MOZ_ASSERT(multi
->GetMultithreadProtected());
955 if (mDecoderDevice
) {
956 RefPtr
<ID3D11Device
> dev
= mDecoderDevice
;
961 if (!sD3D11CreateDeviceFn
) {
962 // We should just be on Windows Vista or XP in this case.
966 RefPtr
<IDXGIAdapter1
> adapter
= GetDXGIAdapterLocked();
972 RefPtr
<ID3D11Device
> device
;
974 UINT flags
= D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
|
975 D3D11_CREATE_DEVICE_VIDEO_SUPPORT
;
976 if (!CreateDevice(adapter
, D3D_DRIVER_TYPE_UNKNOWN
, flags
, hr
, device
)) {
979 if (FAILED(hr
) || !device
|| !D3D11Checks::DoesDeviceWork()) {
983 RefPtr
<ID3D10Multithread
> multi
;
984 device
->QueryInterface(__uuidof(ID3D10Multithread
), getter_AddRefs(multi
));
986 multi
->SetMultithreadProtected(TRUE
);
989 mDecoderDevice
= device
;
994 // ID3D11DeviceChild, IDXGIObject and ID3D11Device implement SetPrivateData with
995 // the exact same parameters.
996 template <typename T
>
997 static HRESULT
SetDebugName(T
* d3d11Object
, const char* debugString
) {
998 return d3d11Object
->SetPrivateData(WKPDID_D3DDebugObjectName
,
999 strlen(debugString
), debugString
);
1002 RefPtr
<ID3D11Device
> DeviceManagerDx::CreateMediaEngineDevice() {
1003 MutexAutoLock
lock(mDeviceLock
);
1009 RefPtr
<ID3D11Device
> device
;
1010 UINT flags
= D3D11_CREATE_DEVICE_VIDEO_SUPPORT
|
1011 D3D11_CREATE_DEVICE_BGRA_SUPPORT
|
1012 D3D11_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS
;
1013 if (!CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE
, flags
, hr
, device
)) {
1016 if (FAILED(hr
) || !device
|| !D3D11Checks::DoesDeviceWork()) {
1019 Unused
<< SetDebugName(device
.get(), "MFMediaEngineDevice");
1021 RefPtr
<ID3D10Multithread
> multi
;
1022 device
->QueryInterface(__uuidof(ID3D10Multithread
), getter_AddRefs(multi
));
1024 multi
->SetMultithreadProtected(TRUE
);
1029 void DeviceManagerDx::ResetDevices() {
1030 MutexAutoLock
lock(mDeviceLock
);
1031 ResetDevicesLocked();
1034 void DeviceManagerDx::ResetDevicesLocked() {
1036 mCompositorAttachments
= nullptr;
1037 mCompositorDevice
= nullptr;
1038 mContentDevice
= nullptr;
1039 mCanvasDevice
= nullptr;
1040 mImageDevice
= nullptr;
1041 mVRDevice
= nullptr;
1042 mDecoderDevice
= nullptr;
1043 mDirectCompositionDevice
= nullptr;
1044 mDeviceStatus
= Nothing();
1045 mDeviceResetReason
= Nothing();
1046 Factory::SetDirect3D11Device(nullptr);
1049 bool DeviceManagerDx::MaybeResetAndReacquireDevices() {
1050 MutexAutoLock
lock(mDeviceLock
);
1052 DeviceResetReason resetReason
;
1053 if (!HasDeviceResetLocked(&resetReason
)) {
1057 GPUProcessManager::RecordDeviceReset(resetReason
);
1059 bool createCompositorDevice
= !!mCompositorDevice
;
1060 bool createContentDevice
= !!mContentDevice
;
1061 bool createCanvasDevice
= !!mCanvasDevice
;
1062 bool createDirectCompositionDevice
= !!mDirectCompositionDevice
;
1064 ResetDevicesLocked();
1066 if (createCompositorDevice
&& !CreateCompositorDevicesLocked()) {
1067 // Just stop, don't try anything more
1070 if (createContentDevice
) {
1071 CreateContentDevicesLocked();
1073 if (createCanvasDevice
) {
1074 CreateCanvasDeviceLocked();
1076 if (createDirectCompositionDevice
) {
1077 CreateDirectCompositionDeviceLocked();
1083 bool DeviceManagerDx::ContentAdapterIsParentAdapter(ID3D11Device
* device
) {
1084 DXGI_ADAPTER_DESC desc
;
1085 if (!D3D11Checks::GetDxgiDesc(device
, &desc
)) {
1086 gfxCriticalNote
<< "Could not query device DXGI adapter info";
1090 const DxgiAdapterDesc
& preferred
= mDeviceStatus
->adapter();
1092 if (desc
.VendorId
!= preferred
.VendorId
||
1093 desc
.DeviceId
!= preferred
.DeviceId
||
1094 desc
.SubSysId
!= preferred
.SubSysId
||
1095 desc
.AdapterLuid
.HighPart
!= preferred
.AdapterLuid
.HighPart
||
1096 desc
.AdapterLuid
.LowPart
!= preferred
.AdapterLuid
.LowPart
) {
1097 gfxCriticalNote
<< "VendorIDMismatch P " << hexa(preferred
.VendorId
) << " "
1098 << hexa(desc
.VendorId
);
1105 static DeviceResetReason
HResultToResetReason(HRESULT hr
) {
1107 case DXGI_ERROR_DEVICE_HUNG
:
1108 return DeviceResetReason::HUNG
;
1109 case DXGI_ERROR_DEVICE_REMOVED
:
1110 return DeviceResetReason::REMOVED
;
1111 case DXGI_ERROR_DEVICE_RESET
:
1112 return DeviceResetReason::RESET
;
1113 case DXGI_ERROR_DRIVER_INTERNAL_ERROR
:
1114 return DeviceResetReason::DRIVER_ERROR
;
1115 case DXGI_ERROR_INVALID_CALL
:
1116 return DeviceResetReason::INVALID_CALL
;
1118 return DeviceResetReason::OUT_OF_MEMORY
;
1122 return DeviceResetReason::OTHER
;
1125 bool DeviceManagerDx::HasDeviceReset(DeviceResetReason
* aOutReason
) {
1126 MutexAutoLock
lock(mDeviceLock
);
1127 return HasDeviceResetLocked(aOutReason
);
1130 bool DeviceManagerDx::HasDeviceResetLocked(DeviceResetReason
* aOutReason
) {
1131 if (mDeviceResetReason
) {
1133 *aOutReason
= mDeviceResetReason
.value();
1138 DeviceResetReason reason
;
1139 if (GetAnyDeviceRemovedReason(&reason
)) {
1140 mDeviceResetReason
= Some(reason
);
1142 *aOutReason
= reason
;
1150 static inline bool DidDeviceReset(const RefPtr
<ID3D11Device
>& aDevice
,
1151 DeviceResetReason
* aOutReason
) {
1155 HRESULT hr
= aDevice
->GetDeviceRemovedReason();
1160 *aOutReason
= HResultToResetReason(hr
);
1164 bool DeviceManagerDx::GetAnyDeviceRemovedReason(DeviceResetReason
* aOutReason
) {
1165 if (DidDeviceReset(mCompositorDevice
, aOutReason
) ||
1166 DidDeviceReset(mContentDevice
, aOutReason
) ||
1167 DidDeviceReset(mCanvasDevice
, aOutReason
)) {
1171 if (XRE_IsParentProcess() && NS_IsMainThread() &&
1172 StaticPrefs::gfx_testing_device_reset()) {
1173 Preferences::SetInt("gfx.testing.device-reset", 0);
1174 *aOutReason
= DeviceResetReason::FORCED_RESET
;
1181 void DeviceManagerDx::ForceDeviceReset(ForcedDeviceResetReason aReason
) {
1182 Telemetry::Accumulate(Telemetry::FORCED_DEVICE_RESET_REASON
,
1185 MutexAutoLock
lock(mDeviceLock
);
1186 if (!mDeviceResetReason
) {
1187 mDeviceResetReason
= Some(DeviceResetReason::FORCED_RESET
);
1192 void DeviceManagerDx::DisableD3D11AfterCrash() {
1193 gfxConfig::Disable(Feature::D3D11_COMPOSITING
,
1194 FeatureStatus::CrashedInHandler
,
1195 "Crashed while acquiring a Direct3D11 device",
1196 "FEATURE_FAILURE_D3D11_CRASH"_ns
);
1200 RefPtr
<ID3D11Device
> DeviceManagerDx::GetCompositorDevice() {
1201 /// ID3D11Device is thread-safe. We need the lock to read the
1202 /// mDeviceLockPointer, but manipulating the pointee outside of the lock is
1204 /// https://learn.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-render-multi-thread-intro
1205 MutexAutoLock
lock(mDeviceLock
);
1206 return mCompositorDevice
;
1209 RefPtr
<ID3D11Device
> DeviceManagerDx::GetContentDevice() {
1210 MOZ_ASSERT(XRE_IsGPUProcess() ||
1211 gfxPlatform::GetPlatform()->DevicesInitialized());
1213 MutexAutoLock
lock(mDeviceLock
);
1214 return mContentDevice
;
1217 RefPtr
<ID3D11Device
> DeviceManagerDx::GetImageDevice() {
1218 MutexAutoLock
lock(mDeviceLock
);
1220 return mImageDevice
;
1223 RefPtr
<ID3D11Device
> device
= mContentDevice
;
1225 device
= mCompositorDevice
;
1232 RefPtr
<ID3D10Multithread
> multi
;
1234 device
->QueryInterface((ID3D10Multithread
**)getter_AddRefs(multi
));
1235 if (FAILED(hr
) || !multi
) {
1236 gfxWarning() << "Multithread safety interface not supported. " << hr
;
1239 MOZ_ASSERT(multi
->GetMultithreadProtected());
1242 mImageDevice
= device
;
1244 return mImageDevice
;
1247 RefPtr
<ID3D11Device
> DeviceManagerDx::GetVRDevice() {
1248 MutexAutoLock
lock(mDeviceLock
);
1255 RefPtr
<ID3D11Device
> DeviceManagerDx::GetCanvasDevice() {
1256 MutexAutoLock
lock(mDeviceLock
);
1257 return mCanvasDevice
;
1260 RefPtr
<IDCompositionDevice2
> DeviceManagerDx::GetDirectCompositionDevice() {
1261 MutexAutoLock
lock(mDeviceLock
);
1262 return mDirectCompositionDevice
;
1265 unsigned DeviceManagerDx::GetCompositorFeatureLevel() const {
1266 MutexAutoLock
lock(mDeviceLock
);
1267 if (!mDeviceStatus
) {
1270 return mDeviceStatus
->featureLevel();
1273 bool DeviceManagerDx::TextureSharingWorks() {
1274 MutexAutoLock
lock(mDeviceLock
);
1275 if (!mDeviceStatus
) {
1278 return mDeviceStatus
->textureSharingWorks();
1281 bool DeviceManagerDx::CanInitializeKeyedMutexTextures() {
1282 MutexAutoLock
lock(mDeviceLock
);
1283 return mDeviceStatus
&& StaticPrefs::gfx_direct3d11_allow_keyed_mutex() &&
1284 gfxVars::AllowD3D11KeyedMutex();
1287 bool DeviceManagerDx::IsWARP() {
1288 MutexAutoLock
lock(mDeviceLock
);
1289 if (!mDeviceStatus
) {
1292 return mDeviceStatus
->isWARP();
1295 bool DeviceManagerDx::CanUseNV12() {
1296 MutexAutoLock
lock(mDeviceLock
);
1297 if (!mDeviceStatus
) {
1300 return mDeviceStatus
->formatOptions().contains(
1301 D3D11Checks::VideoFormatOption::NV12
);
1304 bool DeviceManagerDx::CanUseP010() {
1305 MutexAutoLock
lock(mDeviceLock
);
1306 if (!mDeviceStatus
) {
1309 return mDeviceStatus
->formatOptions().contains(
1310 D3D11Checks::VideoFormatOption::P010
);
1313 bool DeviceManagerDx::CanUseP016() {
1314 MutexAutoLock
lock(mDeviceLock
);
1315 if (!mDeviceStatus
) {
1318 return mDeviceStatus
->formatOptions().contains(
1319 D3D11Checks::VideoFormatOption::P016
);
1322 bool DeviceManagerDx::CanUseDComp() {
1323 MutexAutoLock
lock(mDeviceLock
);
1324 return !!mDirectCompositionDevice
;
1327 void DeviceManagerDx::InitializeDirectDraw() {
1328 MOZ_ASSERT(layers::CompositorThreadHolder::IsInCompositorThread());
1331 // Already initialized.
1335 FeatureState
& ddraw
= gfxConfig::GetFeature(Feature::DIRECT_DRAW
);
1336 if (!ddraw
.IsEnabled()) {
1340 // Check if DirectDraw is available on this system.
1341 mDirectDrawDLL
.own(LoadLibrarySystem32(L
"ddraw.dll"));
1342 if (!mDirectDrawDLL
) {
1343 ddraw
.SetFailed(FeatureStatus::Unavailable
,
1344 "DirectDraw not available on this computer",
1345 "FEATURE_FAILURE_DDRAW_LIB"_ns
);
1349 sDirectDrawCreateExFn
= (decltype(DirectDrawCreateEx
)*)GetProcAddress(
1350 mDirectDrawDLL
, "DirectDrawCreateEx");
1351 if (!sDirectDrawCreateExFn
) {
1352 ddraw
.SetFailed(FeatureStatus::Unavailable
,
1353 "DirectDraw not available on this computer",
1354 "FEATURE_FAILURE_DDRAW_LIB"_ns
);
1360 hr
= sDirectDrawCreateExFn(nullptr, getter_AddRefs(mDirectDraw
),
1361 IID_IDirectDraw7
, nullptr);
1363 MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
1364 ddraw
.SetFailed(FeatureStatus::Failed
, "Failed to create DirectDraw",
1365 "FEATURE_FAILURE_DDRAW_LIB"_ns
);
1366 gfxCriticalNote
<< "DoesCreatingDirectDrawFailed";
1370 ddraw
.SetFailed(FeatureStatus::Failed
, "Failed to create DirectDraw",
1371 "FEATURE_FAILURE_DDRAW_LIB"_ns
);
1372 gfxCriticalNote
<< "DoesCreatingDirectDrawFailed " << hexa(hr
);
1377 IDirectDraw7
* DeviceManagerDx::GetDirectDraw() { return mDirectDraw
; }
1379 void DeviceManagerDx::GetCompositorDevices(
1380 RefPtr
<ID3D11Device
>* aOutDevice
,
1381 RefPtr
<layers::DeviceAttachmentsD3D11
>* aOutAttachments
) {
1382 RefPtr
<ID3D11Device
> device
;
1384 MutexAutoLock
lock(mDeviceLock
);
1385 if (!mCompositorDevice
) {
1388 if (mCompositorAttachments
) {
1389 *aOutDevice
= mCompositorDevice
;
1390 *aOutAttachments
= mCompositorAttachments
;
1394 // Otherwise, we'll try to create attachments outside the lock.
1395 device
= mCompositorDevice
;
1398 // We save the attachments object even if it fails to initialize, so the
1399 // compositor can grab the failure ID.
1400 RefPtr
<layers::DeviceAttachmentsD3D11
> attachments
=
1401 layers::DeviceAttachmentsD3D11::Create(device
);
1403 MutexAutoLock
lock(mDeviceLock
);
1404 if (device
!= mCompositorDevice
) {
1407 mCompositorAttachments
= attachments
;
1410 *aOutDevice
= device
;
1411 *aOutAttachments
= attachments
;
1415 void DeviceManagerDx::PreloadAttachmentsOnCompositorThread() {
1416 if (!CompositorThread()) {
1420 RefPtr
<Runnable
> task
= NS_NewRunnableFunction(
1421 "DeviceManagerDx::PreloadAttachmentsOnCompositorThread", []() -> void {
1422 if (DeviceManagerDx
* dm
= DeviceManagerDx::Get()) {
1423 RefPtr
<ID3D11Device
> device
;
1424 RefPtr
<layers::DeviceAttachmentsD3D11
> attachments
;
1425 dm
->GetCompositorDevices(&device
, &attachments
);
1428 CompositorThread()->Dispatch(task
.forget());
1432 } // namespace mozilla