Compare commits

..

3 Commits

Author SHA1 Message Date
Geoffrey McRae
0140a3f6fb [client/idd] hdr: fix incorrect tone mapping knee bug
Some checks are pending
build / client (Debug, map[cc:clang cxx:clang++], libdecor) (push) Waiting to run
build / client (Debug, map[cc:clang cxx:clang++], xdg-shell) (push) Waiting to run
build / client (Debug, map[cc:gcc cxx:g++], libdecor) (push) Waiting to run
build / client (Debug, map[cc:gcc cxx:g++], xdg-shell) (push) Waiting to run
build / client (Release, map[cc:clang cxx:clang++], libdecor) (push) Waiting to run
build / client (Release, map[cc:clang cxx:clang++], xdg-shell) (push) Waiting to run
build / client (Release, map[cc:gcc cxx:g++], libdecor) (push) Waiting to run
build / client (Release, map[cc:gcc cxx:g++], xdg-shell) (push) Waiting to run
build / module (push) Waiting to run
build / host-linux (push) Waiting to run
build / host-windows-cross (push) Waiting to run
build / host-windows-native (push) Waiting to run
build / idd (push) Waiting to run
build / obs (clang) (push) Waiting to run
build / obs (gcc) (push) Waiting to run
build / docs (push) Waiting to run
2026-07-16 10:48:10 +10:00
Geoffrey McRae
e502af7d9d Revert "[idd/client] correct HDR luminance when PQ conversion is in use"
This reverts commit 05d8bc5311.
2026-07-16 09:58:44 +10:00
Geoffrey McRae
05d8bc5311 [idd/client] correct HDR luminance when PQ conversion is in use 2026-07-16 09:34:02 +10:00
4 changed files with 33 additions and 30 deletions

View File

