GitHub - BigShoots/kwin_HDR_ICC_Fixed: Easy to use, but flexible, Wayland Compositor · GitHub
Skip to content
forked from KDE/kwin

About

Easy to use, but flexible, Wayland Compositor

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

 
 

Latest commit

 

History

31,352 Commits

Folders and files

Repository files navigation

KWin HDR ICC fixes

This fork is used to investigate and correct HDR ICC handling in KWin. It is based on KWin and is not an independent compositor.

The work was prompted by repeatable meter results on an HDR OLED display. The same measured profile produced good results through the Windows MHC2 path, but KWin's ICC cLUT path crushed near black, clipped highlights and shifted colour. Changing profile fitting parameters did not explain the difference. Tracing KWin's profile selection, ICC parser and OpenGL pipeline exposed several independent problems.

The current packaged build is kwin-6.7.4-hdr-icc-pgen24. It contains the complete measured pgen23 fix set plus standard ICC matrix, extended-PCS and VCGT ordering corrections. Fedora and Arch packages are built from the same KWin 6.7.4 source archive and patch series.

The release includes Fedora 44 RPMs, an Arch Linux package, the individual patches, the final test profile and the two acceptance-run JSON files. It also includes reset-hdr-tonemapping.sh for clearing values left by KDE's HDR brightness calibrator without removing the selected ICC profile.

This build was tested on an MSI MPG321UX OLED and an Innoview HDR display. The fixes are not keyed to either monitor. Desktop scale, display peak, MaxFALL and profile luminance remain separate inputs, so a 145% or 180% UI scale cannot change the PQ luminance sent to the display.

Recommended profiles

There are two useful profile paths in this fork:

  1. ICC v4.4 with a Rec. 2020 PQ full-range CICP tag is the recommended native KDE HDR path for this fork. Create an XYZ cLUT display profile, include B2A1, and encode CICP as 9/16/0/1.
  2. MHC2 remains a useful control and compatibility path. It produced the best neutral ramp before the KDE cLUT toe was corrected, but it does not provide the same measured three-dimensional colour correction as B2A.

Do not assume that an ICC v4.4 CICP profile works the same way in unpatched KWin 6.7.4. Stock 6.7.4 does not parse the CICP tag and treats the profile-side HDR transfer function as gamma 2.2.

VCGT is optional. Profiles with VCGT and profiles containing only B2A are both supported. pgen24 evaluates VCGT in its standard position on the B2A device output. If VCGT is included, its effect must be removed from the measurements used to fit B2A. For calibration included without VCGT, pgen23 preserves the full HDR input range before B2A so the profile's output shapers can carry the same rolloff.

Profile contents Expected handling
B2A with no VCGT KWin evaluates the B2A transform directly in the profile's relative PCS domain
B2A with VCGT KWin evaluates B2A, then applies VCGT to its device output
MHC2 KWin keeps PQ analytic and applies the MHC2 adjustment in encoded space

Do not add VCGT to an existing no-VCGT profile, or remove it from a profile that was fitted in a calibrated device space. The B2A data has to be built for the same calibration state that will be active when the profile is used.

Fixes in this fork

The complete pgen24 source set contains these production changes:

Area Correction Commit
HDR output state Select the active HDR ICC profile source 11592b127
ICC intent Fall back from B2A1 to B2A0 fcba79330
ICC pipeline Apply the B2A PCS multiplier 7b6b26ca8
HDR luminance Preserve the output reference luminance 2e9a1b2cb
ICC metadata Parse and validate v4.4 CICP 9/16/0/1 d8ed03bf9
MHC2 Keep PQ analytic and key the shader cache correctly 6e6d1ee1e
PQ B2A Normalize relative PCS against profile luminance fd601186e, beb8c0f44
PQ B2A Retain near-black precision with the quadratic B-shaper domain e88661988, 75ad7d785
mft2 Parse and interpolate high-resolution 16-bit B2A curves safely d4d7b38552, 275e5607d5
Reference ordering Apply B2A in the surface reference domain, then restore output scaling d1c1b786de
HDR metadata Keep profile PCS luminance separate from display mastering metadata d1c1b786de
Desktop scaling Remove UI scale from HDR luminance and reference-white calculations c9dc904f7f
DRM metadata Send configured peak as MaxDML/MaxCLL and average luminance as MaxFALL 880e7af14e
PQ VCGT Apply neutral calibration in source-PQ coordinates 7f6460a378
Compositor buffer Reconstruct source PQ from preserved absolute compositor luminance 24c5b2b96b
PQ B2A without VCGT Preserve highlights above measured white for the profile transform 5bc1c888f9
lut16 matrix Apply the matrix before the input tables 628a89ce5e
Standard VCGT Apply VCGT after B2A and always preserve extended PCS c661f0d424

