mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-07-21 14:52:04 +00:00
[idd] hdr: publish only per-content metadata
Monitor-default HDR metadata describes the virtual display rather than the captured content. Do not expose it through KVMFR or use it to select downstream processing limits. Only publish explicit NEW frame metadata and otherwise use the complete PQ range internally.
This commit is contained in:
@@ -1336,59 +1336,6 @@ CIndirectDeviceContext::GetColorTransform() const
|
|||||||
return transform;
|
return transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAS_IDDCX_110
|
|
||||||
void CIndirectDeviceContext::SetHDRActive(const struct IDDCX_HDR10_METADATA * hdrMeta)
|
|
||||||
{
|
|
||||||
AcquireSRWLockExclusive(&m_hdrLock);
|
|
||||||
|
|
||||||
if (!hdrMeta)
|
|
||||||
{
|
|
||||||
m_hdrActive = false;
|
|
||||||
ReleaseSRWLockExclusive(&m_hdrLock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_hdrActive = true;
|
|
||||||
|
|
||||||
m_hdrDisplayPrimary[0][0] = hdrMeta->RedPrimary [0];
|
|
||||||
m_hdrDisplayPrimary[0][1] = hdrMeta->RedPrimary [1];
|
|
||||||
m_hdrDisplayPrimary[1][0] = hdrMeta->GreenPrimary[0];
|
|
||||||
m_hdrDisplayPrimary[1][1] = hdrMeta->GreenPrimary[1];
|
|
||||||
m_hdrDisplayPrimary[2][0] = hdrMeta->BluePrimary [0];
|
|
||||||
m_hdrDisplayPrimary[2][1] = hdrMeta->BluePrimary [1];
|
|
||||||
m_hdrWhitePoint [0] = hdrMeta->WhitePoint [0];
|
|
||||||
m_hdrWhitePoint [1] = hdrMeta->WhitePoint [1];
|
|
||||||
|
|
||||||
m_hdrMaxDisplayLuminance = hdrMeta->MaxMasteringLuminance;
|
|
||||||
m_hdrMinDisplayLuminance = hdrMeta->MinMasteringLuminance;
|
|
||||||
m_hdrMaxContentLightLevel = hdrMeta->MaxContentLightLevel;
|
|
||||||
m_hdrMaxFrameAverageLightLevel = hdrMeta->MaxFrameAverageLightLevel;
|
|
||||||
|
|
||||||
ReleaseSRWLockExclusive(&m_hdrLock);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool CIndirectDeviceContext::GetHDRMetadata(D12FrameFormat & format) const
|
|
||||||
{
|
|
||||||
AcquireSRWLockShared(&m_hdrLock);
|
|
||||||
|
|
||||||
if (!m_hdrActive)
|
|
||||||
{
|
|
||||||
ReleaseSRWLockShared(&m_hdrLock);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(format.displayPrimary, m_hdrDisplayPrimary, sizeof(format.displayPrimary));
|
|
||||||
memcpy(format.whitePoint , m_hdrWhitePoint , sizeof(format.whitePoint ));
|
|
||||||
format.maxDisplayLuminance = m_hdrMaxDisplayLuminance;
|
|
||||||
format.minDisplayLuminance = m_hdrMinDisplayLuminance;
|
|
||||||
format.maxContentLightLevel = m_hdrMaxContentLightLevel;
|
|
||||||
format.maxFrameAverageLightLevel = m_hdrMaxFrameAverageLightLevel;
|
|
||||||
|
|
||||||
ReleaseSRWLockShared(&m_hdrLock);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CIndirectDeviceContext::SendColorTransform()
|
void CIndirectDeviceContext::SendColorTransform()
|
||||||
{
|
{
|
||||||
if (!m_pointerQueue || !m_pointerTransformMemory[0])
|
if (!m_pointerQueue || !m_pointerTransformMemory[0])
|
||||||
|
|||||||
@@ -119,18 +119,6 @@ private:
|
|||||||
bool m_canProcessFP16 = false;
|
bool m_canProcessFP16 = false;
|
||||||
bool m_softwareMode = true;
|
bool m_softwareMode = true;
|
||||||
|
|
||||||
// HDR state from EvtIddCxMonitorSetDefaultHdrMetadata (IddCx 1.10+)
|
|
||||||
// Protected by m_hdrLock - accessed from both the IDD callback thread
|
|
||||||
// (SetHDRActive) and the swap-chain thread (PrepareFrameBuffer, GetHDRMetadata).
|
|
||||||
mutable SRWLOCK m_hdrLock = SRWLOCK_INIT;
|
|
||||||
bool m_hdrActive = false;
|
|
||||||
uint16_t m_hdrDisplayPrimary[3][2] = {};
|
|
||||||
uint16_t m_hdrWhitePoint[2] = {};
|
|
||||||
uint32_t m_hdrMaxDisplayLuminance = 0;
|
|
||||||
uint32_t m_hdrMinDisplayLuminance = 0;
|
|
||||||
uint32_t m_hdrMaxContentLightLevel = 0;
|
|
||||||
uint32_t m_hdrMaxFrameAverageLightLevel = 0;
|
|
||||||
|
|
||||||
// Previous HDR metadata used to detect changes for formatVer bumps
|
// Previous HDR metadata used to detect changes for formatVer bumps
|
||||||
uint16_t m_lastHDRDisplayPrimary[3][2] = {};
|
uint16_t m_lastHDRDisplayPrimary[3][2] = {};
|
||||||
uint16_t m_lastHDRWhitePoint[2] = {};
|
uint16_t m_lastHDRWhitePoint[2] = {};
|
||||||
@@ -231,25 +219,9 @@ public:
|
|||||||
void SendCursor(const IDARG_OUT_QUERY_HWCURSOR & info, const BYTE * data,
|
void SendCursor(const IDARG_OUT_QUERY_HWCURSOR & info, const BYTE * data,
|
||||||
UINT sdrWhiteLevel);
|
UINT sdrWhiteLevel);
|
||||||
|
|
||||||
// Tracks HDR state from EvtIddCxMonitorSetDefaultHdrMetadata
|
|
||||||
void SetHDRActive(const struct IDDCX_HDR10_METADATA * hdrMeta);
|
|
||||||
|
|
||||||
void SetColorTransform(std::shared_ptr<const D12ColorTransform> transform);
|
void SetColorTransform(std::shared_ptr<const D12ColorTransform> transform);
|
||||||
std::shared_ptr<const D12ColorTransform> GetColorTransform() const;
|
std::shared_ptr<const D12ColorTransform> GetColorTransform() const;
|
||||||
|
|
||||||
// Returns true if the display is currently in HDR mode
|
|
||||||
bool IsHDRActive() const
|
|
||||||
{
|
|
||||||
AcquireSRWLockShared(&m_hdrLock);
|
|
||||||
bool result = m_hdrActive;
|
|
||||||
ReleaseSRWLockShared(&m_hdrLock);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copies current HDR metadata into the provided D12FrameFormat.
|
|
||||||
// Returns true if HDR is active and metadata was copied.
|
|
||||||
bool GetHDRMetadata(D12FrameFormat & format) const;
|
|
||||||
|
|
||||||
CIVSHMEM &GetIVSHMEM() { return m_ivshmem; }
|
CIVSHMEM &GetIVSHMEM() { return m_ivshmem; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,9 @@
|
|||||||
#include "CDebug.h"
|
#include "CDebug.h"
|
||||||
#include "CPipeServer.h"
|
#include "CPipeServer.h"
|
||||||
|
|
||||||
|
static const uint32_t HDR_PQ_MIN_LUMINANCE = 50;
|
||||||
|
static const uint32_t HDR_PQ_MAX_LUMINANCE = 10000;
|
||||||
|
|
||||||
CSwapChainProcessor::CSwapChainProcessor(CIndirectMonitorContext * monitorContext,
|
CSwapChainProcessor::CSwapChainProcessor(CIndirectMonitorContext * monitorContext,
|
||||||
UINT64 assignmentGeneration, IDDCX_MONITOR monitor,
|
UINT64 assignmentGeneration, IDDCX_MONITOR monitor,
|
||||||
CIndirectDeviceContext* devContext, IDDCX_SWAPCHAIN hSwapChain,
|
CIndirectDeviceContext* devContext, IDDCX_SWAPCHAIN hSwapChain,
|
||||||
@@ -439,13 +442,12 @@ void CSwapChainProcessor::UpdateHDRMetadata(const IDDCX_METADATA2& metadata)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool CSwapChainProcessor::GetHDRMetadata(D12FrameFormat& format) const
|
bool CSwapChainProcessor::GetContentHDRMetadata(D12FrameFormat& format) const
|
||||||
{
|
{
|
||||||
#ifdef HAS_IDDCX_110
|
#ifdef HAS_IDDCX_110
|
||||||
if (m_useDefaultHDRMetadata)
|
// The monitor default describes the virtual display, not the content. Only
|
||||||
return m_devContext->GetHDRMetadata(format);
|
// publish an explicit per-frame metadata block to downstream consumers.
|
||||||
|
if (m_useDefaultHDRMetadata || !m_hasNewHDRMetadata)
|
||||||
if (!m_hasNewHDRMetadata)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const IDDCX_HDR10_METADATA& metadata = m_newHDRMetadata;
|
const IDDCX_HDR10_METADATA& metadata = m_newHDRMetadata;
|
||||||
@@ -551,12 +553,11 @@ 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 (!GetHDRMetadata(srcFormat))
|
if (!GetContentHDRMetadata(srcFormat))
|
||||||
{
|
{
|
||||||
// HDR is active but the OS has not delivered static metadata yet
|
// No per-content metadata is active. The pixels are still PQ-encoded,
|
||||||
// (e.g. a brief window during a mode switch). The pixels are still
|
// so keep the PQ flag and use BT.2020/PQ defaults internally rather
|
||||||
// PQ-encoded, so keep the PQ flag and supply BT.2020/PQ defaults
|
// than publishing the virtual monitor metadata as content metadata.
|
||||||
// rather than mislabel the frame as SDR.
|
|
||||||
// BT.2020 primaries (in 0.00002 units):
|
// BT.2020 primaries (in 0.00002 units):
|
||||||
srcFormat.displayPrimary[0][0] = 35400; // Rx
|
srcFormat.displayPrimary[0][0] = 35400; // Rx
|
||||||
srcFormat.displayPrimary[0][1] = 14600; // Ry
|
srcFormat.displayPrimary[0][1] = 14600; // Ry
|
||||||
@@ -567,10 +568,9 @@ bool CSwapChainProcessor::SwapChainNewFrame(ComPtr<IDXGIResource> acquiredBuffer
|
|||||||
// D65 white point (in 0.00002 units):
|
// D65 white point (in 0.00002 units):
|
||||||
srcFormat.whitePoint[0] = 15635;
|
srcFormat.whitePoint[0] = 15635;
|
||||||
srcFormat.whitePoint[1] = 16450;
|
srcFormat.whitePoint[1] = 16450;
|
||||||
// Mastering luminances follow SMPTE ST 2086 units: max in whole cd/m²,
|
// Cover the complete PQ signal range.
|
||||||
// min in 0.0001 cd/m². 1000 cd/m² display, 0.0001 cd/m² black:
|
srcFormat.maxDisplayLuminance = HDR_PQ_MAX_LUMINANCE;
|
||||||
srcFormat.maxDisplayLuminance = 1000;
|
srcFormat.minDisplayLuminance = HDR_PQ_MIN_LUMINANCE;
|
||||||
srcFormat.minDisplayLuminance = 1;
|
|
||||||
// Content light levels unknown:
|
// Content light levels unknown:
|
||||||
srcFormat.maxContentLightLevel = 0;
|
srcFormat.maxContentLightLevel = 0;
|
||||||
srcFormat.maxFrameAverageLightLevel = 0;
|
srcFormat.maxFrameAverageLightLevel = 0;
|
||||||
@@ -584,10 +584,10 @@ 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 (!GetHDRMetadata(srcFormat))
|
if (!GetContentHDRMetadata(srcFormat))
|
||||||
{
|
{
|
||||||
// No HDR metadata from the OS; provide reasonable defaults
|
// No per-content metadata is active. Use reasonable internal defaults
|
||||||
// so downstream consumers have valid primaries and luminances.
|
// without publishing the virtual monitor metadata downstream.
|
||||||
// BT.709/sRGB primaries (in 0.00002 units):
|
// BT.709/sRGB primaries (in 0.00002 units):
|
||||||
srcFormat.displayPrimary[0][0] = 13250; // Rx
|
srcFormat.displayPrimary[0][0] = 13250; // Rx
|
||||||
srcFormat.displayPrimary[0][1] = 34500; // Ry
|
srcFormat.displayPrimary[0][1] = 34500; // Ry
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ private:
|
|||||||
#ifdef HAS_IDDCX_110
|
#ifdef HAS_IDDCX_110
|
||||||
void UpdateHDRMetadata(const IDDCX_METADATA2& metadata);
|
void UpdateHDRMetadata(const IDDCX_METADATA2& metadata);
|
||||||
#endif
|
#endif
|
||||||
bool GetHDRMetadata(D12FrameFormat& format) const;
|
bool GetContentHDRMetadata(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);
|
||||||
|
|
||||||
|
|||||||
@@ -191,17 +191,11 @@ NTSTATUS LGIddAdapterCommitModes2(IDDCX_ADAPTER adapter, const IDARG_IN_COMMITMO
|
|||||||
NTSTATUS LGIddMonitorSetDefaultHdrMetadata(IDDCX_MONITOR monitor,
|
NTSTATUS LGIddMonitorSetDefaultHdrMetadata(IDDCX_MONITOR monitor,
|
||||||
const IDARG_IN_MONITOR_SET_DEFAULT_HDR_METADATA* inArgs)
|
const IDARG_IN_MONITOR_SET_DEFAULT_HDR_METADATA* inArgs)
|
||||||
{
|
{
|
||||||
auto* wrapper = WdfObjectGet_CIndirectMonitorContextWrapper(monitor);
|
UNREFERENCED_PARAMETER(monitor);
|
||||||
auto* ctx = wrapper->context->GetDeviceContext();
|
UNREFERENCED_PARAMETER(inArgs);
|
||||||
|
|
||||||
if (ctx->IsSoftwareMode())
|
|
||||||
{
|
|
||||||
ctx->SetHDRActive(nullptr);
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->SetHDRActive(inArgs->Data.pHdr10);
|
|
||||||
|
|
||||||
|
// This metadata describes the virtual monitor. Explicit per-content HDR10
|
||||||
|
// metadata is obtained from the swap chain and forwarded separately.
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user