diff --git a/idd/LGIdd/CEdid.cpp b/idd/LGIdd/CEdid.cpp index 48e7ce82..70cfe91c 100644 --- a/idd/LGIdd/CEdid.cpp +++ b/idd/LGIdd/CEdid.cpp @@ -36,7 +36,7 @@ static const UINT CTA_DATA_BLOCK_MAX_PAYLOAD_SIZE = 31; static const BYTE EDID_HEADER[8] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }; -static const WORD EDID_MANUFACTURER_ID_LGD = 0xe430; +static const WORD EDID_MANUFACTURER_ID_LGD = 0x30e4; static const WORD EDID_PRODUCT_CODE = 0x1ddd; static const BYTE EDID_SERIAL_NUMBER[4] = { 0x01, 0x00, 0x00, 0x00 }; @@ -45,35 +45,29 @@ 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; -static const BYTE EDID_DISPLAY_GAMMA_2_2 = 0x78; -static const BYTE EDID_FEATURES_PREFERRED_TIMING_RGB = 0x0a; +static const BYTE EDID_VIDEO_INPUT_DIGITAL_8BPC = 0xa0; +static const BYTE EDID_VIDEO_INPUT_DIGITAL_10BPC = 0xb0; +static const BYTE EDID_DISPLAY_GAMMA_2_2 = 0x78; +static const BYTE EDID_FEATURES_PREFERRED_TIMING_RGB = 0x0a; +static const BYTE EDID_FEATURES_PREFERRED_TIMING_SRGB = 0x0e; static const BYTE EDID_STANDARD_TIMING_UNUSED_X = 0x01; static const BYTE EDID_STANDARD_TIMING_UNUSED_AR_REFRESH = 0x01; -static const DWORD EDID_IMAGE_WIDTH_MM = 520; -static const DWORD EDID_IMAGE_HEIGHT_MM = 290; - static const BYTE EDID_DESCRIPTOR_MONITOR_NAME = 0xfc; static const BYTE EDID_DTD_FLAGS_DIGITAL_SEPARATE_SYNC_POSITIVE = 0x1e; static const BYTE CTA_EXTENSION_TAG = 0x02; static const BYTE CTA_REVISION = 0x03; -static const BYTE CTA_DATA_BLOCK_TAG_VENDOR_SPECIFIC = 0x03; -static const BYTE CTA_DATA_BLOCK_TAG_EXTENDED = 0x07; -static const BYTE CTA_DATA_BLOCK_LENGTH_MASK = 0x1f; +static const BYTE CTA_DATA_BLOCK_TAG_EXTENDED = 0x07; +static const BYTE CTA_DATA_BLOCK_LENGTH_MASK = 0x1f; static const BYTE CTA_EXTENDED_TAG_COLORIMETRY = 0x05; static const BYTE CTA_EXTENDED_TAG_HDR_STATIC_METADATA = 0x06; static const BYTE CTA_HDR_EOTF_TRADITIONAL_SDR = (BYTE)(1 << 0); static const BYTE CTA_HDR_EOTF_SMPTE_ST_2084 = (BYTE)(1 << 2); -static const BYTE CTA_HDR_EOTF_HLG = (BYTE)(1 << 3); static const BYTE CTA_HDR_STATIC_METADATA_TYPE_1 = (BYTE)(1 << 0); // The virtual display is a transport rather than a physical light-emitting // device. Advertise the complete PQ range so Windows preserves HDR content @@ -85,24 +79,7 @@ static const BYTE CTA_HDR_DESIRED_MAX_LUMINANCE = 245; static const BYTE CTA_HDR_DESIRED_MAX_FRAME_AVG_LUMINANCE = 245; static const BYTE CTA_HDR_DESIRED_MIN_LUMINANCE = 0; -static const BYTE CTA_COLORIMETRY_OPYCC_601 = (BYTE)(1 << 3); -static const BYTE CTA_COLORIMETRY_OPRGB = (BYTE)(1 << 4); -static const BYTE CTA_COLORIMETRY_BT2020_YCC = (BYTE)(1 << 6); static const BYTE CTA_COLORIMETRY_BT2020_RGB = (BYTE)(1 << 7); -static const BYTE CTA_COLORIMETRY_DCI_P3 = (BYTE)(1 << 7); - -static const BYTE CTA_HDMI_FORUM_OUI [3] = { 0xd8, 0x5d, 0xc4 }; -static const BYTE CTA_HDMI_LICENSING_OUI[3] = { 0x03, 0x0c, 0x00 }; - -static const BYTE CTA_HDMI_FORUM_VERSION_1 = 0x01; -static const BYTE CTA_HDMI_FORUM_MAX_TMDS_CHARACTER_RATE = 0x6e; -static const BYTE CTA_HDMI_FORUM_SCDC_PRESENT = 0x80; - -static const BYTE CTA_HDMI_PHYSICAL_ADDRESS_A_B = 0x00; -static const BYTE CTA_HDMI_PHYSICAL_ADDRESS_C_D = 0x00; -static const BYTE CTA_HDMI_DEEP_COLOR_30_36 = 0x30; -static const BYTE CTA_HDMI_MAX_TMDS_CLOCK_UNSPECIFIED = 0x00; -static const BYTE CTA_HDMI_LATENCY_FIELDS_NONE = 0x0b; #pragma pack(push, 1) struct EdidLe16 @@ -111,6 +88,12 @@ struct EdidLe16 BYTE hi; }; +struct EdidBe16 +{ + BYTE hi; + BYTE lo; +}; + struct EdidStandardTiming { BYTE horizontalActivePixels; @@ -163,7 +146,7 @@ struct EdidBaseBlock { BYTE header[8]; - EdidLe16 manufacturerId; + EdidBe16 manufacturerId; EdidLe16 productCode; BYTE serialNumber[4]; @@ -222,29 +205,10 @@ struct CtaColorimetryDataBlock BYTE metadataAndAdditionalColorimetry; }; -struct CtaHdmiForumVendorSpecificDataBlock -{ - CtaDataBlockHeader header; - BYTE ieeeOui[3]; - BYTE version; - BYTE maxTmdsCharacterRate; - BYTE flags; - BYTE reserved; -}; - -struct CtaHdmiVendorSpecificDataBlock -{ - CtaDataBlockHeader header; - BYTE ieeeOui[3]; - BYTE physicalAddressAB; - BYTE physicalAddressCD; - BYTE flags; - BYTE maxTmdsClock; - BYTE latencyFields; -}; #pragma pack(pop) static_assert(sizeof(EdidLe16) == 2, "Unexpected EDID little-endian word size"); +static_assert(sizeof(EdidBe16) == 2, "Unexpected EDID big-endian word size"); static_assert(sizeof(EdidStandardTiming) == 2, "Unexpected EDID standard timing size"); static_assert(sizeof(EdidDetailedTimingDescriptor) == EDID_DTD_SIZE, "Unexpected EDID detailed timing descriptor size"); @@ -261,17 +225,17 @@ static_assert(sizeof(CtaHdrStaticMetadataDataBlock) == 7, "Unexpected HDR static metadata data block size"); static_assert(sizeof(CtaColorimetryDataBlock) == 4, "Unexpected colorimetry data block size"); -static_assert(sizeof(CtaHdmiForumVendorSpecificDataBlock) == 8, - "Unexpected HDMI Forum VSDB size"); -static_assert(sizeof(CtaHdmiVendorSpecificDataBlock) == 9, - "Unexpected HDMI VSDB size"); static_assert(CTA_HEADER_SIZE + sizeof(CtaHdrStaticMetadataDataBlock) + - sizeof(CtaColorimetryDataBlock) + - sizeof(CtaHdmiForumVendorSpecificDataBlock) + - sizeof(CtaHdmiVendorSpecificDataBlock) <= EDID_BLOCK_SIZE - 1, + sizeof(CtaColorimetryDataBlock) <= EDID_BLOCK_SIZE - 1, "CTA data blocks exceed extension block space"); +static void SetBe16(EdidBe16& dst, DWORD value) +{ + dst.hi = (BYTE)((value >> 8) & 0xff); + dst.lo = (BYTE)(value & 0xff); +} + static void SetLe16(EdidLe16& dst, DWORD value) { dst.lo = (BYTE)(value & 0xff); @@ -316,11 +280,9 @@ static EdidStandardTiming MakeUnusedStandardTiming() return timing; } -#include // Ensure this header is included for std::min and std::max - static WORD EdidChromaticity(double value) { - return (WORD)min(1023.0, max(0.0, value * 1024.0 + 0.5)); + return (WORD)min(1023.0, max(0.0, value * 1024.0 + 0.5)); } static void SetChromaticityCoordinates(BYTE coordinates[10], bool hdr) @@ -350,27 +312,36 @@ static void SetChromaticityCoordinates(BYTE coordinates[10], bool hdr) coordinates[9] = (BYTE)(wy >> 2); } +static BYTE GetVideoInputDefinition(bool hdr) +{ + return hdr ? + EDID_VIDEO_INPUT_DIGITAL_10BPC : + EDID_VIDEO_INPUT_DIGITAL_8BPC; +} + static void InitEdidBaseBlock(EdidBaseBlock& base, bool hdr) { memcpy(base.header, EDID_HEADER, sizeof(base.header)); - // Manufacturer ID: LGD, product/serial values are arbitrary. - SetLe16(base.manufacturerId, EDID_MANUFACTURER_ID_LGD); - SetLe16(base.productCode, EDID_PRODUCT_CODE); - memcpy(base.serialNumber, EDID_SERIAL_NUMBER, sizeof(base.serialNumber)); + // Manufacturer ID: LGD, product/serial values identify the virtual monitor. + SetBe16(base.manufacturerId, EDID_MANUFACTURER_ID_LGD); + SetLe16(base.productCode , EDID_PRODUCT_CODE); + memcpy (base.serialNumber , EDID_SERIAL_NUMBER, sizeof(base.serialNumber)); base.manufactureWeek = EDID_MANUFACTURE_WEEK; base.manufactureYear = EDID_MANUFACTURE_YEAR_2026; base.version = EDID_VERSION; base.revision = EDID_REVISION; - 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; + base.videoInputDefinition = GetVideoInputDefinition(hdr); + // This is a transport endpoint rather than a physical panel, so leave its + // physical dimensions unspecified instead of imposing a false DPI/aspect. + base.horizontalSizeCm = 0; + base.verticalSizeCm = 0; + base.displayGamma = EDID_DISPLAY_GAMMA_2_2; + base.supportedFeatures = hdr ? + EDID_FEATURES_PREFERRED_TIMING_RGB : + EDID_FEATURES_PREFERRED_TIMING_SRGB; SetChromaticityCoordinates(base.chromaticityCoordinates, hdr); for (UINT i = 0; i < EDID_STANDARD_TIMING_COUNT; ++i) @@ -379,68 +350,84 @@ static void InitEdidBaseBlock(EdidBaseBlock& base, bool hdr) base.extensionBlockCount = 1; } -static bool MakeDetailedTiming( - EdidDetailedTimingDescriptor& timing, - const CSettings::DisplayMode& mode) +bool CEdid::GetTiming(Timing& timing, const CSettings::DisplayMode& mode) { - memset(&timing, 0, sizeof(timing)); + timing = {}; - const DWORD hActive = mode.width; - const DWORD vActive = mode.height; - const DWORD refresh = mode.refresh; + timing.hActive = mode.width; + timing.vActive = mode.height; - if (hActive == 0 || vActive == 0 || refresh == 0 || - hActive > 4095 || vActive > 4095) + if (timing.hActive == 0 || timing.vActive == 0 || mode.refresh == 0) return false; - DWORD hBlank = std::max(160, ((hActive / 20) + 7) & ~7UL); - DWORD vBlank = std::max(30, vActive / 20); - if (hBlank > 4095 || vBlank > 4095) - return false; + timing.hBlank = std::max(160, + ((timing.hActive / 20) + 7) & ~7UL); + timing.vBlank = std::max(30, timing.vActive / 20); - DWORD hSync = std::max(32, hActive / 100); - hSync = (hSync + 7) & ~7UL; + timing.hSync = std::max(32, timing.hActive / 100); + timing.hSync = (timing.hSync + 7) & ~7UL; - DWORD hFront = std::max(48, hBlank / 3); - hFront = (hFront + 7) & ~7UL; + timing.hFront = std::max(48, timing.hBlank / 3); + timing.hFront = (timing.hFront + 7) & ~7UL; - if (hFront + hSync >= hBlank) + if (timing.hFront + timing.hSync >= timing.hBlank) { - hFront = 48; - hSync = 32; + timing.hFront = 48; + timing.hSync = 32; } - const DWORD vFront = 3; - const DWORD vSync = 5; - if (vFront + vSync >= vBlank) + timing.vFront = 3; + timing.vSync = 5; + if (timing.vFront + timing.vSync >= timing.vBlank) return false; - const UINT64 pixelClock = (UINT64)(hActive + hBlank) * - (UINT64)(vActive + vBlank) * (UINT64)refresh; + const UINT64 pixelClock = + (UINT64)(timing.hActive + timing.hBlank) * + (UINT64)(timing.vActive + timing.vBlank) * + (UINT64)mode.refresh; const UINT64 pixelClock10KHz = (pixelClock + 5000) / 10000; + timing.pixelClock = pixelClock10KHz * 10000; + return timing.pixelClock != 0; +} + +static bool MakeDetailedTiming( + EdidDetailedTimingDescriptor& descriptor, + const CSettings::DisplayMode& mode) +{ + memset(&descriptor, 0, sizeof(descriptor)); + + CEdid::Timing timing; + if (!CEdid::GetTiming(timing, mode) || + timing.hActive > 4095 || timing.vActive > 4095 || + timing.hBlank > 4095 || timing.vBlank > 4095) + return false; + + const UINT64 pixelClock10KHz = timing.pixelClock / 10000; if (pixelClock10KHz == 0 || pixelClock10KHz > 0xffff) return false; - SetLe16(timing.pixelClock10KHz, (DWORD)pixelClock10KHz); + SetLe16(descriptor.pixelClock10KHz, (DWORD)pixelClock10KHz); - timing.hActiveLo = Lo8(hActive); - timing.hBlankLo = Lo8(hBlank); - timing.hActiveBlankHi = PackMsbNibbles(hActive, hBlank); + descriptor.hActiveLo = Lo8(timing.hActive); + descriptor.hBlankLo = Lo8(timing.hBlank); + descriptor.hActiveBlankHi = PackMsbNibbles(timing.hActive, timing.hBlank); - timing.vActiveLo = Lo8(vActive); - timing.vBlankLo = Lo8(vBlank); - timing.vActiveBlankHi = PackMsbNibbles(vActive, vBlank); + descriptor.vActiveLo = Lo8(timing.vActive); + descriptor.vBlankLo = Lo8(timing.vBlank); + descriptor.vActiveBlankHi = PackMsbNibbles(timing.vActive, timing.vBlank); - timing.hFrontPorchLo = Lo8(hFront); - timing.hSyncPulseWidthLo = Lo8(hSync); - timing.vFrontPorchSyncPulseWidthLo = PackLowNibbles(vFront, vSync); - timing.syncPorchPulseWidthHi = PackSyncPorchPulseWidthHi(hFront, hSync, vFront, vSync); + descriptor.hFrontPorchLo = Lo8(timing.hFront); + descriptor.hSyncPulseWidthLo = Lo8(timing.hSync); + descriptor.vFrontPorchSyncPulseWidthLo = + PackLowNibbles(timing.vFront, timing.vSync); + descriptor.syncPorchPulseWidthHi = PackSyncPorchPulseWidthHi( + timing.hFront, timing.hSync, timing.vFront, timing.vSync); - timing.imageWidthMmLo = Lo8(EDID_IMAGE_WIDTH_MM); - timing.imageHeightMmLo = Lo8(EDID_IMAGE_HEIGHT_MM); - timing.imageSizeMmHi = PackMsbNibbles(EDID_IMAGE_WIDTH_MM, EDID_IMAGE_HEIGHT_MM); + descriptor.imageWidthMmLo = 0; + descriptor.imageHeightMmLo = 0; + descriptor.imageSizeMmHi = 0; - timing.flags = EDID_DTD_FLAGS_DIGITAL_SEPARATE_SYNC_POSITIVE; + descriptor.flags = EDID_DTD_FLAGS_DIGITAL_SEPARATE_SYNC_POSITIVE; return true; } @@ -499,8 +486,7 @@ static CtaHdrStaticMetadataDataBlock MakeCtaHdrStaticMetadataDataBlock() block.extendedTag = CTA_EXTENDED_TAG_HDR_STATIC_METADATA; block.eotf = (BYTE)( CTA_HDR_EOTF_TRADITIONAL_SDR | - CTA_HDR_EOTF_SMPTE_ST_2084 | - CTA_HDR_EOTF_HLG); + CTA_HDR_EOTF_SMPTE_ST_2084); block.staticMetadataDescriptor = CTA_HDR_STATIC_METADATA_TYPE_1; block.desiredContentMaxLuminance = CTA_HDR_DESIRED_MAX_LUMINANCE; @@ -515,41 +501,9 @@ static CtaColorimetryDataBlock MakeCtaColorimetryDataBlock() block.header = MakeCtaDataBlockHeader(CTA_DATA_BLOCK_TAG_EXTENDED, (UINT)(sizeof(block) - sizeof(block.header))); - block.extendedTag = CTA_EXTENDED_TAG_COLORIMETRY; - block.colorimetry = (BYTE)(CTA_COLORIMETRY_OPYCC_601 | - CTA_COLORIMETRY_OPRGB | - CTA_COLORIMETRY_BT2020_YCC | - CTA_COLORIMETRY_BT2020_RGB); - block.metadataAndAdditionalColorimetry = CTA_COLORIMETRY_DCI_P3; - return block; -} - -static CtaHdmiForumVendorSpecificDataBlock MakeCtaHdmiForumVendorSpecificDataBlock() -{ - CtaHdmiForumVendorSpecificDataBlock block = {}; - - block.header = MakeCtaDataBlockHeader(CTA_DATA_BLOCK_TAG_VENDOR_SPECIFIC, - (UINT)(sizeof(block) - sizeof(block.header))); - memcpy(block.ieeeOui, CTA_HDMI_FORUM_OUI, sizeof(block.ieeeOui)); - block.version = CTA_HDMI_FORUM_VERSION_1; - block.maxTmdsCharacterRate = CTA_HDMI_FORUM_MAX_TMDS_CHARACTER_RATE; - block.flags = CTA_HDMI_FORUM_SCDC_PRESENT; - block.reserved = 0x00; - return block; -} - -static CtaHdmiVendorSpecificDataBlock MakeCtaHdmiVendorSpecificDataBlock() -{ - CtaHdmiVendorSpecificDataBlock block = {}; - - block.header = MakeCtaDataBlockHeader(CTA_DATA_BLOCK_TAG_VENDOR_SPECIFIC, - (UINT)(sizeof(block) - sizeof(block.header))); - memcpy(block.ieeeOui, CTA_HDMI_LICENSING_OUI, sizeof(block.ieeeOui)); - block.physicalAddressAB = CTA_HDMI_PHYSICAL_ADDRESS_A_B; - block.physicalAddressCD = CTA_HDMI_PHYSICAL_ADDRESS_C_D; - block.flags = CTA_HDMI_DEEP_COLOR_30_36; - block.maxTmdsClock = CTA_HDMI_MAX_TMDS_CLOCK_UNSPECIFIED; - block.latencyFields = CTA_HDMI_LATENCY_FIELDS_NONE; + block.extendedTag = CTA_EXTENDED_TAG_COLORIMETRY; + block.colorimetry = CTA_COLORIMETRY_BT2020_RGB; + block.metadataAndAdditionalColorimetry = 0; return block; } @@ -582,7 +536,10 @@ bool CEdid::WriteDetailedTiming(BYTE* dtd, const CSettings::DisplayMode& mode) void CEdid::Build(const CSettings::DisplayModes& modes, bool hdr) { - m_data.assign(static_cast>::size_type>(EDID_BLOCK_SIZE) * 2, 0); + m_data.assign( + static_cast>::size_type>( + EDID_BLOCK_SIZE) * 2, + 0); EdidBaseBlock baseBlock = {}; InitEdidBaseBlock(baseBlock, hdr); @@ -637,8 +594,6 @@ void CEdid::Build(const CSettings::DisplayModes& modes, bool hdr) { AppendCtaDataBlock(cta, dataOffset, MakeCtaHdrStaticMetadataDataBlock ()); AppendCtaDataBlock(cta, dataOffset, MakeCtaColorimetryDataBlock ()); - AppendCtaDataBlock(cta, dataOffset, MakeCtaHdmiForumVendorSpecificDataBlock()); - AppendCtaDataBlock(cta, dataOffset, MakeCtaHdmiVendorSpecificDataBlock ()); } ctaBlock.dtdOffset = (BYTE)dataOffset; diff --git a/idd/LGIdd/CEdid.h b/idd/LGIdd/CEdid.h index bb7a4ec9..f9168d1b 100644 --- a/idd/LGIdd/CEdid.h +++ b/idd/LGIdd/CEdid.h @@ -29,8 +29,24 @@ class CEdid { public: + struct Timing + { + DWORD hActive; + DWORD hBlank; + DWORD hFront; + DWORD hSync; + DWORD vActive; + DWORD vBlank; + DWORD vFront; + DWORD vSync; + UINT64 pixelClock; + }; + void Build(const CSettings::DisplayModes& modes, bool hdr); + static bool GetTiming(Timing& timing, + const CSettings::DisplayMode& mode); + const BYTE* Data() const { return m_data.empty() ? nullptr : m_data.data(); } UINT Size() const { return (UINT)m_data.size(); } diff --git a/idd/LGIdd/CIndirectDeviceContext.cpp b/idd/LGIdd/CIndirectDeviceContext.cpp index 64a8e49a..f40adda4 100644 --- a/idd/LGIdd/CIndirectDeviceContext.cpp +++ b/idd/LGIdd/CIndirectDeviceContext.cpp @@ -50,10 +50,13 @@ static const UINT IDDCX_VERSION_1_10 = 0x1A00; static inline IDDCX_WIRE_BITS_PER_COMPONENT GetWireBitsPerComponent(bool hdr) { IDDCX_WIRE_BITS_PER_COMPONENT bits = {}; + // This describes the virtual monitor wire, not the swap-chain format. + // HDR uses a 10-bpc PQ wire while CAN_PROCESS_FP16 requests the FP16/scRGB + // source surface that Looking Glass converts for transport. bits.Rgb = IDDCX_BITS_PER_COMPONENT_8; if (hdr) bits.Rgb = (IDDCX_BITS_PER_COMPONENT)(bits.Rgb | - IDDCX_BITS_PER_COMPONENT_10 | IDDCX_BITS_PER_COMPONENT_16); + IDDCX_BITS_PER_COMPONENT_10); bits.YCbCr444 = IDDCX_BITS_PER_COMPONENT_NONE; bits.YCbCr422 = IDDCX_BITS_PER_COMPONENT_NONE; bits.YCbCr420 = IDDCX_BITS_PER_COMPONENT_NONE; @@ -586,21 +589,28 @@ void CIndirectDeviceContext::OnSwapChainReady() g_pipe.SetDisplayMode(mode.width, mode.height, mode.refresh); } -static inline void FillSignalInfo(DISPLAYCONFIG_VIDEO_SIGNAL_INFO & mode, DWORD width, DWORD height, DWORD vsync, bool monitorMode) +static inline void FillSignalInfo(DISPLAYCONFIG_VIDEO_SIGNAL_INFO& signal, + const CSettings::DisplayMode& mode, bool monitorMode) { - mode.totalSize.cx = mode.activeSize.cx = width; - mode.totalSize.cy = mode.activeSize.cy = height; + CEdid::Timing timing; + if (!CEdid::GetTiming(timing, mode)) + return; - mode.AdditionalSignalInfo.vSyncFreqDivider = monitorMode ? 0 : 1; - mode.AdditionalSignalInfo.videoStandard = 255; + signal.activeSize.cx = timing.hActive; + signal.activeSize.cy = timing.vActive; + signal.totalSize.cx = timing.hActive + timing.hBlank; + signal.totalSize.cy = timing.vActive + timing.vBlank; - mode.vSyncFreq.Numerator = vsync; - mode.vSyncFreq.Denominator = 1; - mode.hSyncFreq.Numerator = vsync * height; - mode.hSyncFreq.Denominator = 1; + signal.AdditionalSignalInfo.vSyncFreqDivider = monitorMode ? 0 : 1; + signal.AdditionalSignalInfo.videoStandard = 255; - mode.scanLineOrdering = DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE; - mode.pixelRate = ((UINT64)vsync) * ((UINT64)width) * ((UINT64)height); + signal.vSyncFreq.Numerator = mode.refresh; + signal.vSyncFreq.Denominator = 1; + signal.hSyncFreq.Numerator = mode.refresh * signal.totalSize.cy; + signal.hSyncFreq.Denominator = 1; + + signal.scanLineOrdering = DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE; + signal.pixelRate = timing.pixelClock; } NTSTATUS CIndirectDeviceContext::ParseMonitorDescription( @@ -620,9 +630,9 @@ NTSTATUS CIndirectDeviceContext::ParseMonitorDescription( auto * mode = inArgs->pMonitorModes; for (auto it = modes.cbegin(); it != modes.cend(); ++it, ++mode) { - mode->Size = sizeof(IDDCX_MONITOR_MODE); + mode->Size = sizeof(IDDCX_MONITOR_MODE); mode->Origin = IDDCX_MONITOR_MODE_ORIGIN_MONITORDESCRIPTOR; - FillSignalInfo(mode->MonitorVideoSignalInfo, it->width, it->height, it->refresh, true); + FillSignalInfo(mode->MonitorVideoSignalInfo, *it, true); if (it->preferred) outArgs->PreferredMonitorModeIdx = @@ -649,9 +659,9 @@ NTSTATUS CIndirectDeviceContext::MonitorGetDefaultModes( auto* mode = inArgs->pDefaultMonitorModes; for (auto it = modes.cbegin(); it != modes.cend(); ++it, ++mode) { - mode->Size = sizeof(IDDCX_MONITOR_MODE); + mode->Size = sizeof(IDDCX_MONITOR_MODE); mode->Origin = IDDCX_MONITOR_MODE_ORIGIN_DRIVER; - FillSignalInfo(mode->MonitorVideoSignalInfo, it->width, it->height, it->refresh, true); + FillSignalInfo(mode->MonitorVideoSignalInfo, *it, true); if (it->preferred) outArgs->PreferredMonitorModeIdx = @@ -678,7 +688,7 @@ NTSTATUS CIndirectDeviceContext::MonitorQueryTargetModes( for (auto it = modes.cbegin(); it != modes.cend(); ++it, ++mode) { mode->Size = sizeof(IDDCX_TARGET_MODE); - FillSignalInfo(mode->TargetVideoSignalInfo.targetVideoSignalInfo, it->width, it->height, it->refresh, false); + FillSignalInfo(mode->TargetVideoSignalInfo.targetVideoSignalInfo, *it, false); } return STATUS_SUCCESS; @@ -704,9 +714,9 @@ NTSTATUS CIndirectDeviceContext::ParseMonitorDescription2( for (auto it = modes.cbegin(); it != modes.cend(); ++it, ++mode) { ZeroMemory(mode, sizeof(*mode)); - mode->Size = sizeof(IDDCX_MONITOR_MODE2); - mode->Origin = IDDCX_MONITOR_MODE_ORIGIN_MONITORDESCRIPTOR; - FillSignalInfo(mode->MonitorVideoSignalInfo, it->width, it->height, it->refresh, true); + mode->Size = sizeof(IDDCX_MONITOR_MODE2); + mode->Origin = IDDCX_MONITOR_MODE_ORIGIN_MONITORDESCRIPTOR; + FillSignalInfo(mode->MonitorVideoSignalInfo, *it, true); mode->BitsPerComponent = GetWireBitsPerComponent(CanProcessFP16()); if (it->preferred) @@ -738,7 +748,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); + FillSignalInfo(mode->TargetVideoSignalInfo.targetVideoSignalInfo, *it, false); mode->BitsPerComponent = GetWireBitsPerComponent(CanProcessFP16()); } diff --git a/idd/LGIdd/CSwapChainProcessor.cpp b/idd/LGIdd/CSwapChainProcessor.cpp index 7cb5107b..1f82da94 100644 --- a/idd/LGIdd/CSwapChainProcessor.cpp +++ b/idd/LGIdd/CSwapChainProcessor.cpp @@ -589,12 +589,12 @@ bool CSwapChainProcessor::SwapChainNewFrame(ComPtr acquiredBuffer // No per-content metadata is active. Use reasonable internal defaults // without publishing the virtual monitor metadata downstream. // BT.709/sRGB primaries (in 0.00002 units): - srcFormat.displayPrimary[0][0] = 13250; // Rx - srcFormat.displayPrimary[0][1] = 34500; // Ry - srcFormat.displayPrimary[1][0] = 7500; // Gx + srcFormat.displayPrimary[0][0] = 32000; // Rx + srcFormat.displayPrimary[0][1] = 16500; // Ry + srcFormat.displayPrimary[1][0] = 15000; // Gx srcFormat.displayPrimary[1][1] = 30000; // Gy - srcFormat.displayPrimary[2][0] = 34000; // Bx - srcFormat.displayPrimary[2][1] = 16000; // By + srcFormat.displayPrimary[2][0] = 7500; // Bx + srcFormat.displayPrimary[2][1] = 3000; // By // D65 white point (in 0.00002 units): srcFormat.whitePoint[0] = 15635; srcFormat.whitePoint[1] = 16450; diff --git a/idd/LGIdd/Device.cpp b/idd/LGIdd/Device.cpp index 8c149a57..ca7b5482 100644 --- a/idd/LGIdd/Device.cpp +++ b/idd/LGIdd/Device.cpp @@ -104,23 +104,6 @@ NTSTATUS LGIddAdapterCommitModes(IDDCX_ADAPTER adapter, const IDARG_IN_COMMITMOD return STATUS_SUCCESS; } -static inline void FillSignalInfo(DISPLAYCONFIG_VIDEO_SIGNAL_INFO & mode, DWORD width, DWORD height, DWORD vsync, bool monitorMode) -{ - mode.totalSize.cx = mode.activeSize.cx = width; - mode.totalSize.cy = mode.activeSize.cy = height; - - mode.AdditionalSignalInfo.vSyncFreqDivider = monitorMode ? 0 : 1; - mode.AdditionalSignalInfo.videoStandard = 255; - - mode.vSyncFreq.Numerator = vsync; - mode.vSyncFreq.Denominator = 1; - mode.hSyncFreq.Numerator = vsync * height; - mode.hSyncFreq.Denominator = 1; - - mode.scanLineOrdering = DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE; - mode.pixelRate = ((UINT64)vsync) * ((UINT64)width) * ((UINT64)height); -} - NTSTATUS LGIddParseMonitorDescription(const IDARG_IN_PARSEMONITORDESCRIPTION* inArgs, IDARG_OUT_PARSEMONITORDESCRIPTION* outArgs) { @@ -170,10 +153,8 @@ NTSTATUS LGIddAdapterQueryTargetInfo(IDDCX_ADAPTER adapter, (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.Rgb = IDDCX_BITS_PER_COMPONENT_NONE; outArgs->DitheringSupport.YCbCr444 = IDDCX_BITS_PER_COMPONENT_NONE; outArgs->DitheringSupport.YCbCr422 = IDDCX_BITS_PER_COMPONENT_NONE; outArgs->DitheringSupport.YCbCr420 = IDDCX_BITS_PER_COMPONENT_NONE;