Use the active HDR profile source

KWin selected the SDR colorProfileSource while deciding whether to keep an ICC profile attached to an HDR output. An output configured with an HDR ICC profile could therefore lose the profile during a modeset. The decision now uses hdrColorProfileSource while HDR is active.

Commit: 11592b127

Fall back from B2A1 to B2A0

KWin requests the media-relative B2A1 transform for normal colour-managed output. Many valid display profiles only publish a single colourimetric table under B2A0. KWin previously dropped to matrix/TRC when B2A1 was absent. It now uses B2A0 as the fallback.

Profiles produced by the matching ArgyllCMS fork publish the single-intent colourimetric table under both B2A0 and B2A1, while preserving a genuinely independent perceptual B2A0 when gamut mapping created one.

Commit: fcba79330

Apply the B2A PCS multiplier

KWin's ICC parser emits a ColorMultiplier operation when decoding the PCS range of a B2A table. The OpenGL profile path skipped that operation and began at the following curve. The shader setup now consumes the multiplier before building the remaining transform.

Commit: 7b6b26ca8

Preserve HDR reference luminance

The ICC HDR path replaced the output reference luminance with the profile's maximum average luminance. That changes the scale used by the HDR pipeline. The patched path keeps the output state's reference luminance and uses the profile luminance tags for their intended metadata fields.

Commit: 2e9a1b2cb

Parse ICC v4.4 CICP metadata

KWin now reads and validates the 12-byte cicp tag. For an RGB profile tagged as Rec. 2020 primaries, PQ transfer, identity matrix and full range (9/16/0/1), the HDR profile description uses a Rec. 2020 container and the Perceptual Quantizer transfer function instead of hard-coded gamma 2.2.

Malformed CICP data and non-identity matrix coefficients are rejected. The measured display primaries still come from the ICC profile. CICP describes the coding of profile data, not the physical display gamut.

Commit: d8ed03bf9

Keep PQ analytic in the MHC2 shader

The original MHC2 path sampled PQ into a LUT whose input was uniformly spaced in linear light. That wastes most of the table in the bright region and leaves very little precision near black. The patched shader evaluates the wire transfer function analytically, then applies the MHC2 adjustment LUT in its encoded domain. The cache key also includes wire colourimetry and transfer function so a stale transform is not reused after an output change.

Commit: 6e6d1ee1e

Preserve near-black precision in B2A curves

KWin uploaded the first B2A shaper as a 4,096-entry texture sampled uniformly in linear PCS. Values below 10 percent PQ occupy less than one useful texture interval in that domain. This clipped dark detail and could leave the first visible neutral patch strongly tinted.

For PQ input, the fork samples the B curve on a quadratic domain and applies the inverse square-root coordinate mapping in the shader. This changes only the sampling distribution. It does not alter the ICC curve or measured fit.

Commit: e88661988

Normalize PQ B2A input to profile luminance

An ICC display B2A table uses relative PCS values. A PCS value of 1.0 means the measured luminance stored in the profile's lumi tag. After CICP selected PQ, KWin instead normalized absolute PQ luminance by PQ's full 10,000 cd/m2 range. On a 308 cd/m2 display this fed the inverse table values about 32 times too small, causing crushed shadows and unstable shadow chroma.

