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.

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/[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
                │   ├───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]
                   ...

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).

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.

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.

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

Reply via email to