Re: [PATCH v4 01/11] drm/colorop: Add DRM_COLOROP_FIXED_MATRIX

"Borah, Chaitanya Kumar" <[email protected]> Fri, 31 Jul 2026 10:04:53 +0530
Newsgroups org.freedesktop.lists.amd-gfx,org.freedesktop.lists.dri-devel
Message-ID <[email protected]>

On 7/31/2026 1:57 AM, Harry Wentland wrote:
> 
> 
> On 2026-07-30 06:59, Pekka Paalanen wrote:
>> On Wed, 22 Jul 2026 09:45:57 -0400
>> Harry Wentland <[email protected]> wrote:
>>
>>> From: Chaitanya Kumar Borah <[email protected]>
>>>
>>> Introduce DRM_COLOROP_FIXED_MATRIX, a new colorop type representing a
>>> hardware that performs a fixed matrix operation.
>>>
>>> Unlike CTM-based colorops, this block does not expose programmable
>>> coefficients. Instead, userspace selects one of the predefined
>>> hardware modes via a new FIXED_MATRIX_TYPE enum property. Supported modes
>>> include common YCbCr->RGB and RGB709->RGB2020 conversions.
>>>
>>> v4:
>>>   - Add limited-range YCbCr-RGB conversion matrix enums (Robert)
>>>   - Document matrix values (Pekka)
>>>   - Clarify RGB709 to RGB2020 is a full-range matrix (Pekka)
>>>   - Fix confusing "CSC preset" doc (Pekka)
>>>
>>> v2:
>>>   - Naming changes (Pekka)
>>>
>>> v3:
>>>   - Fix NC matrix enum name and string (Melissa)
>>>   - Rebase
>>>
>>> Co-developed-by: Harry Wentland <[email protected]>
>>> Signed-off-by: Chaitanya Kumar Borah <[email protected]>
>>> Signed-off-by: Harry Wentland <[email protected]>
>>> Reviewed-by: Melissa Wen <[email protected]>
>>> Reviewed-by: Harry Wentland <[email protected]>
>>> Reviewed-by: Robert Mader <[email protected]>
>>> ---
>>>   drivers/gpu/drm/drm_atomic.c      |   4 +
>>>   drivers/gpu/drm/drm_atomic_uapi.c |   7 ++
>>>   drivers/gpu/drm/drm_colorop.c     | 109 ++++++++++++++++++++
>>>   include/drm/drm_colorop.h         | 159 ++++++++++++++++++++++++++++++
>>>   include/uapi/drm/drm_mode.h       |  12 +++
>>>   5 files changed, 291 insertions(+)
>>
>>> diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
>>> index 682fcc651525..e7ccf7d053b8 100644
>>> --- a/drivers/gpu/drm/drm_colorop.c
>>> +++ b/drivers/gpu/drm/drm_colorop.c
>>> @@ -68,6 +68,7 @@ static const struct drm_prop_enum_list drm_colorop_type_enum_list[] = {
>>>   	{ DRM_COLOROP_CTM_3X4, "3x4 Matrix"},
>>>   	{ DRM_COLOROP_MULTIPLIER, "Multiplier"},
>>>   	{ DRM_COLOROP_3D_LUT, "3D LUT"},
>>> +	{ DRM_COLOROP_FIXED_MATRIX, "Fixed Matrix"},
>>>   };
>>>   
>>>   static const char * const colorop_curve_1d_type_names[] = {
>>> @@ -90,6 +91,17 @@ static const struct drm_prop_enum_list drm_colorop_lut3d_interpolation_list[] =
>>>   	{ DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL, "Tetrahedral" },
>>>   };
>>>   
>>> +static const char * const colorop_fixed_matrix_type_names[] = {
>>> +	[DRM_COLOROP_FM_YCBCR601_FULL_RGB] = "YCbCr 601 Full to RGB",
>>> +	[DRM_COLOROP_FM_YCBCR601_LIMITED_RGB] = "YCbCr 601 Limited to RGB",
>>> +	[DRM_COLOROP_FM_YCBCR709_FULL_RGB] = "YCbCr 709 Full to RGB",
>>> +	[DRM_COLOROP_FM_YCBCR709_LIMITED_RGB] = "YCbCr 709 Limited to RGB",
>>> +	[DRM_COLOROP_FM_YCBCR2020_NC_FULL_RGB] = "YCbCr 2020 NC Full to RGB",
>>> +	[DRM_COLOROP_FM_YCBCR2020_NC_LIMITED_RGB] = "YCbCr 2020 NC Limited to RGB",
>>> +	[DRM_COLOROP_FM_YCBCR_LIMITED_FULL] = "YCbCr limited to full",
>>> +	[DRM_COLOROP_FM_RGB709_RGB2020] = "RGB709 to RGB2020",
>>> +};
>>
>>
>>> diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
>>> index 224fae40ed2b..92eb6463c39f 100644
>>> --- a/include/drm/drm_colorop.h
>>> +++ b/include/drm/drm_colorop.h
>>> @@ -134,6 +134,146 @@ enum drm_colorop_curve_1d_type {
>>>   	DRM_COLOROP_1D_CURVE_COUNT
>>>   };
>>>   
>>> +/**
>>> + * enum drm_colorop_fixed_matrix_type - type of Fixed Matrix
>>> + *
>>> + * Describes a Fixed Matrix operation to be applied by the DRM_COLOROP_FIXED_MATRIX
>>> + */
>>> +enum drm_colorop_fixed_matrix_type {
>>> +	/**
>>> +	 * @DRM_COLOROP_FM_YCBCR601_FULL_RGB:
>>> +	 *
>>> +	 * enum string "YCbCr 601 Full to RGB"
>>> +	 *
>>> +	 * Converts full-range YCbCr into full-range RGB using the BT.601
>>> +	 * coefficients. Y is normalized to [0, 1] and Cb, Cr are centered
>>> +	 * at 0 (the nominal 0.5 offset removed) before the matrix::
>>> +	 *
>>> +	 *   | R |   | 1.0   0.000000   1.402000 |   | Y  |
>>> +	 *   | G | = | 1.0  -0.344136  -0.714136 | x | Cb |
>>> +	 *   | B |   | 1.0   1.772000   0.000000 |   | Cr |
>>> +	 */
>>> +	DRM_COLOROP_FM_YCBCR601_FULL_RGB,
>>> +
>>> +	/**
>>> +	 * @DRM_COLOROP_FM_YCBCR601_LIMITED_RGB:
>>> +	 *
>>> +	 * enum string "YCbCr 601 Limited to RGB"
>>> +	 *
>>> +	 * Converts limited- (narrow-) range YCbCr into full-range RGB using
>>> +	 * the BT.601 coefficients. Before the matrix Y is offset by 16/255
>>> +	 * and Cb, Cr are centered at 0, following the studio-range
>>> +	 * convention of ITU-R BT.601::
>>> +	 *
>>> +	 *   | R |   | 1.164384   0.000000   1.596027 |   | Y - 16/255 |
>>> +	 *   | G | = | 1.164384  -0.391762  -0.812968 | x | Cb         |
>>> +	 *   | B |   | 1.164384   2.017232   0.000000 |   | Cr         |
>>> +	 */
>>> +	DRM_COLOROP_FM_YCBCR601_LIMITED_RGB,
>>> +
>>> +	/**
>>> +	 * @DRM_COLOROP_FM_YCBCR709_FULL_RGB:
>>> +	 *
>>> +	 * enum string "YCbCr 709 Full to RGB"
>>> +	 *
>>> +	 * Converts full-range YCbCr into full-range RGB using the BT.709
>>> +	 * coefficients. Y is normalized to [0, 1] and Cb, Cr are centered
>>> +	 * at 0 (the nominal 0.5 offset removed) before the matrix::
>>> +	 *
>>> +	 *   | R |   | 1.0   0.000000   1.574800 |   | Y  |
>>> +	 *   | G | = | 1.0  -0.187324  -0.468124 | x | Cb |
>>> +	 *   | B |   | 1.0   1.855600   0.000000 |   | Cr |
>>> +	 */
>>> +	DRM_COLOROP_FM_YCBCR709_FULL_RGB,
>>> +
>>> +	/**
>>> +	 * @DRM_COLOROP_FM_YCBCR709_LIMITED_RGB:
>>> +	 *
>>> +	 * enum string "YCbCr 709 Limited to RGB"
>>> +	 *
>>> +	 * Converts limited- (narrow-) range YCbCr into full-range RGB using
>>> +	 * the BT.709 coefficients. Before the matrix Y is offset by 16/255
>>> +	 * and Cb, Cr are centered at 0, following the studio-range
>>> +	 * convention of ITU-R BT.709::
>>> +	 *
>>> +	 *   | R |   | 1.164384   0.000000   1.792741 |   | Y - 16/255 |
>>> +	 *   | G | = | 1.164384  -0.213249  -0.532909 | x | Cb         |
>>> +	 *   | B |   | 1.164384   2.112402   0.000000 |   | Cr         |
>>> +	 */
>>> +	DRM_COLOROP_FM_YCBCR709_LIMITED_RGB,
>>> +
>>> +	/**
>>> +	 * @DRM_COLOROP_FM_YCBCR2020_NC_FULL_RGB:
>>> +	 *
>>> +	 * enum string "YCbCr 2020 NC Full to RGB"
>>> +	 *
>>> +	 * Converts full-range YCbCr into full-range RGB using the BT.2020
>>> +	 * non-constant luminance coefficients. Y is normalized to [0, 1]
>>> +	 * and Cb, Cr are centered at 0 (the nominal 0.5 offset removed)
>>> +	 * before the matrix::
>>> +	 *
>>> +	 *   | R |   | 1.0   0.000000   1.474600 |   | Y  |
>>> +	 *   | G | = | 1.0  -0.164553  -0.571353 | x | Cb |
>>> +	 *   | B |   | 1.0   1.881400   0.000000 |   | Cr |
>>> +	 */
>>> +	DRM_COLOROP_FM_YCBCR2020_NC_FULL_RGB,
>>> +
>>> +	/**
>>> +	 * @DRM_COLOROP_FM_YCBCR2020_NC_LIMITED_RGB:
>>> +	 *
>>> +	 * enum string "YCbCr 2020 NC Limited to RGB"
>>> +	 *
>>> +	 * Converts limited- (narrow-) range YCbCr into full-range RGB using
>>> +	 * the BT.2020 non-constant luminance coefficients. Before the matrix
>>> +	 * Y is offset by 16/255 and Cb, Cr are centered at 0, following the
>>> +	 * studio-range convention of ITU-R BT.2020::
>>> +	 *
>>> +	 *   | R |   | 1.164384   0.000000   1.678674 |   | Y - 16/255 |
>>> +	 *   | G | = | 1.164384  -0.187326  -0.650424 | x | Cb         |
>>> +	 *   | B |   | 1.164384   2.141772   0.000000 |   | Cr         |
>>> +	 */
>>> +	DRM_COLOROP_FM_YCBCR2020_NC_LIMITED_RGB,
>>> +
>>> +	/**
>>> +	 * @DRM_COLOROP_FM_YCBCR_LIMITED_FULL:
>>> +	 *
>>> +	 * enum string "YCbCr limited to full"
>>> +	 *
>>> +	 * Converts limited- (narrow-) range YCbCr into full-range YCbCr.
>>> +	 * Though not strictly a matrix operation it can be represented as
>>> +	 * one. Luma is expanded by 255/219 and chroma by 255/224, keeping
>>> +	 * the black level (16/255) and chroma neutral point (0.5) fixed::
>>> +	 *
>>> +	 *   | Y'      |   | 1.164384  0.000000  0.000000 |   | Y - 16/255 |
>>> +	 *   | Cb'-0.5 | = | 0.000000  1.138393  0.000000 | x | Cb - 0.5   |
>>> +	 *   | Cr'-0.5 |   | 0.000000  0.000000  1.138393 |   | Cr - 0.5   |
>>> +	 */
>>
>> Hi Harry,
>>
>> the prime notation (Y') is often used to signify an electrical domain
>> while in the same context stimulus variables without prime signify an
>> optical domain. Using both forms here might cause some confusion.
>> Instead of an equals sign, maybe you could use an arrow to avoid having
>> to rename all YCbCr variables? (e.g. x ← x + 1)
>>
>> About the chroma offset for both ranges on all coefficients; it depends
>> on the number of bits per channel B such that
>>
>> 	N = 1 << B
>> 	offset = (N / 2) / (N - 1)
>>
>> I assume the drivers and hardware get this right, but I feel a little
>> uncomfortable letting this approximation into the documentation since,
>> strictly speaking, it's incorrect.
>>
> 
> I'm dropping DRM_COLOROP_FM_YCBCR_LIMITED_FULL and DRM_COLOROP_FM_RGB709_RGB2020
> from v5 because we don't have any good non-IGT usermode testing these currently,
> to my knowledge.
> 

Sure Harry, makes sense. We will try to get one user mode implementation 
soon.

> Chaitanya, I expect you'll re-add them for your Intel series. Make sure to take
> Pekka's comments into account then. Would like to see how these fit into any
> compositor implementation.
> 

Ack, sorry for missing Pekka's comment the first time. I will take them 
into account when I create a patch for the colorops that Intel needs.

==
Chaitnaya

> Harry
> 
>>
>>> +	DRM_COLOROP_FM_YCBCR_LIMITED_FULL,
>>> +
>>> +	/**
>>> +	 * @DRM_COLOROP_FM_RGB709_RGB2020:
>>> +	 *
>>> +	 * enum string "RGB709 to RGB2020"
>>> +	 *
>>> +	 * Selects the matrix that converts full-range RGB with BT.709
>>> +	 * primaries to full-range RGB with BT.2020 primaries. The
>>> +	 * coefficients match the RGB-to-RGB conversion defined in
>>> +	 * ITU-R BT.2087::
>>> +	 *
>>> +	 *   | R2020 |   | 0.6274  0.3293  0.0433 |   | R709 |
>>> +	 *   | G2020 | = | 0.0691  0.9195  0.0114 | x | G709 |
>>> +	 *   | B2020 |   | 0.0164  0.0880  0.8956 |   | B709 |
>>> +	 */
>>> +	DRM_COLOROP_FM_RGB709_RGB2020,
>>> +
>>> +	/**
>>> +	 * @DRM_COLOROP_FM_COUNT:
>>> +	 *
>>> +	 * enum value denoting the size of the enum
>>> +	 */
>>> +	DRM_COLOROP_FM_COUNT
>>> +};
>>
>> I have verified all the matrices listed above.
>>
>> I would prefer to see the notational issues addressed, but with or
>> without:
>>
>> Reviewed-by: Pekka Paalanen <[email protected]>
>>
>>
>> Thanks,
>> pq
>