The CICP B2A path now normalizes PQ luminance by the profile lumi value. MHC2 keeps its existing 10,000 cd/m2 normalization because MHC2 adjustment curves are defined in PQ encoded space.

The ICC shader uses a dedicated PCS-luminance uniform. This keeps the profile normalization independent from KWin's general destination-luminance state.

Commits: fd601186e, beb8c0f44

Select the PQ B-shaper domain from CICP

The compositor renders through an intermediate gamma 2.2 shadow buffer even when the original client surface is PQ. The ICC shader previously enabled its quadratic high-resolution B-shaper only when that intermediate buffer reported a PQ transfer function. As a result, the precision path was disabled during the native HDR ICC workflow it was intended to fix.

The shader now selects the quadratic B-shaper from the profile's validated full-range Rec. 2020 PQ CICP declaration. This keeps the decision tied to the encoding expected by B2A instead of KWin's internal blending format.

Commit: 75ad7d785

Parse high-resolution mft2 B2A curves safely

LittleCMS rejects otherwise valid mft2 shaper tables with more than 32,767 entries. Older experimental HDR profiles crossed that boundary, so silently falling back from their transform defeated the profile.

KWin now parses the fixed-layout three-channel mft2 B2A input curves, matrix, cLUT and output curves directly. Curve sizes and every computed offset are bounds checked before allocation or evaluation. The direct evaluator uses linear interpolation over the original 16-bit values, avoiding both the LittleCMS entry limit and a lower-resolution resample.

The current PGenerator+ builder caps new PQ input shapers at 32,767 entries. That retains the measured near-black precision while allowing the profile to pass through the normal LittleCMS parser. The direct parser remains only for backward compatibility with already-created oversized profiles.

Commits: d4d7b38552, 275e5607d5

Decouple HDR luminance from desktop scale

Desktop scale controls logical geometry. It must not multiply SDR reference white, profile PCS luminance or PQ output luminance. The old paired KWin and Companion workaround made the Innoview appear to need 1.8x luminance and the MSI 1.45x, exactly matching their 180% and 145% UI scales. pgen19 removes that coupling. Changing UI scale no longer changes encoded PQ luminance.

Commit: c9dc904f7f

Advertise peak and frame-average HDR metadata separately

KWin wrote the display's desired maximum frame-average luminance into all three static HDR metadata fields. On the MSI this advertised 456 cd/m2 as the mastering peak and MaxCLL even with a configured 1000 cd/m2 peak. pgen20 uses the configured or EDID peak for maximum mastering luminance and MaxCLL, while keeping the display average value in MaxFALL. The verified MSI DRM blob is 1000/1000/456.

Commit: 880e7af14e

Apply PQ neutral calibration in its measured domain

The Companion reference applies VCGT directly to original PQ source codes for neutral and near-neutral pixels, blending to B2A for chromatic pixels. KWin previously folded VCGT into the B2A output curve. On OLED rolloff that changed the coordinates entering the per-channel curves and produced a dim cyan plateau.

The output ICC shader receives KWin's gamma-encoded blending buffer rather than the original client texture. pgen22 decodes that buffer to absolute luminance, reconstructs the equivalent PQ code, samples VCGT there and uses the same neutral-axis blend as the Companion. This keeps the correction tied to absolute luminance and independent of desktop scale.

Commits: 7f6460a378, 24c5b2b96b

Preserve the no-VCGT B2A rolloff

The VCGT path applies its calibration from the original PQ source coordinate, but a profile with calibration included in B2A has no separate curve for KWin to call. KWin previously clamped the linear RGB input to measured white before the B2A matrix. Every brighter PQ value therefore entered the same part of the inverse table, producing a dim, tinted plateau through the display rolloff.

pgen23 keeps that clamp only when a separate source-domain VCGT is active. A no-VCGT profile receives the extended relative PCS range and can apply its included high-resolution output shapers. On the MSI acceptance run this removed the 362 cd/m2 cyan plateau and restored the approximately 447 cd/m2 neutral peak.

