Use DComp surface handle for Swap Chain management (#10023)
## Summary of the Pull Request This PR changes the DxEngine to create a swapchain HANDLE, then have the TermControl attach _that_ handle to the SwapChainPanel, rather than returning the swapchain via a `IDXGISwapChain1`. I didn't write this code originally, @miniksa helped me out. The original commit was so succinct that I didn't think there was anything else to add or take away. I'm going to need this for tear-out (#1256), so that I can have the content process create swap chain handles, then duplicate those handles out to the window process that will end up embedding the content. ## References * [`DCompositionCreateSurfaceHandle`](https://docs.microsoft.com/en-us/windows/win32/api/dcomp/nf-dcomp-dcompositioncreatesurfacehandle) * [`CreateSwapChainForCompositionSurfaceHandle`](https://docs.microsoft.com/en-us/windows/win32/api/dxgi1_3/nf-dxgi1_3-idxgifactorymedia-createswapchainforcompositionsurfacehandle) * [`CreateSwapChainForComposition`](https://docs.microsoft.com/en-us/windows/win32/api/dxgi1_2/nf-dxgi1_2-idxgifactory2-createswapchainforcomposition) * Tear-out: #1256 * Megathread: #5000 * Project: https://github.com/microsoft/terminal/projects/5 ## PR Checklist * [x] Closes https://github.com/microsoft/terminal/projects/5#card-50760249 * [x] I work here * [ ] Tests added/passed * [n/a] Requires documentation to be updated ## Detailed Description of the Pull Request / Additional comments This reverts commitc113b65d9b
. That commit reverted30b8335479
## Validation Steps Performed * [x] Built and ran the Terminal, it still seems to work * [x] Does a TDR still work? or do we need to recreate the handle, or something. * [x] Does this work on Win7? I honestly have no idea how DX compatibility works. Presumably, the WPF version uses the `ForHwnd` path, so this will still work, but I don't know if this will suddenly fail to launch on Win7 or something. Tagging in @miniksa.
This commit is contained in:
parent
e0bd76b30d
commit
9f45963e73
|
@ -1172,7 +1172,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
}
|
||||
}
|
||||
|
||||
IDXGISwapChain1* ControlCore::GetSwapChain() const
|
||||
HANDLE ControlCore::GetSwapChainHandle() const
|
||||
{
|
||||
// This is called by:
|
||||
// * TermControl::RenderEngineSwapChainChanged, who is only registered
|
||||
|
@ -1180,7 +1180,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
// * TermControl::_InitializeTerminal, after the call to Initialize, for
|
||||
// _AttachDxgiSwapChainToXaml.
|
||||
// In both cases, we'll have a _renderEngine by then.
|
||||
return _renderEngine->GetSwapChain().Get();
|
||||
return _renderEngine->GetSwapChainHandle();
|
||||
}
|
||||
|
||||
void ControlCore::_rendererWarning(const HRESULT hr)
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
void UpdateAppearance(const IControlAppearance& newAppearance);
|
||||
void SizeChanged(const double width, const double height);
|
||||
void ScaleChanged(const double scale);
|
||||
IDXGISwapChain1* GetSwapChain() const;
|
||||
HANDLE GetSwapChainHandle() const;
|
||||
|
||||
void AdjustFontSize(int fontSizeDelta);
|
||||
void ResetFontSize();
|
||||
|
|
|
@ -578,8 +578,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
|
||||
if (auto control{ weakThis.get() })
|
||||
{
|
||||
const auto chain = control->_core->GetSwapChain();
|
||||
_AttachDxgiSwapChainToXaml(chain);
|
||||
const auto chainHandle = _core->GetSwapChainHandle();
|
||||
_AttachDxgiSwapChainToXaml(chainHandle);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -625,10 +625,10 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
}
|
||||
}
|
||||
|
||||
void TermControl::_AttachDxgiSwapChainToXaml(IDXGISwapChain1* swapChain)
|
||||
void TermControl::_AttachDxgiSwapChainToXaml(HANDLE swapChainHandle)
|
||||
{
|
||||
auto nativePanel = SwapChainPanel().as<ISwapChainPanelNative>();
|
||||
nativePanel->SetSwapChain(swapChain);
|
||||
auto nativePanel = SwapChainPanel().as<ISwapChainPanelNative2>();
|
||||
nativePanel->SetSwapChainHandle(swapChainHandle);
|
||||
}
|
||||
|
||||
bool TermControl::_InitializeTerminal()
|
||||
|
@ -666,7 +666,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
}
|
||||
_interactivity->Initialize();
|
||||
|
||||
_AttachDxgiSwapChainToXaml(_core->GetSwapChain());
|
||||
_AttachDxgiSwapChainToXaml(_core->GetSwapChainHandle());
|
||||
|
||||
// Tell the DX Engine to notify us when the swap chain changes. We do
|
||||
// this after we initially set the swapchain so as to avoid unnecessary
|
||||
|
|
|
@ -66,7 +66,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
|||
void ToggleShaderEffects();
|
||||
|
||||
winrt::fire_and_forget RenderEngineSwapChainChanged(IInspectable sender, IInspectable args);
|
||||
void _AttachDxgiSwapChainToXaml(IDXGISwapChain1* swapChain);
|
||||
void _AttachDxgiSwapChainToXaml(HANDLE swapChainHandle);
|
||||
winrt::fire_and_forget _RendererEnteredErrorState(IInspectable sender, IInspectable args);
|
||||
|
||||
void _RenderRetryButton_Click(IInspectable const& button, IInspectable const& args);
|
||||
|
|
|
@ -79,6 +79,7 @@ DxEngine::DxEngine() :
|
|||
_backgroundColor{ 0 },
|
||||
_selectionBackground{},
|
||||
_haveDeviceResources{ false },
|
||||
_swapChainHandle{ INVALID_HANDLE_VALUE },
|
||||
_swapChainDesc{ 0 },
|
||||
_swapChainFrameLatencyWaitableObject{ INVALID_HANDLE_VALUE },
|
||||
_recreateDeviceRequested{ false },
|
||||
|
@ -478,6 +479,29 @@ void DxEngine::_ComputePixelShaderSettings() noexcept
|
|||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Use DCompositionCreateSurfaceHandle to create a swapchain handle. This API
|
||||
// is only present in Windows 8.1+, so we need to delay-load it to make sure
|
||||
// we can still load on Windows 7.
|
||||
// - We can't actually hit this on Windows 7, because only the WPF control uses
|
||||
// us on Windows 7, and they're using the ForHwnd path, which doesn't hit this
|
||||
// at all.
|
||||
// Arguments:
|
||||
// - <none>
|
||||
// Return Value:
|
||||
// - An HRESULT for failing to load dcomp.dll, or failing to find the API, or an
|
||||
// actual failure from the API itself.
|
||||
[[nodiscard]] HRESULT DxEngine::_CreateSurfaceHandle() noexcept
|
||||
{
|
||||
wil::unique_hmodule hDComp{ LoadLibraryEx(L"Dcomp.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32) };
|
||||
RETURN_LAST_ERROR_IF(hDComp.get() == nullptr);
|
||||
|
||||
auto fn = GetProcAddressByFunctionDeclaration(hDComp.get(), DCompositionCreateSurfaceHandle);
|
||||
RETURN_LAST_ERROR_IF(fn == nullptr);
|
||||
|
||||
return fn(GENERIC_ALL, nullptr, &_swapChainHandle);
|
||||
}
|
||||
|
||||
// Routine Description;
|
||||
// - Creates device-specific resources required for drawing
|
||||
// which generally means those that are represented on the GPU and can
|
||||
|
@ -618,6 +642,13 @@ try
|
|||
}
|
||||
case SwapChainMode::ForComposition:
|
||||
{
|
||||
if (!_swapChainHandle)
|
||||
{
|
||||
RETURN_IF_FAILED(_CreateSurfaceHandle());
|
||||
}
|
||||
|
||||
RETURN_IF_FAILED(_dxgiFactory2.As(&_dxgiFactoryMedia));
|
||||
|
||||
// Use the given target size for compositions.
|
||||
_swapChainDesc.Width = _displaySizePixels.width<UINT>();
|
||||
_swapChainDesc.Height = _displaySizePixels.height<UINT>();
|
||||
|
@ -627,10 +658,11 @@ try
|
|||
// It's 100% required to use scaling mode stretch for composition. There is no other choice.
|
||||
_swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
|
||||
|
||||
RETURN_IF_FAILED(_dxgiFactory2->CreateSwapChainForComposition(_d3dDevice.Get(),
|
||||
&_swapChainDesc,
|
||||
nullptr,
|
||||
&_dxgiSwapChain));
|
||||
RETURN_IF_FAILED(_dxgiFactoryMedia->CreateSwapChainForCompositionSurfaceHandle(_d3dDevice.Get(),
|
||||
_swapChainHandle.get(),
|
||||
&_swapChainDesc,
|
||||
nullptr,
|
||||
&_dxgiSwapChain));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -1003,14 +1035,14 @@ try
|
|||
}
|
||||
CATCH_LOG()
|
||||
|
||||
Microsoft::WRL::ComPtr<IDXGISwapChain1> DxEngine::GetSwapChain()
|
||||
HANDLE DxEngine::GetSwapChainHandle()
|
||||
{
|
||||
if (_dxgiSwapChain.Get() == nullptr)
|
||||
if (!_swapChainHandle)
|
||||
{
|
||||
THROW_IF_FAILED(_CreateDeviceResources(true));
|
||||
}
|
||||
|
||||
return _dxgiSwapChain;
|
||||
return _swapChainHandle.get();
|
||||
}
|
||||
|
||||
void DxEngine::_InvalidateRectangle(const til::rectangle& rc)
|
||||
|
|
|
@ -70,7 +70,7 @@ namespace Microsoft::Console::Render
|
|||
|
||||
void SetSoftwareRendering(bool enable) noexcept;
|
||||
|
||||
::Microsoft::WRL::ComPtr<IDXGISwapChain1> GetSwapChain();
|
||||
HANDLE GetSwapChainHandle();
|
||||
|
||||
// IRenderEngine Members
|
||||
[[nodiscard]] HRESULT Invalidate(const SMALL_RECT* const psrRegion) noexcept override;
|
||||
|
@ -128,8 +128,6 @@ namespace Microsoft::Console::Render
|
|||
void SetAntialiasingMode(const D2D1_TEXT_ANTIALIAS_MODE antialiasingMode) noexcept;
|
||||
void SetDefaultTextBackgroundOpacity(const float opacity) noexcept;
|
||||
|
||||
wil::unique_handle _swapChainHandle;
|
||||
|
||||
void UpdateHyperlinkHoveredId(const uint16_t hoveredId) noexcept;
|
||||
|
||||
protected:
|
||||
|
@ -184,6 +182,8 @@ namespace Microsoft::Console::Render
|
|||
|
||||
static std::atomic<size_t> _tracelogCount;
|
||||
|
||||
wil::unique_handle _swapChainHandle;
|
||||
|
||||
// Device-Independent Resources
|
||||
::Microsoft::WRL::ComPtr<ID2D1Factory1> _d2dFactory;
|
||||
|
||||
|
@ -212,6 +212,7 @@ namespace Microsoft::Console::Render
|
|||
::Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> _d2dBrushBackground;
|
||||
|
||||
::Microsoft::WRL::ComPtr<IDXGIFactory2> _dxgiFactory2;
|
||||
::Microsoft::WRL::ComPtr<IDXGIFactoryMedia> _dxgiFactoryMedia;
|
||||
::Microsoft::WRL::ComPtr<IDXGIDevice> _dxgiDevice;
|
||||
::Microsoft::WRL::ComPtr<IDXGISurface> _dxgiSurface;
|
||||
|
||||
|
@ -270,6 +271,8 @@ namespace Microsoft::Console::Render
|
|||
} _pixelShaderSettings;
|
||||
|
||||
[[nodiscard]] HRESULT _CreateDeviceResources(const bool createSwapChain) noexcept;
|
||||
[[nodiscard]] HRESULT _CreateSurfaceHandle() noexcept;
|
||||
|
||||
bool _HasTerminalEffects() const noexcept;
|
||||
std::string _LoadPixelShaderFile() const;
|
||||
HRESULT _SetupTerminalEffects();
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include <typeinfo>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <dcomp.h>
|
||||
|
||||
#include <dxgi.h>
|
||||
#include <dxgi1_2.h>
|
||||
#include <dxgi1_3.h>
|
||||
|
|
Loading…
Reference in a new issue