diff --git a/src/Files.App.CsWin32/Windows.Win32.ComPtr.cs b/src/Files.App.CsWin32/Windows.Win32.ComPtr.cs index cbfeaa39e5d5..2d18d76fdf4b 100644 --- a/src/Files.App.CsWin32/Windows.Win32.ComPtr.cs +++ b/src/Files.App.CsWin32/Windows.Win32.ComPtr.cs @@ -27,6 +27,14 @@ public ComPtr(T* ptr) ((IUnknown*)ptr)->AddRef(); } + public void Attach(T* other) + { + if (_ptr is not null) + ((IUnknown*)_ptr)->Release(); + + _ptr = other; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly T* Get() { diff --git a/src/Files.App/ViewModels/UserControls/Previews/ShellPreviewViewModel.cs b/src/Files.App/ViewModels/UserControls/Previews/ShellPreviewViewModel.cs index d164d6729c82..16e2d1de4d3b 100644 --- a/src/Files.App/ViewModels/UserControls/Previews/ShellPreviewViewModel.cs +++ b/src/Files.App/ViewModels/UserControls/Previews/ShellPreviewViewModel.cs @@ -161,61 +161,61 @@ private unsafe bool ChildWindowToXaml(nint parent, UIElement presenter) D3D_DRIVER_TYPE.D3D_DRIVER_TYPE_WARP, ]; - ID3D11Device* pD3D11Device = default; - ID3D11DeviceContext* pD3D11DeviceContext = default; - - foreach (var driveType in driverTypes) + Windows.Win32.Foundation.HRESULT hr = default; + Guid IID_IDCompositionDevice = typeof(IDCompositionDevice).GUID; + using ComPtr pD3D11Device = default; + using ComPtr pD3D11DeviceContext = default; + using ComPtr pDXGIDevice = default; + using ComPtr pDCompositionDevice = default; + using ComPtr pControlSurface = default; + ComPtr pChildVisual = default; // Don't dispose this one, it's used by the compositor + + // Create the D3D11 device + foreach (var driverType in driverTypes) { - var hr = PInvoke.D3D11CreateDevice( - null, - driveType, - new(nint.Zero), + hr = PInvoke.D3D11CreateDevice( + null, driverType, new(nint.Zero), D3D11_CREATE_DEVICE_FLAG.D3D11_CREATE_DEVICE_BGRA_SUPPORT, - null, - 0, - 7, - &pD3D11Device, - null, - &pD3D11DeviceContext); + null, /* FeatureLevels */ 0, /* SDKVersion */ 7, + pD3D11Device.GetAddressOf(), null, + pD3D11DeviceContext.GetAddressOf()); if (hr.Succeeded) break; } - if (pD3D11Device is null) + if (pD3D11Device.IsNull) return false; - IDXGIDevice* pDXGIDevice = (IDXGIDevice*)pD3D11Device; - if (PInvoke.DCompositionCreateDevice(pDXGIDevice, typeof(IDCompositionDevice).GUID, out var compositionDevicePtr).Failed) + // Create the DComp device + pDXGIDevice.Attach((IDXGIDevice*)pD3D11Device.Get()); + hr = PInvoke.DCompositionCreateDevice( + pDXGIDevice.Get(), + &IID_IDCompositionDevice, + (void**)pDCompositionDevice.GetAddressOf()); + if (hr.Failed) return false; - var pDCompositionDevice = (IDCompositionDevice*)compositionDevicePtr; - IDCompositionVisual* pChildVisual = default; - IUnknown* pControlSurface = default; - - pDCompositionDevice->CreateVisual(&pChildVisual); - pDCompositionDevice->CreateSurfaceFromHwnd(new(hwnd.DangerousGetHandle()), &pControlSurface); - pChildVisual->SetContent(pControlSurface); - if (pChildVisual is null || pControlSurface is null) + // Create the visual + hr = pDCompositionDevice.Get()->CreateVisual(pChildVisual.GetAddressOf()); + hr = pDCompositionDevice.Get()->CreateSurfaceFromHwnd(new(hwnd.DangerousGetHandle()), pControlSurface.GetAddressOf()); + hr = pChildVisual.Get()->SetContent(pControlSurface.Get()); + if (pChildVisual.IsNull || pControlSurface.IsNull) return false; + // Get the compositor and set the visual on it var compositor = ElementCompositionPreview.GetElementVisual(presenter).Compositor; outputLink = ContentExternalOutputLink.Create(compositor); var target = outputLink.As(); - target.SetRoot((nint)pChildVisual); + target.SetRoot((nint)pChildVisual.Get()); outputLink.PlacementVisual.Size = new(0, 0); outputLink.PlacementVisual.Scale = new(1 / (float)presenter.XamlRoot.RasterizationScale); ElementCompositionPreview.SetElementChildVisual(presenter, outputLink.PlacementVisual); - pDCompositionDevice->Commit(); - - pControlSurface->Release(); - pDCompositionDevice->Release(); - pDXGIDevice->Release(); - pD3D11Device->Release(); - pD3D11DeviceContext->Release(); + // Commit the all pending DComp commands + pDCompositionDevice.Get()->Commit(); var dwAttrib = Convert.ToUInt32(true);