Commit: 5bc1c888f9

Use standard lut16 and VCGT ordering

The direct mft2 parser previously emitted its input tables before the 3x3 matrix. ICC lut16Type applies the matrix to XYZ PCS first. pgen24 corrects that order and folds the leading matrix into the shader's PCS conversion so the first 1D stage keeps the PQ sampling domain used for shadow precision.

pgen24 also removes the source-domain VCGT neutral override. VCGT now runs on the B2A device output, its standard position. Relative PCS is no longer clamped to measured white based on VCGT presence; the lut16 extended range is available to every HDR B2A profile.

Commits: 628a89ce5e, c661f0d424

Packages

The pgen24 release provides binaries for Fedora 44 and Arch Linux x86-64. These packages replace the distribution's KWin package and are specific to KWin 6.7.4. Download the artifacts for only one distribution and verify them with the release's SHA256SUMS file before installation.

Fedora 44

Download the three Fedora runtime RPMs into one directory and install them together:

sudo dnf install \
  ./kwin-6.7.4-1.fc44.pgen24.x86_64.rpm \
  ./kwin-common-6.7.4-1.fc44.pgen24.x86_64.rpm \
  ./kwin-libs-6.7.4-1.fc44.pgen24.x86_64.rpm
sudo reboot

Confirm the installed build after login:

rpm -q kwin kwin-common kwin-libs

All three packages must report the same pgen24 release. These RPMs are tied to Fedora 44's KWin 6.7.4 ABI. Do not install them on another Fedora release or another distribution.

To return to Fedora's packages:

sudo dnf distro-sync kwin kwin-common kwin-libs
sudo reboot

Arch Linux

The Arch artifact tracks the official Arch KWin 6.7.4 package layout. Install it with pacman, then reboot so the running compositor and loaded libraries come from the same package:

sudo pacman -U ./kwin-6.7.4-4.24-x86_64.pkg.tar.zst
sudo reboot

Confirm the installed build:

pacman -Q kwin

It must report kwin 6.7.4-4.24. To return to Arch's current package:

sudo pacman -S kwin
sudo reboot

Build from the packaging files

For Fedora, install the normal RPM build tools and KWin build dependencies:

sudo dnf install rpm-build rpmdevtools dnf-plugins-core
sudo dnf builddep ./packaging/fedora/kwin-pgen24.spec
rpmdev-setuptree

Download the exact KWin 6.7.4 sources named by the spec, then place the source archive, signature and patch in the RPM source directory:

spectool -g -R packaging/fedora/kwin-pgen24.spec
cp packaging/fedora/kwin-6.7.4-pgen15.patch \
  packaging/fedora/kwin-pgen16-pq-profile-shaper.patch \
  packaging/fedora/kwin-pgen17-neutral-vcgt-reference.patch \
  packaging/fedora/kwin-pgen18-reference-order.patch \
  packaging/fedora/kwin-pgen19-desktop-scale.patch \
  packaging/fedora/kwin-pgen20-hdr-metadata.patch \
  packaging/fedora/kwin-pgen21-source-vcgt.patch \
  packaging/fedora/kwin-pgen22-composited-pq.patch \
  packaging/fedora/kwin-pgen23-extended-b2a.patch \
  packaging/fedora/kwin-pgen24-standard-icc.patch \
  ~/rpmbuild/SOURCES/
rpmbuild -ba packaging/fedora/kwin-pgen24.spec

Fedora may already provide the source archive through an installed source RPM. In that case, keep kwin-6.7.4.tar.xz and its signature in ~/rpmbuild/SOURCES, copy the patch as shown above, and run rpmbuild -ba. The binary packages are written below ~/rpmbuild/RPMS.

On an up-to-date Arch Linux build system, build the package directly from the fork checkout:

cd packaging/arch
makepkg -sfc

The PKGBUILD is derived from Arch's official KWin 6.7.4 recipe and verifies the KDE source archive plus each local patch checksum.

