diff options
| author | Admiral H. Curtiss <pikachu025@gmail.com> | 2023-06-23 18:08:23 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-06-23 18:08:23 +0200 |
| commit | 02909bd1a560673a2d205bc95f5257436d194fad (patch) | |
| tree | f7462671e50770652fae79371645027867d8d560 /Source/Core/VideoBackends/D3DCommon/SwapChain.cpp | |
| parent | 5bf3d55d3864274814efc883fb54e464ae406cf0 (diff) | |
| parent | daddf4cd9cf7c45820f5cadd1539c6a6b366cfbc (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.cpp | 80 |
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 |
