On 7/31/2026 3:31 PM, Robert Mader wrote:
Hi Chaitanya, thanks for the explanation and sorry for the delayed
answer! I needed to think about it for a bit and would like to propose
an idea now, see below.
No problem!
On 30.07.26 16:27, Pekka Paalanen wrote:
...
Limited to RGB",
+ [DRM_COLOROP_FM_YCBCR_LIMITED_FULL] = "YCbCr limited to full",
+ [DRM_COLOROP_FM_RGB709_RGB2020] = "RGB709 to RGB2020",
I'm still a bit unsure how useful the later two values are,
You can see them being used in [1] and tested by [2]. We split out the
"YCbCr limited to full" block because some Intel planes have a 1DLUT
between it and the "YCbCr XXX Full to RGB" block. This keeps the color
pipeline consistent with the actual HW.
Hi Chaitanya,
it would be nice for VKMS to be able to have such a color
pipeline only. Then userspace authors can test it.
That gives me the idea, that perhaps there should be a library of color
pipelines for VKMS that replicates actual hardware pipelines. Maybe it
would be in the kernel, or maybe it would be in some userspace project
if VKMS pipelines can be crafted through configfs or something else.
Based on your experience implementing the colorop in weston, do you
foresee any challenges in supporting limited-range framebuffers using
the "YCbCr Limited-to-Full" fixed matrix block?
I cannot imagine a big problem, but it is yet another configuration
that userspace must be explicitly prepared for.
I agree with Pekka - it shouldn't be hard to implement, especially if it
can be tested on VKMS, but I'm worried that:
1. It could end up resulting in some "Intel-only" code that most Wayland
compositors would need to carry around.
2. While having an additional 1D curve is great, IIUC it wouldn't be
needed/used by Weston and similar compositors for now.
3. It would complicate the use of a cross-vendor helper for the legacy
properties (for clients not setting
DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE) as discussed in https://
lore.kernel.org/dri-devel/d42d5750-f3c5-4e2b-
[email protected]/
IIUC there should be a simple solution for that, though, and I'd like to
ask if you think it would work for you: the Intel driver could just
expose two pipelines: a "complex" one with "YCbCr Limited-to-Full" in
the first fixed-matrix color-op and the additional 1D lut - and a
"simple" one with a single fixed-matrix also support the "Limited to
RGB" values. The later would waste the 1D lut in favor of compatibility
with clients not supporting "YCbCr Limited-to-Full".
To be fully clear what I mean: IIUC right now the drm_info output of you
pipeline looks *roughly* like this:
└───"COLOR_PIPELINE" (atomic): enum {Bypass, Color Pipeline 1} =
Bypass
├───Bypass
└───Color Pipeline 1
├───Color Operation 1
│ └───Properties
│ ├───"TYPE" (immutable): enum {1D Curve, 1D LUT,
3x4 Matrix, Multiplier, 3D LUT, Fixed Matrix} = Fixed Matrix
│ ├───"BYPASS" (atomic): range [0, 1] = 1
│ ├───"NEXT" (atomic, immutable): object colorop = 2
│ └───"FIXED_MATRIX_TYPE" (atomic): enum {YCbCr 601
Full to RGB, YCbCr 709 Full to RGB, YCbCr 2020 NC Full to RGB, YCbCr limited to full,
RGB709 to RGB2020} = YCbCr 601 Full to RGB
├───Color Operation 2
│ └───Properties
│ ├───"TYPE" (immutable): enum {1D Curve, 1D LUT,
3x4 Matrix, Multiplier, 3D LUT, Fixed Matrix} = 1D Curve
│ ├───"BYPASS" (atomic): range [0, 1] = 1
│ ├───"NEXT" (atomic, immutable): object colorop = 3
│ └───"CURVE_1D_TYPE" (atomic): enum {sRGB EOTF,
sRGB Inverse EOTF, Gamma 2.2, Gamma 2.2 Inverse, Gamma 2.4, Gamma 2.4 Inverse} = sRGB
EOTF]
├───Color Operation 3
│ └───Properties
│ ├───"TYPE" (immutable): enum {1D Curve, 1D LUT,
3x4 Matrix, Multiplier, 3D LUT, Fixed Matrix} = Fixed Matrix
│ ├───"BYPASS" (atomic): range [0, 1] = 1
│ ├───"NEXT" (atomic, immutable): object colorop = 4
│ └───"FIXED_MATRIX_TYPE" (atomic): enum {YCbCr 601
Full to RGB, YCbCr 709 Full to RGB, YCbCr 2020 NC Full to RGB, YCbCr limited to full,
RGB709 to RGB2020} = YCbCr 601 Full to RGB
├───Color Operation 4
│ └───Properties
│ ├───"TYPE" (immutable): enum {1D Curve, 1D LUT,
3x4 Matrix, Multiplier, 3D LUT, Fixed Matrix} = 1D Curve
│ ├───"BYPASS" (atomic): range [0, 1] = 1
│ ├───"NEXT" (atomic, immutable): object colorop = 5
│ └───"CURVE_1D_TYPE" (atomic): enum {sRGB EOTF,
sRGB Inverse EOTF, Gamma 2.2, Gamma 2.2 Inverse, Gamma 2.4, Gamma 2.4 Inverse} = sRGB
EOTF]
...
While I think it should look like this:
└───"COLOR_PIPELINE" (atomic): enum {Bypass, Color Pipeline 1,
Color Pipeline 2} = Bypass
├───Bypass
├───Color Pipeline 1
│ ├───Color Operation 11
│ │ └───Properties
│ │ ├───"TYPE" (immutable): enum {1D Curve, 1D LUT,
3x4 Matrix, Multiplier, 3D LUT, Fixed Matrix} = Fixed Matrix
│ │ ├───"BYPASS" (atomic): range [0, 1] = 1
│ │ ├───"NEXT" (atomic, immutable): object colorop = 12
│ │ └───"FIXED_MATRIX_TYPE" (atomic): enum {YCbCr 601
Full to RGB, YCbCr 709 Full to RGB, YCbCr 2020 NC Full to RGB, YCbCr limited to full,
RGB709 to RGB2020} = YCbCr 601 Full to RGB
This would be
{YCbCr limited to full} = YCbCr limited to full
│ ├───Color Operation 12
│ │ └───Properties
│ │ ├───"TYPE" (immutable): enum {1D Curve, 1D LUT,
3x4 Matrix, Multiplier, 3D LUT, Fixed Matrix} = 1D Curve
│ │ ├───"BYPASS" (atomic): range [0, 1] = 1
│ │ ├───"NEXT" (atomic, immutable): object colorop = 13
│ │ └───"CURVE_1D_TYPE" (atomic): enum {sRGB EOTF,
sRGB Inverse EOTF, Gamma 2.2, Gamma 2.2 Inverse, Gamma 2.4, Gamma 2.4 Inverse} = sRGB
EOTF]
│ ├───Color Operation 13
│ │ └───Properties
│ │ ├───"TYPE" (immutable): enum {1D Curve, 1D LUT,
3x4 Matrix, Multiplier, 3D LUT, Fixed Matrix} = Fixed Matrix
│ │ ├───"BYPASS" (atomic): range [0, 1] = 1
│ │ ├───"NEXT" (atomic, immutable): object colorop = 14
│ │ └───"FIXED_MATRIX_TYPE" (atomic): enum {YCbCr 601
Full to RGB, YCbCr 709 Full to RGB, YCbCr 2020 NC Full to RGB, YCbCr limited to full,
RGB709 to RGB2020} = YCbCr 601 Full to RGB
│ ├───Color Operation 14
│ │ └───Properties
│ │ ├───"TYPE" (immutable): enum {1D Curve, 1D LUT,
3x4 Matrix, Multiplier, 3D LUT, Fixed Matrix} = 1D Curve
│ │ ├───"BYPASS" (atomic): range [0, 1] = 1
│ │ ├───"NEXT" (atomic, immutable): object colorop = 15
│ │ └───"CURVE_1D_TYPE" (atomic): enum {sRGB EOTF,
sRGB Inverse EOTF, Gamma 2.2, Gamma 2.2 Inverse, Gamma 2.4, Gamma 2.4 Inverse} = sRGB
EOTF]
...
└───Color Pipeline 2
├───Color Operation 21
│ └───Properties
│ ├───"TYPE" (immutable): enum {1D Curve, 1D LUT,
3x4 Matrix, Multiplier, 3D LUT, Fixed Matrix} = Fixed Matrix
│ ├───"BYPASS" (atomic): range [0, 1] = 1
│ ├───"NEXT" (atomic, immutable): object colorop = 22
│ └───"FIXED_MATRIX_TYPE" (atomic): enum {YCbCr 601
Full to RGB, YCbCr 601 Limited to RGB, YCbCr 709 Full to RGB, YCbCr 709 Limited to RGB,
YCbCr 2020 NC Full to RGB, YCbCr 2020 NC Limited to RGB} = YCbCr 601 Full to RGB
├───Color Operation 22
│ └───Properties
│ ├───"TYPE" (immutable): enum {1D Curve, 1D LUT,
3x4 Matrix, Multiplier, 3D LUT, Fixed Matrix} = 1D Curve
│ ├───"BYPASS" (atomic): range [0, 1] = 1
│ ├───"NEXT" (atomic, immutable): object colorop = 23
│ └───"CURVE_1D_TYPE" (atomic): enum {sRGB EOTF,
sRGB Inverse EOTF, Gamma 2.2, Gamma 2.2 Inverse, Gamma 2.4, Gamma 2.4 Inverse} = sRGB
EOTF]
...
and all the "1D Curve"s will be programmable "1D LUT"s
This should allow us to have the best from both worlds - maximum
flexibility for users wanting the additional 1D lut, as well as simple
clients just needed a drop-in replacement for the legacy properties.
Please let me know if that make sense and you think that would be
possible (especially if I made wrong assumptions here).
That is a good idea. (I am a bit disappointed I did not think of it :/).
We can initially have a pipeline with:
[YUV -> RGB Fixed Matrix] -> [1D LUT]
For now the fixed matrix only exposes -
{YCbCr 601 Full to RGB, YCbCr 601 Limited to RGB, YCbCr 709 Full to RGB,
YCbCr 709 Limited to RGB, YCbCr 2020 NC Full to RGB, YCbCr 2020 NC
Limited to RGB}
Thanks,
pq
As for the "RGB709 to RGB2020" block, I can see it being useful for
converting SDR Rec.709 content into the Rec.2020 color space before
blending it with an HDR plane.
I see, thanks. At least for Weston I think it's unlikely that we will
use that for now - the current plan is to blend in linear space and then
use the post-blending / CRTC pipeline convert to the output color space.
But AFAIK that's not in any way implied by Wayland, so other compositors
may well take different approaches and use this matrix.
Even with linear blending a compositor might need to convert a Rec.709
plane to Rec.2020 if it intends to blend in Rec.2020. Though, I am not
sure which blending space Weston operates in.
My request to drop it from the series was purely about landing it
together with the corresponding implementation - like Harry just
announced for v5 in https://lore.kernel.org/dri-devel/
[email protected]/ - i.e. I don't have any
reservations against the matrix/enum.
I understand. I was merely wondering if there will be some
implementation complexity that you would like to flag.
Thanks a lot for the suggestion! :)
==
Chaitanya
Best regards,
Robert
--
Robert Mader
Consultant Software Developer
Collabora Ltd.
Platinum Building, St John's Innovation Park, Cambridge CB4 0DS, UK
Registered in England & Wales, no. 5513718