Test evidence

The changes have been checked at several levels:

  • Each commit passes git diff --check and the combined patch applies to the Fedora 44 KWin 6.7.4 source package with zero fuzz.
  • Fedora pgen23 RPMs and the Arch 6.7.4-4.23 package build successfully from the same source series.
  • testIccCicpTag creates a v4.4 profile, writes CICP 9/16/0/1, loads it through IccProfile and checks every decoded field.
  • The v4.4 CICP test profile and its v2.2 control have identical transform payloads. LittleCMS produced byte-identical output over 4,913 RGB samples, with a maximum difference of zero. This isolates container and CICP handling from profile fitting.
  • Meter testing reproduced the original cLUT failure independently of patch generation. MHC2 remained the known-good neutral control, which led to the analytic PQ precision fix rather than changing measured data to hide compositor behavior.
  • The same fixed meter position and full-range native PQ sequence compared MHC2, the original v4.4 CICP profile, VCGT-accounted profiles and modified B2A cells on the same OLED display.
  • With the original v4.4 profile, 5 percent measured black and 10 percent measured 0.075 cd/m2 with severe green contamination.
  • With a VCGT-accounted Ultra fit and only the first B2A cLUT cell rebuilt, 5 percent measured 0.070 cd/m2, 10 percent measured 0.244 cd/m2, 20 percent measured 3.008 cd/m2, 50 percent measured 95.451 cd/m2 and peak measured 307.275 cd/m2. The correction did not alter the cLUT outside its first cell.
  • The v4.4 cLUT saturation sweep had lower mean chromaticity error than the MHC2 control in the same run.

pgen23 no-VCGT acceptance result

The pgen23 MSI MPG321UX OLED comparison used the same 423 characterization measurements and the exact calibration curves from the final VCGT profile. Both runs used full-range HDR10, a centered 10 percent patch, LCD meter mode, no CCSS and the same fixed meter position. The no-VCGT profile contains the calibration in its B2A output shapers.

IRE VCGT Y Included cal Y Y difference VCGT x,y Included cal x,y dxy
0 0.0000 0.0000 +0.00% 0.333333, 0.333333 0.333333, 0.333333 0.000000
5 0.0530 0.0482 -9.02% 0.321953, 0.322255 0.328441, 0.331418 0.011227
10 0.2814 0.2811 -0.11% 0.319345, 0.339064 0.317415, 0.335898 0.003708
15 0.9400 0.9597 +2.09% 0.314520, 0.334684 0.313927, 0.332360 0.002398
20 2.3527 2.3909 +1.62% 0.313494, 0.330739 0.313853, 0.330116 0.000719
25 5.0073 5.0858 +1.57% 0.312858, 0.326449 0.311994, 0.325255 0.001474
30 9.9406 10.0535 +1.14% 0.313545, 0.328509 0.313414, 0.327735 0.000785
35 18.1696 18.4417 +1.50% 0.315075, 0.327330 0.315314, 0.326760 0.000618
40 32.2544 32.5211 +0.83% 0.312033, 0.328833 0.312292, 0.328399 0.000505
45 54.6677 55.0243 +0.65% 0.313138, 0.328033 0.312610, 0.327849 0.000559
50 92.2301 92.6910 +0.50% 0.313224, 0.327220 0.313079, 0.327227 0.000145
55 151.2138 151.2556 +0.03% 0.312910, 0.327506 0.312537, 0.327539 0.000374
60 244.1470 242.7471 -0.57% 0.313166, 0.327479 0.312641, 0.327090 0.000653
65 390.5509 390.1389 -0.11% 0.314268, 0.330878 0.313953, 0.330410 0.000564
70 446.3650 444.7009 -0.37% 0.313088, 0.330171 0.312368, 0.329239 0.001178
75 446.7560 447.7941 +0.23% 0.313035, 0.330090 0.312760, 0.329915 0.000326
80 446.5855 448.0091 +0.32% 0.312908, 0.330021 0.312695, 0.329838 0.000281
85 446.5901 448.0128 +0.32% 0.312815, 0.330002 0.312625, 0.329871 0.000231
90 447.5845 447.0638 -0.12% 0.312712, 0.329921 0.312513, 0.329753 0.000260
95 448.4356 447.8440 -0.13% 0.312652, 0.329892 0.312453, 0.329698 0.000278
100 448.2605 447.4929 -0.17% 0.312617, 0.329842 0.312404, 0.329651 0.000286