@@ -280,22 +280,21 @@ void waylandSetHDRImageDescription(const uint16_t displayPrimary[3][2],
hdrPQ ? WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_ST2084_PQ hdrPQ ? WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_ST2084_PQ
: WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_LINEAR); : WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_LINEAR);
// Set luminance range from metadata. // Set the primary colour volume luminances.
// min_lum is in 0.0001 cd/m² units (multiplied by 10000 as per protocol). // min_lum : 0.0001 cd/m² (source already scaled) -> pass through
// max_lum and reference_lum are in unscaled cd/m² units. // max_lum : cd/m² (used only for scRGB; ignored for PQ, where the
// compositor forces it to min_lum + 10000 cd/m²)
// reference_lum : cd/m² -> BT.2408 diffuse white (203 PQ / 80 scRGB)
if (wlWm.cmHasLuminances) if (wlWm.cmHasLuminances)
wp_image_description_creator_params_v1_set_luminances( wp_image_description_creator_params_v1_set_luminances(
wlWm.hdrImageCreator, wlWm.hdrImageCreator,
minDisplayLuminance > 0 ? minDisplayLuminance : 50, minDisplayLuminance > 0 ? minDisplayLuminance : 50,
maxDisplayLuminance > 0 ? maxDisplayLuminance / 10000 : 1000, maxDisplayLuminance > 0 ? maxDisplayLuminance : 1000,
hdrPQ ? 203 : 80); hdrPQ ? 203 : 80);
// Set mastering display primaries from frame HDR metadata. // Advertise the content primaries (BT.2020 for PQ). These describe the real
// Always set when the compositor supports it, falling back to the // colour gamut of the signal and are safe to forward.
// primaries from the metadata (even if zero, in which case the
// compositor uses its own defaults).
if (wlWm.cmHasMasteringPrimaries) if (wlWm.cmHasMasteringPrimaries)
{
wp_image_description_creator_params_v1_set_mastering_display_primaries( wp_image_description_creator_params_v1_set_mastering_display_primaries(
wlWm.hdrImageCreator, wlWm.hdrImageCreator,
displayPrimary[0][0], displayPrimary[0][1], displayPrimary[0][0], displayPrimary[0][1],
@@ -303,19 +302,16 @@ void waylandSetHDRImageDescription(const uint16_t displayPrimary[3][2],
displayPrimary[2][0], displayPrimary[2][1], displayPrimary[2][0], displayPrimary[2][1],
whitePoint[0], whitePoint[1]); whitePoint[0], whitePoint[1]);
// Set mastering luminance range so the compositor knows the target // NOTE: we deliberately do NOT forward the host's mastering luminance range,
// color volume for tone mapping. min_lum is in ×10000 units (0.0001 cd/m²), // MaxCLL or MaxFALL. Those values describe the *virtual display* the IDD
// max_lum is in unscaled cd/m². // advertises to Windows (~1000 cd/m² from our EDID), not the content. LG
wp_image_description_creator_params_v1_set_mastering_luminance( // captures the full-range scRGB desktop composition and passes it through to
wlWm.hdrImageCreator, // PQ without tone mapping, so the signal spans the entire PQ range (scRGB
minDisplayLuminance > 0 ? minDisplayLuminance : 50, // 125.0 == 10000 cd/m²). Advertising the virtual display's peak as the
maxDisplayLuminance > 0 ? maxDisplayLuminance / 10000 : 1000); // content peak makes the compositor place its tone-mapping knee there and
} // hard-clip everything brighter, crushing highlights. Leaving these unset
// lets the content be treated as standard full-range PQ so the compositor
if (maxCLL > 0) // tone-maps it to the actual physical display.
wp_image_description_creator_params_v1_set_max_cll(wlWm.hdrImageCreator, maxCLL);
if (maxFALL > 0)
wp_image_description_creator_params_v1_set_max_fall(wlWm.hdrImageCreator, maxFALL);
wlWm.hdrImageDesc = wlWm.hdrImageDesc =
wp_image_description_creator_params_v1_create(wlWm.hdrImageCreator); wp_image_description_creator_params_v1_create(wlWm.hdrImageCreator);
@@ -342,8 +338,10 @@ void waylandSetHDRImageDescription(const uint16_t displayPrimary[3][2],
WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL); WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL);
wlWm.hdrActive = true; wlWm.hdrActive = true;
DEBUG_INFO("HDR image description set on surface (%s, %s, %u nits)", DEBUG_INFO("HDR image description set on surface (%s, %s, "
hdrPQ ? "PQ" : "scRGB", hdrPQ ? "BT.2020" : "sRGB", maxDisplayLuminance); "maxLum:%u cd/m² minLum:%u (0.0001 cd/m²) maxCLL:%u maxFALL:%u)",
hdrPQ ? "PQ" : "scRGB", hdrPQ ? "BT.2020" : "sRGB",
maxDisplayLuminance, minDisplayLuminance, maxCLL, maxFALL);
} }
bool waylandRequestHDR(const uint16_t displayPrimary[3][2], bool waylandRequestHDR(const uint16_t displayPrimary[3][2],

View File

@@ -167,7 +167,11 @@ typedef struct KVMFRFrame
// 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
uint32_t hdrMaxDisplayLuminance; // Max mastering display luminance (0.0001 cd/m²) // Mastering display luminances follow SMPTE ST 2086 units: the maximum is
// in whole cd/m², the minimum in 0.0001 cd/m². (Note: the DXGI docs
// describe MaxMasteringLuminance as 0.0001 cd/m², but IddCx/ST 2086 provide
// it in whole cd/m².)
uint32_t hdrMaxDisplayLuminance; // Max mastering display luminance (cd/m²)
uint32_t hdrMinDisplayLuminance; // Min mastering display luminance (0.0001 cd/m²) uint32_t hdrMinDisplayLuminance; // Min mastering display luminance (0.0001 cd/m²)
uint32_t hdrMaxContentLightLevel; // MaxCLL (cd/m²) uint32_t hdrMaxContentLightLevel; // MaxCLL (cd/m²)
uint32_t hdrMaxFrameAverageLightLevel; // MaxFALL (cd/m²) uint32_t hdrMaxFrameAverageLightLevel; // MaxFALL (cd/m²)

View File

@@ -396,8 +396,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;
// 80 cd/m² display, 0.005 cd/m² black (in 0.0001 cd/m² units): // Mastering luminances follow SMPTE ST 2086 units: max in whole cd/m²,
srcFormat.maxDisplayLuminance = 800000; // min in 0.0001 cd/m². 80 cd/m² display, 0.005 cd/m² black:
srcFormat.maxDisplayLuminance = 80;
srcFormat.minDisplayLuminance = 50; srcFormat.minDisplayLuminance = 50;
// Content light levels unknown: // Content light levels unknown:
srcFormat.maxContentLightLevel = 0; srcFormat.maxContentLightLevel = 0;

View File

@@ -18,8 +18,8 @@ class CHDR16to10Effect : public CComputeEffect
private: private:
struct Consts struct Consts
{ {
float ReferenceWhiteNits; // scRGB reference white in nits (BT.2408 recommends 203) float ReferenceWhiteNits; // scRGB reference white in nits (typically 80)
} m_consts = { 203.0f }; } m_consts = { 80.0f };
ComPtr<ID3D12Resource> m_constBuffer; ComPtr<ID3D12Resource> m_constBuffer;
public: public: