summaryrefslogtreecommitdiff
path: root/Source/Core/VideoBackends/D3DCommon/SwapChain.cpp
diff options
context:
space:
mode:
authorAdmiral H. Curtiss <pikachu025@gmail.com>2023-06-23 18:08:23 +0200
committerGitHub <noreply@github.com>2023-06-23 18:08:23 +0200
commit02909bd1a560673a2d205bc95f5257436d194fad (patch)
treef7462671e50770652fae79371645027867d8d560 /Source/Core/VideoBackends/D3DCommon/SwapChain.cpp
parent5bf3d55d3864274814efc883fb54e464ae406cf0 (diff)
parentdaddf4cd9cf7c45820f5cadd1539c6a6b366cfbc (diff)
Merge pull request #11850 from Filoppi/post_process_fixes
Video: implement color correction to match the Wii/GC NTSC/PAL color spaces (and gamma)
Diffstat (limited to 'Source/Core/VideoBackends/D3DCommon/SwapChain.cpp')
-rw-r--r--Source/Core/VideoBackends/D3DCommon/SwapChain.cpp80
1 files changed, 74 insertions, 6 deletions
diff --git a/Source/Core/VideoBackends/D3DCommon/SwapChain.cpp b/Source/Core/VideoBackends/D3DCommon/SwapChain.cpp
index a6abc9159f..d0f98b3523 100644
--- a/Source/Core/VideoBackends/D3DCommon/SwapChain.cpp
+++ b/Source/Core/VideoBackends/D3DCommon/SwapChain.cpp
@@ -51,13 +51,18 @@ bool SwapChain::WantsStereo()
return g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer;
}
+bool SwapChain::WantsHDR()
+{
+ return g_ActiveConfig.bHDR;
+}
+
u32 SwapChain::GetSwapChainFlags() const
{
// This flag is necessary if we want to use a flip-model swapchain without locking the framerate
return m_allow_tearing_supported ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
}
-bool SwapChain::CreateSwapChain(bool stereo)
+bool SwapChain::CreateSwapChain(bool stereo, bool hdr)
{
RECT client_rc;
if (GetClientRect(static_cast<HWND>(m_wsi.render_surface), &client_rc))
@@ -66,6 +71,9 @@ bool SwapChain::CreateSwapChain(bool stereo)
m_height = client_rc.bottom - client_rc.top;
}
+ m_stereo = false;
+ m_hdr = false;
+
// Try using the Win8 version if available.
Microsoft::WRL::ComPtr<IDXGIFactory2> dxgi_factory2;
HRESULT hr = m_dxgi_factory.As(&dxgi_factory2);
@@ -81,6 +89,7 @@ bool SwapChain::CreateSwapChain(bool stereo)
swap_chain_desc.SampleDesc.Count = 1;
swap_chain_desc.SampleDesc.Quality = 0;
swap_chain_desc.Format = GetDXGIFormatForAbstractFormat(m_texture_format, false);
+
swap_chain_desc.Scaling = DXGI_SCALING_STRETCH;
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
swap_chain_desc.Stereo = stereo;
@@ -108,6 +117,8 @@ bool SwapChain::CreateSwapChain(bool stereo)
// support the newer DXGI interface aren't going to support DX12 anyway.
if (FAILED(hr))
{
+ hdr = false;
+
DXGI_SWAP_CHAIN_DESC desc = {};
desc.BufferDesc.Width = m_width;
desc.BufferDesc.Height = m_height;
@@ -138,6 +149,37 @@ bool SwapChain::CreateSwapChain(bool stereo)
WARN_LOG_FMT(VIDEO, "MakeWindowAssociation() failed: {}", Common::HRWrap(hr));
m_stereo = stereo;
+
+ if (hdr)
+ {
+ // Only try to activate HDR here, to avoid failing when creating the swapchain
+ // (we can't know if the format is supported upfront)
+ Microsoft::WRL::ComPtr<IDXGISwapChain4> swap_chain4;
+ hr = m_swap_chain->QueryInterface(IID_PPV_ARGS(&swap_chain4));
+ if (SUCCEEDED(hr))
+ {
+ UINT color_space_support = 0;
+ // Note that this should succeed even if HDR is not currently engaged on the monitor,
+ // but it should display fine nonetheless.
+ // We need to check for DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 as checking for
+ // scRGB always returns false (DX bug).
+ hr = swap_chain4->CheckColorSpaceSupport(DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020,
+ &color_space_support);
+ if (SUCCEEDED(hr) && (color_space_support & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT))
+ {
+ hr = swap_chain4->ResizeBuffers(SWAP_CHAIN_BUFFER_COUNT, 0, 0,
+ GetDXGIFormatForAbstractFormat(m_texture_format_hdr, false),
+ GetSwapChainFlags());
+ if (SUCCEEDED(hr))
+ {
+ hr = swap_chain4->SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709);
+ if (SUCCEEDED(hr))
+ m_hdr = hdr;
+ }
+ }
+ }
+ }
+
if (!CreateSwapChainBuffers())
{
PanicAlertFmt("Failed to create swap chain buffers");
@@ -164,12 +206,19 @@ bool SwapChain::ResizeSwapChain()
{
DestroySwapChainBuffers();
- HRESULT hr = m_swap_chain->ResizeBuffers(SWAP_CHAIN_BUFFER_COUNT, 0, 0,
- GetDXGIFormatForAbstractFormat(m_texture_format, false),
+ // The swap chain fills up the size of the window if no size is specified
+ HRESULT hr = m_swap_chain->ResizeBuffers(SWAP_CHAIN_BUFFER_COUNT, 0, 0, DXGI_FORMAT_UNKNOWN,
GetSwapChainFlags());
+
if (FAILED(hr))
WARN_LOG_FMT(VIDEO, "ResizeBuffers() failed: {}", Common::HRWrap(hr));
+ Microsoft::WRL::ComPtr<IDXGISwapChain4> swap_chain4;
+ hr = m_swap_chain->QueryInterface(IID_PPV_ARGS(&swap_chain4));
+ if (SUCCEEDED(hr))
+ hr = swap_chain4->SetColorSpace1(m_hdr ? DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709 :
+ DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709);
+
DXGI_SWAP_CHAIN_DESC desc;
if (SUCCEEDED(m_swap_chain->GetDesc(&desc)))
{
@@ -186,10 +235,28 @@ void SwapChain::SetStereo(bool stereo)
return;
DestroySwapChain();
- if (!CreateSwapChain(stereo))
+ // Do not try to re-activate HDR here if it had already failed
+ if (!CreateSwapChain(stereo, m_hdr))
{
PanicAlertFmt("Failed to switch swap chain stereo mode");
- CreateSwapChain(false);
+ CreateSwapChain(false, false);
+ }
+}
+
+void SwapChain::SetHDR(bool hdr)
+{
+ if (m_hdr == hdr)
+ return;
+
+ // NOTE: as an optimization here we could just call "ResizeSwapChain()"
+ // by adding some code to check if we could change the format to HDR.
+
+ DestroySwapChain();
+ // Do not try to re-activate stereo mode here if it had already failed
+ if (!CreateSwapChain(m_stereo, hdr))
+ {
+ PanicAlertFmt("Failed to switch swap chain SDR/HDR mode");
+ CreateSwapChain(false, false);
}
}
@@ -249,7 +316,8 @@ bool SwapChain::ChangeSurface(void* native_handle)
{
DestroySwapChain();
m_wsi.render_surface = native_handle;
- return CreateSwapChain(m_stereo);
+ // We only keep the swap chain settings (HDR/Stereo) that had successfully applied beofre
+ return CreateSwapChain(m_stereo, m_hdr);
}
} // namespace D3DCommon