From 65 through 100 percent, maximum absolute luminance difference was 0.37 percent and maximum dxy was 0.001178. Peak was 447.49 cd/m2 without VCGT and 448.26 cd/m2 with VCGT. The larger 5 percent chromaticity difference is at less than 0.05 cd/m2, where meter repeatability dominates.

pgen22 acceptance result

The final MSI MPG321UX OLED acceptance used one uninterrupted meter setup, full-range HDR10, a centered fullscreen 10 percent patch and the same final ICC profile for both paths. KWin used the HDR ICC source; the Companion control switched KWin to EDID and evaluated the profile cLUT itself.

The two paths agree across the complete grayscale. From 10 through 100 percent the largest luminance difference was 5.24 percent at only 0.35 cd/m2. From 30 through 100 percent it was 1.18 percent, and through the 65 to 100 percent rolloff it was 0.25 percent. Mean non-black absolute differences were 1.82 percent luminance, 0.000769 x and 0.000693 y. Near-black relative percentages are dominated by meter repeatability at less than 0.1 cd/m2.

Against absolute PQ plus D65, average grayscale error was 1.68 dE ITP for KWin and 1.29 dE ITP for the Companion cLUT. KWin stayed below 1.43 dE ITP from 40 percent through peak and below 0.83 through the 65 to 100 percent rolloff. The former dim cyan plateau is gone: final KWin white measured 443.40 cd/m2 at x 0.31161, y 0.32915; Companion measured 444.41 cd/m2 at x 0.31190, y 0.32972.

Final profile SHA-256: 46f6554b680cc65629ef6b4a5f7f77b272175895b9cbdf578f50831c27d940ae

Final result JSON SHA-256 values:

  • KWin: cf42e1c922ef41e0673d26fa0a9cd636216d9cc47ca4a70e9150d8acb85775f6
  • Companion cLUT: 282d22ad8285d7a371134c9c879eab424dda481be8dbb02b4e66db24b22abf44

Historical pgen14 native HDR mismatch

Later matched testing separated KWin profile handling from application-side cLUT handling. Both runs used the same display, meter position, 10 percent window, full-range HDR10 signal, 21-point sequence and ICC profile.

KWin 6.7.4 pgen14 was first verified with kscreen-doctor -o. Merely storing an HDR ICC path is not sufficient: HDR color profile source must explicitly report ICC. With that setting confirmed and the application transform set to system handling, KWin measured 100 percent at x=0.30455, y=0.32035 and 7063 K. The 70 through 100 percent plateau retained the same blue-white shift.

The control run set KWin back to EDID handling and applied the same profile's B2A cLUT directly in the native Wayland HDR application. It measured 100 percent at x=0.31262, y=0.32961 and 6505 K. Its luminance values also followed PQ closely: 20 percent was 2.453 cd/m2, 30 percent was 10.147 cd/m2, 40 percent was 32.655 cd/m2, 50 percent was 93.492 cd/m2 and 60 percent was 246.027 cd/m2.

A separately built ICC v4.4 CICP profile with the original raw-device B2A0 and B2A1 transforms and no VCGT did not resolve the KWin result. Its 100 percent white was x=0.30451, y=0.32039 and 7065 K, with additional severe errors below 20 percent. Removing VCGT from a profile fitted in a calibrated device domain is not a valid test because that cLUT expects the missing calibration stage.

These measurements established that pgen14 fixed profile selection, B2A fallback, shader representation, CICP parsing and PQ precision, but had not yet reproduced the direct cLUT result. They are retained as the failure baseline that led to the later mft2 and neutral reference-domain fixes. The pgen18 acceptance results below supersede this limitation.

