Re: [PATCH v4 01/11] drm/colorop: Add DRM_COLOROP_FIXED_MATRIX
Robert Mader <[email protected]> Fri, 31 Jul 2026 12:01:42 +0200
| Newsgroups | org.freedesktop.lists.amd-gfx,org.freedesktop.lists.dri-devel |
|---|---|
| Message-ID | <[email protected]> |
This is a multi-part message in MIME format. --------------v5HAvdRonGnF2LpgNUlV3vv1 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit 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 --------------v5HAvdRonGnF2LpgNUlV3vv1 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: 8bit <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> </head> <body> <p>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.</p> <div class="moz-cite-prefix">On 30.07.26 16:27, Pekka Paalanen wrote:<br> </div> <blockquote type="cite" cite="mid:20260730172758.0c65485f@fluorite"> <blockquote type="cite"> <blockquote type="cite"> <blockquote type="cite"> <pre wrap="" class="moz-quote-pre">... Limited to RGB", + [DRM_COLOROP_FM_YCBCR_LIMITED_FULL] = "YCbCr limited to full", + [DRM_COLOROP_FM_RGB709_RGB2020] = "RGB709 to RGB2020", </pre> </blockquote> <pre wrap="" class="moz-quote-pre">I'm still a bit unsure how useful the later two values are, </pre> </blockquote> <pre wrap="" class="moz-quote-pre">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. </pre> </blockquote> <pre wrap="" class="moz-quote-pre">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. </pre> <blockquote type="cite"> <pre wrap="" class="moz-quote-pre">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? </pre> </blockquote> <pre wrap="" class="moz-quote-pre">I cannot imagine a big problem, but it is yet another configuration that userspace must be explicitly prepared for.</pre> </blockquote> <p> I agree with Pekka - it shouldn't be hard to implement, especially if it can be tested on VKMS, but I'm worried that:</p> <p>1. It could end up resulting in some "Intel-only" code that most Wayland compositors would need to carry around.</p> <p>2. While having an additional 1D curve is great, IIUC it wouldn't be needed/used by Weston and similar compositors for now.</p> <p>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 <a class="moz-txt-link-freetext" href="https://lore.kernel.org/dri-devel/[email protected]/">https://lore.kernel.org/dri-devel/[email protected]/</a></p> <p><br> </p> <p>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".</p> <p>To be fully clear what I mean: IIUC right now the drm_info output of you pipeline looks *roughly* like this:</p> <pre> └───"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] ... </pre> <p>While I think it should look like this:</p> <pre> └───"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] ... </pre> <p>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.</p> <p>Please let me know if that make sense and you think that would be possible (especially if I made wrong assumptions here).</p> <blockquote type="cite" cite="mid:20260730172758.0c65485f@fluorite"> <pre wrap="" class="moz-quote-pre">Thanks, pq </pre> <blockquote type="cite"> <pre wrap="" class="moz-quote-pre">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.</pre> </blockquote> </blockquote> <p>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.</p> <p>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 <a class="moz-txt-link-freetext" href="https://lore.kernel.org/dri-devel/[email protected]/">https://lore.kernel.org/dri-devel/[email protected]/</a> - i.e. I don't have any reservations against the matrix/enum.</p> <p>Best regards,</p> <p>Robert</p> <pre class="moz-signature" cols="72">-- Robert Mader Consultant Software Developer Collabora Ltd. Platinum Building, St John's Innovation Park, Cambridge CB4 0DS, UK Registered in England & Wales, no. 5513718</pre> </body> </html> --------------v5HAvdRonGnF2LpgNUlV3vv1--