[idd] disable HDR and post-processing when in software mode

This commit is contained in:
Geoffrey McRae
2026-07-19 05:51:59 +10:00
parent bea35a030b
commit 653cecadeb
12 changed files with 215 additions and 99 deletions

View File

@@ -60,10 +60,13 @@ static void CALLBACK _D3D12DebugCallback(
description);
}
CD3D12Device::InitResult CD3D12Device::Init(CIVSHMEM &ivshmem, UINT64 &alignSize)
CD3D12Device::InitResult CD3D12Device::Init(CIVSHMEM &ivshmem,
UINT64 &alignSize, bool enableCompute)
{
HRESULT hr;
m_computeEnabled = enableCompute;
hr = CreateDXGIFactory2(m_debug ? DXGI_CREATE_FACTORY_DEBUG : 0, IID_PPV_ARGS(&m_factory));
if (FAILED(hr))
{
@@ -132,8 +135,9 @@ CD3D12Device::InitResult CD3D12Device::Init(CIVSHMEM &ivshmem, UINT64 &alignSize
m_indirectCopy ? CD3D12CommandQueue::NORMAL : CD3D12CommandQueue::FAST))
return InitResult::FAILURE;
if (!m_computeQueue.Init(m_device.Get(), D3D12_COMMAND_LIST_TYPE_COMPUTE, L"Compute",
CD3D12CommandQueue::FAST))
if (m_computeEnabled &&
!m_computeQueue.Init(m_device.Get(), D3D12_COMMAND_LIST_TYPE_COMPUTE,
L"Compute", CD3D12CommandQueue::FAST))
return InitResult::FAILURE;
DEBUG_INFO("Created CD3D12Device");
@@ -160,7 +164,8 @@ void CD3D12Device::WaitForIdle()
for (int i = 0; i < ARRAYSIZE(m_copyQueue); ++i)
drain(m_copyQueue[i]);
drain(m_computeQueue);
if (m_computeEnabled)
drain(m_computeQueue);
}
bool CD3D12Device::HeapTest()
@@ -233,6 +238,12 @@ CD3D12CommandQueue * CD3D12Device::GetCopyQueue()
CD3D12CommandQueue * CD3D12Device::GetComputeQueue()
{
if (!m_computeEnabled)
{
DEBUG_ERROR("Compute queue requested while compute processing is disabled");
return nullptr;
}
for (int c = 0; c < 100; ++c)
{
if (m_computeQueue.IsReady())

View File

@@ -52,6 +52,7 @@ struct CD3D12Device
CD3D12CommandQueue m_copyQueue[4];
unsigned m_copyQueueIndex = 0;
CD3D12CommandQueue m_computeQueue;
bool m_computeEnabled = false;
bool HeapTest();
@@ -66,7 +67,8 @@ struct CD3D12Device
SUCCESS
};
InitResult Init(CIVSHMEM &ivshmem, UINT64 &alignSize);
InitResult Init(CIVSHMEM &ivshmem, UINT64 &alignSize,
bool enableCompute);
void DeInit();
// Wait for all command queues to finish in-flight GPU work and run their

View File

@@ -45,6 +45,7 @@ static const BYTE EDID_MANUFACTURE_YEAR_2026 = 36; // 1990 + 36 = 2026
static const BYTE EDID_VERSION = 1;
static const BYTE EDID_REVISION = 4;
static const BYTE EDID_VIDEO_INPUT_DIGITAL_8BPC_HDMI_A = 0xa2;
static const BYTE EDID_VIDEO_INPUT_DIGITAL_10BPC_HDMI_A = 0xb2;
static const BYTE EDID_HORIZONTAL_SIZE_CM = 52;
static const BYTE EDID_VERTICAL_SIZE_CM = 29;
@@ -316,17 +317,16 @@ static WORD EdidChromaticity(double value)
return (WORD)min(1023.0, max(0.0, value * 1024.0 + 0.5));
}
static void SetChromaticityCoordinates(BYTE coordinates[10])
static void SetChromaticityCoordinates(BYTE coordinates[10], bool hdr)
{
// The virtual display transports HDR in the BT.2020 container. Describe
// that full container gamut and its D65 white point rather than leaving an
// invalid all-zero base-block colour volume.
const WORD rx = EdidChromaticity(0.7080);
const WORD ry = EdidChromaticity(0.2920);
const WORD gx = EdidChromaticity(0.1700);
const WORD gy = EdidChromaticity(0.7970);
const WORD bx = EdidChromaticity(0.1310);
const WORD by = EdidChromaticity(0.0460);
// Describe the wire gamut. Accelerated HDR uses the BT.2020 container;
// software rendering is SDR-only and uses the standard sRGB/BT.709 gamut.
const WORD rx = EdidChromaticity(hdr ? 0.7080 : 0.6400);
const WORD ry = EdidChromaticity(hdr ? 0.2920 : 0.3300);
const WORD gx = EdidChromaticity(hdr ? 0.1700 : 0.3000);
const WORD gy = EdidChromaticity(hdr ? 0.7970 : 0.6000);
const WORD bx = EdidChromaticity(hdr ? 0.1310 : 0.1500);
const WORD by = EdidChromaticity(hdr ? 0.0460 : 0.0600);
const WORD wx = EdidChromaticity(0.3127);
const WORD wy = EdidChromaticity(0.3290);
@@ -344,7 +344,7 @@ static void SetChromaticityCoordinates(BYTE coordinates[10])
coordinates[9] = (BYTE)(wy >> 2);
}
static void InitEdidBaseBlock(EdidBaseBlock& base)
static void InitEdidBaseBlock(EdidBaseBlock& base, bool hdr)
{
memcpy(base.header, EDID_HEADER, sizeof(base.header));
@@ -358,12 +358,14 @@ static void InitEdidBaseBlock(EdidBaseBlock& base)
base.version = EDID_VERSION;
base.revision = EDID_REVISION;
base.videoInputDefinition = EDID_VIDEO_INPUT_DIGITAL_10BPC_HDMI_A;
base.videoInputDefinition = hdr ?
EDID_VIDEO_INPUT_DIGITAL_10BPC_HDMI_A :
EDID_VIDEO_INPUT_DIGITAL_8BPC_HDMI_A;
base.horizontalSizeCm = EDID_HORIZONTAL_SIZE_CM;
base.verticalSizeCm = EDID_VERTICAL_SIZE_CM;
base.displayGamma = EDID_DISPLAY_GAMMA_2_2;
base.supportedFeatures = EDID_FEATURES_PREFERRED_TIMING_RGB;
SetChromaticityCoordinates(base.chromaticityCoordinates);
SetChromaticityCoordinates(base.chromaticityCoordinates, hdr);
for (UINT i = 0; i < EDID_STANDARD_TIMING_COUNT; ++i)
base.standardTimings[i] = MakeUnusedStandardTiming();
@@ -572,12 +574,12 @@ bool CEdid::WriteDetailedTiming(BYTE* dtd, const CSettings::DisplayMode& mode)
return true;
}
void CEdid::Build(const CSettings::DisplayModes& modes)
void CEdid::Build(const CSettings::DisplayModes& modes, bool hdr)
{
m_data.assign(static_cast<std::vector<BYTE, std::allocator<BYTE>>::size_type>(EDID_BLOCK_SIZE) * 2, 0);
EdidBaseBlock baseBlock = {};
InitEdidBaseBlock(baseBlock);
InitEdidBaseBlock(baseBlock, hdr);
CSettings::DisplayModes sorted = modes;
std::stable_sort(sorted.begin(), sorted.end(),
@@ -625,10 +627,13 @@ void CEdid::Build(const CSettings::DisplayModes& modes)
ctaBlock.revision = CTA_REVISION;
UINT dataOffset = CTA_HEADER_SIZE;
AppendCtaDataBlock(cta, dataOffset, MakeCtaHdrStaticMetadataDataBlock ());
AppendCtaDataBlock(cta, dataOffset, MakeCtaColorimetryDataBlock ());
AppendCtaDataBlock(cta, dataOffset, MakeCtaHdmiForumVendorSpecificDataBlock());
AppendCtaDataBlock(cta, dataOffset, MakeCtaHdmiVendorSpecificDataBlock ());
if (hdr)
{
AppendCtaDataBlock(cta, dataOffset, MakeCtaHdrStaticMetadataDataBlock ());
AppendCtaDataBlock(cta, dataOffset, MakeCtaColorimetryDataBlock ());
AppendCtaDataBlock(cta, dataOffset, MakeCtaHdmiForumVendorSpecificDataBlock());
AppendCtaDataBlock(cta, dataOffset, MakeCtaHdmiVendorSpecificDataBlock ());
}
ctaBlock.dtdOffset = (BYTE)dataOffset;
ctaBlock.flags = 0x00;

View File

@@ -29,7 +29,7 @@
class CEdid
{
public:
void Build(const CSettings::DisplayModes& modes);
void Build(const CSettings::DisplayModes& modes, bool hdr);
const BYTE* Data() const { return m_data.empty() ? nullptr : m_data.data(); }
UINT Size() const { return (UINT)m_data.size(); }

View File

@@ -27,6 +27,7 @@
#include "CDebug.h"
#include "VersionInfo.h"
#include <dxgi1_2.h>
#include <sstream>
static const struct LGMPQueueConfig FRAME_QUEUE_CONFIG =
@@ -67,6 +68,7 @@ void CIndirectDeviceContext::QueryIddCxCapabilities()
if (!NT_SUCCESS(status))
{
m_iddCxVersion = 0;
m_hasIddCx110DDIs = false;
m_canProcessFP16 = false;
DEBUG_ERROR_HR(status, "IddCxGetVersion Failed");
return;
@@ -89,10 +91,15 @@ void CIndirectDeviceContext::QueryIddCxCapabilities()
const bool hasIddCx110DDIs = false;
#endif
m_canProcessFP16 = m_iddCxVersion >= IDDCX_VERSION_1_10 && hasIddCx110DDIs;
m_hasIddCx110DDIs =
m_iddCxVersion >= IDDCX_VERSION_1_10 && hasIddCx110DDIs;
m_canProcessFP16 = !m_softwareMode && m_hasIddCx110DDIs;
DEBUG_INFO("IddCx version: 0x%04x", m_iddCxVersion);
DEBUG_INFO("IddCx 1.10 HDR/WCG DDIs: %s", m_canProcessFP16 ? "available" : "unavailable");
DEBUG_INFO("IddCx 1.10 HDR/WCG DDIs: %s",
m_hasIddCx110DDIs ? "available" : "unavailable");
if (m_softwareMode && m_hasIddCx110DDIs)
DEBUG_INFO("HDR/WCG disabled for software rendering");
}
void CIndirectDeviceContext::PopulateDefaultModes()
@@ -117,7 +124,7 @@ void CIndirectDeviceContext::InitializeEdid()
{
AcquireSRWLockExclusive(&m_modeLock);
if (!m_edid.Size())
m_edid.Build(m_displayModes);
m_edid.Build(m_displayModes, CanProcessFP16());
ReleaseSRWLockExclusive(&m_modeLock);
}
@@ -194,6 +201,68 @@ void CIndirectDeviceContext::InitAdapter()
m_ivshmemOpened = true;
}
// Select the render adapter before advertising capabilities. If no hardware
// adapter is available, this is a software-rendered display and must remain
// SDR-only; the software path must never depend on compute processing.
bool havePreferredRenderAdapter = false;
LUID preferredRenderAdapter = {};
IDXGIFactory1 * factory = NULL;
HRESULT factoryStatus = CreateDXGIFactory(
__uuidof(IDXGIFactory1), (void **)&factory);
if (FAILED(factoryStatus))
DEBUG_ERROR_HR(factoryStatus, "CreateDXGIFactory Failed");
else
{
for (UINT i = 0;; ++i)
{
IDXGIAdapter1 * dxgiAdapter = nullptr;
HRESULT enumStatus = factory->EnumAdapters1(i, &dxgiAdapter);
if (enumStatus == DXGI_ERROR_NOT_FOUND)
break;
if (FAILED(enumStatus))
{
DEBUG_ERROR_HR(enumStatus, "Failed to enumerate DXGI adapter %u", i);
break;
}
DXGI_ADAPTER_DESC1 adapterDesc = {};
HRESULT descStatus = dxgiAdapter->GetDesc1(&adapterDesc);
dxgiAdapter->Release();
if (FAILED(descStatus))
{
DEBUG_ERROR_HR(descStatus, "Failed to query DXGI adapter %u", i);
continue;
}
if ((adapterDesc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) ||
(adapterDesc.VendorId == 0x1414 && adapterDesc.DeviceId == 0x008c))
{
DEBUG_INFO("Ignoring software render adapter %ls", adapterDesc.Description);
continue;
}
if ((adapterDesc.VendorId == 0x1b36 && adapterDesc.DeviceId == 0x000d) || // QXL
(adapterDesc.VendorId == 0x1234 && adapterDesc.DeviceId == 0x1111)) // QEMU Standard VGA
{
DEBUG_INFO("Ignoring display-only adapter %ls (vendor 0x%04x, device 0x%04x)",
adapterDesc.Description, adapterDesc.VendorId, adapterDesc.DeviceId);
continue;
}
DEBUG_INFO("Selected render adapter %ls (vendor 0x%04x, device 0x%04x)",
adapterDesc.Description, adapterDesc.VendorId, adapterDesc.DeviceId);
preferredRenderAdapter = adapterDesc.AdapterLuid;
havePreferredRenderAdapter = true;
break;
}
factory->Release();
}
m_softwareMode = !havePreferredRenderAdapter;
if (m_softwareMode)
DEBUG_INFO("No hardware render adapter available; using SDR software mode");
QueryIddCxCapabilities();
DEBUG_TRACE("Loading configured display modes");
PopulateDefaultModes();
@@ -218,7 +287,7 @@ void CIndirectDeviceContext::InitAdapter()
*/
caps.Flags = IDDCX_ADAPTER_FLAGS_USE_SMALLEST_MODE;
#ifdef HAS_IDDCX_110
if (CanUseIddCx110DDIs())
if (CanProcessFP16())
caps.Flags |= IDDCX_ADAPTER_FLAGS_CAN_PROCESS_FP16;
#endif
@@ -250,12 +319,17 @@ void CIndirectDeviceContext::InitAdapter()
DEBUG_INFO("Calling IddCxAdapterInitAsync with flags 0x%08x",
caps.Flags);
NTSTATUS status = IddCxAdapterInitAsync(&init, &initOut);
if (!NT_SUCCESS(status) && CanUseIddCx110DDIs())
if (!NT_SUCCESS(status) && CanProcessFP16())
{
DEBUG_WARN(
"IddCxAdapterInitAsync rejected FP16 adapter capabilities (0x%08x), retrying without HDR/WCG",
status);
m_canProcessFP16 = false;
// The monitor has not been created yet, so replace the provisional HDR
// EDID before Windows can observe it.
AcquireSRWLockExclusive(&m_modeLock);
m_edid.Build(m_displayModes, false);
ReleaseSRWLockExclusive(&m_modeLock);
caps.Flags = (IDDCX_ADAPTER_FLAGS)(caps.Flags & ~IDDCX_ADAPTER_FLAGS_CAN_PROCESS_FP16);
ZeroMemory(&initOut, sizeof(initOut));
status = IddCxAdapterInitAsync(&init, &initOut);
@@ -281,63 +355,12 @@ void CIndirectDeviceContext::InitAdapter()
// Try to co-exist with the virtual video device by telling IddCx which
// hardware adapter we prefer to render on.
IDXGIFactory * factory = NULL;
HRESULT factoryStatus = CreateDXGIFactory(
__uuidof(IDXGIFactory), (void **)&factory);
if (FAILED(factoryStatus))
DEBUG_ERROR_HR(factoryStatus, "CreateDXGIFactory Failed");
else
if (havePreferredRenderAdapter)
{
bool renderAdapterSelected = false;
for (UINT i = 0;; ++i)
{
IDXGIAdapter * dxgiAdapter = nullptr;
HRESULT enumStatus = factory->EnumAdapters(i, &dxgiAdapter);
if (enumStatus == DXGI_ERROR_NOT_FOUND)
break;
if (FAILED(enumStatus))
{
DEBUG_ERROR_HR(enumStatus, "Failed to enumerate DXGI adapter %u", i);
break;
}
DXGI_ADAPTER_DESC adapterDesc = {};
HRESULT descStatus = dxgiAdapter->GetDesc(&adapterDesc);
dxgiAdapter->Release();
if (FAILED(descStatus))
{
DEBUG_ERROR_HR(descStatus, "Failed to query DXGI adapter %u", i);
continue;
}
if (adapterDesc.VendorId == 0x1414 && adapterDesc.DeviceId == 0x008c)
{
DEBUG_INFO("Ignoring software render adapter %ls", adapterDesc.Description);
continue;
}
if ((adapterDesc.VendorId == 0x1b36 && adapterDesc.DeviceId == 0x000d) || // QXL
(adapterDesc.VendorId == 0x1234 && adapterDesc.DeviceId == 0x1111)) // QEMU Standard VGA
{
DEBUG_INFO("Ignoring display-only adapter %ls (vendor 0x%04x, device 0x%04x)",
adapterDesc.Description, adapterDesc.VendorId, adapterDesc.DeviceId);
continue;
}
DEBUG_INFO("Selecting render adapter %ls (vendor 0x%04x, device 0x%04x)",
adapterDesc.Description, adapterDesc.VendorId, adapterDesc.DeviceId);
IDARG_IN_ADAPTERSETRENDERADAPTER args = {};
args.PreferredRenderAdapter = adapterDesc.AdapterLuid;
IddCxAdapterSetRenderAdapter(m_adapter, &args);
DEBUG_INFO("Preferred render adapter set");
renderAdapterSelected = true;
break;
}
if (!renderAdapterSelected)
DEBUG_INFO("No preferred hardware render adapter was selected");
factory->Release();
IDARG_IN_ADAPTERSETRENDERADAPTER args = {};
args.PreferredRenderAdapter = preferredRenderAdapter;
IddCxAdapterSetRenderAdapter(m_adapter, &args);
DEBUG_INFO("Preferred render adapter set");
}
auto * wrapper = WdfObjectGet_CIndirectDeviceContextWrapper(m_adapter);
@@ -684,7 +707,7 @@ NTSTATUS CIndirectDeviceContext::ParseMonitorDescription2(
mode->Size = sizeof(IDDCX_MONITOR_MODE2);
mode->Origin = IDDCX_MONITOR_MODE_ORIGIN_MONITORDESCRIPTOR;
FillSignalInfo(mode->MonitorVideoSignalInfo, it->width, it->height, it->refresh, true);
mode->BitsPerComponent = GetWireBitsPerComponent(CanUseIddCx110DDIs());
mode->BitsPerComponent = GetWireBitsPerComponent(CanProcessFP16());
if (it->preferred)
outArgs->PreferredMonitorModeIdx =
@@ -716,7 +739,7 @@ NTSTATUS CIndirectDeviceContext::MonitorQueryTargetModes2(
ZeroMemory(mode, sizeof(*mode));
mode->Size = sizeof(IDDCX_TARGET_MODE2);
FillSignalInfo(mode->TargetVideoSignalInfo.targetVideoSignalInfo, it->width, it->height, it->refresh, false);
mode->BitsPerComponent = GetWireBitsPerComponent(CanUseIddCx110DDIs());
mode->BitsPerComponent = GetWireBitsPerComponent(CanProcessFP16());
}
return STATUS_SUCCESS;

View File

@@ -115,7 +115,9 @@ private:
DXGI_FORMAT m_format = DXGI_FORMAT_UNKNOWN;
FrameType m_frameType = FRAME_TYPE_INVALID;
UINT m_iddCxVersion = 0;
bool m_hasIddCx110DDIs = false;
bool m_canProcessFP16 = false;
bool m_softwareMode = true;
// HDR state from EvtIddCxMonitorSetDefaultHdrMetadata (IddCx 1.10+)
// Protected by m_hdrLock - accessed from both the IDD callback thread
@@ -147,7 +149,6 @@ private:
std::shared_ptr<const D12ColorTransform> m_colorTransform;
void QueryIddCxCapabilities();
bool CanUseIddCx110DDIs() const { return m_canProcessFP16; }
void ScheduleInitRetry();
void StopInitRetry();
@@ -211,7 +212,9 @@ public:
size_t GetAlignSize () const { return m_alignSize ; }
size_t GetMaxFrameSize() const { return m_maxFrameSize ; }
bool HasIddCx110DDIs() const { return m_hasIddCx110DDIs; }
bool CanProcessFP16 () const { return m_canProcessFP16; }
bool IsSoftwareMode () const { return m_softwareMode ; }
struct PreparedFrameBuffer
{

View File

@@ -64,7 +64,8 @@ void CIndirectMonitorContext::AssignSwapChain(IDDCX_SWAPCHAIN swapChain, LUID re
UINT64 alignSize = CPlatformInfo::GetPageSize();
dx12Device = std::make_shared<CD3D12Device>(renderAdapter);
CD3D12Device::InitResult r = dx12Device->Init(m_devContext->GetIVSHMEM(), alignSize);
CD3D12Device::InitResult r = dx12Device->Init(
m_devContext->GetIVSHMEM(), alignSize, !dx11Device->IsSoftware());
if (r == CD3D12Device::RETRY)
{
dx12Device.reset();

View File

@@ -30,6 +30,46 @@
#include <cstring>
#include <utility>
namespace
{
bool NearlyEqual(float a, float b, float tolerance)
{
const float delta = a - b;
return delta >= -tolerance && delta <= tolerance;
}
}
bool IsIdentityColorTransform(const D12ColorTransform& transform)
{
static const float matrixTolerance = 1.0f / 1048576.0f;
static const float lutTolerance = 1.0f / 65535.0f;
if (transform.matrixEnabled)
{
for (unsigned row = 0; row < 3; ++row)
for (unsigned column = 0; column < 4; ++column)
{
const float expected = row == column ? 1.0f : 0.0f;
const float effective =
transform.matrix[row][column] * transform.scalar;
if (!NearlyEqual(effective, expected, matrixTolerance))
return false;
}
}
if (transform.lutEnabled)
for (unsigned i = 0; i < 4096; ++i)
{
const float expected = (float)i / 4095.0f;
if (!NearlyEqual(transform.lut[i][0], expected, lutTolerance) ||
!NearlyEqual(transform.lut[i][1], expected, lutTolerance) ||
!NearlyEqual(transform.lut[i][2], expected, lutTolerance))
return false;
}
return true;
}
static void CopyHDRMetadata(D12FrameFormat& dst, const D12FrameFormat& src)
{
dst.hdrMetadata = src.hdrMetadata;

View File

@@ -52,6 +52,8 @@ struct D12ColorTransform
float lut[4096][4] = {};
};
bool IsIdentityColorTransform(const D12ColorTransform& transform);
struct D12FrameFormat
{
D3D12_RESOURCE_DESC desc = {};

View File

@@ -40,7 +40,9 @@ CSwapChainProcessor::CSwapChainProcessor(CIndirectMonitorContext * monitorContex
{
m_resPool.Init(dx11Device, dx12Device);
m_fbPool.Init(this);
if (!m_postProcessor.Init(dx12Device))
if (m_dx11Device->IsSoftware())
DEBUG_INFO("Software render adapter: post-processing disabled");
else if (!m_postProcessor.Init(dx12Device))
DEBUG_ERROR("Failed to initialize post processor");
// Manual-reset: both worker threads wait on this, so it must stay signalled
@@ -189,7 +191,7 @@ bool CSwapChainProcessor::SwapChainThreadCore()
UINT sdrWhiteLevel = KVMFR_SDR_WHITE_LEVEL_DEFAULT;
#ifdef HAS_IDDCX_110
if (m_devContext->CanProcessFP16())
if (m_devContext->HasIddCx110DDIs())
{
IDARG_IN_RELEASEANDACQUIREBUFFER2 acquireIn = {};
acquireIn.Size = sizeof(acquireIn);
@@ -780,7 +782,7 @@ bool CSwapChainProcessor::QueryHWCursor()
UINT cursorWhiteLevel = m_sdrWhiteLevel.load(std::memory_order_relaxed);
NTSTATUS status;
#ifdef HAS_IDDCX_110
if (m_devContext->CanProcessFP16())
if (m_devContext->HasIddCx110DDIs())
{
IDARG_OUT_QUERY_HWCURSOR3 out3 = {};
status = IddCxMonitorQueryHardwareCursor3(m_monitor, &in, &out3);

View File

@@ -160,13 +160,20 @@ NTSTATUS LGIddParseMonitorDescription2(const IDARG_IN_PARSEMONITORDESCRIPTION2*
NTSTATUS LGIddAdapterQueryTargetInfo(IDDCX_ADAPTER adapter,
IDARG_IN_QUERYTARGET_INFO* inArgs, IDARG_OUT_QUERYTARGET_INFO* outArgs)
{
UNREFERENCED_PARAMETER(adapter);
UNREFERENCED_PARAMETER(inArgs);
outArgs->TargetCaps =
(IDDCX_TARGET_CAPS)(IDDCX_TARGET_CAPS_WIDE_COLOR_SPACE | IDDCX_TARGET_CAPS_HIGH_COLOR_SPACE);
outArgs->DitheringSupport.Rgb =
(IDDCX_BITS_PER_COMPONENT)(IDDCX_BITS_PER_COMPONENT_8 | IDDCX_BITS_PER_COMPONENT_10);
auto* wrapper = WdfObjectGet_CIndirectDeviceContextWrapper(adapter);
const bool hdr = wrapper && wrapper->context &&
wrapper->context->CanProcessFP16();
outArgs->TargetCaps = hdr ?
(IDDCX_TARGET_CAPS)(IDDCX_TARGET_CAPS_WIDE_COLOR_SPACE |
IDDCX_TARGET_CAPS_HIGH_COLOR_SPACE) :
(IDDCX_TARGET_CAPS)0;
outArgs->DitheringSupport.Rgb = hdr ?
(IDDCX_BITS_PER_COMPONENT)(IDDCX_BITS_PER_COMPONENT_8 |
IDDCX_BITS_PER_COMPONENT_10) :
IDDCX_BITS_PER_COMPONENT_8;
outArgs->DitheringSupport.YCbCr444 = IDDCX_BITS_PER_COMPONENT_NONE;
outArgs->DitheringSupport.YCbCr422 = IDDCX_BITS_PER_COMPONENT_NONE;
outArgs->DitheringSupport.YCbCr420 = IDDCX_BITS_PER_COMPONENT_NONE;
@@ -187,6 +194,12 @@ NTSTATUS LGIddMonitorSetDefaultHdrMetadata(IDDCX_MONITOR monitor,
auto* wrapper = WdfObjectGet_CIndirectMonitorContextWrapper(monitor);
auto* ctx = wrapper->context->GetDeviceContext();
if (ctx->IsSoftwareMode())
{
ctx->SetHDRActive(nullptr);
return STATUS_SUCCESS;
}
ctx->SetHDRActive(inArgs->Data.pHdr10);
return STATUS_SUCCESS;
@@ -197,6 +210,13 @@ NTSTATUS LGIddMonitorSetGammaRamp(IDDCX_MONITOR monitor, const IDARG_IN_SET_GAMM
auto* wrapper = WdfObjectGet_CIndirectMonitorContextWrapper(monitor);
auto* ctx = wrapper->context->GetDeviceContext();
if (ctx->IsSoftwareMode())
{
ctx->SetColorTransform(nullptr);
DEBUG_INFO("Ignoring display color transform in software mode");
return STATUS_SUCCESS;
}
if (inArgs->Type == IDDCX_GAMMARAMP_TYPE_DEFAULT)
{
ctx->SetColorTransform(nullptr);
@@ -236,6 +256,13 @@ NTSTATUS LGIddMonitorSetGammaRamp(IDDCX_MONITOR monitor, const IDARG_IN_SET_GAMM
transform->lut[i][3] = 1.0f;
}
if (IsIdentityColorTransform(*transform))
{
ctx->SetColorTransform(nullptr);
DEBUG_INFO("Ignoring identity display color transform");
return STATUS_SUCCESS;
}
ctx->SetColorTransform(std::move(transform));
DEBUG_INFO("Display color transform updated (matrix:%d lut:%d)",
input->MatrixEnabled, input->LutEnabled);

View File

@@ -208,7 +208,7 @@ PostProcessStatus CColorTransformEffect::SetFormat(
const ComPtr<ID3D12Device3>& device,
const D12FrameFormat& src, D12FrameFormat& dst)
{
if (!src.colorTransform ||
if (!src.colorTransform || IsIdentityColorTransform(*src.colorTransform) ||
(!src.colorTransform->matrixEnabled && !src.colorTransform->lutEnabled))
return PostProcessStatus::BYPASS_EFFECT;