Historical pgen15 and pgen16 follow-up

A pgen15 build changed the CICP B2A source conversion to adapt Rec. 2020 D65 directly into the D50 PCS. Its measured grayscale was effectively unchanged from pgen14. It still measured 5 percent at 0.0014 cd/m2, 10 percent at 0.0765 cd/m2 and 15 percent at 0.4334 cd/m2, with severe chromaticity errors.

The pgen16 build additionally selected the quadratic B-shaper from profile CICP. Under the same profile, patch sequence and signal conditions, 5 percent measured 0.0776 cd/m2, 10 percent measured 0.2584 cd/m2 and 15 percent measured 0.7386 cd/m2. The catastrophic shadow collapse was therefore caused by the B-shaper domain being selected from KWin's gamma 2.2 intermediate instead of the PQ profile encoding.

The same run still retained the display's native blue-white from the midrange through peak. Inspection of the tested profile found that its B2A white output and VCGT approximately cancel to equal physical RGB. This is a separate profile-characterization issue, not evidence against the pgen16 precision fix. A calibrated-domain profile must exclude measurements outside the VCGT-reachable device range and must define media white from the calibrated endpoint rather than the uncalibrated native-white sample.

Historical pgen18 reference-order experiment

This section records the earlier pgen18 experiment. The pgen22 source-domain calibration result above supersedes it.

The remaining rolloff mismatch was not an unknown 1.8 power curve and was not specific to the Innoview display. KWin converted a client's surface reference white into the output reference-white domain before running the display B2A transform. The Companion cLUT control correctly ran B2A first. Those operations do not commute when B2A contains a nonlinear HDR rolloff.

For full-range Rec. 2020/PQ B2A profiles, the shader now temporarily restores the surface reference domain, evaluates the profile's complete B/M/cLUT/A pipeline, then reapplies the compositor reference conversion and clips to the real output peak. The scale is KWin's runtime surface-to-output ratio. There is no fitted gamma, hard-coded 1.8 transform or display-specific curve.

The old neutral-only VCGT override was removed. VCGT, when present, remains in the normal ICC pipeline. The same ordering correction therefore supports profiles with VCGT and profiles with no VCGT. Profile PCS luminance is also no longer advertised as display mastering metadata.

The final acceptance run used the MSI MPG321UX OLED, one pattern process, a centered 10 percent window, HDR10, full-range RGB, no pattern insertion and the same uninterrupted meter session for both paths. The profile contained VCGT so this run exercises the complete pipeline. Separate 65, 70 and 100 percent checks with the no-VCGT profile also followed its Companion cLUT result. Luminance is in cd/m2 and dxy is the Euclidean distance between measured x,y chromaticities:

