Don't set HDR metadata on the DXGI swapchain

This is no longer recommended by Microsoft due inconsistencies with display support for HDR metadata.
This commit is contained in:
Cameron Gutman 2023-12-31 15:15:06 -06:00
parent e44e29e7eb
commit 114074bfd8
2 changed files with 28 additions and 76 deletions

View file

@ -82,6 +82,7 @@ D3D11VARenderer::D3D11VARenderer(int decoderSelectionPass)
m_RenderTargetView(nullptr),
m_LastColorSpace(-1),
m_LastFullRange(false),
m_LastColorTrc(AVCOL_TRC_UNSPECIFIED),
m_AllowTearing(false),
m_VideoGenericPixelShader(nullptr),
m_VideoBt601LimPixelShader(nullptr),
@ -467,79 +468,6 @@ bool D3D11VARenderer::prepareDecoderContext(AVCodecContext* context, AVDictionar
return true;
}
void D3D11VARenderer::setHdrMode(bool enabled)
{
HRESULT hr;
// According to MSDN, we need to lock the context even if we're just using DXGI functions
// https://docs.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-render-multi-thread-intro
lockContext(this);
if (enabled) {
DXGI_HDR_METADATA_HDR10 hdr10Metadata;
SS_HDR_METADATA sunshineHdrMetadata;
// Sunshine will have HDR metadata but GFE will not
if (!LiGetHdrMetadata(&sunshineHdrMetadata)) {
RtlZeroMemory(&sunshineHdrMetadata, sizeof(sunshineHdrMetadata));
}
hdr10Metadata.RedPrimary[0] = sunshineHdrMetadata.displayPrimaries[0].x;
hdr10Metadata.RedPrimary[1] = sunshineHdrMetadata.displayPrimaries[0].y;
hdr10Metadata.GreenPrimary[0] = sunshineHdrMetadata.displayPrimaries[1].x;
hdr10Metadata.GreenPrimary[1] = sunshineHdrMetadata.displayPrimaries[1].y;
hdr10Metadata.BluePrimary[0] = sunshineHdrMetadata.displayPrimaries[2].x;
hdr10Metadata.BluePrimary[1] = sunshineHdrMetadata.displayPrimaries[2].y;
hdr10Metadata.WhitePoint[0] = sunshineHdrMetadata.whitePoint.x;
hdr10Metadata.WhitePoint[1] = sunshineHdrMetadata.whitePoint.y;
hdr10Metadata.MaxMasteringLuminance = sunshineHdrMetadata.maxDisplayLuminance;
hdr10Metadata.MinMasteringLuminance = sunshineHdrMetadata.minDisplayLuminance;
hdr10Metadata.MaxContentLightLevel = sunshineHdrMetadata.maxContentLightLevel;
hdr10Metadata.MaxFrameAverageLightLevel = sunshineHdrMetadata.maxFrameAverageLightLevel;
hr = m_SwapChain->SetHDRMetaData(DXGI_HDR_METADATA_TYPE_HDR10, sizeof(hdr10Metadata), &hdr10Metadata);
if (SUCCEEDED(hr)) {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Set display HDR mode: enabled");
}
else {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Failed to enter HDR mode: %x",
hr);
}
// Switch to Rec 2020 PQ (SMPTE ST 2084) colorspace for HDR10 rendering
hr = m_SwapChain->SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020);
if (FAILED(hr)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"IDXGISwapChain::SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) failed: %x",
hr);
}
}
else {
// Restore default sRGB colorspace
hr = m_SwapChain->SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709);
if (FAILED(hr)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"IDXGISwapChain::SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709) failed: %x",
hr);
}
hr = m_SwapChain->SetHDRMetaData(DXGI_HDR_METADATA_TYPE_NONE, 0, nullptr);
if (SUCCEEDED(hr)) {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Set display HDR mode: disabled");
}
else {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Failed to exit HDR mode: %x",
hr);
}
}
unlockContext(this);
}
void D3D11VARenderer::renderFrame(AVFrame* frame)
{
// Acquire the context lock for rendering to prevent concurrent
@ -578,8 +506,33 @@ void D3D11VARenderer::renderFrame(AVFrame* frame)
flags = 0;
}
HRESULT hr;
if (frame->color_trc != m_LastColorTrc) {
if (frame->color_trc == AVCOL_TRC_SMPTE2084) {
// Switch to Rec 2020 PQ (SMPTE ST 2084) colorspace for HDR10 rendering
hr = m_SwapChain->SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020);
if (FAILED(hr)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"IDXGISwapChain::SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) failed: %x",
hr);
}
}
else {
// Restore default sRGB colorspace
hr = m_SwapChain->SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709);
if (FAILED(hr)) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"IDXGISwapChain::SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709) failed: %x",
hr);
}
}
m_LastColorTrc = frame->color_trc;
}
// Present according to the decoder parameters
HRESULT hr = m_SwapChain->Present(0, flags);
hr = m_SwapChain->Present(0, flags);
// Release the context lock
unlockContext(this);

View file

@ -1,7 +1,6 @@
#pragma once
#include "renderer.h"
#include "pacer/pacer.h"
#include <d3d11_1.h>
#include <dxgi1_5.h>
@ -19,7 +18,6 @@ public:
virtual bool prepareDecoderContext(AVCodecContext* context, AVDictionary**) override;
virtual void renderFrame(AVFrame* frame) override;
virtual void notifyOverlayUpdated(Overlay::OverlayType) override;
virtual void setHdrMode(bool enabled) override;
virtual int getRendererAttributes() override;
virtual int getDecoderCapabilities() override;
virtual bool needsTestFrame() override;
@ -50,6 +48,7 @@ private:
int m_DisplayHeight;
int m_LastColorSpace;
bool m_LastFullRange;
AVColorTransferCharacteristic m_LastColorTrc;
bool m_AllowTearing;