mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-07-21 06:42:02 +00:00
[idd] hdr: propagate per-frame HDR metadata
Handle DEFAULT, NEW, and UNCHANGED IDDCX HDR10 metadata states and publish valid mastering metadata through KVMFR. Preserve the metadata across post-processing without reallocating resources for metadata-only changes.
This commit is contained in:
@@ -143,7 +143,8 @@ enum
|
|||||||
FRAME_FLAG_REQUEST_ACTIVATION = 0x2 ,
|
FRAME_FLAG_REQUEST_ACTIVATION = 0x2 ,
|
||||||
FRAME_FLAG_TRUNCATED = 0x4 , // ivshmem was too small for the frame
|
FRAME_FLAG_TRUNCATED = 0x4 , // ivshmem was too small for the frame
|
||||||
FRAME_FLAG_HDR = 0x8 , // RGBA10 may not be HDR
|
FRAME_FLAG_HDR = 0x8 , // RGBA10 may not be HDR
|
||||||
FRAME_FLAG_HDR_PQ = 0x10 // HDR PQ has been applied to the frame
|
FRAME_FLAG_HDR_PQ = 0x10, // HDR PQ has been applied to the frame
|
||||||
|
FRAME_FLAG_HDR_METADATA = 0x20 // HDR static metadata fields are valid
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef uint32_t KVMFRFrameFlags;
|
typedef uint32_t KVMFRFrameFlags;
|
||||||
@@ -167,7 +168,7 @@ typedef struct KVMFRFrame
|
|||||||
FrameDamageRect damageRects[KVMFR_MAX_DAMAGE_RECTS];
|
FrameDamageRect damageRects[KVMFR_MAX_DAMAGE_RECTS];
|
||||||
KVMFRFrameFlags flags; // bit field combination of FRAME_FLAG_*
|
KVMFRFrameFlags flags; // bit field combination of FRAME_FLAG_*
|
||||||
|
|
||||||
// HDR static metadata (valid when FRAME_FLAG_HDR is set)
|
// HDR static metadata (valid when FRAME_FLAG_HDR_METADATA is set)
|
||||||
// Display color primaries in 0.00002 units (SMPTE ST 2086 format)
|
// Display color primaries in 0.00002 units (SMPTE ST 2086 format)
|
||||||
uint16_t hdrDisplayPrimary[3][2]; // Rx,Ry, Gx,Gy, Bx,By
|
uint16_t hdrDisplayPrimary[3][2]; // Rx,Ry, Gx,Gy, Bx,By
|
||||||
uint16_t hdrWhitePoint[2]; // Wx, Wy
|
uint16_t hdrWhitePoint[2]; // Wx, Wy
|
||||||
|
|||||||
@@ -1052,25 +1052,22 @@ CIndirectDeviceContext::PreparedFrameBuffer CIndirectDeviceContext::PrepareFrame
|
|||||||
// Detect HDR metadata changes that require a format version bump
|
// Detect HDR metadata changes that require a format version bump
|
||||||
// so the client knows to re-apply the HDR image description.
|
// so the client knows to re-apply the HDR image description.
|
||||||
//
|
//
|
||||||
// Use dstFormat: post-processing (CHDR16to10Effect) can rotate the gamut
|
// Use dstFormat so post-processing can propagate any metadata adjustments.
|
||||||
// (BT.709 scRGB -> BT.2020 PQ), so the metadata describing the *emitted*
|
|
||||||
// frame lives in dstFormat, not srcFormat. Forwarding srcFormat here would
|
|
||||||
// tag PQ/BT.2020 pixels with the source's BT.709 primaries and mislead
|
|
||||||
// consumers that derive their colour conversion from these values.
|
|
||||||
if (dstFormat.hdr)
|
if (dstFormat.hdr)
|
||||||
{
|
{
|
||||||
if (!m_lastHDRActive ||
|
const bool metadataChanged =
|
||||||
memcmp(m_lastHDRDisplayPrimary, dstFormat.displayPrimary, sizeof(m_lastHDRDisplayPrimary)) != 0 ||
|
m_lastHDRMetadata != dstFormat.hdrMetadata ||
|
||||||
|
(dstFormat.hdrMetadata &&
|
||||||
|
(memcmp(m_lastHDRDisplayPrimary, dstFormat.displayPrimary, sizeof(m_lastHDRDisplayPrimary)) != 0 ||
|
||||||
memcmp(m_lastHDRWhitePoint , dstFormat.whitePoint , sizeof(m_lastHDRWhitePoint )) != 0 ||
|
memcmp(m_lastHDRWhitePoint , dstFormat.whitePoint , sizeof(m_lastHDRWhitePoint )) != 0 ||
|
||||||
m_lastHDRMaxDisplayLuminance != dstFormat.maxDisplayLuminance ||
|
m_lastHDRMaxDisplayLuminance != dstFormat.maxDisplayLuminance ||
|
||||||
m_lastHDRMinDisplayLuminance != dstFormat.minDisplayLuminance ||
|
m_lastHDRMinDisplayLuminance != dstFormat.minDisplayLuminance ||
|
||||||
m_lastHDRMaxContentLightLevel != dstFormat.maxContentLightLevel ||
|
m_lastHDRMaxContentLightLevel != dstFormat.maxContentLightLevel ||
|
||||||
m_lastHDRMaxFrameAverageLightLevel != dstFormat.maxFrameAverageLightLevel ||
|
m_lastHDRMaxFrameAverageLightLevel != dstFormat.maxFrameAverageLightLevel));
|
||||||
m_lastSDRWhiteLevel != dstFormat.sdrWhiteLevel)
|
|
||||||
{
|
if (!m_lastHDRActive || metadataChanged || m_lastSDRWhiteLevel != dstFormat.sdrWhiteLevel)
|
||||||
++m_formatVer;
|
++m_formatVer;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if (m_lastHDRActive)
|
else if (m_lastHDRActive)
|
||||||
{
|
{
|
||||||
// HDR was turned off
|
// HDR was turned off
|
||||||
@@ -1078,6 +1075,7 @@ CIndirectDeviceContext::PreparedFrameBuffer CIndirectDeviceContext::PrepareFrame
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_lastHDRActive = dstFormat.hdr;
|
m_lastHDRActive = dstFormat.hdr;
|
||||||
|
m_lastHDRMetadata = dstFormat.hdrMetadata;
|
||||||
memcpy(m_lastHDRDisplayPrimary, dstFormat.displayPrimary, sizeof(m_lastHDRDisplayPrimary));
|
memcpy(m_lastHDRDisplayPrimary, dstFormat.displayPrimary, sizeof(m_lastHDRDisplayPrimary));
|
||||||
memcpy(m_lastHDRWhitePoint , dstFormat.whitePoint , sizeof(m_lastHDRWhitePoint ));
|
memcpy(m_lastHDRWhitePoint , dstFormat.whitePoint , sizeof(m_lastHDRWhitePoint ));
|
||||||
m_lastHDRMaxDisplayLuminance = dstFormat.maxDisplayLuminance;
|
m_lastHDRMaxDisplayLuminance = dstFormat.maxDisplayLuminance;
|
||||||
@@ -1101,7 +1099,8 @@ CIndirectDeviceContext::PreparedFrameBuffer CIndirectDeviceContext::PrepareFrame
|
|||||||
const int bpp = dstFormat.format == FRAME_TYPE_RGBA16F ? 8 : 4;
|
const int bpp = dstFormat.format == FRAME_TYPE_RGBA16F ? 8 : 4;
|
||||||
KVMFRFrameFlags flags =
|
KVMFRFrameFlags flags =
|
||||||
(dstFormat.hdr ? FRAME_FLAG_HDR : 0) |
|
(dstFormat.hdr ? FRAME_FLAG_HDR : 0) |
|
||||||
(dstFormat.hdrPQ ? FRAME_FLAG_HDR_PQ : 0);
|
(dstFormat.hdrPQ ? FRAME_FLAG_HDR_PQ : 0) |
|
||||||
|
(dstFormat.hdrMetadata ? FRAME_FLAG_HDR_METADATA : 0);
|
||||||
|
|
||||||
if (maxRows < dstFormat.desc.Height)
|
if (maxRows < dstFormat.desc.Height)
|
||||||
flags |= FRAME_FLAG_TRUNCATED;
|
flags |= FRAME_FLAG_TRUNCATED;
|
||||||
@@ -1122,10 +1121,7 @@ CIndirectDeviceContext::PreparedFrameBuffer CIndirectDeviceContext::PrepareFrame
|
|||||||
fi->rotation = FRAME_ROT_0;
|
fi->rotation = FRAME_ROT_0;
|
||||||
fi->type = dstFormat.format;
|
fi->type = dstFormat.format;
|
||||||
|
|
||||||
// Populate HDR metadata if the frame is HDR. Use dstFormat so the primaries
|
if (flags & FRAME_FLAG_HDR_METADATA)
|
||||||
// describe the emitted frame after any gamut conversion in post-processing
|
|
||||||
// (see the metadata-change detection above).
|
|
||||||
if (flags & FRAME_FLAG_HDR)
|
|
||||||
{
|
{
|
||||||
memcpy(fi->hdrDisplayPrimary, dstFormat.displayPrimary, sizeof(fi->hdrDisplayPrimary));
|
memcpy(fi->hdrDisplayPrimary, dstFormat.displayPrimary, sizeof(fi->hdrDisplayPrimary));
|
||||||
memcpy(fi->hdrWhitePoint , dstFormat.whitePoint , sizeof(fi->hdrWhitePoint));
|
memcpy(fi->hdrWhitePoint , dstFormat.whitePoint , sizeof(fi->hdrWhitePoint));
|
||||||
@@ -1134,6 +1130,15 @@ CIndirectDeviceContext::PreparedFrameBuffer CIndirectDeviceContext::PrepareFrame
|
|||||||
fi->hdrMaxContentLightLevel = dstFormat.maxContentLightLevel;
|
fi->hdrMaxContentLightLevel = dstFormat.maxContentLightLevel;
|
||||||
fi->hdrMaxFrameAverageLightLevel = dstFormat.maxFrameAverageLightLevel;
|
fi->hdrMaxFrameAverageLightLevel = dstFormat.maxFrameAverageLightLevel;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(fi->hdrDisplayPrimary, 0, sizeof(fi->hdrDisplayPrimary));
|
||||||
|
memset(fi->hdrWhitePoint , 0, sizeof(fi->hdrWhitePoint ));
|
||||||
|
fi->hdrMaxDisplayLuminance = 0;
|
||||||
|
fi->hdrMinDisplayLuminance = 0;
|
||||||
|
fi->hdrMaxContentLightLevel = 0;
|
||||||
|
fi->hdrMaxFrameAverageLightLevel = 0;
|
||||||
|
}
|
||||||
|
|
||||||
fi->damageRectsCount = 0;
|
fi->damageRectsCount = 0;
|
||||||
if (nbDirtyRects <= ARRAYSIZE(fi->damageRects))
|
if (nbDirtyRects <= ARRAYSIZE(fi->damageRects))
|
||||||
|
|||||||
@@ -135,6 +135,7 @@ private:
|
|||||||
uint32_t m_lastHDRMaxFrameAverageLightLevel = 0;
|
uint32_t m_lastHDRMaxFrameAverageLightLevel = 0;
|
||||||
uint32_t m_lastSDRWhiteLevel = 0;
|
uint32_t m_lastSDRWhiteLevel = 0;
|
||||||
bool m_lastHDRActive = false;
|
bool m_lastHDRActive = false;
|
||||||
|
bool m_lastHDRMetadata = false;
|
||||||
|
|
||||||
void QueryIddCxCapabilities();
|
void QueryIddCxCapabilities();
|
||||||
bool CanUseIddCx110DDIs() const { return m_canProcessFP16; }
|
bool CanUseIddCx110DDIs() const { return m_canProcessFP16; }
|
||||||
|
|||||||
@@ -17,8 +17,21 @@
|
|||||||
#include "effect/CHDR16to10Effect.h"
|
#include "effect/CHDR16to10Effect.h"
|
||||||
#include "effect/CRGB24Effect.h"
|
#include "effect/CRGB24Effect.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
static void CopyHDRMetadata(D12FrameFormat& dst, const D12FrameFormat& src)
|
||||||
|
{
|
||||||
|
dst.hdrMetadata = src.hdrMetadata;
|
||||||
|
dst.sdrWhiteLevel = src.sdrWhiteLevel;
|
||||||
|
std::memcpy(dst.displayPrimary, src.displayPrimary, sizeof(dst.displayPrimary));
|
||||||
|
std::memcpy(dst.whitePoint, src.whitePoint, sizeof(dst.whitePoint));
|
||||||
|
dst.maxDisplayLuminance = src.maxDisplayLuminance;
|
||||||
|
dst.minDisplayLuminance = src.minDisplayLuminance;
|
||||||
|
dst.maxContentLightLevel = src.maxContentLightLevel;
|
||||||
|
dst.maxFrameAverageLightLevel = src.maxFrameAverageLightLevel;
|
||||||
|
}
|
||||||
|
|
||||||
bool CPostProcessor::Init(std::shared_ptr<CD3D12Device> dx12Device)
|
bool CPostProcessor::Init(std::shared_ptr<CD3D12Device> dx12Device)
|
||||||
{
|
{
|
||||||
m_dx12Device = dx12Device;
|
m_dx12Device = dx12Device;
|
||||||
@@ -73,9 +86,14 @@ bool CPostProcessor::Configure(const D12FrameFormat& srcFormat, bool * formatCha
|
|||||||
srcFormat.width == m_srcFormat.width &&
|
srcFormat.width == m_srcFormat.width &&
|
||||||
srcFormat.height == m_srcFormat.height &&
|
srcFormat.height == m_srcFormat.height &&
|
||||||
srcFormat.hdr == m_srcFormat.hdr &&
|
srcFormat.hdr == m_srcFormat.hdr &&
|
||||||
srcFormat.hdrPQ == m_srcFormat.hdrPQ &&
|
srcFormat.hdrPQ == m_srcFormat.hdrPQ)
|
||||||
srcFormat.sdrWhiteLevel == m_srcFormat.sdrWhiteLevel)
|
{
|
||||||
|
// Static HDR metadata may change independently of the resource format.
|
||||||
|
// Propagate it without recreating textures or post-processing state.
|
||||||
|
CopyHDRMetadata(m_srcFormat, srcFormat);
|
||||||
|
CopyHDRMetadata(m_dstFormat, srcFormat);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
D12FrameFormat oldDst = m_dstFormat;
|
D12FrameFormat oldDst = m_dstFormat;
|
||||||
D12FrameFormat cur = srcFormat;
|
D12FrameFormat cur = srcFormat;
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ struct D12FrameFormat
|
|||||||
FrameType format = FRAME_TYPE_INVALID;
|
FrameType format = FRAME_TYPE_INVALID;
|
||||||
bool hdr = false;
|
bool hdr = false;
|
||||||
bool hdrPQ = false;
|
bool hdrPQ = false;
|
||||||
|
bool hdrMetadata = false;
|
||||||
uint32_t sdrWhiteLevel = KVMFR_SDR_WHITE_LEVEL_DEFAULT;
|
uint32_t sdrWhiteLevel = KVMFR_SDR_WHITE_LEVEL_DEFAULT;
|
||||||
|
|
||||||
// HDR static metadata (SMPTE ST 2086)
|
// HDR static metadata (SMPTE ST 2086)
|
||||||
@@ -49,9 +50,9 @@ struct D12FrameFormat
|
|||||||
uint16_t displayPrimary[3][2];
|
uint16_t displayPrimary[3][2];
|
||||||
// White point in 0.00002 units
|
// White point in 0.00002 units
|
||||||
uint16_t whitePoint[2];
|
uint16_t whitePoint[2];
|
||||||
// Max display luminance in 0.0001 cd/m² units
|
// Max mastering display luminance in whole cd/m²
|
||||||
uint32_t maxDisplayLuminance;
|
uint32_t maxDisplayLuminance;
|
||||||
// Min display luminance in 0.0001 cd/m² units
|
// Min mastering display luminance in 0.0001 cd/m² units
|
||||||
uint32_t minDisplayLuminance;
|
uint32_t minDisplayLuminance;
|
||||||
// MaxCLL and MaxFALL in cd/m²
|
// MaxCLL and MaxFALL in cd/m²
|
||||||
uint32_t maxContentLightLevel;
|
uint32_t maxContentLightLevel;
|
||||||
|
|||||||
@@ -206,6 +206,7 @@ bool CSwapChainProcessor::SwapChainThreadCore()
|
|||||||
surface = buffer.MetaData.pSurface;
|
surface = buffer.MetaData.pSurface;
|
||||||
colorSpace = buffer.MetaData.SurfaceColorSpace;
|
colorSpace = buffer.MetaData.SurfaceColorSpace;
|
||||||
sdrWhiteLevel = buffer.MetaData.SdrWhiteLevel;
|
sdrWhiteLevel = buffer.MetaData.SdrWhiteLevel;
|
||||||
|
UpdateHDRMetadata(buffer.MetaData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -398,6 +399,72 @@ void CSwapChainProcessor::AccumulateFrameDamage(
|
|||||||
m_nbPendingDirtyRects += nbDirtyRects;
|
m_nbPendingDirtyRects += nbDirtyRects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAS_IDDCX_110
|
||||||
|
void CSwapChainProcessor::UpdateHDRMetadata(const IDDCX_METADATA2& metadata)
|
||||||
|
{
|
||||||
|
if (!(metadata.ValidFlags & IDDCX_METADATA2_VALID_FLAGS_HDR10METADATA))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const IDDCX_HDR10_FRAME_METADATA& frame = metadata.Hdr10FrameMetaData;
|
||||||
|
switch (frame.Type)
|
||||||
|
{
|
||||||
|
case IDDCX_HDR10_FRAME_METADATA_TYPE_DEFAULT:
|
||||||
|
if (!m_useDefaultHDRMetadata)
|
||||||
|
DEBUG_TRACE("HDR10 frame metadata switched to the monitor default");
|
||||||
|
m_useDefaultHDRMetadata = true;
|
||||||
|
m_hasNewHDRMetadata = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDDCX_HDR10_FRAME_METADATA_TYPE_UNCHANGED:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDDCX_HDR10_FRAME_METADATA_TYPE_NEW:
|
||||||
|
if (!m_hasNewHDRMetadata ||
|
||||||
|
memcmp(&m_newHDRMetadata, &frame.NewMetaData,
|
||||||
|
sizeof(m_newHDRMetadata)) != 0)
|
||||||
|
DEBUG_TRACE("Received new HDR10 frame metadata");
|
||||||
|
m_newHDRMetadata = frame.NewMetaData;
|
||||||
|
m_useDefaultHDRMetadata = false;
|
||||||
|
m_hasNewHDRMetadata = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
DEBUG_WARN("Invalid HDR10 frame metadata type %u",
|
||||||
|
static_cast<unsigned>(frame.Type));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool CSwapChainProcessor::GetHDRMetadata(D12FrameFormat& format) const
|
||||||
|
{
|
||||||
|
#ifdef HAS_IDDCX_110
|
||||||
|
if (m_useDefaultHDRMetadata)
|
||||||
|
return m_devContext->GetHDRMetadata(format);
|
||||||
|
|
||||||
|
if (!m_hasNewHDRMetadata)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const IDDCX_HDR10_METADATA& metadata = m_newHDRMetadata;
|
||||||
|
format.displayPrimary[0][0] = metadata.RedPrimary [0];
|
||||||
|
format.displayPrimary[0][1] = metadata.RedPrimary [1];
|
||||||
|
format.displayPrimary[1][0] = metadata.GreenPrimary[0];
|
||||||
|
format.displayPrimary[1][1] = metadata.GreenPrimary[1];
|
||||||
|
format.displayPrimary[2][0] = metadata.BluePrimary [0];
|
||||||
|
format.displayPrimary[2][1] = metadata.BluePrimary [1];
|
||||||
|
format.whitePoint [0] = metadata.WhitePoint [0];
|
||||||
|
format.whitePoint [1] = metadata.WhitePoint [1];
|
||||||
|
format.maxDisplayLuminance = metadata.MaxMasteringLuminance;
|
||||||
|
format.minDisplayLuminance = metadata.MinMasteringLuminance;
|
||||||
|
format.maxContentLightLevel = metadata.MaxContentLightLevel;
|
||||||
|
format.maxFrameAverageLightLevel = metadata.MaxFrameAverageLightLevel;
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
UNREFERENCED_PARAMETER(format);
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer, unsigned dirtyRectCount,
|
bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer, unsigned dirtyRectCount,
|
||||||
DXGI_COLOR_SPACE_TYPE colorSpace, UINT sdrWhiteLevel)
|
DXGI_COLOR_SPACE_TYPE colorSpace, UINT sdrWhiteLevel)
|
||||||
{
|
{
|
||||||
@@ -480,7 +547,7 @@ bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer
|
|||||||
// already applied to the pixel data.
|
// already applied to the pixel data.
|
||||||
srcFormat.hdr = true;
|
srcFormat.hdr = true;
|
||||||
srcFormat.hdrPQ = true;
|
srcFormat.hdrPQ = true;
|
||||||
if (!m_devContext->GetHDRMetadata(srcFormat))
|
if (!GetHDRMetadata(srcFormat))
|
||||||
{
|
{
|
||||||
// HDR is active but the OS has not delivered static metadata yet
|
// HDR is active but the OS has not delivered static metadata yet
|
||||||
// (e.g. a brief window during a mode switch). The pixels are still
|
// (e.g. a brief window during a mode switch). The pixels are still
|
||||||
@@ -504,6 +571,8 @@ bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer
|
|||||||
srcFormat.maxContentLightLevel = 0;
|
srcFormat.maxContentLightLevel = 0;
|
||||||
srcFormat.maxFrameAverageLightLevel = 0;
|
srcFormat.maxFrameAverageLightLevel = 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
srcFormat.hdrMetadata = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709:
|
case DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709:
|
||||||
@@ -511,7 +580,7 @@ bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer
|
|||||||
// curve has not been applied.
|
// curve has not been applied.
|
||||||
srcFormat.hdr = true;
|
srcFormat.hdr = true;
|
||||||
srcFormat.hdrPQ = false;
|
srcFormat.hdrPQ = false;
|
||||||
if (!m_devContext->GetHDRMetadata(srcFormat))
|
if (!GetHDRMetadata(srcFormat))
|
||||||
{
|
{
|
||||||
// No HDR metadata from the OS; provide reasonable defaults
|
// No HDR metadata from the OS; provide reasonable defaults
|
||||||
// so downstream consumers have valid primaries and luminances.
|
// so downstream consumers have valid primaries and luminances.
|
||||||
@@ -533,6 +602,8 @@ bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer
|
|||||||
srcFormat.maxContentLightLevel = 0;
|
srcFormat.maxContentLightLevel = 0;
|
||||||
srcFormat.maxFrameAverageLightLevel = 0;
|
srcFormat.maxFrameAverageLightLevel = 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
srcFormat.hdrMetadata = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -75,6 +75,14 @@ private:
|
|||||||
unsigned m_nbPendingDirtyRects = 0;
|
unsigned m_nbPendingDirtyRects = 0;
|
||||||
bool m_hasPendingDamage = true;
|
bool m_hasPendingDamage = true;
|
||||||
|
|
||||||
|
#ifdef HAS_IDDCX_110
|
||||||
|
// The per-frame metadata stream can select the monitor default, provide a
|
||||||
|
// replacement block, or retain the selection from the previous frame.
|
||||||
|
bool m_useDefaultHDRMetadata = true;
|
||||||
|
bool m_hasNewHDRMetadata = false;
|
||||||
|
IDDCX_HDR10_METADATA m_newHDRMetadata = {};
|
||||||
|
#endif
|
||||||
|
|
||||||
static DWORD CALLBACK _SwapChainThread(LPVOID arg);
|
static DWORD CALLBACK _SwapChainThread(LPVOID arg);
|
||||||
void SwapChainThread();
|
void SwapChainThread();
|
||||||
bool SwapChainThreadCore();
|
bool SwapChainThreadCore();
|
||||||
@@ -87,6 +95,10 @@ private:
|
|||||||
CD3D12CommandQueue * queue, bool result, void * param1, void * param2);
|
CD3D12CommandQueue * queue, bool result, void * param1, void * param2);
|
||||||
void AccumulateFrameDamage(const RECT * dirtyRects, unsigned nbDirtyRects);
|
void AccumulateFrameDamage(const RECT * dirtyRects, unsigned nbDirtyRects);
|
||||||
void SetFullPendingDamage();
|
void SetFullPendingDamage();
|
||||||
|
#ifdef HAS_IDDCX_110
|
||||||
|
void UpdateHDRMetadata(const IDDCX_METADATA2& metadata);
|
||||||
|
#endif
|
||||||
|
bool GetHDRMetadata(D12FrameFormat& format) const;
|
||||||
bool SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer, unsigned dirtyRectCount,
|
bool SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer, unsigned dirtyRectCount,
|
||||||
DXGI_COLOR_SPACE_TYPE colorSpace, UINT sdrWhiteLevel);
|
DXGI_COLOR_SPACE_TYPE colorSpace, UINT sdrWhiteLevel);
|
||||||
|
|
||||||
|
|||||||
@@ -123,18 +123,10 @@ PostProcessStatus CHDR16to10Effect::SetFormat(
|
|||||||
dst.hdr = true;
|
dst.hdr = true;
|
||||||
dst.hdrPQ = true;
|
dst.hdrPQ = true;
|
||||||
|
|
||||||
// Explicitly propagate HDR static metadata so it survives post-processing.
|
// Gamut conversion changes the signal's container primaries to BT.2020, but
|
||||||
// Do not rely on the caller's copy semantics in CPostProcessor::Configure().
|
// does not change the mastering display chromaticities described by ST 2086.
|
||||||
// The shader rotates the gamut from BT.709 to BT.2020, so advertise BT.2020
|
dst.hdrMetadata = src.hdrMetadata;
|
||||||
// mastering primaries here rather than forwarding the source's BT.709 set
|
memcpy(dst.displayPrimary, src.displayPrimary, sizeof(dst.displayPrimary));
|
||||||
// (in 0.00002 units) - otherwise consumers see PQ/BT.2020 content tagged
|
|
||||||
// with BT.709 primaries.
|
|
||||||
dst.displayPrimary[0][0] = 35400; // Rx
|
|
||||||
dst.displayPrimary[0][1] = 14600; // Ry
|
|
||||||
dst.displayPrimary[1][0] = 8500; // Gx
|
|
||||||
dst.displayPrimary[1][1] = 39850; // Gy
|
|
||||||
dst.displayPrimary[2][0] = 6550; // Bx
|
|
||||||
dst.displayPrimary[2][1] = 2300; // By
|
|
||||||
memcpy(dst.whitePoint , src.whitePoint , sizeof(dst.whitePoint ));
|
memcpy(dst.whitePoint , src.whitePoint , sizeof(dst.whitePoint ));
|
||||||
dst.maxDisplayLuminance = src.maxDisplayLuminance;
|
dst.maxDisplayLuminance = src.maxDisplayLuminance;
|
||||||
dst.minDisplayLuminance = src.minDisplayLuminance;
|
dst.minDisplayLuminance = src.minDisplayLuminance;
|
||||||
|
|||||||
Reference in New Issue
Block a user