IRE Companion cLUT Y KWin Y Y difference Companion x,y KWin x,y dxy
0 0.0000 0.0000 0.00% 0.333333, 0.333333 0.333333, 0.333333 0.000000
5 0.0559 0.0500 -10.66% 0.308379, 0.333297 0.305667, 0.306456 0.026978
10 0.2888 0.2817 -2.45% 0.307931, 0.331160 0.316919, 0.331630 0.009000
15 1.0069 0.9760 -3.07% 0.303493, 0.341637 0.304956, 0.340946 0.001618
20 2.4495 2.4011 -1.98% 0.300027, 0.337289 0.299388, 0.338238 0.001144
25 5.1548 5.0883 -1.29% 0.302417, 0.338554 0.304229, 0.336985 0.002397
30 10.0413 10.0042 -0.37% 0.304920, 0.335258 0.305298, 0.336031 0.000860
35 18.4958 18.3276 -0.91% 0.305650, 0.337476 0.306025, 0.336846 0.000733
40 32.5370 32.3611 -0.54% 0.304741, 0.335147 0.304765, 0.335851 0.000704
45 54.6147 54.1910 -0.78% 0.305188, 0.336212 0.305078, 0.336532 0.000338
50 92.3726 91.4889 -0.96% 0.303605, 0.335262 0.303530, 0.335215 0.000089
55 150.5402 148.7209 -1.21% 0.305426, 0.336210 0.306368, 0.336412 0.000963
60 240.0745 238.7515 -0.55% 0.306445, 0.337013 0.307012, 0.337392 0.000682
65 394.1778 393.7813 -0.10% 0.307803, 0.335807 0.307988, 0.335992 0.000262
70 453.7256 453.8291 +0.02% 0.307877, 0.336440 0.307935, 0.336516 0.000096
75 454.0822 454.2964 +0.05% 0.307816, 0.336410 0.307775, 0.336381 0.000050
80 454.2302 454.4443 +0.05% 0.307683, 0.336335 0.307642, 0.336307 0.000050
85 455.0104 454.3744 -0.14% 0.307632, 0.336267 0.307620, 0.336227 0.000042
90 455.1203 454.5215 -0.13% 0.307555, 0.336216 0.307508, 0.336206 0.000048
95 455.2636 454.3463 -0.20% 0.307514, 0.336162 0.307471, 0.336158 0.000043
100 455.8670 454.1377 -0.38% 0.307470, 0.336153 0.307398, 0.336113 0.000082

At the rolloff from 65 through 100 percent, maximum absolute luminance difference was 0.38 percent and maximum dxy was 0.000262. The much larger relative 5 percent error is based on only about 0.05 cd/m2 and includes meter and display repeatability near black.

Commit: d1c1b786de

Reproducible measurement procedure

For a useful comparison:

  1. Enable HDR and full RGB range on the test output.
  2. Disable any unrelated ICC profile or calibration stage during profiling.
  3. Use native PQ patches. Use a 10 percent window on OLED unless the display's behavior has been established with another geometry.
  4. Measure an identity or no-correction control first.
  5. Measure the MHC2 profile, then the v4.4 CICP cLUT profile without moving the meter or changing display controls.
  6. Include low-level points below 10 percent, a 21-point grayscale, saturation sweeps and a colour checker.
  7. Confirm with kscreen-doctor -o that HDR color profile source is ICC. A populated HDR ICC path can remain stored while the active source is still EDID.
  8. Record KWin version, profile hash, HDR profile source, range, bit depth, reference luminance and whether VCGT is present.

The pgen22 VCGT baseline profile used for the controlled comparison has SHA-256 46f6554b680cc65629ef6b4a5f7f77b272175895b9cbdf578f50831c27d940ae.

Scope

This is an experimental integration branch. It is useful for producing a reviewable KWin fix and repeatable measurement evidence. It is not a claim that every HDR ICC profile is PQ encoded. Profiles without the matching CICP tag retain KWin's existing gamma 2.2 behavior.

Upstream KWin documentation and contribution guidance are available at https://invent.kde.org/plasma/kwin.

Reset HDR tone mapping without changing ICC selection

KDE's HDR brightness calibrator changes the output peak override, SDR reference brightness and physical brightness while it is open. Reapplying those values can also leave the live output pipeline in a different state from the one used to validate an ICC profile.

reset-hdr-tonemapping.sh resets only the tone-mapping inputs. It discovers connected HDR outputs, clears peak, maximum-average and minimum-luminance overrides, restores KWin's default SDR reference from the display-advertised maximum-average luminance, and cycles HDR so the output pipeline is rebuilt. It does not set or clear an ICC path and does not change the HDR profile source.

The script is a separate asset on the pgen23 release page. Download it, make it executable, and run it from a Plasma Wayland session as the logged-in desktop user. Do not run it with sudo.

Preview the reset first:

./reset-hdr-tonemapping.sh --dry-run

Reset all active HDR monitors:

./reset-hdr-tonemapping.sh

Reset one connector while preserving its current SDR reference brightness:

./reset-hdr-tonemapping.sh --output DP-2 --keep-sdr

About

Easy to use, but flexible, Wayland Compositor

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages