dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V8 00/43] Color Pipeline API w/ VKMS
@ 2025-03-26 23:46 Alex Hung
  2025-03-26 23:46 ` [PATCH V8 01/43] drm: Add helper for conversion from signed-magnitude Alex Hung
                   ` (43 more replies)
  0 siblings, 44 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:46 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet, Arthur Grillo

This is an RFC set for a color pipeline API, along with implementations
in VKMS and amdgpu. It is tested with a set of IGT tests that can be
found at [1]. The IGT tests run a pixel-by-pixel comparison with an
allowable delta variation as the goal for these transformations is
perceptual correctness, not complete pixel accuracy.

v5 of this patchset fleshed out documentation for colorops and the
various defines that are being introduced.

v6 addresses a few comments from various reviewers.

v7 simplifies 3D LUT and addresses more comments from various reviewers.

v8 fixes typo and errors and address comments from reviewers.

VKMS supports two named transfer function colorops and two matrix
colorops.

Amdgpu advertises the following pipeline for GPUs with DCN 3 or newer:

1. 1D Curve EOTF
2. 3x4 CTM
3. Multiplier
4. 1D Curve Inverse EOTF
5. 1D LUT
6. 3D LUT
7. 1D Curve EOTF
8. 1D LUT

The supported curves for the 1D Curve type are:
- sRGB EOTF and its inverse
- PQ EOTF, scaled to [0.0, 125.0] and its inverse
- BT.2020/BT.709 OETF and its inverse

Note that the 1st and 5th colorops take the EOTF or Inverse
OETF while the 3rd colorop takes the Inverse EOTF or OETF.

The 3D LUT is a 17^3 tetrahedrally interpolated LUT but the mechanism
exists for other drivers to describe their own 3D LUT capability.

This mirrors the color pipeline used by gamescope and presented by
Melissa Wen, with the exception of the DEGAM LUT, which is not currently
used. See [1]
https://indico.freedesktop.org/event/4/contributions/186/attachments/138/218/xdc2023-TheRainbowTreasureMap-MelissaWen.pdf

At this point we're hoping to see gamescope and kwin implementations
take shape. The existing pipeline should be enough to satisfy the
gamescope use-cases on the drm_plane.

In order to support YUV we'll need to add COLOR_ENCODING and COLOR_RANGE
support to the color pipeline. I have sketched these out already but
don't have it all hooked up yet. This should not hinder adoption of this
API for gaming use-cases.

We'll also want to advertise IN_FORMATS on a color pipeline as some
color pipelines won't be able to work for all IN_FORMATS on a plane.
Again, I have a sketch but no full implementation yet. This is not
currently required by the AMD color pipeline and could be added after
the merge of this set.

VKMS patches could still be improved in a few ways, though the
payoff might be limited and I would rather focus on other work
at the moment. The most obvious thing to improve would be to
eliminate the hard-coded LUTs for identity, and sRGB, and replace
them with fixed-point math instead.

There are plenty of things that I would like to see, but they could
be added after the merge of this patchset:
 - COLOR_ENCODING and COLOR_RANGE
 - IN_FORMATS for a color pipeline
 - Is it possible to support HW which can't bypass entire pipeline?
 - Can we do a LOAD / COMMIT model for LUTs (and other properties)?
 - read-only scaling colorop which defines scaling taps and position
 - named matrices, for things like converting YUV to RGB
 - Add custom LUT colorops to VKMS

IGT tests can be found at [1] or on the igt-dev mailing list. There
have been no updates since v5 and rebase on latest main is straight-
forward.

A kernel branch can be found at [2].

[1] https://gitlab.freedesktop.org/alex.hung/igt-gpu-tools/-/tree/amd-color-pipeline-v7
[2] https://gitlab.freedesktop.org/alex.hung/linux/-/tree/amd-color-pipeline-v8

v8:
 - Change VKMS config names (Louis Chauvet)
 - Remove deprecated function "drm_atomic_get_existing_colorop_state" (Louis Chauvet)
 - Remove null check in drm_colorop_set_next_property (Simon Ser)
 - Remove MAX_COLOR_PIPELINES in drm (Simon Ser)
 - Update kernel docs and documents for DRM_COLOROP_3D_LUT (Simon Ser)
 - Add comments for dmr_color_lut (Louis Chauvet)
 - Fix typos and replace DRM_ERROR and DRM_WARN_ONCE by drm_err drm_WARN_ONCE (Louis Chauvet)
 - Fix incorrect conditions in __set_colorop_in_tf_1d_curve (Leo Li)
 - Add DRM_MODE_PROP_ATOMIC to drm_property_create_range (Simon Ser)
 - Change "1D Curve Custom LUT" to "1D LUT" (Simon Ser)
 - Return error when __set_output_tf fails (Leo Li)
 - Return -EINVAL when drm_color_ctm_3x4's size mismatches (Leo Li)
 - Set initialized to 0 and return when drm_lut3d_size is 0 (Harry Wentland)
 - Rework tf->type = TF_TYPE_BYPASS for shaper (Harry Wentland & Leo Li)

v7:
 - Simplify 3D LUT by removing lut_3d_modes and update doc accordingly (Simon Ser)
 - Add destroy / cleanup functions when color pipeline initialization
   fails (Louis Chauvet)
 - Fix checkpatch errors and warning (spaces, long lines, {}, and etc)
 - Change lut's size from drm_colorop_state->size to drm_colorop->lut_size
   and from size_property to lut_size_property
 - Update some kernel updates and commit messagesa (Louis Chauvet)
 - Squash "drm/colorop: Add atomic state print for drm_colorop" and
   "drm/colorop: Add NEXT to colorop state print" (Simon Ser)
 - Add missing MODULE_DESCRIPTION (Jeff Johnson)

v6:
 - Eliminate need to include test as .c file (Louis Chauvet)
 - some doc updates
 - cleanup if colorop alloc or init fails in VKMS and amdgpu (Louis Chauvet)
 - couple other small improvements in VKMS, such as rounding (Louis Chauvet)
 - take ref for DATA blob in duplicate_state func & fix refcount issues (Xaver Hugl)

v5:
 - amdgpu 3D LUT
 - Don't require BYPASS
 - update RFC docs and add to TOC tree
 - add drm_colorop and COLOR_PIPELINE kernel docs (non-RFC)
 - add amdgpu color pipeline doc
 - define SIZE property similar to drm_crtc's GAMMA_SIZE
 - various minor fixes and cleanups

v4:
 - Add amdgpu color pipeline (WIP)
 - Don't block setting of deprecated properties, instead pass client cap
   to atomic check so drivers can ignore these props
 - Drop IOCTL definitions (Pekka)
 - Use enum property for colorop TYPE (Pekka)
 - A few cleanups to the docs (Pekka)
 - Rework the TYPE enum to name relation to avoid code duplication (Pekka)
 - Add missing function declarations (Chaitanya Kumar Borah)
 - Allow setting of NEXT property to NULL in _set_ function (Chaitanya Kumar Borah)
 - Add helper for creation of pipeline drm_plane property (Pekka)
 - Always create Bypass pipeline (Pekka)
 - A bunch of changes to VKMS kunit tests (Pekka)
 - Fix index in CTM doc (Pekka)

v3:
 - Abandon IOCTLs and discover colorops as clients iterate the pipeline
 - Remove need for libdrm
 - Add color_pipeline client cap and make mutually exclusive with
   COLOR_RANGE and COLOR_ENCODING properties
 - add CTM colorop to VKMS
 - Use include way for kunit testing static functions (Arthur)
 - Make TYPE a range property
 - Move enum drm_colorop_type to uapi header
 - and a bunch of smaller bits that are highlighted in the relevant commit
   description

v2:
 - Rebased on drm-misc-next
 - Introduce a VKMS Kunit so we can test LUT functionality in vkms_composer
 - Incorporate feedback in color_pipeline.rst doc
 - Add support for sRGB inverse EOTF
 - Add 2nd enumerated TF colorop to VKMS
 - Fix LUTs and some issues with applying LUTs in VKMS

Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
Cc: Pekka Paalanen <pekka.paalanen@collabora.com>
Cc: Simon Ser <contact@emersion.fr>
Cc: Harry Wentland <harry.wentland@amd.com>
Cc: Melissa Wen <mwen@igalia.com>
Cc: Jonas Ådahl <jadahl@redhat.com>
Cc: Sebastian Wick <sebastian.wick@redhat.com>
Cc: Shashank Sharma <shashank.sharma@amd.com>
Cc: Alexander Goins <agoins@nvidia.com>
Cc: Joshua Ashton <joshua@froggi.es>
Cc: Michel Dänzer <mdaenzer@redhat.com>
Cc: Aleix Pol <aleixpol@kde.org>
Cc: Xaver Hugl <xaver.hugl@gmail.com>
Cc: Victoria Brekenfeld <victoria@system76.com>
Cc: Sima <daniel@ffwll.ch>
Cc: Uma Shankar <uma.shankar@intel.com>
Cc: Naseer Ahmed <quic_naseer@quicinc.com>
Cc: Christopher Braga <quic_cbraga@quicinc.com>
Cc: Abhinav Kumar <quic_abhinavk@quicinc.com>
Cc: Arthur Grillo <arthurgrillo@riseup.net>
Cc: Hector Martin <marcan@marcan.st>
Cc: Liviu Dudau <Liviu.Dudau@arm.com>
Cc: Sasha McIntosh <sashamcintosh@google.com>
Cc: Chaitanya Kumar Borah <chaitanya.kumar.borah@intel.com>

Alex Hung (14):
  drm/colorop: define a new macro for_each_new_colorop_in_state
  drm/amd/display: Skip color pipeline initialization for cursor plane
  drm/amd/display: Add support for sRGB EOTF in DEGAM block
  drm/amd/display: Add support for sRGB Inverse EOTF in SHAPER block
  drm/amd/display: Add support for sRGB EOTF in BLND block
  drm/colorop: Add 1D Curve Custom LUT type
  drm/amd/display: add shaper and blend colorops for 1D Curve Custom LUT
  drm/amd/display: add 3x4 matrix colorop
  drm/colorop: Add mutliplier type
  drm/amd/display: add multiplier colorop
  drm/amd/display: Swap matrix and multiplier
  drm/colorop: Add 3D LUT support to color pipeline
  drm/amd/display: add 3D LUT colorop
  drm/colorop: Add destroy functions for color pipeline

Harry Wentland (29):
  drm: Add helper for conversion from signed-magnitude
  drm/vkms: Add kunit tests for VKMS LUT handling
  drm/doc/rfc: Describe why prescriptive color pipeline is needed
  drm/colorop: Introduce new drm_colorop mode object
  drm/colorop: Add TYPE property
  drm/colorop: Add 1D Curve subtype
  drm/colorop: Add BYPASS property
  drm/colorop: Add NEXT property
  drm/colorop: Add atomic state print for drm_colorop
  drm/plane: Add COLOR PIPELINE property
  drm/colorop: Introduce DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE
  Documentation/gpu: document drm_colorop
  drm/vkms: Add enumerated 1D curve colorop
  drm/vkms: Add kunit tests for linear and sRGB LUTs
  drm/colorop: Add 3x4 CTM type
  drm/vkms: Use s32 for internal color pipeline precision
  drm/vkms: add 3x4 matrix in color pipeline
  drm/tests: Add a few tests around drm_fixed.h
  drm/vkms: Add tests for CTM handling
  drm/colorop: pass plane_color_pipeline client cap to atomic check
  drm/amd/display: Ignore deprecated props when plane_color_pipeline set
  drm/amd/display: Add bypass COLOR PIPELINE
  drm/colorop: Add PQ 125 EOTF and its inverse
  drm/amd/display: Enable support for PQ 125 EOTF and Inverse
  drm/colorop: add BT2020/BT709 OETF and Inverse OETF
  drm/amd/display: Add support for BT.709 and BT.2020 TFs
  drm/colorop: Define LUT_1D interpolation
  drm/colorop: allow non-bypass colorops
  drm/amd/display: Add AMD color pipeline doc

 Documentation/gpu/drm-kms.rst                 |  15 +
 Documentation/gpu/rfc/color_pipeline.rst      | 378 ++++++++
 Documentation/gpu/rfc/index.rst               |   3 +
 drivers/gpu/drm/Makefile                      |   1 +
 .../gpu/drm/amd/display/amdgpu_dm/Makefile    |   3 +-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   4 +
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 573 ++++++++++++-
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.c | 206 +++++
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.h |  36 +
 .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   |  32 +
 drivers/gpu/drm/drm_atomic.c                  | 170 +++-
 drivers/gpu/drm/drm_atomic_helper.c           |  12 +
 drivers/gpu/drm/drm_atomic_state_helper.c     |   5 +
 drivers/gpu/drm/drm_atomic_uapi.c             | 176 ++++
 drivers/gpu/drm/drm_colorop.c                 | 607 +++++++++++++
 drivers/gpu/drm/drm_ioctl.c                   |   7 +
 drivers/gpu/drm/drm_mode_config.c             |   7 +
 drivers/gpu/drm/drm_plane.c                   |  59 ++
 drivers/gpu/drm/tests/Makefile                |   3 +-
 drivers/gpu/drm/tests/drm_fixp_test.c         |  71 ++
 drivers/gpu/drm/vkms/Kconfig                  |  15 +
 drivers/gpu/drm/vkms/Makefile                 |   5 +-
 drivers/gpu/drm/vkms/tests/.kunitconfig       |   4 +
 drivers/gpu/drm/vkms/tests/Makefile           |   3 +
 drivers/gpu/drm/vkms/tests/vkms_color_test.c  | 459 ++++++++++
 drivers/gpu/drm/vkms/vkms_colorop.c           | 113 +++
 drivers/gpu/drm/vkms/vkms_composer.c          | 134 ++-
 drivers/gpu/drm/vkms/vkms_composer.h          |  27 +
 drivers/gpu/drm/vkms/vkms_drv.h               |   7 +
 drivers/gpu/drm/vkms/vkms_luts.c              | 808 ++++++++++++++++++
 drivers/gpu/drm/vkms/vkms_luts.h              |  12 +
 drivers/gpu/drm/vkms/vkms_plane.c             |   2 +
 include/drm/drm_atomic.h                      | 111 +++
 include/drm/drm_atomic_uapi.h                 |   3 +
 include/drm/drm_colorop.h                     | 441 ++++++++++
 include/drm/drm_file.h                        |   7 +
 include/drm/drm_fixed.h                       |  18 +
 include/drm/drm_mode_config.h                 |  18 +
 include/drm/drm_plane.h                       |  19 +
 include/uapi/drm/amdgpu_drm.h                 |   9 -
 include/uapi/drm/drm.h                        |  15 +
 include/uapi/drm/drm_mode.h                   | 121 +++
 42 files changed, 4670 insertions(+), 49 deletions(-)
 create mode 100644 Documentation/gpu/rfc/color_pipeline.rst
 create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
 create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h
 create mode 100644 drivers/gpu/drm/drm_colorop.c
 create mode 100644 drivers/gpu/drm/tests/drm_fixp_test.c
 create mode 100644 drivers/gpu/drm/vkms/tests/.kunitconfig
 create mode 100644 drivers/gpu/drm/vkms/tests/Makefile
 create mode 100644 drivers/gpu/drm/vkms/tests/vkms_color_test.c
 create mode 100644 drivers/gpu/drm/vkms/vkms_colorop.c
 create mode 100644 drivers/gpu/drm/vkms/vkms_composer.h
 create mode 100644 drivers/gpu/drm/vkms/vkms_luts.c
 create mode 100644 drivers/gpu/drm/vkms/vkms_luts.h
 create mode 100644 include/drm/drm_colorop.h

-- 
2.43.0


^ permalink raw reply	[flat|nested] 128+ messages in thread

* [PATCH V8 01/43] drm: Add helper for conversion from signed-magnitude
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
@ 2025-03-26 23:46 ` Alex Hung
  2025-03-26 23:46 ` [PATCH V8 02/43] drm/vkms: Add kunit tests for VKMS LUT handling Alex Hung
                   ` (42 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:46 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

CTM values are defined as signed-magnitude values. Add
a helper that converts from CTM signed-magnitude fixed
point value to the twos-complement value used by
drm_fixed.

Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
 include/drm/drm_fixed.h | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/include/drm/drm_fixed.h b/include/drm/drm_fixed.h
index 1922188f00e8..0b44f2f294ce 100644
--- a/include/drm/drm_fixed.h
+++ b/include/drm/drm_fixed.h
@@ -78,6 +78,24 @@ static inline u32 dfixed_div(fixed20_12 A, fixed20_12 B)
 #define DRM_FIXED_EPSILON	1LL
 #define DRM_FIXED_ALMOST_ONE	(DRM_FIXED_ONE - DRM_FIXED_EPSILON)
 
+/**
+ * @drm_sm2fixp
+ *
+ * Convert a 1.31.32 signed-magnitude fixed point to 32.32
+ * 2s-complement fixed point
+ *
+ * @return s64 2s-complement fixed point
+ */
+static inline s64 drm_sm2fixp(__u64 a)
+{
+	if ((a & (1LL << 63))) {
+		return -(a & 0x7fffffffffffffffll);
+	} else {
+		return a;
+	}
+
+}
+
 static inline s64 drm_int2fixp(int a)
 {
 	return ((s64)a) << DRM_FIXED_POINT;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 02/43] drm/vkms: Add kunit tests for VKMS LUT handling
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
  2025-03-26 23:46 ` [PATCH V8 01/43] drm: Add helper for conversion from signed-magnitude Alex Hung
@ 2025-03-26 23:46 ` Alex Hung
  2025-03-26 23:46 ` [PATCH V8 03/43] drm/doc/rfc: Describe why prescriptive color pipeline is needed Alex Hung
                   ` (41 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:46 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet, Arthur Grillo

From: Harry Wentland <harry.wentland@amd.com>

Debugging LUT math is much easier when we can unit test
it. Add kunit functionality to VKMS and add tests for
 - get_lut_index
 - lerp_u16

Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Cc: Arthur Grillo <arthurgrillo@riseup.net>
---
v8:
 - Update config names (Louis Chauvet)

v7:
 - Fix checkpatch warnings and errors (Louis Chauvet)
  - Change SPDX-License-Identifier: GPL-2.0+ from /* */ to //
  - Fix checkpatch errors and warnings (new line at EOF, redundant spaces, and long lines)
  - Add static to const struct vkms_color_lut test_linear_lut
 - Add "MODULE_DESCRIPTION" (Jeff Johnson)


v6:
 - Eliminate need to include test as .c file (Louis Chauvet)

v5:
 - Bring back static for lerp_u16 and get_lut_index (Arthur)

v4:
 - Test the critical points of the lerp function (Pekka)

v3:
 - Use include way of testing static functions (Arthur)

 drivers/gpu/drm/vkms/Kconfig                 |  15 ++
 drivers/gpu/drm/vkms/Makefile                |   1 +
 drivers/gpu/drm/vkms/tests/.kunitconfig      |   4 +
 drivers/gpu/drm/vkms/tests/Makefile          |   3 +
 drivers/gpu/drm/vkms/tests/vkms_color_test.c | 172 +++++++++++++++++++
 drivers/gpu/drm/vkms/vkms_composer.c         |   8 +-
 drivers/gpu/drm/vkms/vkms_composer.h         |  13 ++
 7 files changed, 214 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/drm/vkms/tests/.kunitconfig
 create mode 100644 drivers/gpu/drm/vkms/tests/Makefile
 create mode 100644 drivers/gpu/drm/vkms/tests/vkms_color_test.c
 create mode 100644 drivers/gpu/drm/vkms/vkms_composer.h

diff --git a/drivers/gpu/drm/vkms/Kconfig b/drivers/gpu/drm/vkms/Kconfig
index 9def079f685b..3c02f928ffe6 100644
--- a/drivers/gpu/drm/vkms/Kconfig
+++ b/drivers/gpu/drm/vkms/Kconfig
@@ -14,3 +14,18 @@ config DRM_VKMS
 	  a VKMS.
 
 	  If M is selected the module will be called vkms.
+
+config DRM_VKMS_KUNIT_TEST
+	tristate "KUnit tests for VKMS" if !KUNIT_ALL_TESTS
+	depends on DRM_VKMS && KUNIT
+	default KUNIT_ALL_TESTS
+	help
+	  This builds unit tests for VKMS. This option is not useful for
+	  distributions or general kernels, but only for kernel
+	  developers working on VKMS.
+
+	  For more information on KUnit and unit tests in general,
+	  please refer to the KUnit documentation in
+	  Documentation/dev-tools/kunit/.
+
+	  If in doubt, say "N".
diff --git a/drivers/gpu/drm/vkms/Makefile b/drivers/gpu/drm/vkms/Makefile
index 1b28a6a32948..490b26d2e69d 100644
--- a/drivers/gpu/drm/vkms/Makefile
+++ b/drivers/gpu/drm/vkms/Makefile
@@ -9,3 +9,4 @@ vkms-y := \
 	vkms_writeback.o
 
 obj-$(CONFIG_DRM_VKMS) += vkms.o
+obj-$(CONFIG_DRM_VKMS_KUNIT_TEST) += tests/
diff --git a/drivers/gpu/drm/vkms/tests/.kunitconfig b/drivers/gpu/drm/vkms/tests/.kunitconfig
new file mode 100644
index 000000000000..6a2d87068edc
--- /dev/null
+++ b/drivers/gpu/drm/vkms/tests/.kunitconfig
@@ -0,0 +1,4 @@
+CONFIG_KUNIT=y
+CONFIG_DRM=y
+CONFIG_DRM_VKMS=y
+CONFIG_DRM_VKMS_KUNIT_TEST=y
diff --git a/drivers/gpu/drm/vkms/tests/Makefile b/drivers/gpu/drm/vkms/tests/Makefile
new file mode 100644
index 000000000000..de1af87cbb11
--- /dev/null
+++ b/drivers/gpu/drm/vkms/tests/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-$(CONFIG_DRM_VKMS_KUNIT_TEST) += vkms_color_test.o
\ No newline at end of file
diff --git a/drivers/gpu/drm/vkms/tests/vkms_color_test.c b/drivers/gpu/drm/vkms/tests/vkms_color_test.c
new file mode 100644
index 000000000000..affca56cac7b
--- /dev/null
+++ b/drivers/gpu/drm/vkms/tests/vkms_color_test.c
@@ -0,0 +1,172 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <kunit/test.h>
+
+#include <drm/drm_fixed.h>
+#include <drm/drm_mode.h>
+#include "../vkms_drv.h"
+#include "../vkms_composer.h"
+
+#define TEST_LUT_SIZE 16
+
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
+
+static struct drm_color_lut test_linear_array[TEST_LUT_SIZE] = {
+	{ 0x0, 0x0, 0x0, 0 },
+	{ 0x1111, 0x1111, 0x1111, 0 },
+	{ 0x2222, 0x2222, 0x2222, 0 },
+	{ 0x3333, 0x3333, 0x3333, 0 },
+	{ 0x4444, 0x4444, 0x4444, 0 },
+	{ 0x5555, 0x5555, 0x5555, 0 },
+	{ 0x6666, 0x6666, 0x6666, 0 },
+	{ 0x7777, 0x7777, 0x7777, 0 },
+	{ 0x8888, 0x8888, 0x8888, 0 },
+	{ 0x9999, 0x9999, 0x9999, 0 },
+	{ 0xaaaa, 0xaaaa, 0xaaaa, 0 },
+	{ 0xbbbb, 0xbbbb, 0xbbbb, 0 },
+	{ 0xcccc, 0xcccc, 0xcccc, 0 },
+	{ 0xdddd, 0xdddd, 0xdddd, 0 },
+	{ 0xeeee, 0xeeee, 0xeeee, 0 },
+	{ 0xffff, 0xffff, 0xffff, 0 },
+};
+
+static const struct vkms_color_lut test_linear_lut = {
+	.base = test_linear_array,
+	.lut_length = TEST_LUT_SIZE,
+	.channel_value2index_ratio = 0xf000fll
+};
+
+
+static void vkms_color_test_get_lut_index(struct kunit *test)
+{
+	s64 lut_index;
+	int i;
+
+	lut_index = get_lut_index(&test_linear_lut, test_linear_array[0].red);
+	KUNIT_EXPECT_EQ(test, drm_fixp2int(lut_index), 0);
+
+	for (i = 0; i < TEST_LUT_SIZE; i++) {
+		lut_index = get_lut_index(&test_linear_lut, test_linear_array[i].red);
+		KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(lut_index), i);
+	}
+}
+
+static void vkms_color_test_lerp(struct kunit *test)
+{
+	/*** half-way round down ***/
+	s64 t = 0x80000000 - 1;
+
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x0, 0x10, t), 0x8);
+
+	/* odd a */
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x1, 0x10, t), 0x8);
+
+	/* odd b */
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x1, 0xf, t), 0x8);
+
+	/* b = a */
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x10, 0x10, t), 0x10);
+
+	/* b = a + 1 */
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x10, 0x11, t), 0x10);
+
+	/*** half-way round up ***/
+	t = 0x80000000;
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x0, 0x10, t), 0x8);
+
+	/* odd a */
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x1, 0x10, t), 0x9);
+
+	/* odd b */
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x1, 0xf, t), 0x8);
+
+	/* b = a */
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x10, 0x10, t), 0x10);
+
+	/* b = a + 1 */
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x10, 0x11, t), 0x11);
+
+	/*** t = 0.0 ***/
+	t = 0x0;
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x0, 0x10, t), 0x0);
+
+	/* odd a */
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x1, 0x10, t), 0x1);
+
+	/* odd b */
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x1, 0xf, t), 0x1);
+
+	/* b = a */
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x10, 0x10, t), 0x10);
+
+	/* b = a + 1 */
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x10, 0x11, t), 0x10);
+
+	/*** t = 1.0 ***/
+	t = 0x100000000;
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x0, 0x10, t), 0x10);
+
+	/* odd a */
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x1, 0x10, t), 0x10);
+
+	/* odd b */
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x1, 0xf, t), 0xf);
+
+	/* b = a */
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x10, 0x10, t), 0x10);
+
+	/* b = a + 1 */
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x10, 0x11, t), 0x11);
+
+	/*** t = 0.0 + 1 ***/
+	t = 0x0 + 1;
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x0, 0x10, t), 0x0);
+
+	/* odd a */
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x1, 0x10, t), 0x1);
+
+	/* odd b */
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x1, 0xf, t), 0x1);
+
+	/* b = a */
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x10, 0x10, t), 0x10);
+
+	/* b = a + 1 */
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x10, 0x11, t), 0x10);
+
+	/*** t = 1.0 - 1 ***/
+	t = 0x100000000 - 1;
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x0, 0x10, t), 0x10);
+
+	/* odd a */
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x1, 0x10, t), 0x10);
+
+	/* odd b */
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x1, 0xf, t), 0xf);
+
+	/* b = a */
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x10, 0x10, t), 0x10);
+
+	/* b = a + 1 */
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x10, 0x11, t), 0x11);
+
+	/*** t chosen to verify the flipping point of result a (or b) to a+1 (or b-1) ***/
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x0, 0x1, 0x80000000 - 1), 0x0);
+	KUNIT_EXPECT_EQ(test, lerp_u16(0x0, 0x1, 0x80000000), 0x1);
+}
+
+static struct kunit_case vkms_color_test_cases[] = {
+	KUNIT_CASE(vkms_color_test_get_lut_index),
+	KUNIT_CASE(vkms_color_test_lerp),
+	{}
+};
+
+static struct kunit_suite vkms_color_test_suite = {
+	.name = "vkms-color",
+	.test_cases = vkms_color_test_cases,
+};
+
+kunit_test_suite(vkms_color_test_suite);
+
+MODULE_DESCRIPTION("Kunit test for VKMS LUT handling");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c
index fa269d279e25..b0dc95f971d8 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -12,6 +12,8 @@
 #include <linux/minmax.h>
 
 #include "vkms_drv.h"
+#include <kunit/visibility.h>
+#include "vkms_composer.h"
 
 static u16 pre_mul_blend_channel(u16 src, u16 dst, u16 alpha)
 {
@@ -60,7 +62,7 @@ static void fill_background(const struct pixel_argb_u16 *background_color,
 }
 
 // lerp(a, b, t) = a + (b - a) * t
-static u16 lerp_u16(u16 a, u16 b, s64 t)
+VISIBLE_IF_KUNIT u16 lerp_u16(u16 a, u16 b, s64 t)
 {
 	s64 a_fp = drm_int2fixp(a);
 	s64 b_fp = drm_int2fixp(b);
@@ -69,13 +71,15 @@ static u16 lerp_u16(u16 a, u16 b, s64 t)
 
 	return drm_fixp2int_round(a_fp + delta);
 }
+EXPORT_SYMBOL_IF_KUNIT(lerp_u16);
 
-static s64 get_lut_index(const struct vkms_color_lut *lut, u16 channel_value)
+VISIBLE_IF_KUNIT s64 get_lut_index(const struct vkms_color_lut *lut, u16 channel_value)
 {
 	s64 color_channel_fp = drm_int2fixp(channel_value);
 
 	return drm_fixp_mul(color_channel_fp, lut->channel_value2index_ratio);
 }
+EXPORT_SYMBOL_IF_KUNIT(get_lut_index);
 
 /*
  * This enum is related to the positions of the variables inside
diff --git a/drivers/gpu/drm/vkms/vkms_composer.h b/drivers/gpu/drm/vkms/vkms_composer.h
new file mode 100644
index 000000000000..9316a053e7d7
--- /dev/null
+++ b/drivers/gpu/drm/vkms/vkms_composer.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef _VKMS_COMPOSER_H_
+#define _VKMS_COMPOSER_H_
+
+#include <kunit/visibility.h>
+
+#if IS_ENABLED(CONFIG_KUNIT)
+u16 lerp_u16(u16 a, u16 b, s64 t);
+s64 get_lut_index(const struct vkms_color_lut *lut, u16 channel_value);
+#endif
+
+#endif /* _VKMS_COMPOSER_H_ */
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 03/43] drm/doc/rfc: Describe why prescriptive color pipeline is needed
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
  2025-03-26 23:46 ` [PATCH V8 01/43] drm: Add helper for conversion from signed-magnitude Alex Hung
  2025-03-26 23:46 ` [PATCH V8 02/43] drm/vkms: Add kunit tests for VKMS LUT handling Alex Hung
@ 2025-03-26 23:46 ` Alex Hung
  2025-03-29 15:26   ` Simon Ser
  2025-03-31 16:24   ` Shengyu Qu
  2025-03-26 23:46 ` [PATCH V8 04/43] drm/colorop: Introduce new drm_colorop mode object Alex Hung
                   ` (40 subsequent siblings)
  43 siblings, 2 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:46 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

Add documentation for color pipeline API.

Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
v8:
 - Fix typo "definint" -> "defining"

v7:
 - Add a commit messages

v5:
 - Don't require BYPASS to succeed (Sebastian)
 - use DATA for 1D and 3D LUT types (Sebastian)
 - update 3DLUT ops to use 3DLUT_MODES and 3DLUT_MODE_INDEX
 - Add section on drm_colorop extensibility
 - Add color_pipeline.rst to RFC toc tree

v4:
 - Drop IOCTL docs since we dropped the IOCTLs (Pekka)
 - Clarify reading and setting of COLOR_PIPELINE prop (Pekka)
 - Add blurb about not requiring to reject a pipeline due to
   incompatible ops, as long as op can be bypassed (Pekka)
 - Dropped informational strings (such as input CSC) as they're
   not actually intended to be advertised (Pekka)

v3:
 - Describe DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE (Sebastian)
 - Ask for clear documentation of colorop behavior (Sebastian)

v2:
 - Update colorop visualizations to match reality (Sebastian, Alex Hung)
 - Updated wording (Pekka)
 - Change BYPASS wording to make it non-mandatory (Sebastian)
 - Drop cover-letter-like paragraph from COLOR_PIPELINE Plane Property
   section (Pekka)
 - Use PQ EOTF instead of its inverse in Pipeline Programming example (Melissa)
 - Add "Driver Implementer's Guide" section (Pekka)
 - Add "Driver Forward/Backward Compatibility" section (Sebastian, Pekka)

 Documentation/gpu/rfc/color_pipeline.rst | 378 +++++++++++++++++++++++
 Documentation/gpu/rfc/index.rst          |   3 +
 2 files changed, 381 insertions(+)
 create mode 100644 Documentation/gpu/rfc/color_pipeline.rst

diff --git a/Documentation/gpu/rfc/color_pipeline.rst b/Documentation/gpu/rfc/color_pipeline.rst
new file mode 100644
index 000000000000..58bcc2a5ffd8
--- /dev/null
+++ b/Documentation/gpu/rfc/color_pipeline.rst
@@ -0,0 +1,378 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+========================
+Linux Color Pipeline API
+========================
+
+What problem are we solving?
+============================
+
+We would like to support pre-, and post-blending complex color
+transformations in display controller hardware in order to allow for
+HW-supported HDR use-cases, as well as to provide support to
+color-managed applications, such as video or image editors.
+
+It is possible to support an HDR output on HW supporting the Colorspace
+and HDR Metadata drm_connector properties, but that requires the
+compositor or application to render and compose the content into one
+final buffer intended for display. Doing so is costly.
+
+Most modern display HW offers various 1D LUTs, 3D LUTs, matrices, and other
+operations to support color transformations. These operations are often
+implemented in fixed-function HW and therefore much more power efficient than
+performing similar operations via shaders or CPU.
+
+We would like to make use of this HW functionality to support complex color
+transformations with no, or minimal CPU or shader load.
+
+
+How are other OSes solving this problem?
+========================================
+
+The most widely supported use-cases regard HDR content, whether video or
+gaming.
+
+Most OSes will specify the source content format (color gamut, encoding transfer
+function, and other metadata, such as max and average light levels) to a driver.
+Drivers will then program their fixed-function HW accordingly to map from a
+source content buffer's space to a display's space.
+
+When fixed-function HW is not available the compositor will assemble a shader to
+ask the GPU to perform the transformation from the source content format to the
+display's format.
+
+A compositor's mapping function and a driver's mapping function are usually
+entirely separate concepts. On OSes where a HW vendor has no insight into
+closed-source compositor code such a vendor will tune their color management
+code to visually match the compositor's. On other OSes, where both mapping
+functions are open to an implementer they will ensure both mappings match.
+
+This results in mapping algorithm lock-in, meaning that no-one alone can
+experiment with or introduce new mapping algorithms and achieve
+consistent results regardless of which implementation path is taken.
+
+Why is Linux different?
+=======================
+
+Unlike other OSes, where there is one compositor for one or more drivers, on
+Linux we have a many-to-many relationship. Many compositors; many drivers.
+In addition each compositor vendor or community has their own view of how
+color management should be done. This is what makes Linux so beautiful.
+
+This means that a HW vendor can now no longer tune their driver to one
+compositor, as tuning it to one could make it look fairly different from
+another compositor's color mapping.
+
+We need a better solution.
+
+
+Descriptive API
+===============
+
+An API that describes the source and destination colorspaces is a descriptive
+API. It describes the input and output color spaces but does not describe
+how precisely they should be mapped. Such a mapping includes many minute
+design decision that can greatly affect the look of the final result.
+
+It is not feasible to describe such mapping with enough detail to ensure the
+same result from each implementation. In fact, these mappings are a very active
+research area.
+
+
+Prescriptive API
+================
+
+A prescriptive API describes not the source and destination colorspaces. It
+instead prescribes a recipe for how to manipulate pixel values to arrive at the
+desired outcome.
+
+This recipe is generally an ordered list of straight-forward operations,
+with clear mathematical definitions, such as 1D LUTs, 3D LUTs, matrices,
+or other operations that can be described in a precise manner.
+
+
+The Color Pipeline API
+======================
+
+HW color management pipelines can significantly differ between HW
+vendors in terms of availability, ordering, and capabilities of HW
+blocks. This makes a common definition of color management blocks and
+their ordering nigh impossible. Instead we are defining an API that
+allows user space to discover the HW capabilities in a generic manner,
+agnostic of specific drivers and hardware.
+
+
+drm_colorop Object
+==================
+
+To support the definition of color pipelines we define the DRM core
+object type drm_colorop. Individual drm_colorop objects will be chained
+via the NEXT property of a drm_colorop to constitute a color pipeline.
+Each drm_colorop object is unique, i.e., even if multiple color
+pipelines have the same operation they won't share the same drm_colorop
+object to describe that operation.
+
+Note that drivers are not expected to map drm_colorop objects statically
+to specific HW blocks. The mapping of drm_colorop objects is entirely a
+driver-internal detail and can be as dynamic or static as a driver needs
+it to be. See more in the Driver Implementation Guide section below.
+
+Each drm_colorop has three core properties:
+
+TYPE: An enumeration property, defining the type of transformation, such as
+* enumerated curve
+* custom (uniform) 1D LUT
+* 3x3 matrix
+* 3x4 matrix
+* 3D LUT
+* etc.
+
+Depending on the type of transformation other properties will describe
+more details.
+
+BYPASS: A boolean property that can be used to easily put a block into
+bypass mode. The BYPASS property is not mandatory for a colorop, as long
+as the entire pipeline can get bypassed by setting the COLOR_PIPELINE on
+a plane to '0'.
+
+NEXT: The ID of the next drm_colorop in a color pipeline, or 0 if this
+drm_colorop is the last in the chain.
+
+An example of a drm_colorop object might look like one of these::
+
+    /* 1D enumerated curve */
+    Color operation 42
+    ├─ "TYPE": immutable enum {1D enumerated curve, 1D LUT, 3x3 matrix, 3x4 matrix, 3D LUT, etc.} = 1D enumerated curve
+    ├─ "BYPASS": bool {true, false}
+    ├─ "CURVE_1D_TYPE": enum {sRGB EOTF, sRGB inverse EOTF, PQ EOTF, PQ inverse EOTF, …}
+    └─ "NEXT": immutable color operation ID = 43
+
+    /* custom 4k entry 1D LUT */
+    Color operation 52
+    ├─ "TYPE": immutable enum {1D enumerated curve, 1D LUT, 3x3 matrix, 3x4 matrix, 3D LUT, etc.} = 1D LUT
+    ├─ "BYPASS": bool {true, false}
+    ├─ "SIZE": immutable range = 4096
+    ├─ "DATA": blob
+    └─ "NEXT": immutable color operation ID = 0
+
+    /* 17^3 3D LUT */
+    Color operation 72
+    ├─ "TYPE": immutable enum {1D enumerated curve, 1D LUT, 3x3 matrix, 3x4 matrix, 3D LUT, etc.} = 3D LUT
+    ├─ "BYPASS": bool {true, false}
+    ├─ "3DLUT_MODES": read-only blob of supported 3DLUT modes
+    ├─ "3DLUT_MODE_INDEX": index of selected 3DLUT mode
+    ├─ "DATA": blob
+    └─ "NEXT": immutable color operation ID = 73
+
+drm_colorop extensibility
+-------------------------
+
+Unlike existing DRM core objects, like &drm_plane, drm_colorop is not
+extensible. This simplifies implementations and keeps all functionality
+for managing &drm_colorop objects in the DRM core.
+
+If there is a need one may introduce a simple &drm_colorop_funcs
+function table in the future, for example to support an IN_FORMATS
+property on a &drm_colorop.
+
+If a driver requires the ability to create a driver-specific colorop
+object they will need to add &drm_colorop func table support with
+support for the usual functions, like destroy, atomic_duplicate_state,
+and atomic_destroy_state.
+
+
+COLOR_PIPELINE Plane Property
+=============================
+
+Color Pipelines are created by a driver and advertised via a new
+COLOR_PIPELINE enum property on each plane. Values of the property
+always include object id 0, which is the default and means all color
+processing is disabled. Additional values will be the object IDs of the
+first drm_colorop in a pipeline. A driver can create and advertise none,
+one, or more possible color pipelines. A DRM client will select a color
+pipeline by setting the COLOR PIPELINE to the respective value.
+
+NOTE: Many DRM clients will set enumeration properties via the string
+value, often hard-coding it. Since this enumeration is generated based
+on the colorop object IDs it is important to perform the Color Pipeline
+Discovery, described below, instead of hard-coding color pipeline
+assignment. Drivers might generate the enum strings dynamically.
+Hard-coded strings might only work for specific drivers on a specific
+pieces of HW. Color Pipeline Discovery can work universally, as long as
+drivers implement the required color operations.
+
+The COLOR_PIPELINE property is only exposed when the
+DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE is set. Drivers shall ignore any
+existing pre-blend color operations when this cap is set, such as
+COLOR_RANGE and COLOR_ENCODING. If drivers want to support COLOR_RANGE
+or COLOR_ENCODING functionality when the color pipeline client cap is
+set, they are expected to expose colorops in the pipeline to allow for
+the appropriate color transformation.
+
+Setting of the COLOR_PIPELINE plane property or drm_colorop properties
+is only allowed for userspace that sets this client cap.
+
+An example of a COLOR_PIPELINE property on a plane might look like this::
+
+    Plane 10
+    ├─ "TYPE": immutable enum {Overlay, Primary, Cursor} = Primary
+    ├─ …
+    └─ "COLOR_PIPELINE": enum {0, 42, 52} = 0
+
+
+Color Pipeline Discovery
+========================
+
+A DRM client wanting color management on a drm_plane will:
+
+1. Get the COLOR_PIPELINE property of the plane
+2. iterate all COLOR_PIPELINE enum values
+3. for each enum value walk the color pipeline (via the NEXT pointers)
+   and see if the available color operations are suitable for the
+   desired color management operations
+
+If userspace encounters an unknown or unsuitable color operation during
+discovery it does not need to reject the entire color pipeline outright,
+as long as the unknown or unsuitable colorop has a "BYPASS" property.
+Drivers will ensure that a bypassed block does not have any effect.
+
+An example of chained properties to define an AMD pre-blending color
+pipeline might look like this::
+
+    Plane 10
+    ├─ "TYPE" (immutable) = Primary
+    └─ "COLOR_PIPELINE": enum {0, 44} = 0
+
+    Color operation 44
+    ├─ "TYPE" (immutable) = 1D enumerated curve
+    ├─ "BYPASS": bool
+    ├─ "CURVE_1D_TYPE": enum {sRGB EOTF, PQ EOTF} = sRGB EOTF
+    └─ "NEXT" (immutable) = 45
+
+    Color operation 45
+    ├─ "TYPE" (immutable) = 3x4 Matrix
+    ├─ "BYPASS": bool
+    ├─ "DATA": blob
+    └─ "NEXT" (immutable) = 46
+
+    Color operation 46
+    ├─ "TYPE" (immutable) = 1D enumerated curve
+    ├─ "BYPASS": bool
+    ├─ "CURVE_1D_TYPE": enum {sRGB Inverse EOTF, PQ Inverse EOTF} = sRGB EOTF
+    └─ "NEXT" (immutable) = 47
+
+    Color operation 47
+    ├─ "TYPE" (immutable) = 1D LUT
+    ├─ "SIZE": immutable range = 4096
+    ├─ "DATA": blob
+    └─ "NEXT" (immutable) = 48
+
+    Color operation 48
+    ├─ "TYPE" (immutable) = 3D LUT
+    ├─ "3DLUT_MODE_INDEX": 0
+    ├─ "DATA": blob
+    └─ "NEXT" (immutable) = 49
+
+    Color operation 49
+    ├─ "TYPE" (immutable) = 1D enumerated curve
+    ├─ "BYPASS": bool
+    ├─ "CURVE_1D_TYPE": enum {sRGB EOTF, PQ EOTF} = sRGB EOTF
+    └─ "NEXT" (immutable) = 0
+
+
+Color Pipeline Programming
+==========================
+
+Once a DRM client has found a suitable pipeline it will:
+
+1. Set the COLOR_PIPELINE enum value to the one pointing at the first
+   drm_colorop object of the desired pipeline
+2. Set the properties for all drm_colorop objects in the pipeline to the
+   desired values, setting BYPASS to true for unused drm_colorop blocks,
+   and false for enabled drm_colorop blocks
+3. Perform (TEST_ONLY or not) atomic commit with all the other KMS
+   states it wishes to change
+
+To configure the pipeline for an HDR10 PQ plane and blending in linear
+space, a compositor might perform an atomic commit with the following
+property values::
+
+    Plane 10
+    └─ "COLOR_PIPELINE" = 42
+
+    Color operation 42
+    └─ "BYPASS" = true
+
+    Color operation 44
+    └─ "BYPASS" = true
+
+    Color operation 45
+    └─ "BYPASS" = true
+
+    Color operation 46
+    └─ "BYPASS" = true
+
+    Color operation 47
+    ├─ "LUT_3D_DATA" = Gamut mapping + tone mapping + night mode
+    └─ "BYPASS" = false
+
+    Color operation 48
+    ├─ "CURVE_1D_TYPE" = PQ EOTF
+    └─ "BYPASS" = false
+
+
+Driver Implementer's Guide
+==========================
+
+What does this all mean for driver implementations? As noted above the
+colorops can map to HW directly but don't need to do so. Here are some
+suggestions on how to think about creating your color pipelines:
+
+- Try to expose pipelines that use already defined colorops, even if
+  your hardware pipeline is split differently. This allows existing
+  userspace to immediately take advantage of the hardware.
+
+- Additionally, try to expose your actual hardware blocks as colorops.
+  Define new colorop types where you believe it can offer significant
+  benefits if userspace learns to program them.
+
+- Avoid defining new colorops for compound operations with very narrow
+  scope. If you have a hardware block for a special operation that
+  cannot be split further, you can expose that as a new colorop type.
+  However, try to not define colorops for "use cases", especially if
+  they require you to combine multiple hardware blocks.
+
+- Design new colorops as prescriptive, not descriptive; by the
+  mathematical formula, not by the assumed input and output.
+
+A defined colorop type must be deterministic. The exact behavior of the
+colorop must be documented entirely, whether via a mathematical formula
+or some other description. Its operation can depend only on its
+properties and input and nothing else, allowed error tolerance
+notwithstanding.
+
+
+Driver Forward/Backward Compatibility
+=====================================
+
+As this is uAPI drivers can't regress color pipelines that have been
+introduced for a given HW generation. New HW generations are free to
+abandon color pipelines advertised for previous generations.
+Nevertheless, it can be beneficial to carry support for existing color
+pipelines forward as those will likely already have support in DRM
+clients.
+
+Introducing new colorops to a pipeline is fine, as long as they can be
+bypassed or are purely informational. DRM clients implementing support
+for the pipeline can always skip unknown properties as long as they can
+be confident that doing so will not cause unexpected results.
+
+If a new colorop doesn't fall into one of the above categories
+(bypassable or informational) the modified pipeline would be unusable
+for user space. In this case a new pipeline should be defined.
+
+
+References
+==========
+
+1. https://lore.kernel.org/dri-devel/QMers3awXvNCQlyhWdTtsPwkp5ie9bze_hD5nAccFW7a_RXlWjYB7MoUW_8CKLT2bSQwIXVi5H6VULYIxCdgvryZoAoJnC5lZgyK1QWn488=@emersion.fr/
\ No newline at end of file
diff --git a/Documentation/gpu/rfc/index.rst b/Documentation/gpu/rfc/index.rst
index 396e535377fb..ef19b0ba2a3e 100644
--- a/Documentation/gpu/rfc/index.rst
+++ b/Documentation/gpu/rfc/index.rst
@@ -35,3 +35,6 @@ host such documentation:
 .. toctree::
 
     i915_vm_bind.rst
+
+.. toctree::
+    color_pipeline.rst
\ No newline at end of file
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 04/43] drm/colorop: Introduce new drm_colorop mode object
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (2 preceding siblings ...)
  2025-03-26 23:46 ` [PATCH V8 03/43] drm/doc/rfc: Describe why prescriptive color pipeline is needed Alex Hung
@ 2025-03-26 23:46 ` Alex Hung
  2025-03-26 23:46 ` [PATCH V8 05/43] drm/colorop: Add TYPE property Alex Hung
                   ` (39 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:46 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

This patches introduces a new drm_colorop mode object. This
object represents color transformations and can be used to
define color pipelines.

We also introduce the drm_colorop_state here, as well as
various helpers and state tracking bits.

Reviewed-by: Simon Ser <contact@emersion.fr>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
v8:
 - Remove drm_atomic_get_existing_colorop_state (Louis Chauvet)

v7:
 - Fix checkpatch warnings and errors
  - Add a tab to for_each_oldnew_colorop_in_state definition
  - Change unsigned index to unsigned int index
  - Fix a checkpatch warning - a new line after variable declaration

v6:
 - Comment that properties validity depends on type (Louis Chauvet)

v5:
 - Add comment to drm_atomic_state.colorops
 - Replace a misplaced 'plane' with 'colorop' in comment
 - Fix colorop_list kernel doc
 - Add kernel doc for color_pipeline
 - drop unused drm_colorop_destroy_state
 - drop drm_colorop_init, to be introduced in later patch
   when used
 - Add kernel docs
 - Drop TODOs

v4:
 - Drop IOCTL definitions (Pekka)
 - add missing declaration (Chaitanya Kumar Borah)

v3:
 - Drop TODO for lock (it's handled in drm_modeset_drop_locks)
   (Melissa)
 - Don't get plane state when getting colorop state
 - Make some functions static (kernel test robot)

 drivers/gpu/drm/Makefile            |   1 +
 drivers/gpu/drm/drm_atomic.c        |  70 ++++++++++++
 drivers/gpu/drm/drm_atomic_helper.c |  12 ++
 drivers/gpu/drm/drm_atomic_uapi.c   |  48 ++++++++
 drivers/gpu/drm/drm_colorop.c       | 104 +++++++++++++++++
 drivers/gpu/drm/drm_mode_config.c   |   7 ++
 include/drm/drm_atomic.h            |  70 ++++++++++++
 include/drm/drm_atomic_uapi.h       |   1 +
 include/drm/drm_colorop.h           | 171 ++++++++++++++++++++++++++++
 include/drm/drm_mode_config.h       |  18 +++
 include/drm/drm_plane.h             |   8 ++
 include/uapi/drm/drm_mode.h         |   1 +
 12 files changed, 511 insertions(+)
 create mode 100644 drivers/gpu/drm/drm_colorop.c
 create mode 100644 include/drm/drm_colorop.h

diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index ed54a546bbe2..50bb6be2cad1 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -41,6 +41,7 @@ drm-y := \
 	drm_bridge.o \
 	drm_cache.o \
 	drm_color_mgmt.o \
+	drm_colorop.o \
 	drm_connector.o \
 	drm_crtc.o \
 	drm_displayid.o \
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 9ea2611770f4..85d492a1f3d4 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -42,6 +42,7 @@
 #include <drm/drm_mode.h>
 #include <drm/drm_print.h>
 #include <drm/drm_writeback.h>
+#include <drm/drm_colorop.h>
 
 #include "drm_crtc_internal.h"
 #include "drm_internal.h"
@@ -107,6 +108,7 @@ void drm_atomic_state_default_release(struct drm_atomic_state *state)
 	kfree(state->connectors);
 	kfree(state->crtcs);
 	kfree(state->planes);
+	kfree(state->colorops);
 	kfree(state->private_objs);
 }
 EXPORT_SYMBOL(drm_atomic_state_default_release);
@@ -138,6 +140,10 @@ drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state)
 				sizeof(*state->planes), GFP_KERNEL);
 	if (!state->planes)
 		goto fail;
+	state->colorops = kcalloc(dev->mode_config.num_colorop,
+				  sizeof(*state->colorops), GFP_KERNEL);
+	if (!state->colorops)
+		goto fail;
 
 	/*
 	 * Because drm_atomic_state can be committed asynchronously we need our
@@ -249,6 +255,20 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state)
 		state->planes[i].new_state = NULL;
 	}
 
+	for (i = 0; i < config->num_colorop; i++) {
+		struct drm_colorop *colorop = state->colorops[i].ptr;
+
+		if (!colorop)
+			continue;
+
+		drm_colorop_atomic_destroy_state(colorop,
+						 state->colorops[i].state);
+		state->colorops[i].ptr = NULL;
+		state->colorops[i].state = NULL;
+		state->colorops[i].old_state = NULL;
+		state->colorops[i].new_state = NULL;
+	}
+
 	for (i = 0; i < state->num_private_objs; i++) {
 		struct drm_private_obj *obj = state->private_objs[i].ptr;
 
@@ -568,6 +588,56 @@ drm_atomic_get_plane_state(struct drm_atomic_state *state,
 }
 EXPORT_SYMBOL(drm_atomic_get_plane_state);
 
+
+/**
+ * drm_atomic_get_colorop_state - get colorop state
+ * @state: global atomic state object
+ * @colorop: colorop to get state object for
+ *
+ * This function returns the colorop state for the given colorop, allocating it
+ * if needed. It will also grab the relevant plane lock to make sure that the
+ * state is consistent.
+ *
+ * Returns:
+ *
+ * Either the allocated state or the error code encoded into the pointer. When
+ * the error is EDEADLK then the w/w mutex code has detected a deadlock and the
+ * entire atomic sequence must be restarted. All other errors are fatal.
+ */
+struct drm_colorop_state *
+drm_atomic_get_colorop_state(struct drm_atomic_state *state,
+			     struct drm_colorop *colorop)
+{
+	int ret, index = drm_colorop_index(colorop);
+	struct drm_colorop_state *colorop_state;
+
+	WARN_ON(!state->acquire_ctx);
+
+	colorop_state = drm_atomic_get_new_colorop_state(state, colorop);
+	if (colorop_state)
+		return colorop_state;
+
+	ret = drm_modeset_lock(&colorop->plane->mutex, state->acquire_ctx);
+	if (ret)
+		return ERR_PTR(ret);
+
+	colorop_state = drm_atomic_helper_colorop_duplicate_state(colorop);
+	if (!colorop_state)
+		return ERR_PTR(-ENOMEM);
+
+	state->colorops[index].state = colorop_state;
+	state->colorops[index].ptr = colorop;
+	state->colorops[index].old_state = colorop->state;
+	state->colorops[index].new_state = colorop_state;
+	colorop_state->state = state;
+
+	drm_dbg_atomic(colorop->dev, "Added [COLOROP:%d] %p state to %p\n",
+		       colorop->base.id, colorop_state, state);
+
+	return colorop_state;
+}
+EXPORT_SYMBOL(drm_atomic_get_colorop_state);
+
 static bool
 plane_switching_crtc(const struct drm_plane_state *old_plane_state,
 		     const struct drm_plane_state *new_plane_state)
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 5302ab324898..65db840f8b20 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -3060,6 +3060,8 @@ int drm_atomic_helper_swap_state(struct drm_atomic_state *state,
 	struct drm_crtc_state *old_crtc_state, *new_crtc_state;
 	struct drm_plane *plane;
 	struct drm_plane_state *old_plane_state, *new_plane_state;
+	struct drm_colorop *colorop;
+	struct drm_colorop_state *old_colorop_state, *new_colorop_state;
 	struct drm_crtc_commit *commit;
 	struct drm_private_obj *obj;
 	struct drm_private_state *old_obj_state, *new_obj_state;
@@ -3137,6 +3139,16 @@ int drm_atomic_helper_swap_state(struct drm_atomic_state *state,
 		}
 	}
 
+	for_each_oldnew_colorop_in_state(state, colorop, old_colorop_state, new_colorop_state, i) {
+		WARN_ON(colorop->state != old_colorop_state);
+
+		old_colorop_state->state = state;
+		new_colorop_state->state = NULL;
+
+		state->colorops[i].state = old_colorop_state;
+		colorop->state = new_colorop_state;
+	}
+
 	drm_panic_lock(state->dev, flags);
 	for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
 		WARN_ON(plane->state != old_plane_state);
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index 2765ba90ad8f..cf1772118895 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -35,6 +35,7 @@
 #include <drm/drm_drv.h>
 #include <drm/drm_writeback.h>
 #include <drm/drm_vblank.h>
+#include <drm/drm_colorop.h>
 
 #include <linux/dma-fence.h>
 #include <linux/uaccess.h>
@@ -643,6 +644,26 @@ drm_atomic_plane_get_property(struct drm_plane *plane,
 	return 0;
 }
 
+
+static int drm_atomic_colorop_set_property(struct drm_colorop *colorop,
+		struct drm_colorop_state *state, struct drm_file *file_priv,
+		struct drm_property *property, uint64_t val)
+{
+	drm_dbg_atomic(colorop->dev,
+			"[COLOROP:%d] unknown property [PROP:%d:%s]]\n",
+			colorop->base.id,
+			property->base.id, property->name);
+	return -EINVAL;
+}
+
+static int
+drm_atomic_colorop_get_property(struct drm_colorop *colorop,
+		const struct drm_colorop_state *state,
+		struct drm_property *property, uint64_t *val)
+{
+	return -EINVAL;
+}
+
 static int drm_atomic_set_writeback_fb_for_connector(
 		struct drm_connector_state *conn_state,
 		struct drm_framebuffer *fb)
@@ -909,6 +930,16 @@ int drm_atomic_get_property(struct drm_mode_object *obj,
 				plane->state, property, val);
 		break;
 	}
+	case DRM_MODE_OBJECT_COLOROP: {
+		struct drm_colorop *colorop = obj_to_colorop(obj);
+
+		if (colorop->plane)
+			WARN_ON(!drm_modeset_is_locked(&colorop->plane->mutex));
+
+		ret = drm_atomic_colorop_get_property(colorop,
+				colorop->state, property, val);
+		break;
+	}
 	default:
 		drm_dbg_atomic(dev, "[OBJECT:%d] has no properties\n", obj->id);
 		ret = -EINVAL;
@@ -1101,6 +1132,23 @@ int drm_atomic_set_property(struct drm_atomic_state *state,
 		ret = drm_atomic_plane_set_property(plane,
 				plane_state, file_priv,
 				prop, prop_value);
+
+		break;
+	}
+	case DRM_MODE_OBJECT_COLOROP: {
+		struct drm_colorop *colorop = obj_to_colorop(obj);
+		struct drm_colorop_state *colorop_state;
+
+		colorop_state = drm_atomic_get_colorop_state(state, colorop);
+		if (IS_ERR(colorop_state)) {
+			ret = PTR_ERR(colorop_state);
+			break;
+		}
+
+		ret = drm_atomic_colorop_set_property(colorop,
+				colorop_state, file_priv,
+				prop, prop_value);
+
 		break;
 	}
 	default:
diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
new file mode 100644
index 000000000000..d215e22c9d20
--- /dev/null
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include <drm/drm_colorop.h>
+#include <drm/drm_print.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_plane.h>
+
+#include "drm_crtc_internal.h"
+
+static void __drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop,
+							struct drm_colorop_state *state)
+{
+	memcpy(state, colorop->state, sizeof(*state));
+}
+
+struct drm_colorop_state *
+drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop)
+{
+	struct drm_colorop_state *state;
+
+	if (WARN_ON(!colorop->state))
+		return NULL;
+
+	state = kmalloc(sizeof(*state), GFP_KERNEL);
+	if (state)
+		__drm_atomic_helper_colorop_duplicate_state(colorop, state);
+
+	return state;
+}
+
+
+void drm_colorop_atomic_destroy_state(struct drm_colorop *colorop,
+				      struct drm_colorop_state *state)
+{
+	kfree(state);
+}
+
+/**
+ * __drm_colorop_state_reset - resets colorop state to default values
+ * @colorop_state: atomic colorop state, must not be NULL
+ * @colorop: colorop object, must not be NULL
+ *
+ * Initializes the newly allocated @colorop_state with default
+ * values. This is useful for drivers that subclass the CRTC state.
+ */
+static void __drm_colorop_state_reset(struct drm_colorop_state *colorop_state,
+				      struct drm_colorop *colorop)
+{
+	colorop_state->colorop = colorop;
+}
+
+/**
+ * __drm_colorop_reset - reset state on colorop
+ * @colorop: drm colorop
+ * @colorop_state: colorop state to assign
+ *
+ * Initializes the newly allocated @colorop_state and assigns it to
+ * the &drm_crtc->state pointer of @colorop, usually required when
+ * initializing the drivers or when called from the &drm_colorop_funcs.reset
+ * hook.
+ *
+ * This is useful for drivers that subclass the colorop state.
+ */
+static void __drm_colorop_reset(struct drm_colorop *colorop,
+				struct drm_colorop_state *colorop_state)
+{
+	if (colorop_state)
+		__drm_colorop_state_reset(colorop_state, colorop);
+
+	colorop->state = colorop_state;
+}
+
+void drm_colorop_reset(struct drm_colorop *colorop)
+{
+	kfree(colorop->state);
+	colorop->state = kzalloc(sizeof(*colorop->state), GFP_KERNEL);
+
+	if (colorop->state)
+		__drm_colorop_reset(colorop, colorop->state);
+}
diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c
index 8642a2fb25a9..369a66bad9da 100644
--- a/drivers/gpu/drm/drm_mode_config.c
+++ b/drivers/gpu/drm/drm_mode_config.c
@@ -29,6 +29,7 @@
 #include <drm/drm_managed.h>
 #include <drm/drm_mode_config.h>
 #include <drm/drm_print.h>
+#include <drm/drm_colorop.h>
 #include <linux/dma-resv.h>
 
 #include "drm_crtc_internal.h"
@@ -191,11 +192,15 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
 void drm_mode_config_reset(struct drm_device *dev)
 {
 	struct drm_crtc *crtc;
+	struct drm_colorop *colorop;
 	struct drm_plane *plane;
 	struct drm_encoder *encoder;
 	struct drm_connector *connector;
 	struct drm_connector_list_iter conn_iter;
 
+	drm_for_each_colorop(colorop, dev)
+		drm_colorop_reset(colorop);
+
 	drm_for_each_plane(plane, dev)
 		if (plane->funcs->reset)
 			plane->funcs->reset(plane);
@@ -429,6 +434,7 @@ int drmm_mode_config_init(struct drm_device *dev)
 	INIT_LIST_HEAD(&dev->mode_config.property_list);
 	INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
 	INIT_LIST_HEAD(&dev->mode_config.plane_list);
+	INIT_LIST_HEAD(&dev->mode_config.colorop_list);
 	INIT_LIST_HEAD(&dev->mode_config.privobj_list);
 	idr_init_base(&dev->mode_config.object_idr, 1);
 	idr_init_base(&dev->mode_config.tile_idr, 1);
@@ -450,6 +456,7 @@ int drmm_mode_config_init(struct drm_device *dev)
 	dev->mode_config.num_crtc = 0;
 	dev->mode_config.num_encoder = 0;
 	dev->mode_config.num_total_plane = 0;
+	dev->mode_config.num_colorop = 0;
 
 	if (IS_ENABLED(CONFIG_LOCKDEP)) {
 		struct drm_modeset_acquire_ctx modeset_ctx;
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 4c673f0698fe..b294f5ee11da 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -30,6 +30,7 @@
 
 #include <drm/drm_crtc.h>
 #include <drm/drm_util.h>
+#include <drm/drm_colorop.h>
 
 /**
  * struct drm_crtc_commit - track modeset commits on a CRTC
@@ -157,6 +158,11 @@ struct drm_crtc_commit {
 	bool abort_completion;
 };
 
+struct __drm_colorops_state {
+	struct drm_colorop *ptr;
+	struct drm_colorop_state *state, *old_state, *new_state;
+};
+
 struct __drm_planes_state {
 	struct drm_plane *ptr;
 	struct drm_plane_state *state, *old_state, *new_state;
@@ -458,6 +464,14 @@ struct drm_atomic_state {
 	 */
 	bool duplicated : 1;
 
+	/**
+	 * @colorops:
+	 *
+	 * Pointer to array of @drm_colorop and @drm_colorop_state part of this
+	 * update.
+	 */
+	struct __drm_colorops_state *colorops;
+
 	/**
 	 * @planes:
 	 *
@@ -599,6 +613,9 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state,
 struct drm_plane_state * __must_check
 drm_atomic_get_plane_state(struct drm_atomic_state *state,
 			   struct drm_plane *plane);
+struct drm_colorop_state *
+drm_atomic_get_colorop_state(struct drm_atomic_state *state,
+			     struct drm_colorop *colorop);
 struct drm_connector_state * __must_check
 drm_atomic_get_connector_state(struct drm_atomic_state *state,
 			       struct drm_connector *connector);
@@ -728,6 +745,36 @@ drm_atomic_get_new_plane_state(const struct drm_atomic_state *state,
 	return state->planes[drm_plane_index(plane)].new_state;
 }
 
+/**
+ * drm_atomic_get_old_colorop_state - get colorop state, if it exists
+ * @state: global atomic state object
+ * @colorop: colorop to grab
+ *
+ * This function returns the old colorop state for the given colorop, or
+ * NULL if the colorop is not part of the global atomic state.
+ */
+static inline struct drm_colorop_state *
+drm_atomic_get_old_colorop_state(struct drm_atomic_state *state,
+			       struct drm_colorop *colorop)
+{
+	return state->colorops[drm_colorop_index(colorop)].old_state;
+}
+
+/**
+ * drm_atomic_get_new_colorop_state - get colorop state, if it exists
+ * @state: global atomic state object
+ * @colorop: colorop to grab
+ *
+ * This function returns the new colorop state for the given colorop, or
+ * NULL if the colorop is not part of the global atomic state.
+ */
+static inline struct drm_colorop_state *
+drm_atomic_get_new_colorop_state(struct drm_atomic_state *state,
+			       struct drm_colorop *colorop)
+{
+	return state->colorops[drm_colorop_index(colorop)].new_state;
+}
+
 /**
  * drm_atomic_get_existing_connector_state - get connector state, if it exists
  * @state: global atomic state object
@@ -975,6 +1022,29 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
 			     (new_crtc_state) = (__state)->crtcs[__i].new_state, \
 			     (void)(new_crtc_state) /* Only to avoid unused-but-set-variable warning */, 1))
 
+/**
+ * for_each_oldnew_colorop_in_state - iterate over all colorops in an atomic update
+ * @__state: &struct drm_atomic_state pointer
+ * @colorop: &struct drm_colorop iteration cursor
+ * @old_colorop_state: &struct drm_colorop_state iteration cursor for the old state
+ * @new_colorop_state: &struct drm_colorop_state iteration cursor for the new state
+ * @__i: int iteration cursor, for macro-internal use
+ *
+ * This iterates over all colorops in an atomic update, tracking both old and
+ * new state. This is useful in places where the state delta needs to be
+ * considered, for example in atomic check functions.
+ */
+#define for_each_oldnew_colorop_in_state(__state, colorop, old_colorop_state, new_colorop_state, __i) \
+	for ((__i) = 0;							\
+	     (__i) < (__state)->dev->mode_config.num_colorop;		\
+	     (__i)++)							\
+		for_each_if ((__state)->colorops[__i].ptr &&		\
+			     ((colorop) = (__state)->colorops[__i].ptr,	\
+			      (void)(colorop) /* Only to avoid unused-but-set-variable warning */, \
+			      (old_colorop_state) = (__state)->colorops[__i].old_state,\
+			      (new_colorop_state) = (__state)->colorops[__i].new_state, 1))
+
+
 /**
  * for_each_oldnew_plane_in_state - iterate over all planes in an atomic update
  * @__state: &struct drm_atomic_state pointer
diff --git a/include/drm/drm_atomic_uapi.h b/include/drm/drm_atomic_uapi.h
index 4c6d39d7bdb2..70a115d523cd 100644
--- a/include/drm/drm_atomic_uapi.h
+++ b/include/drm/drm_atomic_uapi.h
@@ -37,6 +37,7 @@ struct drm_crtc;
 struct drm_connector_state;
 struct dma_fence;
 struct drm_framebuffer;
+struct drm_colorop;
 
 int __must_check
 drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
new file mode 100644
index 000000000000..008665d2d960
--- /dev/null
+++ b/include/drm/drm_colorop.h
@@ -0,0 +1,171 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DRM_COLOROP_H__
+#define __DRM_COLOROP_H__
+
+#include <drm/drm_mode_object.h>
+#include <drm/drm_mode.h>
+#include <drm/drm_property.h>
+
+/**
+ * struct drm_colorop_state - mutable colorop state
+ */
+struct drm_colorop_state {
+	/** @colorop: backpointer to the colorop */
+	struct drm_colorop *colorop;
+
+	/*
+	 * Color properties
+	 *
+	 * The following fields are not always valid, their usage depends
+	 * on the colorop type. See their associated comment for more
+	 * information.
+	 */
+
+	/** @state: backpointer to global drm_atomic_state */
+	struct drm_atomic_state *state;
+};
+
+/**
+ * struct drm_colorop - DRM color operation control structure
+ *
+ * A colorop represents one color operation. They can be chained via
+ * the 'next' pointer to build a color pipeline.
+ *
+ * Since colorops cannot stand-alone and are used to describe colorop
+ * operations on a plane they don't have their own locking mechanism but
+ * are locked and programmed along with their associated &drm_plane.
+ *
+ */
+struct drm_colorop {
+	/** @dev: parent DRM device */
+	struct drm_device *dev;
+
+	/**
+	 * @head:
+	 *
+	 * List of all colorops on @dev, linked from &drm_mode_config.colorop_list.
+	 * Invariant over the lifetime of @dev and therefore does not need
+	 * locking.
+	 */
+	struct list_head head;
+
+	/**
+	 * @index: Position inside the mode_config.list, can be used as an array
+	 * index. It is invariant over the lifetime of the colorop.
+	 */
+	unsigned int index;
+
+	/** @base: base mode object */
+	struct drm_mode_object base;
+
+	/**
+	 * @plane:
+	 *
+	 * The plane on which the colorop sits. A drm_colorop is always unique
+	 * to a plane.
+	 */
+	struct drm_plane *plane;
+
+	/**
+	 * @state:
+	 *
+	 * Current atomic state for this colorop.
+	 *
+	 * This is protected by @mutex. Note that nonblocking atomic commits
+	 * access the current colorop state without taking locks.
+	 */
+	struct drm_colorop_state *state;
+
+	/*
+	 * Color properties
+	 *
+	 * The following fields are not always valid, their usage depends
+	 * on the colorop type. See their associated comment for more
+	 * information.
+	 */
+
+	/** @properties: property tracking for this colorop */
+	struct drm_object_properties properties;
+
+};
+
+#define obj_to_colorop(x) container_of(x, struct drm_colorop, base)
+
+/**
+ * drm_colorop_find - look up a Colorop object from its ID
+ * @dev: DRM device
+ * @file_priv: drm file to check for lease against.
+ * @id: &drm_mode_object ID
+ *
+ * This can be used to look up a Colorop from its userspace ID. Only used by
+ * drivers for legacy IOCTLs and interface, nowadays extensions to the KMS
+ * userspace interface should be done using &drm_property.
+ */
+static inline struct drm_colorop *drm_colorop_find(struct drm_device *dev,
+		struct drm_file *file_priv,
+		uint32_t id)
+{
+	struct drm_mode_object *mo;
+
+	mo = drm_mode_object_find(dev, file_priv, id, DRM_MODE_OBJECT_COLOROP);
+	return mo ? obj_to_colorop(mo) : NULL;
+}
+
+struct drm_colorop_state *
+drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop);
+
+void drm_colorop_atomic_destroy_state(struct drm_colorop *colorop,
+				      struct drm_colorop_state *state);
+
+/**
+ * drm_colorop_reset - reset colorop atomic state
+ * @colorop: drm colorop
+ *
+ * Resets the atomic state for @colorop by freeing the state pointer (which might
+ * be NULL, e.g. at driver load time) and allocating a new empty state object.
+ */
+void drm_colorop_reset(struct drm_colorop *colorop);
+
+/**
+ * drm_colorop_index - find the index of a registered colorop
+ * @colorop: colorop to find index for
+ *
+ * Given a registered colorop, return the index of that colorop within a DRM
+ * device's list of colorops.
+ */
+static inline unsigned int drm_colorop_index(const struct drm_colorop *colorop)
+{
+	return colorop->index;
+}
+
+
+#define drm_for_each_colorop(colorop, dev) \
+	list_for_each_entry(colorop, &(dev)->mode_config.colorop_list, head)
+
+
+#endif /* __DRM_COLOROP_H__ */
diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
index 271765e2e9f2..d4661d4431dc 100644
--- a/include/drm/drm_mode_config.h
+++ b/include/drm/drm_mode_config.h
@@ -499,6 +499,24 @@ struct drm_mode_config {
 	 */
 	struct raw_spinlock panic_lock;
 
+	/**
+	 * @num_colorop:
+	 *
+	 * Number of colorop objects on this device.
+	 * This is invariant over the lifetime of a device and hence doesn't
+	 * need any locks.
+	 */
+	int num_colorop;
+
+	/**
+	 * @colorop_list:
+	 *
+	 * List of colorop objects linked with &drm_colorop.head. This is
+	 * invariant over the lifetime of a device and hence doesn't need any
+	 * locks.
+	 */
+	struct list_head colorop_list;
+
 	/**
 	 * @num_crtc:
 	 *
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index dd718c62ac31..2a9b902623c0 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -243,6 +243,14 @@ struct drm_plane_state {
 	 */
 	enum drm_scaling_filter scaling_filter;
 
+	/**
+	 * @color_pipeline:
+	 *
+	 * The first colorop of the active color pipeline, or NULL, if no
+	 * color pipeline is active.
+	 */
+	struct drm_colorop *color_pipeline;
+
 	/**
 	 * @commit: Tracks the pending commit to prevent use-after-free conditions,
 	 * and for async plane updates.
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index c082810c08a8..d49cded6c568 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -629,6 +629,7 @@ struct drm_mode_connector_set_property {
 #define DRM_MODE_OBJECT_FB 0xfbfbfbfb
 #define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb
 #define DRM_MODE_OBJECT_PLANE 0xeeeeeeee
+#define DRM_MODE_OBJECT_COLOROP 0xfafafafa
 #define DRM_MODE_OBJECT_ANY 0
 
 struct drm_mode_obj_get_properties {
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 05/43] drm/colorop: Add TYPE property
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (3 preceding siblings ...)
  2025-03-26 23:46 ` [PATCH V8 04/43] drm/colorop: Introduce new drm_colorop mode object Alex Hung
@ 2025-03-26 23:46 ` Alex Hung
  2025-03-26 23:46 ` [PATCH V8 06/43] drm/colorop: Add 1D Curve subtype Alex Hung
                   ` (38 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:46 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

Add a read-only TYPE property. The TYPE specifies the colorop
type, such as enumerated curve, 1D LUT, CTM, 3D LUT, PWL LUT,
etc.

For now we're only introducing an enumerated 1D LUT type to
illustrate the concept.

Reviewed-by: Simon Ser <contact@emersion.fr>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
v6:
 - fix doc typo (Alex Hung)

v5:
 - Add drm_get_colorop_type_name in header
 - Add kernel docs

v4:
 - Use enum property for TYPE (Pekka)

v3:
 - Make TYPE a range property
 - Move enum drm_colorop_type to uapi header
 - Fix drm_get_colorop_type_name description

 drivers/gpu/drm/drm_atomic.c      |  4 ++--
 drivers/gpu/drm/drm_atomic_uapi.c |  8 +++++++-
 drivers/gpu/drm/drm_colorop.c     | 12 ++++++++++++
 include/drm/drm_colorop.h         | 23 +++++++++++++++++++++++
 include/uapi/drm/drm_mode.h       | 19 +++++++++++++++++++
 5 files changed, 63 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 85d492a1f3d4..12c313d43e56 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -631,8 +631,8 @@ drm_atomic_get_colorop_state(struct drm_atomic_state *state,
 	state->colorops[index].new_state = colorop_state;
 	colorop_state->state = state;
 
-	drm_dbg_atomic(colorop->dev, "Added [COLOROP:%d] %p state to %p\n",
-		       colorop->base.id, colorop_state, state);
+	drm_dbg_atomic(colorop->dev, "Added [COLOROP:%d:%d] %p state to %p\n",
+		       colorop->base.id, colorop->type, colorop_state, state);
 
 	return colorop_state;
 }
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index cf1772118895..5e8ce781fcd7 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -661,7 +661,13 @@ drm_atomic_colorop_get_property(struct drm_colorop *colorop,
 		const struct drm_colorop_state *state,
 		struct drm_property *property, uint64_t *val)
 {
-	return -EINVAL;
+	if (property == colorop->type_property) {
+		*val = colorop->type;
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
 }
 
 static int drm_atomic_set_writeback_fb_for_connector(
diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index d215e22c9d20..1459a28c7e7b 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -102,3 +102,15 @@ void drm_colorop_reset(struct drm_colorop *colorop)
 	if (colorop->state)
 		__drm_colorop_reset(colorop, colorop->state);
 }
+
+static const char * const colorop_type_name[] = {
+	[DRM_COLOROP_1D_CURVE] = "1D Curve",
+};
+
+const char *drm_get_colorop_type_name(enum drm_colorop_type type)
+{
+	if (WARN_ON(type >= ARRAY_SIZE(colorop_type_name)))
+		return "unknown";
+
+	return colorop_type_name[type];
+}
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index 008665d2d960..9c9698545f63 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -112,6 +112,21 @@ struct drm_colorop {
 	/** @properties: property tracking for this colorop */
 	struct drm_object_properties properties;
 
+	/**
+	 * @type:
+	 *
+	 * Read-only
+	 * Type of color operation
+	 */
+	enum drm_colorop_type type;
+
+	/**
+	 * @type_property:
+	 *
+	 * Read-only "TYPE" property for specifying the type of
+	 * this color operation. The type is enum drm_colorop_type.
+	 */
+	struct drm_property *type_property;
 };
 
 #define obj_to_colorop(x) container_of(x, struct drm_colorop, base)
@@ -167,5 +182,13 @@ static inline unsigned int drm_colorop_index(const struct drm_colorop *colorop)
 #define drm_for_each_colorop(colorop, dev) \
 	list_for_each_entry(colorop, &(dev)->mode_config.colorop_list, head)
 
+/**
+ * drm_get_colorop_type_name - return a string for colorop type
+ * @type: colorop type to compute name of
+ *
+ * In contrast to the other drm_get_*_name functions this one here returns a
+ * const pointer and hence is threadsafe.
+ */
+const char *drm_get_colorop_type_name(enum drm_colorop_type type);
 
 #endif /* __DRM_COLOROP_H__ */
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index d49cded6c568..ea6d88f683cd 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -858,6 +858,25 @@ struct drm_color_lut {
 	__u16 reserved;
 };
 
+/**
+ * enum drm_colorop_type - Type of color operation
+ *
+ * drm_colorops can be of many different types. Each type behaves differently
+ * and defines a different set of properties. This enum defines all types and
+ * gives a high-level description.
+ */
+enum drm_colorop_type {
+	/**
+	 * @DRM_COLOROP_1D_CURVE:
+	 *
+	 * enum string "1D Curve"
+	 *
+	 * A 1D curve that is being applied to all color channels. The
+	 * curve is specified via the CURVE_1D_TYPE colorop property.
+	 */
+	DRM_COLOROP_1D_CURVE
+};
+
 /**
  * struct drm_plane_size_hint - Plane size hints
  * @width: The width of the plane in pixel
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 06/43] drm/colorop: Add 1D Curve subtype
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (4 preceding siblings ...)
  2025-03-26 23:46 ` [PATCH V8 05/43] drm/colorop: Add TYPE property Alex Hung
@ 2025-03-26 23:46 ` Alex Hung
  2025-04-01 15:14   ` Daniel Stone
  2025-03-26 23:46 ` [PATCH V8 07/43] drm/colorop: Add BYPASS property Alex Hung
                   ` (37 subsequent siblings)
  43 siblings, 1 reply; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:46 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

Add a new drm_colorop with DRM_COLOROP_1D_CURVE with two subtypes:
DRM_COLOROP_1D_CURVE_SRGB_EOTF and DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF.

Reviewed-by: Simon Ser <contact@emersion.fr>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Co-developed-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
v5:
 - Add drm_get_colorop_curve_1d_type_name in header
 - Add drm_colorop_init
 - Set default curve
 - Add kernel docs

v4:
 - Use drm_colorop_curve_1d_type_enum_list to get name (Pekka)
 - Create separate init function for 1D curve
 - Pass supported TFs into 1D curve init function

 drivers/gpu/drm/drm_atomic_uapi.c |  18 ++--
 drivers/gpu/drm/drm_colorop.c     | 134 ++++++++++++++++++++++++++++++
 include/drm/drm_colorop.h         |  63 ++++++++++++++
 3 files changed, 210 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index 5e8ce781fcd7..f75c987f8913 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -649,11 +649,17 @@ static int drm_atomic_colorop_set_property(struct drm_colorop *colorop,
 		struct drm_colorop_state *state, struct drm_file *file_priv,
 		struct drm_property *property, uint64_t val)
 {
-	drm_dbg_atomic(colorop->dev,
-			"[COLOROP:%d] unknown property [PROP:%d:%s]]\n",
-			colorop->base.id,
-			property->base.id, property->name);
-	return -EINVAL;
+	if (property == colorop->curve_1d_type_property) {
+		state->curve_1d_type = val;
+	} else {
+		drm_dbg_atomic(colorop->dev,
+			       "[COLOROP:%d:%d] unknown property [PROP:%d:%s]]\n",
+			       colorop->base.id, colorop->type,
+			       property->base.id, property->name);
+		return -EINVAL;
+	}
+
+	return 0;
 }
 
 static int
@@ -663,6 +669,8 @@ drm_atomic_colorop_get_property(struct drm_colorop *colorop,
 {
 	if (property == colorop->type_property) {
 		*val = colorop->type;
+	} else if (property == colorop->curve_1d_type_property) {
+		*val = state->curve_1d_type;
 	} else {
 		return -EINVAL;
 	}
diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index 1459a28c7e7b..a42de0aa48e1 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -31,6 +31,123 @@
 
 #include "drm_crtc_internal.h"
 
+static const struct drm_prop_enum_list drm_colorop_type_enum_list[] = {
+	{ DRM_COLOROP_1D_CURVE, "1D Curve" },
+};
+
+static const char * const colorop_curve_1d_type_names[] = {
+	[DRM_COLOROP_1D_CURVE_SRGB_EOTF] = "sRGB EOTF",
+	[DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF] = "sRGB Inverse EOTF",
+};
+
+
+/* Init Helpers */
+
+static int drm_colorop_init(struct drm_device *dev, struct drm_colorop *colorop,
+			    struct drm_plane *plane, enum drm_colorop_type type)
+{
+	struct drm_mode_config *config = &dev->mode_config;
+	struct drm_property *prop;
+	int ret = 0;
+
+	ret = drm_mode_object_add(dev, &colorop->base, DRM_MODE_OBJECT_COLOROP);
+	if (ret)
+		return ret;
+
+	colorop->base.properties = &colorop->properties;
+	colorop->dev = dev;
+	colorop->type = type;
+	colorop->plane = plane;
+
+	list_add_tail(&colorop->head, &config->colorop_list);
+	colorop->index = config->num_colorop++;
+
+	/* add properties */
+
+	/* type */
+	prop = drm_property_create_enum(dev,
+					DRM_MODE_PROP_IMMUTABLE,
+					"TYPE", drm_colorop_type_enum_list,
+					ARRAY_SIZE(drm_colorop_type_enum_list));
+
+	if (!prop)
+		return -ENOMEM;
+
+	colorop->type_property = prop;
+
+	drm_object_attach_property(&colorop->base,
+				   colorop->type_property,
+				   colorop->type);
+
+	return ret;
+}
+
+/**
+ * drm_colorop_curve_1d_init - Initialize a DRM_COLOROP_1D_CURVE
+ *
+ * @dev: DRM device
+ * @colorop: The drm_colorop object to initialize
+ * @plane: The associated drm_plane
+ * @supported_tfs: A bitfield of supported drm_colorop_curve_1d_init enum values,
+ *                 created using BIT(curve_type) and combined with the OR '|'
+ *                 operator.
+ * @return zero on success, -E value on failure
+ */
+int drm_colorop_curve_1d_init(struct drm_device *dev, struct drm_colorop *colorop,
+			      struct drm_plane *plane, u64 supported_tfs)
+{
+	struct drm_prop_enum_list enum_list[DRM_COLOROP_1D_CURVE_COUNT];
+	int i, len;
+
+	struct drm_property *prop;
+	int ret;
+
+	if (!supported_tfs) {
+		drm_err(dev,
+			"No supported TFs for new 1D curve colorop on [PLANE:%d:%s]\n",
+			plane->base.id, plane->name);
+		return -EINVAL;
+	}
+
+	if ((supported_tfs & -BIT(DRM_COLOROP_1D_CURVE_COUNT)) != 0) {
+		drm_err(dev, "Unknown TF provided on [PLANE:%d:%s]\n",
+			plane->base.id, plane->name);
+		return -EINVAL;
+	}
+
+	ret = drm_colorop_init(dev, colorop, plane, DRM_COLOROP_1D_CURVE);
+	if (ret)
+		return ret;
+
+	len = 0;
+	for (i = 0; i < DRM_COLOROP_1D_CURVE_COUNT; i++) {
+		if ((supported_tfs & BIT(i)) == 0)
+			continue;
+
+		enum_list[len].type = i;
+		enum_list[len].name = colorop_curve_1d_type_names[i];
+		len++;
+	}
+
+	if (WARN_ON(len <= 0))
+		return -EINVAL;
+
+
+	/* initialize 1D curve only attribute */
+	prop = drm_property_create_enum(dev, DRM_MODE_PROP_ATOMIC, "CURVE_1D_TYPE",
+					enum_list, len);
+	if (!prop)
+		return -ENOMEM;
+
+	colorop->curve_1d_type_property = prop;
+	drm_object_attach_property(&colorop->base, colorop->curve_1d_type_property,
+				   enum_list[0].type);
+	drm_colorop_reset(colorop);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_colorop_curve_1d_init);
+
 static void __drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop,
 							struct drm_colorop_state *state)
 {
@@ -70,7 +187,16 @@ void drm_colorop_atomic_destroy_state(struct drm_colorop *colorop,
 static void __drm_colorop_state_reset(struct drm_colorop_state *colorop_state,
 				      struct drm_colorop *colorop)
 {
+	u64 val;
+
 	colorop_state->colorop = colorop;
+
+	if (colorop->curve_1d_type_property) {
+		drm_object_property_get_default_value(&colorop->base,
+						colorop->curve_1d_type_property,
+						&val);
+		colorop_state->curve_1d_type = val;
+	}
 }
 
 /**
@@ -114,3 +240,11 @@ const char *drm_get_colorop_type_name(enum drm_colorop_type type)
 
 	return colorop_type_name[type];
 }
+
+const char *drm_get_colorop_curve_1d_type_name(enum drm_colorop_curve_1d_type type)
+{
+	if (WARN_ON(type >= ARRAY_SIZE(colorop_curve_1d_type_names)))
+		return "unknown";
+
+	return colorop_curve_1d_type_names[type];
+}
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index 9c9698545f63..fc1b2e0f33e0 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -31,6 +31,42 @@
 #include <drm/drm_mode.h>
 #include <drm/drm_property.h>
 
+
+/**
+ * enum drm_colorop_curve_1d_type - type of 1D curve
+ *
+ * Describes a 1D curve to be applied by the DRM_COLOROP_1D_CURVE colorop.
+ */
+enum drm_colorop_curve_1d_type {
+	/**
+	 * @DRM_COLOROP_1D_CURVE_SRGB_EOTF:
+	 *
+	 * enum string "sRGB EOTF"
+	 *
+	 * sRGB piece-wise electro-optical transfer function. Transfer
+	 * characteristics as defined by IEC 61966-2-1 sRGB. Equivalent
+	 * to H.273 TransferCharacteristics code point 13 with
+	 * MatrixCoefficients set to 0.
+	 */
+	DRM_COLOROP_1D_CURVE_SRGB_EOTF,
+
+	/**
+	 * @DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF:
+	 *
+	 * enum string "sRGB Inverse EOTF"
+	 *
+	 * The inverse of &DRM_COLOROP_1D_CURVE_SRGB_EOTF
+	 */
+	DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF,
+
+	/**
+	 * @DRM_COLOROP_1D_CURVE_COUNT:
+	 *
+	 * enum value denoting the size of the enum
+	 */
+	DRM_COLOROP_1D_CURVE_COUNT
+};
+
 /**
  * struct drm_colorop_state - mutable colorop state
  */
@@ -46,6 +82,13 @@ struct drm_colorop_state {
 	 * information.
 	 */
 
+	/**
+	 * @curve_1d_type:
+	 *
+	 * Type of 1D curve.
+	 */
+	enum drm_colorop_curve_1d_type curve_1d_type;
+
 	/** @state: backpointer to global drm_atomic_state */
 	struct drm_atomic_state *state;
 };
@@ -127,6 +170,14 @@ struct drm_colorop {
 	 * this color operation. The type is enum drm_colorop_type.
 	 */
 	struct drm_property *type_property;
+
+	/**
+	 * @curve_1d_type_property:
+	 *
+	 * Sub-type for DRM_COLOROP_1D_CURVE type.
+	 */
+	struct drm_property *curve_1d_type_property;
+
 };
 
 #define obj_to_colorop(x) container_of(x, struct drm_colorop, base)
@@ -151,6 +202,9 @@ static inline struct drm_colorop *drm_colorop_find(struct drm_device *dev,
 	return mo ? obj_to_colorop(mo) : NULL;
 }
 
+int drm_colorop_curve_1d_init(struct drm_device *dev, struct drm_colorop *colorop,
+			      struct drm_plane *plane, u64 supported_tfs);
+
 struct drm_colorop_state *
 drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop);
 
@@ -191,4 +245,13 @@ static inline unsigned int drm_colorop_index(const struct drm_colorop *colorop)
  */
 const char *drm_get_colorop_type_name(enum drm_colorop_type type);
 
+/**
+ * drm_get_colorop_curve_1d_type_name - return a string for 1D curve type
+ * @type: 1d curve type to compute name of
+ *
+ * In contrast to the other drm_get_*_name functions this one here returns a
+ * const pointer and hence is threadsafe.
+ */
+const char *drm_get_colorop_curve_1d_type_name(enum drm_colorop_curve_1d_type type);
+
 #endif /* __DRM_COLOROP_H__ */
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 07/43] drm/colorop: Add BYPASS property
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (5 preceding siblings ...)
  2025-03-26 23:46 ` [PATCH V8 06/43] drm/colorop: Add 1D Curve subtype Alex Hung
@ 2025-03-26 23:46 ` Alex Hung
  2025-03-26 23:46 ` [PATCH V8 08/43] drm/colorop: Add NEXT property Alex Hung
                   ` (36 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:46 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

We want to be able to bypass each colorop at all times.
Introduce a new BYPASS boolean property for this.

Reviewed-by: Simon Ser <contact@emersion.fr>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
v6:
 - clarify that bypass is only valid if BYPASS prop exists (Louis Chauvet)

 drivers/gpu/drm/drm_atomic_uapi.c |  6 +++++-
 drivers/gpu/drm/drm_colorop.c     | 15 +++++++++++++++
 include/drm/drm_colorop.h         | 22 ++++++++++++++++++++++
 3 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index f75c987f8913..744eb3a8c9db 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -649,7 +649,9 @@ static int drm_atomic_colorop_set_property(struct drm_colorop *colorop,
 		struct drm_colorop_state *state, struct drm_file *file_priv,
 		struct drm_property *property, uint64_t val)
 {
-	if (property == colorop->curve_1d_type_property) {
+	if (property == colorop->bypass_property) {
+		state->bypass = val;
+	} else if (property == colorop->curve_1d_type_property) {
 		state->curve_1d_type = val;
 	} else {
 		drm_dbg_atomic(colorop->dev,
@@ -669,6 +671,8 @@ drm_atomic_colorop_get_property(struct drm_colorop *colorop,
 {
 	if (property == colorop->type_property) {
 		*val = colorop->type;
+	} else if (property == colorop->bypass_property) {
+		*val = state->bypass;
 	} else if (property == colorop->curve_1d_type_property) {
 		*val = state->curve_1d_type;
 	} else {
diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index a42de0aa48e1..60edf6671643 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -79,6 +79,17 @@ static int drm_colorop_init(struct drm_device *dev, struct drm_colorop *colorop,
 				   colorop->type_property,
 				   colorop->type);
 
+	/* bypass */
+	prop = drm_property_create_bool(dev, DRM_MODE_PROP_ATOMIC,
+					"BYPASS");
+	if (!prop)
+		return -ENOMEM;
+
+	colorop->bypass_property = prop;
+	drm_object_attach_property(&colorop->base,
+				   colorop->bypass_property,
+				   1);
+
 	return ret;
 }
 
@@ -136,6 +147,7 @@ int drm_colorop_curve_1d_init(struct drm_device *dev, struct drm_colorop *coloro
 	/* initialize 1D curve only attribute */
 	prop = drm_property_create_enum(dev, DRM_MODE_PROP_ATOMIC, "CURVE_1D_TYPE",
 					enum_list, len);
+
 	if (!prop)
 		return -ENOMEM;
 
@@ -152,6 +164,8 @@ static void __drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colo
 							struct drm_colorop_state *state)
 {
 	memcpy(state, colorop->state, sizeof(*state));
+
+	state->bypass = true;
 }
 
 struct drm_colorop_state *
@@ -190,6 +204,7 @@ static void __drm_colorop_state_reset(struct drm_colorop_state *colorop_state,
 	u64 val;
 
 	colorop_state->colorop = colorop;
+	colorop_state->bypass = true;
 
 	if (colorop->curve_1d_type_property) {
 		drm_object_property_get_default_value(&colorop->base,
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index fc1b2e0f33e0..315d748e212e 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -82,6 +82,16 @@ struct drm_colorop_state {
 	 * information.
 	 */
 
+
+	/**
+	 * @bypass:
+	 *
+	 * When the property BYPASS exists on this colorop, this stores
+	 * the requested bypass state: true if colorop shall be bypassed,
+	 * false if colorop is enabled.
+	 */
+	bool bypass;
+
 	/**
 	 * @curve_1d_type:
 	 *
@@ -171,6 +181,18 @@ struct drm_colorop {
 	 */
 	struct drm_property *type_property;
 
+	/**
+	 * @bypass_property:
+	 *
+	 * Boolean property to control enablement of the color
+	 * operation. Setting bypass to "true" shall always be supported
+	 * in order to allow compositors to quickly fall back to
+	 * alternate methods of color processing. This is important
+	 * since setting color operations can fail due to unique
+	 * HW constraints.
+	 */
+	struct drm_property *bypass_property;
+
 	/**
 	 * @curve_1d_type_property:
 	 *
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 08/43] drm/colorop: Add NEXT property
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (6 preceding siblings ...)
  2025-03-26 23:46 ` [PATCH V8 07/43] drm/colorop: Add BYPASS property Alex Hung
@ 2025-03-26 23:46 ` Alex Hung
  2025-03-27 23:26   ` Simon Ser
  2025-03-26 23:46 ` [PATCH V8 09/43] drm/colorop: Add atomic state print for drm_colorop Alex Hung
                   ` (35 subsequent siblings)
  43 siblings, 1 reply; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:46 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

We'll construct color pipelines out of drm_colorop by
chaining them via the NEXT pointer. NEXT will point to
the next drm_colorop in the pipeline, or by 0 if we're
at the end of the pipeline.

Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
v8:
 - Remove null check "colorop->next_property" in drm_colorop_set_next_property

v5:
 - move next comment here from Add 3x4 CTM patch (Sebastian)
 - Add kernel doc

v4:
 - Allow setting of NEXT property to NULL (Chaitanya Kumar Borah)

v3:
 - Add next pointer to colorop to be used by drivers
   and in DRM core

 drivers/gpu/drm/drm_colorop.c | 27 +++++++++++++++++++++++++++
 include/drm/drm_colorop.h     | 17 +++++++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index 60edf6671643..05de9bf118ed 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -58,6 +58,7 @@ static int drm_colorop_init(struct drm_device *dev, struct drm_colorop *colorop,
 	colorop->dev = dev;
 	colorop->type = type;
 	colorop->plane = plane;
+	colorop->next = NULL;
 
 	list_add_tail(&colorop->head, &config->colorop_list);
 	colorop->index = config->num_colorop++;
@@ -90,6 +91,16 @@ static int drm_colorop_init(struct drm_device *dev, struct drm_colorop *colorop,
 				   colorop->bypass_property,
 				   1);
 
+	/* next */
+	prop = drm_property_create_object(dev, DRM_MODE_PROP_IMMUTABLE | DRM_MODE_PROP_ATOMIC,
+					  "NEXT", DRM_MODE_OBJECT_COLOROP);
+	if (!prop)
+		return -ENOMEM;
+	colorop->next_property = prop;
+	drm_object_attach_property(&colorop->base,
+				   colorop->next_property,
+				   0);
+
 	return ret;
 }
 
@@ -263,3 +274,19 @@ const char *drm_get_colorop_curve_1d_type_name(enum drm_colorop_curve_1d_type ty
 
 	return colorop_curve_1d_type_names[type];
 }
+
+/**
+ * drm_colorop_set_next_property - sets the next pointer
+ * @colorop: drm colorop
+ * @next: next colorop
+ *
+ * Should be used when constructing the color pipeline
+ */
+void drm_colorop_set_next_property(struct drm_colorop *colorop, struct drm_colorop *next)
+{
+	drm_object_property_set_value(&colorop->base,
+				      colorop->next_property,
+				      next ? next->base.id : 0);
+	colorop->next = next;
+}
+EXPORT_SYMBOL(drm_colorop_set_next_property);
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index 315d748e212e..7948de5c4994 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -173,6 +173,14 @@ struct drm_colorop {
 	 */
 	enum drm_colorop_type type;
 
+	/**
+	 * @next:
+	 *
+	 * Read-only
+	 * Pointer to next drm_colorop in pipeline
+	 */
+	struct drm_colorop *next;
+
 	/**
 	 * @type_property:
 	 *
@@ -200,6 +208,13 @@ struct drm_colorop {
 	 */
 	struct drm_property *curve_1d_type_property;
 
+	/**
+	 * @next_property:
+	 *
+	 * Read-only property to next colorop in the pipeline
+	 */
+	struct drm_property *next_property;
+
 };
 
 #define obj_to_colorop(x) container_of(x, struct drm_colorop, base)
@@ -276,4 +291,6 @@ const char *drm_get_colorop_type_name(enum drm_colorop_type type);
  */
 const char *drm_get_colorop_curve_1d_type_name(enum drm_colorop_curve_1d_type type);
 
+void drm_colorop_set_next_property(struct drm_colorop *colorop, struct drm_colorop *next);
+
 #endif /* __DRM_COLOROP_H__ */
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 09/43] drm/colorop: Add atomic state print for drm_colorop
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (7 preceding siblings ...)
  2025-03-26 23:46 ` [PATCH V8 08/43] drm/colorop: Add NEXT property Alex Hung
@ 2025-03-26 23:46 ` Alex Hung
  2025-03-27 23:29   ` Simon Ser
  2025-03-26 23:46 ` [PATCH V8 10/43] drm/plane: Add COLOR PIPELINE property Alex Hung
                   ` (34 subsequent siblings)
  43 siblings, 1 reply; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:46 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

Print atomic state for drm_colorop in debugfs

Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
v8:
 - Add switch statement to print colorop type (Simon Ser)

v7:
 - Add a commit messages
 - Squash "drm/colorop: Add NEXT to colorop state print" (Simon Ser)

 drivers/gpu/drm/drm_atomic.c | 35 ++++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 12c313d43e56..97a30d6a68a1 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -777,6 +777,29 @@ static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state,
 	return 0;
 }
 
+
+
+static void drm_atomic_colorop_print_state(struct drm_printer *p,
+		const struct drm_colorop_state *state)
+{
+	struct drm_colorop *colorop = state->colorop;
+
+	drm_printf(p, "colorop[%u]:\n", colorop->base.id);
+	drm_printf(p, "\ttype=%s\n", drm_get_colorop_type_name(colorop->type));
+	drm_printf(p, "\tbypass=%u\n", state->bypass);
+
+	switch (colorop->type) {
+	case DRM_COLOROP_1D_CURVE:
+		drm_printf(p, "\tcurve_1d_type=%s\n",
+			   drm_get_colorop_curve_1d_type_name(state->curve_1d_type));
+		break;
+	default:
+		break;
+	}
+
+	drm_printf(p, "\tnext=%d\n", colorop->next ? colorop->next->base.id : 0);
+}
+
 static void drm_atomic_plane_print_state(struct drm_printer *p,
 		const struct drm_plane_state *state)
 {
@@ -798,7 +821,8 @@ static void drm_atomic_plane_print_state(struct drm_printer *p,
 	drm_printf(p, "\tcolor-range=%s\n",
 		   drm_get_color_range_name(state->color_range));
 	drm_printf(p, "\tcolor_mgmt_changed=%d\n", state->color_mgmt_changed);
-
+	drm_printf(p, "\tcolor-pipeline=%d\n",
+		   state->color_pipeline ? state->color_pipeline->base.id : 0);
 	if (plane->funcs->atomic_print_state)
 		plane->funcs->atomic_print_state(p, state);
 }
@@ -1844,6 +1868,7 @@ static void __drm_state_dump(struct drm_device *dev, struct drm_printer *p,
 			     bool take_locks)
 {
 	struct drm_mode_config *config = &dev->mode_config;
+	struct drm_colorop *colorop;
 	struct drm_plane *plane;
 	struct drm_crtc *crtc;
 	struct drm_connector *connector;
@@ -1853,6 +1878,14 @@ static void __drm_state_dump(struct drm_device *dev, struct drm_printer *p,
 	if (!drm_drv_uses_atomic_modeset(dev))
 		return;
 
+	list_for_each_entry(colorop, &config->colorop_list, head) {
+		if (take_locks)
+			drm_modeset_lock(&colorop->plane->mutex, NULL);
+		drm_atomic_colorop_print_state(p, colorop->state);
+		if (take_locks)
+			drm_modeset_unlock(&colorop->plane->mutex);
+	}
+
 	list_for_each_entry(plane, &config->plane_list, head) {
 		if (take_locks)
 			drm_modeset_lock(&plane->mutex, NULL);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 10/43] drm/plane: Add COLOR PIPELINE property
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (8 preceding siblings ...)
  2025-03-26 23:46 ` [PATCH V8 09/43] drm/colorop: Add atomic state print for drm_colorop Alex Hung
@ 2025-03-26 23:46 ` Alex Hung
  2025-03-29 14:33   ` Simon Ser
  2025-03-26 23:46 ` [PATCH V8 11/43] drm/colorop: Introduce DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE Alex Hung
                   ` (33 subsequent siblings)
  43 siblings, 1 reply; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:46 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

We're adding a new enum COLOR PIPELINE property. This
property will have entries for each COLOR PIPELINE by
referencing the DRM object ID of the first drm_colorop
of the pipeline. 0 disables the entire COLOR PIPELINE.

Userspace can use this to discover the available color
pipelines, as well as set the desired one. The color
pipelines are programmed via properties on the actual
drm_colorop objects.

Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
v8:
 - Use upper case in drm_dbg_atomic (Simon Ser)
 - Remove MAX_COLOR_PIPELINES (Simon Ser)
 - Make pipelines const in drm_plane_create_color_pipeline_property (Simon Ser)

v7:
 - Fix a checkpatch warning - a new line after variable declaration

v4:
 - Add pipeline property creation helper (Pekka)
 - Fix function comment for
   drm_atomic_set_colorop_for_plane (Pekka)
 - Always create Bypass pipeline (Pekka)
 - Add missing function declaration (Chaitanya Kumar Borah)

 drivers/gpu/drm/drm_atomic.c              | 46 ++++++++++++++++++
 drivers/gpu/drm/drm_atomic_state_helper.c |  5 ++
 drivers/gpu/drm/drm_atomic_uapi.c         | 43 +++++++++++++++++
 drivers/gpu/drm/drm_plane.c               | 59 +++++++++++++++++++++++
 include/drm/drm_atomic.h                  |  3 ++
 include/drm/drm_atomic_uapi.h             |  2 +
 include/drm/drm_plane.h                   | 11 +++++
 7 files changed, 169 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 97a30d6a68a1..e67d7a68e8a8 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1472,6 +1472,52 @@ drm_atomic_add_affected_planes(struct drm_atomic_state *state,
 }
 EXPORT_SYMBOL(drm_atomic_add_affected_planes);
 
+/**
+ * drm_atomic_add_affected_colorops - add colorops for plane
+ * @state: atomic state
+ * @plane: DRM plane
+ *
+ * This function walks the current configuration and adds all colorops
+ * currently used by @plane to the atomic configuration @state. This is useful
+ * when an atomic commit also needs to check all currently enabled colorop on
+ * @plane, e.g. when changing the mode. It's also useful when re-enabling a plane
+ * to avoid special code to force-enable all colorops.
+ *
+ * Since acquiring a colorop state will always also acquire the w/w mutex of the
+ * current plane for that colorop (if there is any) adding all the colorop states for
+ * a plane will not reduce parallelism of atomic updates.
+ *
+ * Returns:
+ * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
+ * then the w/w mutex code has detected a deadlock and the entire atomic
+ * sequence must be restarted. All other errors are fatal.
+ */
+int
+drm_atomic_add_affected_colorops(struct drm_atomic_state *state,
+				 struct drm_plane *plane)
+{
+	struct drm_colorop *colorop;
+	struct drm_colorop_state *colorop_state;
+
+	WARN_ON(!drm_atomic_get_new_plane_state(state, plane));
+
+	drm_dbg_atomic(plane->dev,
+		       "Adding all current colorops for [PLANE:%d:%s] to %p\n",
+		       plane->base.id, plane->name, state);
+
+	drm_for_each_colorop(colorop, plane->dev) {
+		if (colorop->plane != plane)
+			continue;
+
+		colorop_state = drm_atomic_get_colorop_state(state, colorop);
+		if (IS_ERR(colorop_state))
+			return PTR_ERR(colorop_state);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_atomic_add_affected_colorops);
+
 /**
  * drm_atomic_check_only - check whether a given config would work
  * @state: atomic configuration to check
diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c
index 519228eb1095..d1dd082b1286 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -267,6 +267,11 @@ void __drm_atomic_helper_plane_state_reset(struct drm_plane_state *plane_state,
 			plane_state->color_range = val;
 	}
 
+	if (plane->color_pipeline_property) {
+		/* default is always NULL, i.e., bypass */
+		plane_state->color_pipeline = NULL;
+	}
+
 	if (plane->zpos_property) {
 		if (!drm_object_property_get_default_value(&plane->base,
 							   plane->zpos_property,
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index 744eb3a8c9db..5738b1c18755 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -257,6 +257,36 @@ drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
 }
 EXPORT_SYMBOL(drm_atomic_set_fb_for_plane);
 
+
+/**
+ * drm_atomic_set_colorop_for_plane - set colorop for plane
+ * @plane_state: atomic state object for the plane
+ * @colorop: colorop to use for the plane
+ *
+ * Helper function to select the color pipeline on a plane by setting
+ * it to the first drm_colorop element of the pipeline.
+ */
+void
+drm_atomic_set_colorop_for_plane(struct drm_plane_state *plane_state,
+				 struct drm_colorop *colorop)
+{
+	struct drm_plane *plane = plane_state->plane;
+
+	if (colorop)
+		drm_dbg_atomic(plane->dev,
+			       "Set [COLOROP:%d] for [PLANE:%d:%s] state %p\n",
+			       colorop->base.id, plane->base.id, plane->name,
+			       plane_state);
+	else
+		drm_dbg_atomic(plane->dev,
+			       "Set [NOCOLOROP] for [PLANE:%d:%s] state %p\n",
+			       plane->base.id, plane->name, plane_state);
+
+	plane_state->color_pipeline = colorop;
+}
+EXPORT_SYMBOL(drm_atomic_set_colorop_for_plane);
+
+
 /**
  * drm_atomic_set_crtc_for_connector - set CRTC for connector
  * @conn_state: atomic state object for the connector
@@ -540,6 +570,17 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane,
 		state->color_encoding = val;
 	} else if (property == plane->color_range_property) {
 		state->color_range = val;
+	} else if (property == plane->color_pipeline_property) {
+		/* find DRM colorop object */
+		struct drm_colorop *colorop = NULL;
+
+		colorop = drm_colorop_find(dev, file_priv, val);
+
+		if (val && !colorop)
+			return -EACCES;
+
+		/* set it on drm_plane_state */
+		drm_atomic_set_colorop_for_plane(state, colorop);
 	} else if (property == config->prop_fb_damage_clips) {
 		ret = drm_property_replace_blob_from_id(dev,
 					&state->fb_damage_clips,
@@ -622,6 +663,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane,
 		*val = state->color_encoding;
 	} else if (property == plane->color_range_property) {
 		*val = state->color_range;
+	} else if (property == plane->color_pipeline_property) {
+		*val = (state->color_pipeline) ? state->color_pipeline->base.id : 0;
 	} else if (property == config->prop_fb_damage_clips) {
 		*val = (state->fb_damage_clips) ?
 			state->fb_damage_clips->base.id : 0;
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index a28b22fdd7a4..1daac7c57aac 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -1793,3 +1793,62 @@ int drm_plane_add_size_hints_property(struct drm_plane *plane,
 	return 0;
 }
 EXPORT_SYMBOL(drm_plane_add_size_hints_property);
+
+/**
+ * drm_plane_create_color_pipeline_property - create a new color pipeline
+ * property
+ *
+ * @plane: drm plane
+ * @pipelines: list of pipelines
+ * @num_pipelines: number of pipelines
+ *
+ * Create the COLOR_PIPELINE plane property to specific color pipelines on
+ * the plane.
+ *
+ * RETURNS:
+ * Zero for success or -errno
+ */
+int drm_plane_create_color_pipeline_property(struct drm_plane *plane,
+					     const struct drm_prop_enum_list *pipelines,
+					     const int num_pipelines)
+{
+	struct drm_prop_enum_list *all_pipelines;
+	struct drm_property *prop;
+	int len = 0;
+	int i;
+
+	all_pipelines = kcalloc(num_pipelines + 1,
+				sizeof(*all_pipelines),
+				GFP_KERNEL);
+
+	if (!all_pipelines) {
+		drm_err(plane->dev, "failed to allocate color pipeline\n");
+		return -ENOMEM;
+	}
+
+	/* Create default Bypass color pipeline */
+	all_pipelines[len].type = 0;
+	all_pipelines[len].name = "Bypass";
+	len++;
+
+	/* Add all other color pipelines */
+	for (i = 0; i < num_pipelines; i++, len++) {
+		all_pipelines[len].type = pipelines[i].type;
+		all_pipelines[len].name = pipelines[i].name;
+	}
+
+	prop = drm_property_create_enum(plane->dev, DRM_MODE_PROP_ATOMIC,
+					"COLOR_PIPELINE",
+					all_pipelines, len);
+	if (IS_ERR(prop)) {
+		kfree(all_pipelines);
+		return PTR_ERR(prop);
+	}
+
+	drm_object_attach_property(&plane->base, prop, 0);
+	plane->color_pipeline_property = prop;
+
+	kfree(all_pipelines);
+	return 0;
+}
+EXPORT_SYMBOL(drm_plane_create_color_pipeline_property);
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index b294f5ee11da..0f76ee3caa9d 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -883,6 +883,9 @@ drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
 int __must_check
 drm_atomic_add_affected_planes(struct drm_atomic_state *state,
 			       struct drm_crtc *crtc);
+int __must_check
+drm_atomic_add_affected_colorops(struct drm_atomic_state *state,
+				 struct drm_plane *plane);
 
 int __must_check drm_atomic_check_only(struct drm_atomic_state *state);
 int __must_check drm_atomic_commit(struct drm_atomic_state *state);
diff --git a/include/drm/drm_atomic_uapi.h b/include/drm/drm_atomic_uapi.h
index 70a115d523cd..436315523326 100644
--- a/include/drm/drm_atomic_uapi.h
+++ b/include/drm/drm_atomic_uapi.h
@@ -50,6 +50,8 @@ drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
 			      struct drm_crtc *crtc);
 void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
 				 struct drm_framebuffer *fb);
+void drm_atomic_set_colorop_for_plane(struct drm_plane_state *plane_state,
+				      struct drm_colorop *colorop);
 int __must_check
 drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
 				  struct drm_crtc *crtc);
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index 2a9b902623c0..d6f514fe5d78 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -774,6 +774,14 @@ struct drm_plane {
 	 */
 	struct drm_property *color_range_property;
 
+	/**
+	 * @color_pipeline_property:
+	 *
+	 * Optional "COLOR_PIPELINE" enum property for specifying
+	 * a color pipeline to use on the plane.
+	 */
+	struct drm_property *color_pipeline_property;
+
 	/**
 	 * @scaling_filter_property: property to apply a particular filter while
 	 * scaling.
@@ -997,4 +1005,7 @@ int drm_plane_add_size_hints_property(struct drm_plane *plane,
 				      const struct drm_plane_size_hint *hints,
 				      int num_hints);
 
+int drm_plane_create_color_pipeline_property(struct drm_plane *plane,
+					     const struct drm_prop_enum_list *pipelines,
+					     const int num_pipelines);
 #endif
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 11/43] drm/colorop: Introduce DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (9 preceding siblings ...)
  2025-03-26 23:46 ` [PATCH V8 10/43] drm/plane: Add COLOR PIPELINE property Alex Hung
@ 2025-03-26 23:46 ` Alex Hung
  2025-03-29 14:37   ` Simon Ser
  2025-04-01  1:42   ` Shengyu Qu
  2025-03-26 23:46 ` [PATCH V8 12/43] Documentation/gpu: document drm_colorop Alex Hung
                   ` (32 subsequent siblings)
  43 siblings, 2 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:46 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

With the introduction of the pre-blending color pipeline we
can no longer have color operations that don't have a clear
position in the color pipeline. We deprecate all existing
plane properties. For upstream drivers those are:
 - COLOR_ENCODING
 - COLOR_RANGE

Drivers are expected to ignore these properties when
programming the HW. DRM clients that don't register with
DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE will not be allowed to
set the COLOR_ENCODING and COLOR_RANGE properties.

Setting of the COLOR_PIPELINE plane property or drm_colorop
properties is only allowed for userspace that sets this
client cap.

Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
v8:
 - Disallow setting of COLOR_RANGE and COLOR_ENCODING when
   DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE is set

v5:
 - Fix kernel docs

v4:
 - Don't block setting of COLOR_RANGE and COLOR_ENCODING
   when client cap is set


 drivers/gpu/drm/drm_atomic_uapi.c | 23 ++++++++++++++++++++++-
 drivers/gpu/drm/drm_ioctl.c       |  7 +++++++
 include/drm/drm_file.h            |  7 +++++++
 include/uapi/drm/drm.h            | 15 +++++++++++++++
 4 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index 5738b1c18755..e0b4b122ef6b 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -567,10 +567,26 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane,
 	} else if (property == plane->zpos_property) {
 		state->zpos = val;
 	} else if (property == plane->color_encoding_property) {
+		if (file_priv->plane_color_pipeline) {
+			drm_dbg_atomic(dev,
+				       "Setting COLOR_ENCODING plane property not permitted with DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE client cap\n");
+			return -EINVAL;
+		}
 		state->color_encoding = val;
 	} else if (property == plane->color_range_property) {
+		if (file_priv->plane_color_pipeline) {
+			drm_dbg_atomic(dev,
+				       "Setting COLOR_RANGE plane property not permitted with DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE client cap\n");
+			return -EINVAL;
+		}
 		state->color_range = val;
 	} else if (property == plane->color_pipeline_property) {
+		if (!file_priv->plane_color_pipeline) {
+			drm_dbg_atomic(dev,
+				       "Setting COLOR_PIPELINE plane property not permitted unless DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE is set\n");
+			return -EINVAL;
+		}
+
 		/* find DRM colorop object */
 		struct drm_colorop *colorop = NULL;
 
@@ -1197,6 +1213,12 @@ int drm_atomic_set_property(struct drm_atomic_state *state,
 		break;
 	}
 	case DRM_MODE_OBJECT_COLOROP: {
+		if (!file_priv->plane_color_pipeline) {
+			drm_dbg_atomic(prop->dev,
+				       "[OBJECT:%d] is a colorop but DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE not set\n",
+				       obj->id);
+			ret = -EINVAL;
+		}
 		struct drm_colorop *colorop = obj_to_colorop(obj);
 		struct drm_colorop_state *colorop_state;
 
@@ -1209,7 +1231,6 @@ int drm_atomic_set_property(struct drm_atomic_state *state,
 		ret = drm_atomic_colorop_set_property(colorop,
 				colorop_state, file_priv,
 				prop, prop_value);
-
 		break;
 	}
 	default:
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index f593dc569d31..5c89c586da7c 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -373,6 +373,13 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
 			return -EINVAL;
 		file_priv->supports_virtualized_cursor_plane = req->value;
 		break;
+	case DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE:
+		if (!file_priv->atomic)
+			return -EINVAL;
+		if (req->value > 1)
+			return -EINVAL;
+		file_priv->plane_color_pipeline = req->value;
+		break;
 	default:
 		return -EINVAL;
 	}
diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h
index 94d365b22505..86929ca667aa 100644
--- a/include/drm/drm_file.h
+++ b/include/drm/drm_file.h
@@ -206,6 +206,13 @@ struct drm_file {
 	 */
 	bool writeback_connectors;
 
+	/**
+	 * @plane_color_pipeline:
+	 *
+	 * True if client understands plane color pipelines
+	 */
+	bool plane_color_pipeline;
+
 	/**
 	 * @was_master:
 	 *
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index 7fba37b94401..3d12fbab066f 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -875,6 +875,21 @@ struct drm_get_cap {
  */
 #define DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT	6
 
+/**
+ * DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE
+ *
+ * If set to 1 the DRM core will allow setting the COLOR_PIPELINE
+ * property on a &drm_plane, as well as drm_colorop properties.
+ *
+ * Setting of these plane properties will be rejected when this client
+ * cap is set:
+ * - COLOR_ENCODING
+ * - COLOR_RANGE
+ *
+ * The client must enable &DRM_CLIENT_CAP_ATOMIC first.
+ */
+#define DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE	7
+
 /* DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */
 struct drm_set_client_cap {
 	__u64 capability;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 12/43] Documentation/gpu: document drm_colorop
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (10 preceding siblings ...)
  2025-03-26 23:46 ` [PATCH V8 11/43] drm/colorop: Introduce DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE Alex Hung
@ 2025-03-26 23:46 ` Alex Hung
  2025-03-29 14:40   ` Simon Ser
  2025-03-26 23:46 ` [PATCH V8 13/43] drm/vkms: Add enumerated 1D curve colorop Alex Hung
                   ` (31 subsequent siblings)
  43 siblings, 1 reply; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:46 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

Add kernel doc for drm_colorop objects.

Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
v8:
 - Move this after "drm/colorop: Introduce DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE" (Simon Ser)
 - Update DOC overview (Simon Ser)

v7:
 - Add a commit messages

v5:
 - Drop TODO

 Documentation/gpu/drm-kms.rst | 15 +++++++++++++++
 drivers/gpu/drm/drm_colorop.c | 31 +++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+)

diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index abfe220764e1..2292e65f044c 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -413,6 +413,21 @@ Plane Panic Functions Reference
 .. kernel-doc:: drivers/gpu/drm/drm_panic.c
    :export:
 
+Colorop Abstraction
+===================
+
+.. kernel-doc:: drivers/gpu/drm/drm_colorop.c
+   :doc: overview
+
+Colorop Functions Reference
+---------------------------
+
+.. kernel-doc:: include/drm/drm_colorop.h
+   :internal:
+
+.. kernel-doc:: drivers/gpu/drm/drm_colorop.c
+   :export:
+
 Display Modes Function Reference
 ================================
 
diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index 05de9bf118ed..a554c51fa7f5 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -31,6 +31,37 @@
 
 #include "drm_crtc_internal.h"
 
+/**
+ * DOC: overview
+ *
+ * When userspace signals the &DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE it
+ * should use the COLOR_PIPELINE plane property and associated colorops
+ * for any color operation on the &drm_plane. Setting of all old color
+ * properties, such as COLOR_ENCODING and COLOR_RANGE, will be rejected
+ * and the values of the properties will be ignored.
+ *
+ * Colorops are only advertised and valid for atomic drivers and atomic
+ * userspace that signals the &DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE
+ * client cap.
+ *
+ * A colorop represents a single color operation. Colorops are chained
+ * via the NEXT property and make up color pipelines. Color pipelines
+ * are advertised and selected via the COLOR_PIPELINE &drm_plane
+ * property.
+ *
+ * A colorop will be of a certain type, advertised by the read-only TYPE
+ * property. Each type of colorop will advertise a different set of
+ * properties and is programmed in a different manner. Types can be
+ * enumerated 1D curves, 1D LUTs, 3D LUTs, matrices, etc. See the
+ * &drm_colorop_type documentation for information on each type.
+ *
+ * If a colorop advertises the BYPASS property it can be bypassed.
+ *
+ * Information about colorop and color pipeline design decisions can be
+ * found at rfc/color_pipeline.rst, but note that this document will
+ * grow stale over time.
+ */
+
 static const struct drm_prop_enum_list drm_colorop_type_enum_list[] = {
 	{ DRM_COLOROP_1D_CURVE, "1D Curve" },
 };
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 13/43] drm/vkms: Add enumerated 1D curve colorop
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (11 preceding siblings ...)
  2025-03-26 23:46 ` [PATCH V8 12/43] Documentation/gpu: document drm_colorop Alex Hung
@ 2025-03-26 23:46 ` Alex Hung
  2025-03-26 23:46 ` [PATCH V8 14/43] drm/vkms: Add kunit tests for linear and sRGB LUTs Alex Hung
                   ` (30 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:46 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

This patch introduces a VKMS color pipeline that includes two
drm_colorops for named transfer functions. For now the only ones
supported are sRGB EOTF, sRGB Inverse EOTF, and a Linear TF.
We will expand this in the future but I don't want to do so
without accompanying IGT tests.

We introduce a new vkms_luts.c file that hard-codes sRGB EOTF,
sRGB Inverse EOTF, and a linear EOTF LUT. These have been
generated with 256 entries each as IGT is currently testing
only 8 bpc surfaces. We will likely need higher precision
but I'm reluctant to make that change without clear indication
that we need it. We'll revisit and, if necessary, regenerate
the LUTs when we have IGT tests for higher precision buffers.

Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
v8:
 - Replace DRM_ERROR by drm_err (Louis Chauvet)
 - Replace DRM_WARN_ONCE by drm_WARN_ONCE (Louis Chauvet)
 - Fix conflicts with upstream VKMS (Louis Chauvet)
 - Add comments for drm_color_lut linear_array (Louis Chauvet)

v7:
 - Fix checkpatch warnings (Louis Chauvet)
  - Change kzalloc(sizeof(struct drm_colorop) ...) to kzalloc(sizeof(*ops[i]) ...)
  - Remove if (ops[i]) before kfree(ops[i])
  - Fix styles by adding and removing spaces (new lines, tabs and so on)

v6:
 - drop 'len' var (Louis Chauvet)
 - cleanup if colorop alloc or init fails (Louis Chauvet)
 - switch loop in pre_blend_transform (Louis Chauvet)
 - drop extraneous if (colorop) inside while (colorop) (Louis Chauvet)

v5:
 - Squash with "Pull apply_colorop out of pre_blend_color_transform"
   (Sebastian)
 - Fix warnings
 - Fix include
 - Drop TODOs

v4:
 - Drop _tf_ from color_pipeline init function
 - Pass supported TFs into colorop init
 - Create bypass pipeline in DRM helper (Pekka)

v2:
 - Add commit description
 - Fix sRGB EOTF LUT definition
 - Add linear and sRGB inverse EOTF LUTs

 drivers/gpu/drm/vkms/Makefile        |   4 +-
 drivers/gpu/drm/vkms/vkms_colorop.c  |  82 +++
 drivers/gpu/drm/vkms/vkms_composer.c |  51 +-
 drivers/gpu/drm/vkms/vkms_drv.h      |   3 +
 drivers/gpu/drm/vkms/vkms_luts.c     | 808 +++++++++++++++++++++++++++
 drivers/gpu/drm/vkms/vkms_luts.h     |  12 +
 drivers/gpu/drm/vkms/vkms_plane.c    |   2 +
 7 files changed, 960 insertions(+), 2 deletions(-)
 create mode 100644 drivers/gpu/drm/vkms/vkms_colorop.c
 create mode 100644 drivers/gpu/drm/vkms/vkms_luts.c
 create mode 100644 drivers/gpu/drm/vkms/vkms_luts.h

diff --git a/drivers/gpu/drm/vkms/Makefile b/drivers/gpu/drm/vkms/Makefile
index 490b26d2e69d..357583fcb841 100644
--- a/drivers/gpu/drm/vkms/Makefile
+++ b/drivers/gpu/drm/vkms/Makefile
@@ -6,7 +6,9 @@ vkms-y := \
 	vkms_formats.o \
 	vkms_crtc.o \
 	vkms_composer.o \
-	vkms_writeback.o
+	vkms_writeback.o \
+	vkms_colorop.o \
+	vkms_luts.o
 
 obj-$(CONFIG_DRM_VKMS) += vkms.o
 obj-$(CONFIG_DRM_VKMS_KUNIT_TEST) += tests/
diff --git a/drivers/gpu/drm/vkms/vkms_colorop.c b/drivers/gpu/drm/vkms/vkms_colorop.c
new file mode 100644
index 000000000000..4fe22368c8e3
--- /dev/null
+++ b/drivers/gpu/drm/vkms/vkms_colorop.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <linux/slab.h>
+#include <drm/drm_colorop.h>
+#include <drm/drm_print.h>
+#include <drm/drm_property.h>
+#include <drm/drm_plane.h>
+
+#include "vkms_drv.h"
+
+static const u64 supported_tfs =
+	BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) |
+	BIT(DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF);
+
+#define MAX_COLOR_PIPELINE_OPS 2
+
+static int vkms_initialize_color_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list)
+{
+	struct drm_colorop *ops[MAX_COLOR_PIPELINE_OPS];
+	struct drm_device *dev = plane->dev;
+	int ret;
+	int i = 0;
+
+	memset(ops, 0, sizeof(ops));
+
+	/* 1st op: 1d curve */
+	ops[i] = kzalloc(sizeof(*ops[i]), GFP_KERNEL);
+	if (!ops[i]) {
+		drm_err(dev, "KMS: Failed to allocate colorop\n");
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	ret = drm_colorop_curve_1d_init(dev, ops[i], plane, supported_tfs);
+	if (ret)
+		goto cleanup;
+
+	list->type = ops[i]->base.id;
+	list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", ops[i]->base.id);
+
+	i++;
+
+	/* 2nd op: 1d curve */
+	ops[i] = kzalloc(sizeof(*ops[i]), GFP_KERNEL);
+	if (!ops[i]) {
+		drm_err(dev, "KMS: Failed to allocate colorop\n");
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	ret = drm_colorop_curve_1d_init(dev, ops[i], plane, supported_tfs);
+	if (ret)
+		goto cleanup;
+
+	drm_colorop_set_next_property(ops[i - 1], ops[i]);
+
+	return 0;
+
+cleanup:
+	for (; i >= 0; i--)
+		kfree(ops[i]);
+
+	return ret;
+}
+
+int vkms_initialize_colorops(struct drm_plane *plane)
+{
+	struct drm_prop_enum_list pipeline;
+	int ret;
+
+	/* Add color pipeline */
+	ret = vkms_initialize_color_pipeline(plane, &pipeline);
+	if (ret)
+		return ret;
+
+	/* Create COLOR_PIPELINE property and attach */
+	ret = drm_plane_create_color_pipeline_property(plane, &pipeline, 1);
+	if (ret)
+		return ret;
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c
index b0dc95f971d8..3ab829556db2 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -14,6 +14,7 @@
 #include "vkms_drv.h"
 #include <kunit/visibility.h>
 #include "vkms_composer.h"
+#include "vkms_luts.h"
 
 static u16 pre_mul_blend_channel(u16 src, u16 dst, u16 alpha)
 {
@@ -136,6 +137,54 @@ static void apply_lut(const struct vkms_crtc_state *crtc_state, struct line_buff
 	}
 }
 
+static void apply_colorop(struct pixel_argb_u16 *pixel, struct drm_colorop *colorop)
+{
+	struct drm_colorop_state *colorop_state = colorop->state;
+	struct drm_device *dev = colorop->dev;
+
+	if (colorop->type == DRM_COLOROP_1D_CURVE) {
+		switch (colorop_state->curve_1d_type) {
+		case DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF:
+			pixel->r = apply_lut_to_channel_value(&srgb_inv_eotf, pixel->r, LUT_RED);
+			pixel->g = apply_lut_to_channel_value(&srgb_inv_eotf, pixel->g, LUT_GREEN);
+			pixel->b = apply_lut_to_channel_value(&srgb_inv_eotf, pixel->b, LUT_BLUE);
+			break;
+		case DRM_COLOROP_1D_CURVE_SRGB_EOTF:
+			pixel->r = apply_lut_to_channel_value(&srgb_eotf, pixel->r, LUT_RED);
+			pixel->g = apply_lut_to_channel_value(&srgb_eotf, pixel->g, LUT_GREEN);
+			pixel->b = apply_lut_to_channel_value(&srgb_eotf, pixel->b, LUT_BLUE);
+			break;
+		default:
+			drm_WARN_ONCE(dev, true,
+				      "unknown colorop 1D curve type %d\n",
+				      colorop_state->curve_1d_type);
+			break;
+		}
+	}
+}
+
+static void pre_blend_color_transform(const struct vkms_plane_state *plane_state,
+				      struct line_buffer *output_buffer)
+{
+	for (size_t x = 0; x < output_buffer->n_pixels; x++) {
+		struct drm_colorop *colorop = plane_state->base.base.color_pipeline;
+
+		while (colorop) {
+			struct drm_colorop_state *colorop_state;
+
+			colorop_state = colorop->state;
+
+			if (!colorop_state)
+				return;
+
+			if (!colorop_state->bypass)
+				apply_colorop(&output_buffer->pixels[x], colorop);
+
+			colorop = colorop->next;
+		}
+	}
+}
+
 /**
  * direction_for_rotation() - Get the correct reading direction for a given rotation
  *
@@ -351,7 +400,7 @@ static void blend_line(struct vkms_plane_state *current_plane, int y,
 	 */
 	current_plane->pixel_read_line(current_plane, src_x_start, src_y_start, direction,
 				       pixel_count, &stage_buffer->pixels[dst_x_start]);
-
+	pre_blend_color_transform(current_plane, stage_buffer);
 	pre_mul_alpha_blend(stage_buffer, output_buffer,
 			    dst_x_start, pixel_count);
 }
diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
index abbb652be2b5..999625de0050 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.h
+++ b/drivers/gpu/drm/vkms/vkms_drv.h
@@ -276,4 +276,7 @@ void vkms_writeback_row(struct vkms_writeback_job *wb, const struct line_buffer
 /* Writeback */
 int vkms_enable_writeback_connector(struct vkms_device *vkmsdev, struct vkms_output *vkms_out);
 
+/* Colorops */
+int vkms_initialize_colorops(struct drm_plane *plane);
+
 #endif /* _VKMS_DRV_H_ */
diff --git a/drivers/gpu/drm/vkms/vkms_luts.c b/drivers/gpu/drm/vkms/vkms_luts.c
new file mode 100644
index 000000000000..7e8d3070deea
--- /dev/null
+++ b/drivers/gpu/drm/vkms/vkms_luts.c
@@ -0,0 +1,808 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <drm/drm_mode.h>
+
+#include "vkms_drv.h"
+#include "vkms_luts.h"
+
+/*
+ * These luts were generated with a LUT generated based on
+ * skia's transfer function code. The LUT generator can be
+ * found at
+ * https://gitlab.freedesktop.org/hwentland/lutgen
+ */
+
+static struct drm_color_lut linear_array[LUT_SIZE] = {
+	{ 0x0, 0x0, 0x0, 0 },
+	{ 0x101, 0x101, 0x101, 0 },
+	{ 0x202, 0x202, 0x202, 0 },
+	{ 0x303, 0x303, 0x303, 0 },
+	{ 0x404, 0x404, 0x404, 0 },
+	{ 0x505, 0x505, 0x505, 0 },
+	{ 0x606, 0x606, 0x606, 0 },
+	{ 0x707, 0x707, 0x707, 0 },
+	{ 0x808, 0x808, 0x808, 0 },
+	{ 0x909, 0x909, 0x909, 0 },
+	{ 0xa0a, 0xa0a, 0xa0a, 0 },
+	{ 0xb0b, 0xb0b, 0xb0b, 0 },
+	{ 0xc0c, 0xc0c, 0xc0c, 0 },
+	{ 0xd0d, 0xd0d, 0xd0d, 0 },
+	{ 0xe0e, 0xe0e, 0xe0e, 0 },
+	{ 0xf0f, 0xf0f, 0xf0f, 0 },
+	{ 0x1010, 0x1010, 0x1010, 0 },
+	{ 0x1111, 0x1111, 0x1111, 0 },
+	{ 0x1212, 0x1212, 0x1212, 0 },
+	{ 0x1313, 0x1313, 0x1313, 0 },
+	{ 0x1414, 0x1414, 0x1414, 0 },
+	{ 0x1515, 0x1515, 0x1515, 0 },
+	{ 0x1616, 0x1616, 0x1616, 0 },
+	{ 0x1717, 0x1717, 0x1717, 0 },
+	{ 0x1818, 0x1818, 0x1818, 0 },
+	{ 0x1919, 0x1919, 0x1919, 0 },
+	{ 0x1a1a, 0x1a1a, 0x1a1a, 0 },
+	{ 0x1b1b, 0x1b1b, 0x1b1b, 0 },
+	{ 0x1c1c, 0x1c1c, 0x1c1c, 0 },
+	{ 0x1d1d, 0x1d1d, 0x1d1d, 0 },
+	{ 0x1e1e, 0x1e1e, 0x1e1e, 0 },
+	{ 0x1f1f, 0x1f1f, 0x1f1f, 0 },
+	{ 0x2020, 0x2020, 0x2020, 0 },
+	{ 0x2121, 0x2121, 0x2121, 0 },
+	{ 0x2222, 0x2222, 0x2222, 0 },
+	{ 0x2323, 0x2323, 0x2323, 0 },
+	{ 0x2424, 0x2424, 0x2424, 0 },
+	{ 0x2525, 0x2525, 0x2525, 0 },
+	{ 0x2626, 0x2626, 0x2626, 0 },
+	{ 0x2727, 0x2727, 0x2727, 0 },
+	{ 0x2828, 0x2828, 0x2828, 0 },
+	{ 0x2929, 0x2929, 0x2929, 0 },
+	{ 0x2a2a, 0x2a2a, 0x2a2a, 0 },
+	{ 0x2b2b, 0x2b2b, 0x2b2b, 0 },
+	{ 0x2c2c, 0x2c2c, 0x2c2c, 0 },
+	{ 0x2d2d, 0x2d2d, 0x2d2d, 0 },
+	{ 0x2e2e, 0x2e2e, 0x2e2e, 0 },
+	{ 0x2f2f, 0x2f2f, 0x2f2f, 0 },
+	{ 0x3030, 0x3030, 0x3030, 0 },
+	{ 0x3131, 0x3131, 0x3131, 0 },
+	{ 0x3232, 0x3232, 0x3232, 0 },
+	{ 0x3333, 0x3333, 0x3333, 0 },
+	{ 0x3434, 0x3434, 0x3434, 0 },
+	{ 0x3535, 0x3535, 0x3535, 0 },
+	{ 0x3636, 0x3636, 0x3636, 0 },
+	{ 0x3737, 0x3737, 0x3737, 0 },
+	{ 0x3838, 0x3838, 0x3838, 0 },
+	{ 0x3939, 0x3939, 0x3939, 0 },
+	{ 0x3a3a, 0x3a3a, 0x3a3a, 0 },
+	{ 0x3b3b, 0x3b3b, 0x3b3b, 0 },
+	{ 0x3c3c, 0x3c3c, 0x3c3c, 0 },
+	{ 0x3d3d, 0x3d3d, 0x3d3d, 0 },
+	{ 0x3e3e, 0x3e3e, 0x3e3e, 0 },
+	{ 0x3f3f, 0x3f3f, 0x3f3f, 0 },
+	{ 0x4040, 0x4040, 0x4040, 0 },
+	{ 0x4141, 0x4141, 0x4141, 0 },
+	{ 0x4242, 0x4242, 0x4242, 0 },
+	{ 0x4343, 0x4343, 0x4343, 0 },
+	{ 0x4444, 0x4444, 0x4444, 0 },
+	{ 0x4545, 0x4545, 0x4545, 0 },
+	{ 0x4646, 0x4646, 0x4646, 0 },
+	{ 0x4747, 0x4747, 0x4747, 0 },
+	{ 0x4848, 0x4848, 0x4848, 0 },
+	{ 0x4949, 0x4949, 0x4949, 0 },
+	{ 0x4a4a, 0x4a4a, 0x4a4a, 0 },
+	{ 0x4b4b, 0x4b4b, 0x4b4b, 0 },
+	{ 0x4c4c, 0x4c4c, 0x4c4c, 0 },
+	{ 0x4d4d, 0x4d4d, 0x4d4d, 0 },
+	{ 0x4e4e, 0x4e4e, 0x4e4e, 0 },
+	{ 0x4f4f, 0x4f4f, 0x4f4f, 0 },
+	{ 0x5050, 0x5050, 0x5050, 0 },
+	{ 0x5151, 0x5151, 0x5151, 0 },
+	{ 0x5252, 0x5252, 0x5252, 0 },
+	{ 0x5353, 0x5353, 0x5353, 0 },
+	{ 0x5454, 0x5454, 0x5454, 0 },
+	{ 0x5555, 0x5555, 0x5555, 0 },
+	{ 0x5656, 0x5656, 0x5656, 0 },
+	{ 0x5757, 0x5757, 0x5757, 0 },
+	{ 0x5858, 0x5858, 0x5858, 0 },
+	{ 0x5959, 0x5959, 0x5959, 0 },
+	{ 0x5a5a, 0x5a5a, 0x5a5a, 0 },
+	{ 0x5b5b, 0x5b5b, 0x5b5b, 0 },
+	{ 0x5c5c, 0x5c5c, 0x5c5c, 0 },
+	{ 0x5d5d, 0x5d5d, 0x5d5d, 0 },
+	{ 0x5e5e, 0x5e5e, 0x5e5e, 0 },
+	{ 0x5f5f, 0x5f5f, 0x5f5f, 0 },
+	{ 0x6060, 0x6060, 0x6060, 0 },
+	{ 0x6161, 0x6161, 0x6161, 0 },
+	{ 0x6262, 0x6262, 0x6262, 0 },
+	{ 0x6363, 0x6363, 0x6363, 0 },
+	{ 0x6464, 0x6464, 0x6464, 0 },
+	{ 0x6565, 0x6565, 0x6565, 0 },
+	{ 0x6666, 0x6666, 0x6666, 0 },
+	{ 0x6767, 0x6767, 0x6767, 0 },
+	{ 0x6868, 0x6868, 0x6868, 0 },
+	{ 0x6969, 0x6969, 0x6969, 0 },
+	{ 0x6a6a, 0x6a6a, 0x6a6a, 0 },
+	{ 0x6b6b, 0x6b6b, 0x6b6b, 0 },
+	{ 0x6c6c, 0x6c6c, 0x6c6c, 0 },
+	{ 0x6d6d, 0x6d6d, 0x6d6d, 0 },
+	{ 0x6e6e, 0x6e6e, 0x6e6e, 0 },
+	{ 0x6f6f, 0x6f6f, 0x6f6f, 0 },
+	{ 0x7070, 0x7070, 0x7070, 0 },
+	{ 0x7171, 0x7171, 0x7171, 0 },
+	{ 0x7272, 0x7272, 0x7272, 0 },
+	{ 0x7373, 0x7373, 0x7373, 0 },
+	{ 0x7474, 0x7474, 0x7474, 0 },
+	{ 0x7575, 0x7575, 0x7575, 0 },
+	{ 0x7676, 0x7676, 0x7676, 0 },
+	{ 0x7777, 0x7777, 0x7777, 0 },
+	{ 0x7878, 0x7878, 0x7878, 0 },
+	{ 0x7979, 0x7979, 0x7979, 0 },
+	{ 0x7a7a, 0x7a7a, 0x7a7a, 0 },
+	{ 0x7b7b, 0x7b7b, 0x7b7b, 0 },
+	{ 0x7c7c, 0x7c7c, 0x7c7c, 0 },
+	{ 0x7d7d, 0x7d7d, 0x7d7d, 0 },
+	{ 0x7e7e, 0x7e7e, 0x7e7e, 0 },
+	{ 0x7f7f, 0x7f7f, 0x7f7f, 0 },
+	{ 0x8080, 0x8080, 0x8080, 0 },
+	{ 0x8181, 0x8181, 0x8181, 0 },
+	{ 0x8282, 0x8282, 0x8282, 0 },
+	{ 0x8383, 0x8383, 0x8383, 0 },
+	{ 0x8484, 0x8484, 0x8484, 0 },
+	{ 0x8585, 0x8585, 0x8585, 0 },
+	{ 0x8686, 0x8686, 0x8686, 0 },
+	{ 0x8787, 0x8787, 0x8787, 0 },
+	{ 0x8888, 0x8888, 0x8888, 0 },
+	{ 0x8989, 0x8989, 0x8989, 0 },
+	{ 0x8a8a, 0x8a8a, 0x8a8a, 0 },
+	{ 0x8b8b, 0x8b8b, 0x8b8b, 0 },
+	{ 0x8c8c, 0x8c8c, 0x8c8c, 0 },
+	{ 0x8d8d, 0x8d8d, 0x8d8d, 0 },
+	{ 0x8e8e, 0x8e8e, 0x8e8e, 0 },
+	{ 0x8f8f, 0x8f8f, 0x8f8f, 0 },
+	{ 0x9090, 0x9090, 0x9090, 0 },
+	{ 0x9191, 0x9191, 0x9191, 0 },
+	{ 0x9292, 0x9292, 0x9292, 0 },
+	{ 0x9393, 0x9393, 0x9393, 0 },
+	{ 0x9494, 0x9494, 0x9494, 0 },
+	{ 0x9595, 0x9595, 0x9595, 0 },
+	{ 0x9696, 0x9696, 0x9696, 0 },
+	{ 0x9797, 0x9797, 0x9797, 0 },
+	{ 0x9898, 0x9898, 0x9898, 0 },
+	{ 0x9999, 0x9999, 0x9999, 0 },
+	{ 0x9a9a, 0x9a9a, 0x9a9a, 0 },
+	{ 0x9b9b, 0x9b9b, 0x9b9b, 0 },
+	{ 0x9c9c, 0x9c9c, 0x9c9c, 0 },
+	{ 0x9d9d, 0x9d9d, 0x9d9d, 0 },
+	{ 0x9e9e, 0x9e9e, 0x9e9e, 0 },
+	{ 0x9f9f, 0x9f9f, 0x9f9f, 0 },
+	{ 0xa0a0, 0xa0a0, 0xa0a0, 0 },
+	{ 0xa1a1, 0xa1a1, 0xa1a1, 0 },
+	{ 0xa2a2, 0xa2a2, 0xa2a2, 0 },
+	{ 0xa3a3, 0xa3a3, 0xa3a3, 0 },
+	{ 0xa4a4, 0xa4a4, 0xa4a4, 0 },
+	{ 0xa5a5, 0xa5a5, 0xa5a5, 0 },
+	{ 0xa6a6, 0xa6a6, 0xa6a6, 0 },
+	{ 0xa7a7, 0xa7a7, 0xa7a7, 0 },
+	{ 0xa8a8, 0xa8a8, 0xa8a8, 0 },
+	{ 0xa9a9, 0xa9a9, 0xa9a9, 0 },
+	{ 0xaaaa, 0xaaaa, 0xaaaa, 0 },
+	{ 0xabab, 0xabab, 0xabab, 0 },
+	{ 0xacac, 0xacac, 0xacac, 0 },
+	{ 0xadad, 0xadad, 0xadad, 0 },
+	{ 0xaeae, 0xaeae, 0xaeae, 0 },
+	{ 0xafaf, 0xafaf, 0xafaf, 0 },
+	{ 0xb0b0, 0xb0b0, 0xb0b0, 0 },
+	{ 0xb1b1, 0xb1b1, 0xb1b1, 0 },
+	{ 0xb2b2, 0xb2b2, 0xb2b2, 0 },
+	{ 0xb3b3, 0xb3b3, 0xb3b3, 0 },
+	{ 0xb4b4, 0xb4b4, 0xb4b4, 0 },
+	{ 0xb5b5, 0xb5b5, 0xb5b5, 0 },
+	{ 0xb6b6, 0xb6b6, 0xb6b6, 0 },
+	{ 0xb7b7, 0xb7b7, 0xb7b7, 0 },
+	{ 0xb8b8, 0xb8b8, 0xb8b8, 0 },
+	{ 0xb9b9, 0xb9b9, 0xb9b9, 0 },
+	{ 0xbaba, 0xbaba, 0xbaba, 0 },
+	{ 0xbbbb, 0xbbbb, 0xbbbb, 0 },
+	{ 0xbcbc, 0xbcbc, 0xbcbc, 0 },
+	{ 0xbdbd, 0xbdbd, 0xbdbd, 0 },
+	{ 0xbebe, 0xbebe, 0xbebe, 0 },
+	{ 0xbfbf, 0xbfbf, 0xbfbf, 0 },
+	{ 0xc0c0, 0xc0c0, 0xc0c0, 0 },
+	{ 0xc1c1, 0xc1c1, 0xc1c1, 0 },
+	{ 0xc2c2, 0xc2c2, 0xc2c2, 0 },
+	{ 0xc3c3, 0xc3c3, 0xc3c3, 0 },
+	{ 0xc4c4, 0xc4c4, 0xc4c4, 0 },
+	{ 0xc5c5, 0xc5c5, 0xc5c5, 0 },
+	{ 0xc6c6, 0xc6c6, 0xc6c6, 0 },
+	{ 0xc7c7, 0xc7c7, 0xc7c7, 0 },
+	{ 0xc8c8, 0xc8c8, 0xc8c8, 0 },
+	{ 0xc9c9, 0xc9c9, 0xc9c9, 0 },
+	{ 0xcaca, 0xcaca, 0xcaca, 0 },
+	{ 0xcbcb, 0xcbcb, 0xcbcb, 0 },
+	{ 0xcccc, 0xcccc, 0xcccc, 0 },
+	{ 0xcdcd, 0xcdcd, 0xcdcd, 0 },
+	{ 0xcece, 0xcece, 0xcece, 0 },
+	{ 0xcfcf, 0xcfcf, 0xcfcf, 0 },
+	{ 0xd0d0, 0xd0d0, 0xd0d0, 0 },
+	{ 0xd1d1, 0xd1d1, 0xd1d1, 0 },
+	{ 0xd2d2, 0xd2d2, 0xd2d2, 0 },
+	{ 0xd3d3, 0xd3d3, 0xd3d3, 0 },
+	{ 0xd4d4, 0xd4d4, 0xd4d4, 0 },
+	{ 0xd5d5, 0xd5d5, 0xd5d5, 0 },
+	{ 0xd6d6, 0xd6d6, 0xd6d6, 0 },
+	{ 0xd7d7, 0xd7d7, 0xd7d7, 0 },
+	{ 0xd8d8, 0xd8d8, 0xd8d8, 0 },
+	{ 0xd9d9, 0xd9d9, 0xd9d9, 0 },
+	{ 0xdada, 0xdada, 0xdada, 0 },
+	{ 0xdbdb, 0xdbdb, 0xdbdb, 0 },
+	{ 0xdcdc, 0xdcdc, 0xdcdc, 0 },
+	{ 0xdddd, 0xdddd, 0xdddd, 0 },
+	{ 0xdede, 0xdede, 0xdede, 0 },
+	{ 0xdfdf, 0xdfdf, 0xdfdf, 0 },
+	{ 0xe0e0, 0xe0e0, 0xe0e0, 0 },
+	{ 0xe1e1, 0xe1e1, 0xe1e1, 0 },
+	{ 0xe2e2, 0xe2e2, 0xe2e2, 0 },
+	{ 0xe3e3, 0xe3e3, 0xe3e3, 0 },
+	{ 0xe4e4, 0xe4e4, 0xe4e4, 0 },
+	{ 0xe5e5, 0xe5e5, 0xe5e5, 0 },
+	{ 0xe6e6, 0xe6e6, 0xe6e6, 0 },
+	{ 0xe7e7, 0xe7e7, 0xe7e7, 0 },
+	{ 0xe8e8, 0xe8e8, 0xe8e8, 0 },
+	{ 0xe9e9, 0xe9e9, 0xe9e9, 0 },
+	{ 0xeaea, 0xeaea, 0xeaea, 0 },
+	{ 0xebeb, 0xebeb, 0xebeb, 0 },
+	{ 0xecec, 0xecec, 0xecec, 0 },
+	{ 0xeded, 0xeded, 0xeded, 0 },
+	{ 0xeeee, 0xeeee, 0xeeee, 0 },
+	{ 0xefef, 0xefef, 0xefef, 0 },
+	{ 0xf0f0, 0xf0f0, 0xf0f0, 0 },
+	{ 0xf1f1, 0xf1f1, 0xf1f1, 0 },
+	{ 0xf2f2, 0xf2f2, 0xf2f2, 0 },
+	{ 0xf3f3, 0xf3f3, 0xf3f3, 0 },
+	{ 0xf4f4, 0xf4f4, 0xf4f4, 0 },
+	{ 0xf5f5, 0xf5f5, 0xf5f5, 0 },
+	{ 0xf6f6, 0xf6f6, 0xf6f6, 0 },
+	{ 0xf7f7, 0xf7f7, 0xf7f7, 0 },
+	{ 0xf8f8, 0xf8f8, 0xf8f8, 0 },
+	{ 0xf9f9, 0xf9f9, 0xf9f9, 0 },
+	{ 0xfafa, 0xfafa, 0xfafa, 0 },
+	{ 0xfbfb, 0xfbfb, 0xfbfb, 0 },
+	{ 0xfcfc, 0xfcfc, 0xfcfc, 0 },
+	{ 0xfdfd, 0xfdfd, 0xfdfd, 0 },
+	{ 0xfefe, 0xfefe, 0xfefe, 0 },
+	{ 0xffff, 0xffff, 0xffff, 0 },
+};
+
+const struct vkms_color_lut linear_eotf = {
+	.base = linear_array,
+	.lut_length = LUT_SIZE,
+	.channel_value2index_ratio = 0xff00ffll
+};
+
+static struct drm_color_lut srgb_array[LUT_SIZE] = {
+	{ 0x0, 0x0, 0x0, 0 },
+	{ 0x13, 0x13, 0x13, 0 },
+	{ 0x27, 0x27, 0x27, 0 },
+	{ 0x3b, 0x3b, 0x3b, 0 },
+	{ 0x4f, 0x4f, 0x4f, 0 },
+	{ 0x63, 0x63, 0x63, 0 },
+	{ 0x77, 0x77, 0x77, 0 },
+	{ 0x8b, 0x8b, 0x8b, 0 },
+	{ 0x9f, 0x9f, 0x9f, 0 },
+	{ 0xb3, 0xb3, 0xb3, 0 },
+	{ 0xc6, 0xc6, 0xc6, 0 },
+	{ 0xdb, 0xdb, 0xdb, 0 },
+	{ 0xf0, 0xf0, 0xf0, 0 },
+	{ 0x107, 0x107, 0x107, 0 },
+	{ 0x11f, 0x11f, 0x11f, 0 },
+	{ 0x139, 0x139, 0x139, 0 },
+	{ 0x153, 0x153, 0x153, 0 },
+	{ 0x16f, 0x16f, 0x16f, 0 },
+	{ 0x18c, 0x18c, 0x18c, 0 },
+	{ 0x1aa, 0x1aa, 0x1aa, 0 },
+	{ 0x1ca, 0x1ca, 0x1ca, 0 },
+	{ 0x1eb, 0x1eb, 0x1eb, 0 },
+	{ 0x20d, 0x20d, 0x20d, 0 },
+	{ 0x231, 0x231, 0x231, 0 },
+	{ 0x256, 0x256, 0x256, 0 },
+	{ 0x27d, 0x27d, 0x27d, 0 },
+	{ 0x2a4, 0x2a4, 0x2a4, 0 },
+	{ 0x2ce, 0x2ce, 0x2ce, 0 },
+	{ 0x2f9, 0x2f9, 0x2f9, 0 },
+	{ 0x325, 0x325, 0x325, 0 },
+	{ 0x352, 0x352, 0x352, 0 },
+	{ 0x381, 0x381, 0x381, 0 },
+	{ 0x3b2, 0x3b2, 0x3b2, 0 },
+	{ 0x3e4, 0x3e4, 0x3e4, 0 },
+	{ 0x418, 0x418, 0x418, 0 },
+	{ 0x44d, 0x44d, 0x44d, 0 },
+	{ 0x484, 0x484, 0x484, 0 },
+	{ 0x4bc, 0x4bc, 0x4bc, 0 },
+	{ 0x4f6, 0x4f6, 0x4f6, 0 },
+	{ 0x531, 0x531, 0x531, 0 },
+	{ 0x56e, 0x56e, 0x56e, 0 },
+	{ 0x5ad, 0x5ad, 0x5ad, 0 },
+	{ 0x5ed, 0x5ed, 0x5ed, 0 },
+	{ 0x62f, 0x62f, 0x62f, 0 },
+	{ 0x672, 0x672, 0x672, 0 },
+	{ 0x6b7, 0x6b7, 0x6b7, 0 },
+	{ 0x6fe, 0x6fe, 0x6fe, 0 },
+	{ 0x746, 0x746, 0x746, 0 },
+	{ 0x791, 0x791, 0x791, 0 },
+	{ 0x7dc, 0x7dc, 0x7dc, 0 },
+	{ 0x82a, 0x82a, 0x82a, 0 },
+	{ 0x879, 0x879, 0x879, 0 },
+	{ 0x8ca, 0x8ca, 0x8ca, 0 },
+	{ 0x91d, 0x91d, 0x91d, 0 },
+	{ 0x971, 0x971, 0x971, 0 },
+	{ 0x9c7, 0x9c7, 0x9c7, 0 },
+	{ 0xa1f, 0xa1f, 0xa1f, 0 },
+	{ 0xa79, 0xa79, 0xa79, 0 },
+	{ 0xad4, 0xad4, 0xad4, 0 },
+	{ 0xb32, 0xb32, 0xb32, 0 },
+	{ 0xb91, 0xb91, 0xb91, 0 },
+	{ 0xbf2, 0xbf2, 0xbf2, 0 },
+	{ 0xc54, 0xc54, 0xc54, 0 },
+	{ 0xcb9, 0xcb9, 0xcb9, 0 },
+	{ 0xd1f, 0xd1f, 0xd1f, 0 },
+	{ 0xd88, 0xd88, 0xd88, 0 },
+	{ 0xdf2, 0xdf2, 0xdf2, 0 },
+	{ 0xe5e, 0xe5e, 0xe5e, 0 },
+	{ 0xecc, 0xecc, 0xecc, 0 },
+	{ 0xf3c, 0xf3c, 0xf3c, 0 },
+	{ 0xfad, 0xfad, 0xfad, 0 },
+	{ 0x1021, 0x1021, 0x1021, 0 },
+	{ 0x1096, 0x1096, 0x1096, 0 },
+	{ 0x110e, 0x110e, 0x110e, 0 },
+	{ 0x1187, 0x1187, 0x1187, 0 },
+	{ 0x1203, 0x1203, 0x1203, 0 },
+	{ 0x1280, 0x1280, 0x1280, 0 },
+	{ 0x12ff, 0x12ff, 0x12ff, 0 },
+	{ 0x1380, 0x1380, 0x1380, 0 },
+	{ 0x1404, 0x1404, 0x1404, 0 },
+	{ 0x1489, 0x1489, 0x1489, 0 },
+	{ 0x1510, 0x1510, 0x1510, 0 },
+	{ 0x1599, 0x1599, 0x1599, 0 },
+	{ 0x1624, 0x1624, 0x1624, 0 },
+	{ 0x16b2, 0x16b2, 0x16b2, 0 },
+	{ 0x1741, 0x1741, 0x1741, 0 },
+	{ 0x17d2, 0x17d2, 0x17d2, 0 },
+	{ 0x1865, 0x1865, 0x1865, 0 },
+	{ 0x18fb, 0x18fb, 0x18fb, 0 },
+	{ 0x1992, 0x1992, 0x1992, 0 },
+	{ 0x1a2c, 0x1a2c, 0x1a2c, 0 },
+	{ 0x1ac8, 0x1ac8, 0x1ac8, 0 },
+	{ 0x1b65, 0x1b65, 0x1b65, 0 },
+	{ 0x1c05, 0x1c05, 0x1c05, 0 },
+	{ 0x1ca7, 0x1ca7, 0x1ca7, 0 },
+	{ 0x1d4b, 0x1d4b, 0x1d4b, 0 },
+	{ 0x1df1, 0x1df1, 0x1df1, 0 },
+	{ 0x1e99, 0x1e99, 0x1e99, 0 },
+	{ 0x1f44, 0x1f44, 0x1f44, 0 },
+	{ 0x1ff0, 0x1ff0, 0x1ff0, 0 },
+	{ 0x209f, 0x209f, 0x209f, 0 },
+	{ 0x2150, 0x2150, 0x2150, 0 },
+	{ 0x2203, 0x2203, 0x2203, 0 },
+	{ 0x22b8, 0x22b8, 0x22b8, 0 },
+	{ 0x2370, 0x2370, 0x2370, 0 },
+	{ 0x2429, 0x2429, 0x2429, 0 },
+	{ 0x24e5, 0x24e5, 0x24e5, 0 },
+	{ 0x25a3, 0x25a3, 0x25a3, 0 },
+	{ 0x2663, 0x2663, 0x2663, 0 },
+	{ 0x2726, 0x2726, 0x2726, 0 },
+	{ 0x27ea, 0x27ea, 0x27ea, 0 },
+	{ 0x28b1, 0x28b1, 0x28b1, 0 },
+	{ 0x297a, 0x297a, 0x297a, 0 },
+	{ 0x2a45, 0x2a45, 0x2a45, 0 },
+	{ 0x2b13, 0x2b13, 0x2b13, 0 },
+	{ 0x2be3, 0x2be3, 0x2be3, 0 },
+	{ 0x2cb5, 0x2cb5, 0x2cb5, 0 },
+	{ 0x2d89, 0x2d89, 0x2d89, 0 },
+	{ 0x2e60, 0x2e60, 0x2e60, 0 },
+	{ 0x2f39, 0x2f39, 0x2f39, 0 },
+	{ 0x3014, 0x3014, 0x3014, 0 },
+	{ 0x30f2, 0x30f2, 0x30f2, 0 },
+	{ 0x31d2, 0x31d2, 0x31d2, 0 },
+	{ 0x32b4, 0x32b4, 0x32b4, 0 },
+	{ 0x3398, 0x3398, 0x3398, 0 },
+	{ 0x347f, 0x347f, 0x347f, 0 },
+	{ 0x3569, 0x3569, 0x3569, 0 },
+	{ 0x3654, 0x3654, 0x3654, 0 },
+	{ 0x3742, 0x3742, 0x3742, 0 },
+	{ 0x3832, 0x3832, 0x3832, 0 },
+	{ 0x3925, 0x3925, 0x3925, 0 },
+	{ 0x3a1a, 0x3a1a, 0x3a1a, 0 },
+	{ 0x3b11, 0x3b11, 0x3b11, 0 },
+	{ 0x3c0b, 0x3c0b, 0x3c0b, 0 },
+	{ 0x3d07, 0x3d07, 0x3d07, 0 },
+	{ 0x3e05, 0x3e05, 0x3e05, 0 },
+	{ 0x3f06, 0x3f06, 0x3f06, 0 },
+	{ 0x400a, 0x400a, 0x400a, 0 },
+	{ 0x410f, 0x410f, 0x410f, 0 },
+	{ 0x4218, 0x4218, 0x4218, 0 },
+	{ 0x4322, 0x4322, 0x4322, 0 },
+	{ 0x442f, 0x442f, 0x442f, 0 },
+	{ 0x453f, 0x453f, 0x453f, 0 },
+	{ 0x4650, 0x4650, 0x4650, 0 },
+	{ 0x4765, 0x4765, 0x4765, 0 },
+	{ 0x487c, 0x487c, 0x487c, 0 },
+	{ 0x4995, 0x4995, 0x4995, 0 },
+	{ 0x4ab1, 0x4ab1, 0x4ab1, 0 },
+	{ 0x4bcf, 0x4bcf, 0x4bcf, 0 },
+	{ 0x4cf0, 0x4cf0, 0x4cf0, 0 },
+	{ 0x4e13, 0x4e13, 0x4e13, 0 },
+	{ 0x4f39, 0x4f39, 0x4f39, 0 },
+	{ 0x5061, 0x5061, 0x5061, 0 },
+	{ 0x518b, 0x518b, 0x518b, 0 },
+	{ 0x52b9, 0x52b9, 0x52b9, 0 },
+	{ 0x53e8, 0x53e8, 0x53e8, 0 },
+	{ 0x551b, 0x551b, 0x551b, 0 },
+	{ 0x5650, 0x5650, 0x5650, 0 },
+	{ 0x5787, 0x5787, 0x5787, 0 },
+	{ 0x58c1, 0x58c1, 0x58c1, 0 },
+	{ 0x59fd, 0x59fd, 0x59fd, 0 },
+	{ 0x5b3c, 0x5b3c, 0x5b3c, 0 },
+	{ 0x5c7e, 0x5c7e, 0x5c7e, 0 },
+	{ 0x5dc2, 0x5dc2, 0x5dc2, 0 },
+	{ 0x5f09, 0x5f09, 0x5f09, 0 },
+	{ 0x6052, 0x6052, 0x6052, 0 },
+	{ 0x619e, 0x619e, 0x619e, 0 },
+	{ 0x62ec, 0x62ec, 0x62ec, 0 },
+	{ 0x643d, 0x643d, 0x643d, 0 },
+	{ 0x6591, 0x6591, 0x6591, 0 },
+	{ 0x66e7, 0x66e7, 0x66e7, 0 },
+	{ 0x6840, 0x6840, 0x6840, 0 },
+	{ 0x699b, 0x699b, 0x699b, 0 },
+	{ 0x6afa, 0x6afa, 0x6afa, 0 },
+	{ 0x6c5a, 0x6c5a, 0x6c5a, 0 },
+	{ 0x6dbe, 0x6dbe, 0x6dbe, 0 },
+	{ 0x6f24, 0x6f24, 0x6f24, 0 },
+	{ 0x708c, 0x708c, 0x708c, 0 },
+	{ 0x71f8, 0x71f8, 0x71f8, 0 },
+	{ 0x7366, 0x7366, 0x7366, 0 },
+	{ 0x74d6, 0x74d6, 0x74d6, 0 },
+	{ 0x764a, 0x764a, 0x764a, 0 },
+	{ 0x77c0, 0x77c0, 0x77c0, 0 },
+	{ 0x7938, 0x7938, 0x7938, 0 },
+	{ 0x7ab4, 0x7ab4, 0x7ab4, 0 },
+	{ 0x7c32, 0x7c32, 0x7c32, 0 },
+	{ 0x7db3, 0x7db3, 0x7db3, 0 },
+	{ 0x7f36, 0x7f36, 0x7f36, 0 },
+	{ 0x80bc, 0x80bc, 0x80bc, 0 },
+	{ 0x8245, 0x8245, 0x8245, 0 },
+	{ 0x83d1, 0x83d1, 0x83d1, 0 },
+	{ 0x855f, 0x855f, 0x855f, 0 },
+	{ 0x86f0, 0x86f0, 0x86f0, 0 },
+	{ 0x8884, 0x8884, 0x8884, 0 },
+	{ 0x8a1a, 0x8a1a, 0x8a1a, 0 },
+	{ 0x8bb4, 0x8bb4, 0x8bb4, 0 },
+	{ 0x8d50, 0x8d50, 0x8d50, 0 },
+	{ 0x8eee, 0x8eee, 0x8eee, 0 },
+	{ 0x9090, 0x9090, 0x9090, 0 },
+	{ 0x9234, 0x9234, 0x9234, 0 },
+	{ 0x93db, 0x93db, 0x93db, 0 },
+	{ 0x9585, 0x9585, 0x9585, 0 },
+	{ 0x9732, 0x9732, 0x9732, 0 },
+	{ 0x98e1, 0x98e1, 0x98e1, 0 },
+	{ 0x9a93, 0x9a93, 0x9a93, 0 },
+	{ 0x9c48, 0x9c48, 0x9c48, 0 },
+	{ 0x9e00, 0x9e00, 0x9e00, 0 },
+	{ 0x9fbb, 0x9fbb, 0x9fbb, 0 },
+	{ 0xa178, 0xa178, 0xa178, 0 },
+	{ 0xa338, 0xa338, 0xa338, 0 },
+	{ 0xa4fb, 0xa4fb, 0xa4fb, 0 },
+	{ 0xa6c1, 0xa6c1, 0xa6c1, 0 },
+	{ 0xa88a, 0xa88a, 0xa88a, 0 },
+	{ 0xaa56, 0xaa56, 0xaa56, 0 },
+	{ 0xac24, 0xac24, 0xac24, 0 },
+	{ 0xadf5, 0xadf5, 0xadf5, 0 },
+	{ 0xafc9, 0xafc9, 0xafc9, 0 },
+	{ 0xb1a0, 0xb1a0, 0xb1a0, 0 },
+	{ 0xb37a, 0xb37a, 0xb37a, 0 },
+	{ 0xb557, 0xb557, 0xb557, 0 },
+	{ 0xb736, 0xb736, 0xb736, 0 },
+	{ 0xb919, 0xb919, 0xb919, 0 },
+	{ 0xbafe, 0xbafe, 0xbafe, 0 },
+	{ 0xbce6, 0xbce6, 0xbce6, 0 },
+	{ 0xbed2, 0xbed2, 0xbed2, 0 },
+	{ 0xc0c0, 0xc0c0, 0xc0c0, 0 },
+	{ 0xc2b0, 0xc2b0, 0xc2b0, 0 },
+	{ 0xc4a4, 0xc4a4, 0xc4a4, 0 },
+	{ 0xc69b, 0xc69b, 0xc69b, 0 },
+	{ 0xc895, 0xc895, 0xc895, 0 },
+	{ 0xca91, 0xca91, 0xca91, 0 },
+	{ 0xcc91, 0xcc91, 0xcc91, 0 },
+	{ 0xce93, 0xce93, 0xce93, 0 },
+	{ 0xd098, 0xd098, 0xd098, 0 },
+	{ 0xd2a1, 0xd2a1, 0xd2a1, 0 },
+	{ 0xd4ac, 0xd4ac, 0xd4ac, 0 },
+	{ 0xd6ba, 0xd6ba, 0xd6ba, 0 },
+	{ 0xd8cb, 0xd8cb, 0xd8cb, 0 },
+	{ 0xdadf, 0xdadf, 0xdadf, 0 },
+	{ 0xdcf7, 0xdcf7, 0xdcf7, 0 },
+	{ 0xdf11, 0xdf11, 0xdf11, 0 },
+	{ 0xe12e, 0xe12e, 0xe12e, 0 },
+	{ 0xe34e, 0xe34e, 0xe34e, 0 },
+	{ 0xe571, 0xe571, 0xe571, 0 },
+	{ 0xe796, 0xe796, 0xe796, 0 },
+	{ 0xe9bf, 0xe9bf, 0xe9bf, 0 },
+	{ 0xebeb, 0xebeb, 0xebeb, 0 },
+	{ 0xee1a, 0xee1a, 0xee1a, 0 },
+	{ 0xf04c, 0xf04c, 0xf04c, 0 },
+	{ 0xf281, 0xf281, 0xf281, 0 },
+	{ 0xf4b9, 0xf4b9, 0xf4b9, 0 },
+	{ 0xf6f4, 0xf6f4, 0xf6f4, 0 },
+	{ 0xf932, 0xf932, 0xf932, 0 },
+	{ 0xfb73, 0xfb73, 0xfb73, 0 },
+	{ 0xfdb7, 0xfdb7, 0xfdb7, 0 },
+	{ 0xffff, 0xffff, 0xffff, 0 },
+};
+
+const struct vkms_color_lut srgb_eotf = {
+	.base = srgb_array,
+	.lut_length = LUT_SIZE,
+	.channel_value2index_ratio = 0xff00ffll
+};
+
+static struct drm_color_lut srgb_inv_array[LUT_SIZE] = {
+	{ 0x0, 0x0, 0x0, 0 },
+	{ 0xcc2, 0xcc2, 0xcc2, 0 },
+	{ 0x15be, 0x15be, 0x15be, 0 },
+	{ 0x1c56, 0x1c56, 0x1c56, 0 },
+	{ 0x21bd, 0x21bd, 0x21bd, 0 },
+	{ 0x2666, 0x2666, 0x2666, 0 },
+	{ 0x2a8a, 0x2a8a, 0x2a8a, 0 },
+	{ 0x2e4c, 0x2e4c, 0x2e4c, 0 },
+	{ 0x31c0, 0x31c0, 0x31c0, 0 },
+	{ 0x34f6, 0x34f6, 0x34f6, 0 },
+	{ 0x37f9, 0x37f9, 0x37f9, 0 },
+	{ 0x3acf, 0x3acf, 0x3acf, 0 },
+	{ 0x3d80, 0x3d80, 0x3d80, 0 },
+	{ 0x4010, 0x4010, 0x4010, 0 },
+	{ 0x4284, 0x4284, 0x4284, 0 },
+	{ 0x44dd, 0x44dd, 0x44dd, 0 },
+	{ 0x4720, 0x4720, 0x4720, 0 },
+	{ 0x494e, 0x494e, 0x494e, 0 },
+	{ 0x4b69, 0x4b69, 0x4b69, 0 },
+	{ 0x4d73, 0x4d73, 0x4d73, 0 },
+	{ 0x4f6e, 0x4f6e, 0x4f6e, 0 },
+	{ 0x5159, 0x5159, 0x5159, 0 },
+	{ 0x5337, 0x5337, 0x5337, 0 },
+	{ 0x5509, 0x5509, 0x5509, 0 },
+	{ 0x56cf, 0x56cf, 0x56cf, 0 },
+	{ 0x588a, 0x588a, 0x588a, 0 },
+	{ 0x5a3b, 0x5a3b, 0x5a3b, 0 },
+	{ 0x5be2, 0x5be2, 0x5be2, 0 },
+	{ 0x5d80, 0x5d80, 0x5d80, 0 },
+	{ 0x5f16, 0x5f16, 0x5f16, 0 },
+	{ 0x60a4, 0x60a4, 0x60a4, 0 },
+	{ 0x6229, 0x6229, 0x6229, 0 },
+	{ 0x63a8, 0x63a8, 0x63a8, 0 },
+	{ 0x6520, 0x6520, 0x6520, 0 },
+	{ 0x6691, 0x6691, 0x6691, 0 },
+	{ 0x67fc, 0x67fc, 0x67fc, 0 },
+	{ 0x6961, 0x6961, 0x6961, 0 },
+	{ 0x6ac0, 0x6ac0, 0x6ac0, 0 },
+	{ 0x6c19, 0x6c19, 0x6c19, 0 },
+	{ 0x6d6e, 0x6d6e, 0x6d6e, 0 },
+	{ 0x6ebd, 0x6ebd, 0x6ebd, 0 },
+	{ 0x7008, 0x7008, 0x7008, 0 },
+	{ 0x714d, 0x714d, 0x714d, 0 },
+	{ 0x728f, 0x728f, 0x728f, 0 },
+	{ 0x73cc, 0x73cc, 0x73cc, 0 },
+	{ 0x7504, 0x7504, 0x7504, 0 },
+	{ 0x7639, 0x7639, 0x7639, 0 },
+	{ 0x776a, 0x776a, 0x776a, 0 },
+	{ 0x7897, 0x7897, 0x7897, 0 },
+	{ 0x79c1, 0x79c1, 0x79c1, 0 },
+	{ 0x7ae7, 0x7ae7, 0x7ae7, 0 },
+	{ 0x7c09, 0x7c09, 0x7c09, 0 },
+	{ 0x7d28, 0x7d28, 0x7d28, 0 },
+	{ 0x7e44, 0x7e44, 0x7e44, 0 },
+	{ 0x7f5d, 0x7f5d, 0x7f5d, 0 },
+	{ 0x8073, 0x8073, 0x8073, 0 },
+	{ 0x8186, 0x8186, 0x8186, 0 },
+	{ 0x8296, 0x8296, 0x8296, 0 },
+	{ 0x83a4, 0x83a4, 0x83a4, 0 },
+	{ 0x84ae, 0x84ae, 0x84ae, 0 },
+	{ 0x85b6, 0x85b6, 0x85b6, 0 },
+	{ 0x86bc, 0x86bc, 0x86bc, 0 },
+	{ 0x87bf, 0x87bf, 0x87bf, 0 },
+	{ 0x88bf, 0x88bf, 0x88bf, 0 },
+	{ 0x89be, 0x89be, 0x89be, 0 },
+	{ 0x8ab9, 0x8ab9, 0x8ab9, 0 },
+	{ 0x8bb3, 0x8bb3, 0x8bb3, 0 },
+	{ 0x8cab, 0x8cab, 0x8cab, 0 },
+	{ 0x8da0, 0x8da0, 0x8da0, 0 },
+	{ 0x8e93, 0x8e93, 0x8e93, 0 },
+	{ 0x8f84, 0x8f84, 0x8f84, 0 },
+	{ 0x9073, 0x9073, 0x9073, 0 },
+	{ 0x9161, 0x9161, 0x9161, 0 },
+	{ 0x924c, 0x924c, 0x924c, 0 },
+	{ 0x9335, 0x9335, 0x9335, 0 },
+	{ 0x941d, 0x941d, 0x941d, 0 },
+	{ 0x9503, 0x9503, 0x9503, 0 },
+	{ 0x95e7, 0x95e7, 0x95e7, 0 },
+	{ 0x96c9, 0x96c9, 0x96c9, 0 },
+	{ 0x97aa, 0x97aa, 0x97aa, 0 },
+	{ 0x9889, 0x9889, 0x9889, 0 },
+	{ 0x9966, 0x9966, 0x9966, 0 },
+	{ 0x9a42, 0x9a42, 0x9a42, 0 },
+	{ 0x9b1c, 0x9b1c, 0x9b1c, 0 },
+	{ 0x9bf5, 0x9bf5, 0x9bf5, 0 },
+	{ 0x9ccc, 0x9ccc, 0x9ccc, 0 },
+	{ 0x9da1, 0x9da1, 0x9da1, 0 },
+	{ 0x9e76, 0x9e76, 0x9e76, 0 },
+	{ 0x9f49, 0x9f49, 0x9f49, 0 },
+	{ 0xa01a, 0xa01a, 0xa01a, 0 },
+	{ 0xa0ea, 0xa0ea, 0xa0ea, 0 },
+	{ 0xa1b9, 0xa1b9, 0xa1b9, 0 },
+	{ 0xa286, 0xa286, 0xa286, 0 },
+	{ 0xa352, 0xa352, 0xa352, 0 },
+	{ 0xa41d, 0xa41d, 0xa41d, 0 },
+	{ 0xa4e7, 0xa4e7, 0xa4e7, 0 },
+	{ 0xa5af, 0xa5af, 0xa5af, 0 },
+	{ 0xa676, 0xa676, 0xa676, 0 },
+	{ 0xa73c, 0xa73c, 0xa73c, 0 },
+	{ 0xa801, 0xa801, 0xa801, 0 },
+	{ 0xa8c5, 0xa8c5, 0xa8c5, 0 },
+	{ 0xa987, 0xa987, 0xa987, 0 },
+	{ 0xaa48, 0xaa48, 0xaa48, 0 },
+	{ 0xab09, 0xab09, 0xab09, 0 },
+	{ 0xabc8, 0xabc8, 0xabc8, 0 },
+	{ 0xac86, 0xac86, 0xac86, 0 },
+	{ 0xad43, 0xad43, 0xad43, 0 },
+	{ 0xadff, 0xadff, 0xadff, 0 },
+	{ 0xaeba, 0xaeba, 0xaeba, 0 },
+	{ 0xaf74, 0xaf74, 0xaf74, 0 },
+	{ 0xb02d, 0xb02d, 0xb02d, 0 },
+	{ 0xb0e5, 0xb0e5, 0xb0e5, 0 },
+	{ 0xb19c, 0xb19c, 0xb19c, 0 },
+	{ 0xb252, 0xb252, 0xb252, 0 },
+	{ 0xb307, 0xb307, 0xb307, 0 },
+	{ 0xb3bb, 0xb3bb, 0xb3bb, 0 },
+	{ 0xb46f, 0xb46f, 0xb46f, 0 },
+	{ 0xb521, 0xb521, 0xb521, 0 },
+	{ 0xb5d3, 0xb5d3, 0xb5d3, 0 },
+	{ 0xb683, 0xb683, 0xb683, 0 },
+	{ 0xb733, 0xb733, 0xb733, 0 },
+	{ 0xb7e2, 0xb7e2, 0xb7e2, 0 },
+	{ 0xb890, 0xb890, 0xb890, 0 },
+	{ 0xb93d, 0xb93d, 0xb93d, 0 },
+	{ 0xb9ea, 0xb9ea, 0xb9ea, 0 },
+	{ 0xba96, 0xba96, 0xba96, 0 },
+	{ 0xbb40, 0xbb40, 0xbb40, 0 },
+	{ 0xbbea, 0xbbea, 0xbbea, 0 },
+	{ 0xbc94, 0xbc94, 0xbc94, 0 },
+	{ 0xbd3c, 0xbd3c, 0xbd3c, 0 },
+	{ 0xbde4, 0xbde4, 0xbde4, 0 },
+	{ 0xbe8b, 0xbe8b, 0xbe8b, 0 },
+	{ 0xbf31, 0xbf31, 0xbf31, 0 },
+	{ 0xbfd7, 0xbfd7, 0xbfd7, 0 },
+	{ 0xc07b, 0xc07b, 0xc07b, 0 },
+	{ 0xc120, 0xc120, 0xc120, 0 },
+	{ 0xc1c3, 0xc1c3, 0xc1c3, 0 },
+	{ 0xc266, 0xc266, 0xc266, 0 },
+	{ 0xc308, 0xc308, 0xc308, 0 },
+	{ 0xc3a9, 0xc3a9, 0xc3a9, 0 },
+	{ 0xc449, 0xc449, 0xc449, 0 },
+	{ 0xc4e9, 0xc4e9, 0xc4e9, 0 },
+	{ 0xc589, 0xc589, 0xc589, 0 },
+	{ 0xc627, 0xc627, 0xc627, 0 },
+	{ 0xc6c5, 0xc6c5, 0xc6c5, 0 },
+	{ 0xc763, 0xc763, 0xc763, 0 },
+	{ 0xc7ff, 0xc7ff, 0xc7ff, 0 },
+	{ 0xc89b, 0xc89b, 0xc89b, 0 },
+	{ 0xc937, 0xc937, 0xc937, 0 },
+	{ 0xc9d2, 0xc9d2, 0xc9d2, 0 },
+	{ 0xca6c, 0xca6c, 0xca6c, 0 },
+	{ 0xcb06, 0xcb06, 0xcb06, 0 },
+	{ 0xcb9f, 0xcb9f, 0xcb9f, 0 },
+	{ 0xcc37, 0xcc37, 0xcc37, 0 },
+	{ 0xcccf, 0xcccf, 0xcccf, 0 },
+	{ 0xcd66, 0xcd66, 0xcd66, 0 },
+	{ 0xcdfd, 0xcdfd, 0xcdfd, 0 },
+	{ 0xce93, 0xce93, 0xce93, 0 },
+	{ 0xcf29, 0xcf29, 0xcf29, 0 },
+	{ 0xcfbe, 0xcfbe, 0xcfbe, 0 },
+	{ 0xd053, 0xd053, 0xd053, 0 },
+	{ 0xd0e7, 0xd0e7, 0xd0e7, 0 },
+	{ 0xd17a, 0xd17a, 0xd17a, 0 },
+	{ 0xd20d, 0xd20d, 0xd20d, 0 },
+	{ 0xd2a0, 0xd2a0, 0xd2a0, 0 },
+	{ 0xd331, 0xd331, 0xd331, 0 },
+	{ 0xd3c3, 0xd3c3, 0xd3c3, 0 },
+	{ 0xd454, 0xd454, 0xd454, 0 },
+	{ 0xd4e4, 0xd4e4, 0xd4e4, 0 },
+	{ 0xd574, 0xd574, 0xd574, 0 },
+	{ 0xd603, 0xd603, 0xd603, 0 },
+	{ 0xd692, 0xd692, 0xd692, 0 },
+	{ 0xd720, 0xd720, 0xd720, 0 },
+	{ 0xd7ae, 0xd7ae, 0xd7ae, 0 },
+	{ 0xd83c, 0xd83c, 0xd83c, 0 },
+	{ 0xd8c9, 0xd8c9, 0xd8c9, 0 },
+	{ 0xd955, 0xd955, 0xd955, 0 },
+	{ 0xd9e1, 0xd9e1, 0xd9e1, 0 },
+	{ 0xda6d, 0xda6d, 0xda6d, 0 },
+	{ 0xdaf8, 0xdaf8, 0xdaf8, 0 },
+	{ 0xdb83, 0xdb83, 0xdb83, 0 },
+	{ 0xdc0d, 0xdc0d, 0xdc0d, 0 },
+	{ 0xdc97, 0xdc97, 0xdc97, 0 },
+	{ 0xdd20, 0xdd20, 0xdd20, 0 },
+	{ 0xdda9, 0xdda9, 0xdda9, 0 },
+	{ 0xde31, 0xde31, 0xde31, 0 },
+	{ 0xdeb9, 0xdeb9, 0xdeb9, 0 },
+	{ 0xdf41, 0xdf41, 0xdf41, 0 },
+	{ 0xdfc8, 0xdfc8, 0xdfc8, 0 },
+	{ 0xe04f, 0xe04f, 0xe04f, 0 },
+	{ 0xe0d5, 0xe0d5, 0xe0d5, 0 },
+	{ 0xe15b, 0xe15b, 0xe15b, 0 },
+	{ 0xe1e0, 0xe1e0, 0xe1e0, 0 },
+	{ 0xe266, 0xe266, 0xe266, 0 },
+	{ 0xe2ea, 0xe2ea, 0xe2ea, 0 },
+	{ 0xe36f, 0xe36f, 0xe36f, 0 },
+	{ 0xe3f3, 0xe3f3, 0xe3f3, 0 },
+	{ 0xe476, 0xe476, 0xe476, 0 },
+	{ 0xe4f9, 0xe4f9, 0xe4f9, 0 },
+	{ 0xe57c, 0xe57c, 0xe57c, 0 },
+	{ 0xe5fe, 0xe5fe, 0xe5fe, 0 },
+	{ 0xe680, 0xe680, 0xe680, 0 },
+	{ 0xe702, 0xe702, 0xe702, 0 },
+	{ 0xe783, 0xe783, 0xe783, 0 },
+	{ 0xe804, 0xe804, 0xe804, 0 },
+	{ 0xe884, 0xe884, 0xe884, 0 },
+	{ 0xe905, 0xe905, 0xe905, 0 },
+	{ 0xe984, 0xe984, 0xe984, 0 },
+	{ 0xea04, 0xea04, 0xea04, 0 },
+	{ 0xea83, 0xea83, 0xea83, 0 },
+	{ 0xeb02, 0xeb02, 0xeb02, 0 },
+	{ 0xeb80, 0xeb80, 0xeb80, 0 },
+	{ 0xebfe, 0xebfe, 0xebfe, 0 },
+	{ 0xec7b, 0xec7b, 0xec7b, 0 },
+	{ 0xecf9, 0xecf9, 0xecf9, 0 },
+	{ 0xed76, 0xed76, 0xed76, 0 },
+	{ 0xedf2, 0xedf2, 0xedf2, 0 },
+	{ 0xee6f, 0xee6f, 0xee6f, 0 },
+	{ 0xeeeb, 0xeeeb, 0xeeeb, 0 },
+	{ 0xef66, 0xef66, 0xef66, 0 },
+	{ 0xefe2, 0xefe2, 0xefe2, 0 },
+	{ 0xf05d, 0xf05d, 0xf05d, 0 },
+	{ 0xf0d7, 0xf0d7, 0xf0d7, 0 },
+	{ 0xf152, 0xf152, 0xf152, 0 },
+	{ 0xf1cc, 0xf1cc, 0xf1cc, 0 },
+	{ 0xf245, 0xf245, 0xf245, 0 },
+	{ 0xf2bf, 0xf2bf, 0xf2bf, 0 },
+	{ 0xf338, 0xf338, 0xf338, 0 },
+	{ 0xf3b0, 0xf3b0, 0xf3b0, 0 },
+	{ 0xf429, 0xf429, 0xf429, 0 },
+	{ 0xf4a1, 0xf4a1, 0xf4a1, 0 },
+	{ 0xf519, 0xf519, 0xf519, 0 },
+	{ 0xf590, 0xf590, 0xf590, 0 },
+	{ 0xf608, 0xf608, 0xf608, 0 },
+	{ 0xf67e, 0xf67e, 0xf67e, 0 },
+	{ 0xf6f5, 0xf6f5, 0xf6f5, 0 },
+	{ 0xf76b, 0xf76b, 0xf76b, 0 },
+	{ 0xf7e1, 0xf7e1, 0xf7e1, 0 },
+	{ 0xf857, 0xf857, 0xf857, 0 },
+	{ 0xf8cd, 0xf8cd, 0xf8cd, 0 },
+	{ 0xf942, 0xf942, 0xf942, 0 },
+	{ 0xf9b7, 0xf9b7, 0xf9b7, 0 },
+	{ 0xfa2b, 0xfa2b, 0xfa2b, 0 },
+	{ 0xfaa0, 0xfaa0, 0xfaa0, 0 },
+	{ 0xfb14, 0xfb14, 0xfb14, 0 },
+	{ 0xfb88, 0xfb88, 0xfb88, 0 },
+	{ 0xfbfb, 0xfbfb, 0xfbfb, 0 },
+	{ 0xfc6e, 0xfc6e, 0xfc6e, 0 },
+	{ 0xfce1, 0xfce1, 0xfce1, 0 },
+	{ 0xfd54, 0xfd54, 0xfd54, 0 },
+	{ 0xfdc6, 0xfdc6, 0xfdc6, 0 },
+	{ 0xfe39, 0xfe39, 0xfe39, 0 },
+	{ 0xfeaa, 0xfeaa, 0xfeaa, 0 },
+	{ 0xff1c, 0xff1c, 0xff1c, 0 },
+	{ 0xff8d, 0xff8d, 0xff8d, 0 },
+	{ 0xffff, 0xffff, 0xffff, 0 },
+};
+
+const struct vkms_color_lut srgb_inv_eotf = {
+	.base = srgb_inv_array,
+	.lut_length = LUT_SIZE,
+	.channel_value2index_ratio = 0xff00ffll
+};
diff --git a/drivers/gpu/drm/vkms/vkms_luts.h b/drivers/gpu/drm/vkms/vkms_luts.h
new file mode 100644
index 000000000000..925a4a7b84e2
--- /dev/null
+++ b/drivers/gpu/drm/vkms/vkms_luts.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef _VKMS_LUTS_H_
+#define _VKMS_LUTS_H_
+
+#define LUT_SIZE 256
+
+extern const struct vkms_color_lut linear_eotf;
+extern const struct vkms_color_lut srgb_eotf;
+extern const struct vkms_color_lut srgb_inv_eotf;
+
+#endif /* _VKMS_LUTS_H_ */
diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c
index e34f8c7f83c3..b39c4fe471f2 100644
--- a/drivers/gpu/drm/vkms/vkms_plane.c
+++ b/drivers/gpu/drm/vkms/vkms_plane.c
@@ -205,5 +205,7 @@ struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,
 	drm_plane_create_rotation_property(&plane->base, DRM_MODE_ROTATE_0,
 					   DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK);
 
+	vkms_initialize_colorops(&plane->base);
+
 	return plane;
 }
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 14/43] drm/vkms: Add kunit tests for linear and sRGB LUTs
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (12 preceding siblings ...)
  2025-03-26 23:46 ` [PATCH V8 13/43] drm/vkms: Add enumerated 1D curve colorop Alex Hung
@ 2025-03-26 23:46 ` Alex Hung
  2025-03-26 23:46 ` [PATCH V8 15/43] drm/colorop: Add 3x4 CTM type Alex Hung
                   ` (29 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:46 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

Two tests are added to VKMS LUT handling:
- linear
- inv_srgb

Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
v7:
 - Fix checkpatch warnings (Louis Chauvet)
  - Adde a commit messages
  - Fix code styles by adding and removing spaces (new lines, tabs and so on)

 drivers/gpu/drm/vkms/tests/vkms_color_test.c | 39 +++++++++++++++++++-
 drivers/gpu/drm/vkms/vkms_composer.c         | 17 ++-------
 drivers/gpu/drm/vkms/vkms_composer.h         | 13 +++++++
 3 files changed, 55 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/vkms/tests/vkms_color_test.c b/drivers/gpu/drm/vkms/tests/vkms_color_test.c
index affca56cac7b..02fbe19c744a 100644
--- a/drivers/gpu/drm/vkms/tests/vkms_color_test.c
+++ b/drivers/gpu/drm/vkms/tests/vkms_color_test.c
@@ -6,6 +6,7 @@
 #include <drm/drm_mode.h>
 #include "../vkms_drv.h"
 #include "../vkms_composer.h"
+#include "../vkms_luts.h"
 
 #define TEST_LUT_SIZE 16
 
@@ -36,7 +37,6 @@ static const struct vkms_color_lut test_linear_lut = {
 	.channel_value2index_ratio = 0xf000fll
 };
 
-
 static void vkms_color_test_get_lut_index(struct kunit *test)
 {
 	s64 lut_index;
@@ -49,6 +49,19 @@ static void vkms_color_test_get_lut_index(struct kunit *test)
 		lut_index = get_lut_index(&test_linear_lut, test_linear_array[i].red);
 		KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(lut_index), i);
 	}
+
+	KUNIT_EXPECT_EQ(test, drm_fixp2int(get_lut_index(&srgb_eotf, 0x0)), 0x0);
+	KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(get_lut_index(&srgb_eotf, 0x0)), 0x0);
+	KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(get_lut_index(&srgb_eotf, 0x101)), 0x1);
+	KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(get_lut_index(&srgb_eotf, 0x202)), 0x2);
+
+	KUNIT_EXPECT_EQ(test, drm_fixp2int(get_lut_index(&srgb_inv_eotf, 0x0)), 0x0);
+	KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(get_lut_index(&srgb_inv_eotf, 0x0)), 0x0);
+	KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(get_lut_index(&srgb_inv_eotf, 0x101)), 0x1);
+	KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(get_lut_index(&srgb_inv_eotf, 0x202)), 0x2);
+
+	KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(get_lut_index(&srgb_eotf, 0xfefe)), 0xfe);
+	KUNIT_EXPECT_EQ(test, drm_fixp2int_ceil(get_lut_index(&srgb_eotf, 0xffff)), 0xff);
 }
 
 static void vkms_color_test_lerp(struct kunit *test)
@@ -155,9 +168,33 @@ static void vkms_color_test_lerp(struct kunit *test)
 	KUNIT_EXPECT_EQ(test, lerp_u16(0x0, 0x1, 0x80000000), 0x1);
 }
 
+static void vkms_color_test_linear(struct kunit *test)
+{
+	for (int i = 0; i < LUT_SIZE; i++) {
+		int linear = apply_lut_to_channel_value(&linear_eotf, i * 0x101, LUT_RED);
+
+		KUNIT_EXPECT_EQ(test, DIV_ROUND_CLOSEST(linear, 0x101), i);
+	}
+}
+
+static void vkms_color_srgb_inv_srgb(struct kunit *test)
+{
+	u16 srgb, final;
+
+	for (int i = 0; i < LUT_SIZE; i++) {
+		srgb = apply_lut_to_channel_value(&srgb_eotf, i * 0x101, LUT_RED);
+		final = apply_lut_to_channel_value(&srgb_inv_eotf, srgb, LUT_RED);
+
+		KUNIT_EXPECT_GE(test, final / 0x101, i - 1);
+		KUNIT_EXPECT_LE(test, final / 0x101, i + 1);
+	}
+}
+
 static struct kunit_case vkms_color_test_cases[] = {
 	KUNIT_CASE(vkms_color_test_get_lut_index),
 	KUNIT_CASE(vkms_color_test_lerp),
+	KUNIT_CASE(vkms_color_test_linear),
+	KUNIT_CASE(vkms_color_srgb_inv_srgb),
 	{}
 };
 
diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c
index 3ab829556db2..72890ffea13a 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -82,19 +82,8 @@ VISIBLE_IF_KUNIT s64 get_lut_index(const struct vkms_color_lut *lut, u16 channel
 }
 EXPORT_SYMBOL_IF_KUNIT(get_lut_index);
 
-/*
- * This enum is related to the positions of the variables inside
- * `struct drm_color_lut`, so the order of both needs to be the same.
- */
-enum lut_channel {
-	LUT_RED = 0,
-	LUT_GREEN,
-	LUT_BLUE,
-	LUT_RESERVED
-};
-
-static u16 apply_lut_to_channel_value(const struct vkms_color_lut *lut, u16 channel_value,
-				      enum lut_channel channel)
+VISIBLE_IF_KUNIT u16 apply_lut_to_channel_value(const struct vkms_color_lut *lut, u16 channel_value,
+						enum lut_channel channel)
 {
 	s64 lut_index = get_lut_index(lut, channel_value);
 	u16 *floor_lut_value, *ceil_lut_value;
@@ -119,6 +108,8 @@ static u16 apply_lut_to_channel_value(const struct vkms_color_lut *lut, u16 chan
 	return lerp_u16(floor_channel_value, ceil_channel_value,
 			lut_index & DRM_FIXED_DECIMAL_MASK);
 }
+EXPORT_SYMBOL_IF_KUNIT(apply_lut_to_channel_value);
+
 
 static void apply_lut(const struct vkms_crtc_state *crtc_state, struct line_buffer *output_buffer)
 {
diff --git a/drivers/gpu/drm/vkms/vkms_composer.h b/drivers/gpu/drm/vkms/vkms_composer.h
index 9316a053e7d7..67ae09913460 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.h
+++ b/drivers/gpu/drm/vkms/vkms_composer.h
@@ -5,9 +5,22 @@
 
 #include <kunit/visibility.h>
 
+/*
+ * This enum is related to the positions of the variables inside
+ * `struct drm_color_lut`, so the order of both needs to be the same.
+ */
+enum lut_channel {
+	LUT_RED = 0,
+	LUT_GREEN,
+	LUT_BLUE,
+	LUT_RESERVED
+};
+
 #if IS_ENABLED(CONFIG_KUNIT)
 u16 lerp_u16(u16 a, u16 b, s64 t);
 s64 get_lut_index(const struct vkms_color_lut *lut, u16 channel_value);
+u16 apply_lut_to_channel_value(const struct vkms_color_lut *lut, u16 channel_value,
+			       enum lut_channel channel);
 #endif
 
 #endif /* _VKMS_COMPOSER_H_ */
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 15/43] drm/colorop: Add 3x4 CTM type
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (13 preceding siblings ...)
  2025-03-26 23:46 ` [PATCH V8 14/43] drm/vkms: Add kunit tests for linear and sRGB LUTs Alex Hung
@ 2025-03-26 23:46 ` Alex Hung
  2025-03-26 23:46 ` [PATCH V8 16/43] drm/vkms: Use s32 for internal color pipeline precision Alex Hung
                   ` (28 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:46 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

This type is used to support a 3x4 matrix in colorops. A 3x4
matrix uses the last column as a "bias" column. Some HW exposes
support for 3x4. The calculation looks like:

 out   matrix    in
 |R|   |0  1  2  3 |   | R |
 |G| = |4  5  6  7 | x | G |
 |B|   |8  9  10 11|   | B |
                       |1.0|

This is also the first colorop where we need a blob property to
program the property. For that we'll introduce a new DATA
property that can be used by all colorop TYPEs requiring a
blob. The way a DATA blob is read depends on the TYPE of
the colorop.

We only create the DATA property for property types that
need it.

Reviewed-by: Simon Ser <contact@emersion.fr>
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
v6:
 - take ref for DATA blob in duplicate_state func (Xaver Hugl)

v5:
 - Add function signature for init (Sebastian)
 - Fix kernel-doc

v4:
 - Create helper function for creating 3x4 CTM colorop
 - Fix CTM indexes in comment (Pekka)

 drivers/gpu/drm/drm_atomic.c      |  3 +++
 drivers/gpu/drm/drm_atomic_uapi.c | 30 ++++++++++++++++++++++
 drivers/gpu/drm/drm_colorop.c     | 42 +++++++++++++++++++++++++++++++
 include/drm/drm_colorop.h         | 24 ++++++++++++++++++
 include/uapi/drm/amdgpu_drm.h     |  9 -------
 include/uapi/drm/drm_mode.h       | 32 ++++++++++++++++++++++-
 6 files changed, 130 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index e67d7a68e8a8..5223cf363692 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -793,6 +793,9 @@ static void drm_atomic_colorop_print_state(struct drm_printer *p,
 		drm_printf(p, "\tcurve_1d_type=%s\n",
 			   drm_get_colorop_curve_1d_type_name(state->curve_1d_type));
 		break;
+	case DRM_COLOROP_CTM_3X4:
+		drm_printf(p, "\tdata blob id=%d\n", state->data ? state->data->base.id : 0);
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index e0b4b122ef6b..52c6a4dfbc47 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -703,6 +703,31 @@ drm_atomic_plane_get_property(struct drm_plane *plane,
 	return 0;
 }
 
+static int drm_atomic_color_set_data_property(struct drm_colorop *colorop,
+					      struct drm_colorop_state *state,
+					      struct drm_property *property,
+					      uint64_t val)
+{
+	ssize_t elem_size = -1;
+	ssize_t size = -1;
+	bool replaced = false;
+
+	switch (colorop->type) {
+	case DRM_COLOROP_CTM_3X4:
+		size = sizeof(struct drm_color_ctm_3x4);
+		break;
+	default:
+		/* should never get here */
+		return -EINVAL;
+	}
+
+	return drm_property_replace_blob_from_id(colorop->dev,
+						 &state->data,
+						 val,
+						 size,
+						 elem_size,
+						 &replaced);
+}
 
 static int drm_atomic_colorop_set_property(struct drm_colorop *colorop,
 		struct drm_colorop_state *state, struct drm_file *file_priv,
@@ -712,6 +737,9 @@ static int drm_atomic_colorop_set_property(struct drm_colorop *colorop,
 		state->bypass = val;
 	} else if (property == colorop->curve_1d_type_property) {
 		state->curve_1d_type = val;
+	} else if (property == colorop->data_property) {
+		return drm_atomic_color_set_data_property(colorop, state,
+							  property, val);
 	} else {
 		drm_dbg_atomic(colorop->dev,
 			       "[COLOROP:%d:%d] unknown property [PROP:%d:%s]]\n",
@@ -734,6 +762,8 @@ drm_atomic_colorop_get_property(struct drm_colorop *colorop,
 		*val = state->bypass;
 	} else if (property == colorop->curve_1d_type_property) {
 		*val = state->curve_1d_type;
+	} else if (property == colorop->data_property) {
+		*val = (state->data) ? state->data->base.id : 0;
 	} else {
 		return -EINVAL;
 	}
diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index a554c51fa7f5..8ab754f935e6 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -64,6 +64,7 @@
 
 static const struct drm_prop_enum_list drm_colorop_type_enum_list[] = {
 	{ DRM_COLOROP_1D_CURVE, "1D Curve" },
+	{ DRM_COLOROP_CTM_3X4, "3x4 Matrix"},
 };
 
 static const char * const colorop_curve_1d_type_names[] = {
@@ -202,11 +203,51 @@ int drm_colorop_curve_1d_init(struct drm_device *dev, struct drm_colorop *coloro
 }
 EXPORT_SYMBOL(drm_colorop_curve_1d_init);
 
+static int drm_colorop_create_data_prop(struct drm_device *dev, struct drm_colorop *colorop)
+{
+	struct drm_property *prop;
+
+	/* data */
+	prop = drm_property_create(dev, DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_BLOB,
+				   "DATA", 0);
+	if (!prop)
+		return -ENOMEM;
+
+	colorop->data_property = prop;
+	drm_object_attach_property(&colorop->base,
+				   colorop->data_property,
+				   0);
+
+	return 0;
+}
+
+int drm_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop,
+			     struct drm_plane *plane)
+{
+	int ret;
+
+	ret = drm_colorop_init(dev, colorop, plane, DRM_COLOROP_CTM_3X4);
+	if (ret)
+		return ret;
+
+	ret = drm_colorop_create_data_prop(dev, colorop);
+	if (ret)
+		return ret;
+
+	drm_colorop_reset(colorop);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_colorop_ctm_3x4_init);
+
 static void __drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop,
 							struct drm_colorop_state *state)
 {
 	memcpy(state, colorop->state, sizeof(*state));
 
+	if (state->data)
+		drm_property_blob_get(state->data);
+
 	state->bypass = true;
 }
 
@@ -288,6 +329,7 @@ void drm_colorop_reset(struct drm_colorop *colorop)
 
 static const char * const colorop_type_name[] = {
 	[DRM_COLOROP_1D_CURVE] = "1D Curve",
+	[DRM_COLOROP_CTM_3X4] = "3x4 Matrix",
 };
 
 const char *drm_get_colorop_type_name(enum drm_colorop_type type)
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index 7948de5c4994..d9149c320bac 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -99,6 +99,17 @@ struct drm_colorop_state {
 	 */
 	enum drm_colorop_curve_1d_type curve_1d_type;
 
+	/**
+	 * @data:
+	 *
+	 * Data blob for any TYPE that requires such a blob. The
+	 * interpretation of the blob is TYPE-specific.
+	 *
+	 * See the &drm_colorop_type documentation for how blob is laid
+	 * out.
+	 */
+	struct drm_property_blob *data;
+
 	/** @state: backpointer to global drm_atomic_state */
 	struct drm_atomic_state *state;
 };
@@ -208,6 +219,17 @@ struct drm_colorop {
 	 */
 	struct drm_property *curve_1d_type_property;
 
+	/**
+	 * @data_property:
+	 *
+	 * blob property for any TYPE that requires a blob of data,
+	 * such as 1DLUT, CTM, 3DLUT, etc.
+	 *
+	 * The way this blob is interpreted depends on the TYPE of
+	 * this
+	 */
+	struct drm_property *data_property;
+
 	/**
 	 * @next_property:
 	 *
@@ -241,6 +263,8 @@ static inline struct drm_colorop *drm_colorop_find(struct drm_device *dev,
 
 int drm_colorop_curve_1d_init(struct drm_device *dev, struct drm_colorop *colorop,
 			      struct drm_plane *plane, u64 supported_tfs);
+int drm_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop,
+			     struct drm_plane *plane);
 
 struct drm_colorop_state *
 drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop);
diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
index 25d5c6e90a99..96fabf9c9827 100644
--- a/include/uapi/drm/amdgpu_drm.h
+++ b/include/uapi/drm/amdgpu_drm.h
@@ -1300,15 +1300,6 @@ struct drm_amdgpu_info_gpuvm_fault {
 #define AMDGPU_FAMILY_GC_11_5_0			150 /* GC 11.5.0 */
 #define AMDGPU_FAMILY_GC_12_0_0			152 /* GC 12.0.0 */
 
-/* FIXME wrong namespace! */
-struct drm_color_ctm_3x4 {
-	/*
-	 * Conversion matrix with 3x4 dimensions in S31.32 sign-magnitude
-	 * (not two's complement!) format.
-	 */
-	__u64 matrix[12];
-};
-
 #if defined(__cplusplus)
 }
 #endif
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index ea6d88f683cd..651bdf48b766 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -847,6 +847,20 @@ struct drm_color_ctm {
 	__u64 matrix[9];
 };
 
+struct drm_color_ctm_3x4 {
+	/*
+	 * Conversion matrix with 3x4 dimensions in S31.32 sign-magnitude
+	 * (not two's complement!) format.
+	 *
+	 * out   matrix          in
+	 * |R|   |0  1  2  3 |   | R |
+	 * |G| = |4  5  6  7 | x | G |
+	 * |B|   |8  9  10 11|   | B |
+	 *                       |1.0|
+	 */
+	__u64 matrix[12];
+};
+
 struct drm_color_lut {
 	/*
 	 * Values are mapped linearly to 0.0 - 1.0 range, with 0x0 == 0.0 and
@@ -874,7 +888,23 @@ enum drm_colorop_type {
 	 * A 1D curve that is being applied to all color channels. The
 	 * curve is specified via the CURVE_1D_TYPE colorop property.
 	 */
-	DRM_COLOROP_1D_CURVE
+	DRM_COLOROP_1D_CURVE,
+
+	/**
+	 * @DRM_COLOROP_CTM_3X4:
+	 *
+	 * enum string "3x4 Matrix"
+	 *
+	 * A 3x4 matrix. Its values are specified via the
+	 * &drm_color_ctm_3x4 struct provided via the DATA property.
+	 *
+	 * The DATA blob is a float[12]:
+	 * out   matrix          in
+	 * | R |   | 0  1  2  3  |   | R |
+	 * | G | = | 4  5  6  7  | x | G |
+	 * | B |   | 8  9  10 12 |   | B |
+	 */
+	DRM_COLOROP_CTM_3X4,
 };
 
 /**
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 16/43] drm/vkms: Use s32 for internal color pipeline precision
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (14 preceding siblings ...)
  2025-03-26 23:46 ` [PATCH V8 15/43] drm/colorop: Add 3x4 CTM type Alex Hung
@ 2025-03-26 23:46 ` Alex Hung
  2025-03-26 23:46 ` [PATCH V8 17/43] drm/vkms: add 3x4 matrix in color pipeline Alex Hung
                   ` (27 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:46 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

Certain operations require us to preserve values below 0.0 and
above 1.0 (0x0 and 0xffff respectively in 16 bpc unorm). One
such operation is a BT709 encoding operation followed by its
decoding operation, or the reverse.

We'll use s32 values as intermediate in and outputs of our
color operations, for the operations where it matters.

For now this won't apply to LUT operations. We might want to
update those to work on s32 as well, but it's unclear how
that should work for unorm LUT definitions. We'll revisit
that once we add LUT + CTM tests.

In order to allow for this we'll also invert the nesting of our
colorop processing loops. We now use the pixel iteration loop
on the outside and the colorop iteration on the inside.

Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
v7:
 - Fix checkpatch warnings
  - Add a commit messages
  - Fix code styles by adding and removing spaces (new lines, tabs and so on)

v6:
 - use clamp_val instead of manual clamping (Louis Chauvet)

v4:
 - Clarify that we're packing 16-bit UNORM into s32, not
   converting values to a different representation (Pekka)

v3:
 - Use new colorop->next pointer

 drivers/gpu/drm/vkms/vkms_composer.c | 27 +++++++++++++++++++++++++--
 drivers/gpu/drm/vkms/vkms_drv.h      |  4 ++++
 2 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c
index 72890ffea13a..36f0caabb67b 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -128,7 +128,7 @@ static void apply_lut(const struct vkms_crtc_state *crtc_state, struct line_buff
 	}
 }
 
-static void apply_colorop(struct pixel_argb_u16 *pixel, struct drm_colorop *colorop)
+static void apply_colorop(struct pixel_argb_s32 *pixel, struct drm_colorop *colorop)
 {
 	struct drm_colorop_state *colorop_state = colorop->state;
 	struct drm_device *dev = colorop->dev;
@@ -157,9 +157,26 @@ static void apply_colorop(struct pixel_argb_u16 *pixel, struct drm_colorop *colo
 static void pre_blend_color_transform(const struct vkms_plane_state *plane_state,
 				      struct line_buffer *output_buffer)
 {
+	struct pixel_argb_s32 pixel;
+
 	for (size_t x = 0; x < output_buffer->n_pixels; x++) {
 		struct drm_colorop *colorop = plane_state->base.base.color_pipeline;
 
+		/*
+		 * Some operations, such as applying a BT709 encoding matrix,
+		 * followed by a decoding matrix, require that we preserve
+		 * values above 1.0 and below 0.0 until the end of the pipeline.
+		 *
+		 * Pack the 16-bit UNORM values into s32 to give us head-room to
+		 * avoid clipping until we're at the end of the pipeline. Clip
+		 * intentionally at the end of the pipeline before packing
+		 * UNORM values back into u16.
+		 */
+		pixel.a = output_buffer->pixels[x].a;
+		pixel.r = output_buffer->pixels[x].r;
+		pixel.g = output_buffer->pixels[x].g;
+		pixel.b = output_buffer->pixels[x].b;
+
 		while (colorop) {
 			struct drm_colorop_state *colorop_state;
 
@@ -169,10 +186,16 @@ static void pre_blend_color_transform(const struct vkms_plane_state *plane_state
 				return;
 
 			if (!colorop_state->bypass)
-				apply_colorop(&output_buffer->pixels[x], colorop);
+				apply_colorop(&pixel, colorop);
 
 			colorop = colorop->next;
 		}
+
+		/* clamp values */
+		output_buffer->pixels[x].a = clamp_val(pixel.a, 0, 0xffff);
+		output_buffer->pixels[x].r = clamp_val(pixel.r, 0, 0xffff);
+		output_buffer->pixels[x].g = clamp_val(pixel.g, 0, 0xffff);
+		output_buffer->pixels[x].b = clamp_val(pixel.b, 0, 0xffff);
 	}
 }
 
diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
index 999625de0050..d9196b9db025 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.h
+++ b/drivers/gpu/drm/vkms/vkms_drv.h
@@ -43,6 +43,10 @@ struct vkms_frame_info {
 	unsigned int rotation;
 };
 
+struct pixel_argb_s32 {
+	s32 a, r, g, b;
+};
+
 struct pixel_argb_u16 {
 	u16 a, r, g, b;
 };
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 17/43] drm/vkms: add 3x4 matrix in color pipeline
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (15 preceding siblings ...)
  2025-03-26 23:46 ` [PATCH V8 16/43] drm/vkms: Use s32 for internal color pipeline precision Alex Hung
@ 2025-03-26 23:46 ` Alex Hung
  2025-03-26 23:46 ` [PATCH V8 18/43] drm/tests: Add a few tests around drm_fixed.h Alex Hung
                   ` (26 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:46 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

We add two 3x4 matrices into the VKMS color pipeline. The reason
we're adding matrices is so that we can test that application
of a matrix and its inverse yields an output equal to the input
image.

One complication with the matrix implementation has to do with
the fact that the matrix entries are in signed-magnitude fixed
point, whereas the drm_fixed.h implementation uses 2s-complement.
The latter one is the one that we want for easy addition and
subtraction, so we convert all entries to 2s-complement.

Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
v8:
 - Replace DRM_ERROR with drm_err (Louis Chauvet)

v7:
 - Fix checkpatch warnings
  - Change kzalloc(sizeof(struct drm_colorop) ...) to kzalloc(sizeof(*ops[i]) ...)
  - Change i-1to i - 1
  - Add a new line at EOF

v6:
 - pre-compute colors (Louis Chauvet)
 - round matrix output (Louis Chauvet)

 drivers/gpu/drm/vkms/vkms_colorop.c  | 34 +++++++++++++++++++++++++++-
 drivers/gpu/drm/vkms/vkms_composer.c | 33 +++++++++++++++++++++++++++
 2 files changed, 66 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vkms/vkms_colorop.c b/drivers/gpu/drm/vkms/vkms_colorop.c
index 4fe22368c8e3..0fbb9262bfc5 100644
--- a/drivers/gpu/drm/vkms/vkms_colorop.c
+++ b/drivers/gpu/drm/vkms/vkms_colorop.c
@@ -12,7 +12,7 @@ static const u64 supported_tfs =
 	BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) |
 	BIT(DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF);
 
-#define MAX_COLOR_PIPELINE_OPS 2
+#define MAX_COLOR_PIPELINE_OPS 4
 
 static int vkms_initialize_color_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list)
 {
@@ -48,6 +48,38 @@ static int vkms_initialize_color_pipeline(struct drm_plane *plane, struct drm_pr
 		goto cleanup;
 	}
 
+	ret = drm_colorop_ctm_3x4_init(dev, ops[i], plane);
+	if (ret)
+		goto cleanup;
+
+	drm_colorop_set_next_property(ops[i - 1], ops[i]);
+
+	i++;
+
+	/* 3rd op: 3x4 matrix */
+	ops[i] = kzalloc(sizeof(*ops[i]), GFP_KERNEL);
+	if (!ops[i]) {
+		drm_err(dev, "KMS: Failed to allocate colorop\n");
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	ret = drm_colorop_ctm_3x4_init(dev, ops[i], plane);
+	if (ret)
+		goto cleanup;
+
+	drm_colorop_set_next_property(ops[i - 1], ops[i]);
+
+	i++;
+
+	/* 4th op: 1d curve */
+	ops[i] = kzalloc(sizeof(*ops[i]), GFP_KERNEL);
+	if (!ops[i]) {
+		drm_err(dev, "KMS: Failed to allocate colorop\n");
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
 	ret = drm_colorop_curve_1d_init(dev, ops[i], plane, supported_tfs);
 	if (ret)
 		goto cleanup;
diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c
index 36f0caabb67b..8fe16d26d680 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -128,6 +128,35 @@ static void apply_lut(const struct vkms_crtc_state *crtc_state, struct line_buff
 	}
 }
 
+static void apply_3x4_matrix(struct pixel_argb_s32 *pixel, const struct drm_color_ctm_3x4 *matrix)
+{
+	s64 rf, gf, bf;
+	s64 r, g, b;
+
+	r = drm_int2fixp(pixel->r);
+	g = drm_int2fixp(pixel->g);
+	b = drm_int2fixp(pixel->b);
+
+	rf = drm_fixp_mul(drm_sm2fixp(matrix->matrix[0]), r) +
+	     drm_fixp_mul(drm_sm2fixp(matrix->matrix[1]), g) +
+	     drm_fixp_mul(drm_sm2fixp(matrix->matrix[2]), b) +
+	     drm_sm2fixp(matrix->matrix[3]);
+
+	gf = drm_fixp_mul(drm_sm2fixp(matrix->matrix[4]), r) +
+	     drm_fixp_mul(drm_sm2fixp(matrix->matrix[5]), g) +
+	     drm_fixp_mul(drm_sm2fixp(matrix->matrix[6]), b) +
+	     drm_sm2fixp(matrix->matrix[7]);
+
+	bf = drm_fixp_mul(drm_sm2fixp(matrix->matrix[8]), r) +
+	     drm_fixp_mul(drm_sm2fixp(matrix->matrix[9]), g) +
+	     drm_fixp_mul(drm_sm2fixp(matrix->matrix[10]), b) +
+	     drm_sm2fixp(matrix->matrix[11]);
+
+	pixel->r = drm_fixp2int_round(rf);
+	pixel->g = drm_fixp2int_round(gf);
+	pixel->b = drm_fixp2int_round(bf);
+}
+
 static void apply_colorop(struct pixel_argb_s32 *pixel, struct drm_colorop *colorop)
 {
 	struct drm_colorop_state *colorop_state = colorop->state;
@@ -151,6 +180,10 @@ static void apply_colorop(struct pixel_argb_s32 *pixel, struct drm_colorop *colo
 				      colorop_state->curve_1d_type);
 			break;
 		}
+	} else if (colorop->type == DRM_COLOROP_CTM_3X4) {
+		if (colorop_state->data)
+			apply_3x4_matrix(pixel,
+					 (struct drm_color_ctm_3x4 *) colorop_state->data->data);
 	}
 }
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 18/43] drm/tests: Add a few tests around drm_fixed.h
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (16 preceding siblings ...)
  2025-03-26 23:46 ` [PATCH V8 17/43] drm/vkms: add 3x4 matrix in color pipeline Alex Hung
@ 2025-03-26 23:46 ` Alex Hung
  2025-03-26 23:47 ` [PATCH V8 19/43] drm/vkms: Add tests for CTM handling Alex Hung
                   ` (25 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:46 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

While working on the CTM implementation of VKMS I had to ascertain
myself of a few assumptions. One of those is whether drm_fixed.h
treats its numbers using signed-magnitude or twos-complement. It is
twos-complement.

In order to make someone else's day easier I am adding the
drm_test_int2fixp test that validates the above assumption.

I am also adding a test for the new sm2fixp function that converts
from a signed-magnitude fixed point to the twos-complement fixed
point.

Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
v7:
 - Fix checkpatch warnings (Louis Chauvet)

v6:
 - add missing MODULE_DESCRIPTION (Jeff Johnson)
 - fix buffer overflow


 drivers/gpu/drm/tests/Makefile        |  3 +-
 drivers/gpu/drm/tests/drm_fixp_test.c | 71 +++++++++++++++++++++++++++
 2 files changed, 73 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/tests/drm_fixp_test.c

diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile
index 0109bcf7faa5..1fbb8e9e2869 100644
--- a/drivers/gpu/drm/tests/Makefile
+++ b/drivers/gpu/drm/tests/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_DRM_KUNIT_TEST) += \
 	drm_modes_test.o \
 	drm_plane_helper_test.o \
 	drm_probe_helper_test.o \
-	drm_rect_test.o
+	drm_rect_test.o	\
+	drm_fixp_test.o
 
 CFLAGS_drm_mm_test.o := $(DISABLE_STRUCTLEAK_PLUGIN)
diff --git a/drivers/gpu/drm/tests/drm_fixp_test.c b/drivers/gpu/drm/tests/drm_fixp_test.c
new file mode 100644
index 000000000000..de91177af213
--- /dev/null
+++ b/drivers/gpu/drm/tests/drm_fixp_test.c
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2022 Advanced Micro Devices, Inc.
+ */
+
+#include <kunit/test.h>
+#include <drm/drm_fixed.h>
+
+static void drm_test_sm2fixp(struct kunit *test)
+{
+	KUNIT_EXPECT_EQ(test, 0x7fffffffffffffffll, ((1ull << 63) - 1));
+
+	/* 1 */
+	KUNIT_EXPECT_EQ(test, drm_int2fixp(1), drm_sm2fixp(1ull << DRM_FIXED_POINT));
+
+	/* -1 */
+	KUNIT_EXPECT_EQ(test, drm_int2fixp(-1),
+			drm_sm2fixp((1ull << 63) | (1ull << DRM_FIXED_POINT)));
+
+	/* 0.5 */
+	KUNIT_EXPECT_EQ(test, drm_fixp_from_fraction(1, 2),
+			drm_sm2fixp(1ull << (DRM_FIXED_POINT - 1)));
+
+	/* -0.5 */
+	KUNIT_EXPECT_EQ(test, drm_fixp_from_fraction(-1, 2),
+			drm_sm2fixp((1ull << 63) | (1ull << (DRM_FIXED_POINT - 1))));
+}
+
+static void drm_test_int2fixp(struct kunit *test)
+{
+	/* 1 */
+	KUNIT_EXPECT_EQ(test, 1ll << 32, drm_int2fixp(1));
+
+	/* -1 */
+	KUNIT_EXPECT_EQ(test, -(1ll << 32), drm_int2fixp(-1));
+
+	/* 1 + (-1) = 0 */
+	KUNIT_EXPECT_EQ(test, 0, drm_int2fixp(1) + drm_int2fixp(-1));
+
+	/* 1 / 2 */
+	KUNIT_EXPECT_EQ(test, 1ll << 31, drm_fixp_from_fraction(1, 2));
+
+	/* -0.5 */
+	KUNIT_EXPECT_EQ(test, -(1ll << 31), drm_fixp_from_fraction(-1, 2));
+
+	/* (1 / 2) + (-1) = 0.5 */
+	KUNIT_EXPECT_EQ(test, 1ll << 31, drm_fixp_from_fraction(-1, 2) + drm_int2fixp(1));
+
+	/* (1 / 2) - 1) = 0.5 */
+	KUNIT_EXPECT_EQ(test, -(1ll << 31), drm_fixp_from_fraction(1, 2) + drm_int2fixp(-1));
+
+	/* (1 / 2) - 1) = 0.5 */
+	KUNIT_EXPECT_EQ(test, -(1ll << 31), drm_fixp_from_fraction(1, 2) - drm_int2fixp(1));
+}
+
+static struct kunit_case drm_fixp_tests[] = {
+	KUNIT_CASE(drm_test_int2fixp),
+	KUNIT_CASE(drm_test_sm2fixp),
+	{ }
+};
+
+static struct kunit_suite drm_rect_test_suite = {
+	.name = "drm_fixp",
+	.test_cases = drm_fixp_tests,
+};
+
+kunit_test_suite(drm_rect_test_suite);
+
+MODULE_AUTHOR("AMD");
+MODULE_LICENSE("GPL and additional rights");
+MODULE_DESCRIPTION("Unit tests for drm_fixed.h");
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 19/43] drm/vkms: Add tests for CTM handling
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (17 preceding siblings ...)
  2025-03-26 23:46 ` [PATCH V8 18/43] drm/tests: Add a few tests around drm_fixed.h Alex Hung
@ 2025-03-26 23:47 ` Alex Hung
  2025-03-26 23:47 ` [PATCH V8 20/43] drm/colorop: pass plane_color_pipeline client cap to atomic check Alex Hung
                   ` (24 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:47 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

A whole slew of tests for CTM handling that greatly helped in
debugging the CTM code. The extent of tests might seem a bit
silly but they're fast and might someday help save someone
else's day when debugging this.

Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
v7:
 - Fix a checkpatch a long-line warning (Louis Chauvet)

v6:
 - update reference values since we're now rounding

v5:
 - Make apply_3x4_matrix static

v4:
 - Comment on origin of bt709_enc matrix (Pekka)
 - Use full opaque alpha (Pekka)
 - Add additional check for Y < 0xffff (Pekka)
 - Remove unused code (Pekka)

 drivers/gpu/drm/vkms/tests/vkms_color_test.c | 250 +++++++++++++++++++
 drivers/gpu/drm/vkms/vkms_composer.c         |   4 +-
 drivers/gpu/drm/vkms/vkms_composer.h         |   1 +
 3 files changed, 254 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vkms/tests/vkms_color_test.c b/drivers/gpu/drm/vkms/tests/vkms_color_test.c
index 02fbe19c744a..a9c3af5025b3 100644
--- a/drivers/gpu/drm/vkms/tests/vkms_color_test.c
+++ b/drivers/gpu/drm/vkms/tests/vkms_color_test.c
@@ -190,11 +190,261 @@ static void vkms_color_srgb_inv_srgb(struct kunit *test)
 	}
 }
 
+#define FIXPT_HALF        (DRM_FIXED_ONE >> 1)
+#define FIXPT_QUARTER     (DRM_FIXED_ONE >> 2)
+
+static const struct drm_color_ctm_3x4 test_matrix_3x4_50_desat = { {
+	FIXPT_HALF, FIXPT_QUARTER, FIXPT_QUARTER, 0,
+	FIXPT_QUARTER, FIXPT_HALF, FIXPT_QUARTER, 0,
+	FIXPT_QUARTER, FIXPT_QUARTER, FIXPT_HALF, 0
+} };
+
+static void vkms_color_ctm_3x4_50_desat(struct kunit *test)
+{
+	struct pixel_argb_s32 ref, out;
+
+	/* full white */
+	ref.a = 0xffff;
+	ref.r = 0xffff;
+	ref.g = 0xffff;
+	ref.b = 0xffff;
+
+	memcpy(&out, &ref, sizeof(out));
+	apply_3x4_matrix(&out, &test_matrix_3x4_50_desat);
+
+	KUNIT_EXPECT_MEMEQ(test, &ref, &out, sizeof(out));
+
+	/* full black */
+	ref.a = 0xffff;
+	ref.r = 0x0;
+	ref.g = 0x0;
+	ref.b = 0x0;
+
+	memcpy(&out, &ref, sizeof(out));
+	apply_3x4_matrix(&out, &test_matrix_3x4_50_desat);
+
+	KUNIT_EXPECT_MEMEQ(test, &ref, &out, sizeof(out));
+
+	/* 50% grey */
+	ref.a = 0xffff;
+	ref.r = 0x8000;
+	ref.g = 0x8000;
+	ref.b = 0x8000;
+
+	memcpy(&out, &ref, sizeof(out));
+	apply_3x4_matrix(&out, &test_matrix_3x4_50_desat);
+
+	KUNIT_EXPECT_MEMEQ(test, &ref, &out, sizeof(out));
+
+	/* full red to 50% desat */
+	ref.a = 0xffff;
+	ref.r = 0x8000;
+	ref.g = 0x4000;
+	ref.b = 0x4000;
+
+	out.a = 0xffff;
+	out.r = 0xffff;
+	out.g = 0x0;
+	out.b = 0x0;
+
+	apply_3x4_matrix(&out, &test_matrix_3x4_50_desat);
+
+	KUNIT_EXPECT_MEMEQ(test, &ref, &out, sizeof(out));
+}
+
+/*
+ * BT.709 encoding matrix
+ *
+ * Values printed from within IGT when converting
+ * igt_matrix_3x4_bt709_enc to the fixed-point format expected
+ * by DRM/KMS.
+ */
+static const struct drm_color_ctm_3x4 test_matrix_3x4_bt709_enc = { {
+	0x00000000366cf400ull, 0x00000000b7175900ull, 0x0000000127bb300ull, 0,
+	0x800000001993b3a0ull, 0x800000005609fe80ull, 0x000000006f9db200ull, 0,
+	0x000000009d70a400ull, 0x800000008f011100ull, 0x800000000e6f9330ull, 0
+} };
+
+static void vkms_color_ctm_3x4_bt709(struct kunit *test)
+{
+	struct pixel_argb_s32 out;
+
+	/* full white to bt709 */
+	out.a = 0xffff;
+	out.r = 0xffff;
+	out.g = 0xffff;
+	out.b = 0xffff;
+
+	apply_3x4_matrix(&out, &test_matrix_3x4_bt709_enc);
+
+	/* Y 255 */
+	KUNIT_EXPECT_GT(test, out.r, 0xfe00);
+	KUNIT_EXPECT_LT(test, out.r, 0x10000);
+
+	/* U 0 */
+	KUNIT_EXPECT_LT(test, out.g, 0x0100);
+
+	/* V 0 */
+	KUNIT_EXPECT_LT(test, out.b, 0x0100);
+
+	/* full black to bt709 */
+	out.a = 0xffff;
+	out.r = 0x0;
+	out.g = 0x0;
+	out.b = 0x0;
+
+	apply_3x4_matrix(&out, &test_matrix_3x4_bt709_enc);
+
+	/* Y 0 */
+	KUNIT_EXPECT_LT(test, out.r, 0x100);
+
+	/* U 0 */
+	KUNIT_EXPECT_LT(test, out.g, 0x0100);
+
+	/* V 0 */
+	KUNIT_EXPECT_LT(test, out.b, 0x0100);
+
+	/* gray to bt709 */
+	out.a = 0xffff;
+	out.r = 0x7fff;
+	out.g = 0x7fff;
+	out.b = 0x7fff;
+
+	apply_3x4_matrix(&out, &test_matrix_3x4_bt709_enc);
+
+	/* Y 127 */
+	KUNIT_EXPECT_GT(test, out.r, 0x7e00);
+	KUNIT_EXPECT_LT(test, out.r, 0x8000);
+
+	/* U 0 */
+	KUNIT_EXPECT_LT(test, out.g, 0x0100);
+
+	/* V 0 */
+	KUNIT_EXPECT_LT(test, out.b, 0x0100);
+
+	/* == red 255 - bt709 enc == */
+	out.a = 0xffff;
+	out.r = 0xffff;
+	out.g = 0x0;
+	out.b = 0x0;
+
+	apply_3x4_matrix(&out, &test_matrix_3x4_bt709_enc);
+
+	/* Y 54 */
+	KUNIT_EXPECT_GT(test, out.r, 0x3500);
+	KUNIT_EXPECT_LT(test, out.r, 0x3700);
+
+	/* U 0 */
+	KUNIT_EXPECT_LT(test, out.g, 0x0100);
+
+	/* V 157 */
+	KUNIT_EXPECT_GT(test, out.b, 0x9C00);
+	KUNIT_EXPECT_LT(test, out.b, 0x9E00);
+
+
+	/* == green 255 - bt709 enc == */
+	out.a = 0xffff;
+	out.r = 0x0;
+	out.g = 0xffff;
+	out.b = 0x0;
+
+	apply_3x4_matrix(&out, &test_matrix_3x4_bt709_enc);
+
+	/* Y 182 */
+	KUNIT_EXPECT_GT(test, out.r, 0xB500);
+	KUNIT_EXPECT_LT(test, out.r, 0xB780); /* laxed by half*/
+
+	/* U 0 */
+	KUNIT_EXPECT_LT(test, out.g, 0x0100);
+
+	/* V 0 */
+	KUNIT_EXPECT_LT(test, out.b, 0x0100);
+
+	/* == blue 255 - bt709 enc == */
+	out.a = 0xffff;
+	out.r = 0x0;
+	out.g = 0x0;
+	out.b = 0xffff;
+
+	apply_3x4_matrix(&out, &test_matrix_3x4_bt709_enc);
+
+	/* Y 18 */
+	KUNIT_EXPECT_GT(test, out.r, 0x1100);
+	KUNIT_EXPECT_LT(test, out.r, 0x1300);
+
+	/* U 111 */
+	KUNIT_EXPECT_GT(test, out.g, 0x6E00);
+	KUNIT_EXPECT_LT(test, out.g, 0x7000);
+
+	/* V 0 */
+	KUNIT_EXPECT_LT(test, out.b, 0x0100);
+
+	/* == red 140 - bt709 enc == */
+	out.a = 0xffff;
+	out.r = 0x8c8c;
+	out.g = 0x0;
+	out.b = 0x0;
+
+	apply_3x4_matrix(&out, &test_matrix_3x4_bt709_enc);
+
+	/* Y 30 */
+	KUNIT_EXPECT_GT(test, out.r, 0x1D00);
+	KUNIT_EXPECT_LT(test, out.r, 0x1F00);
+
+	/* U 0 */
+	KUNIT_EXPECT_LT(test, out.g, 0x100);
+
+	/* V 87 */
+	KUNIT_EXPECT_GT(test, out.b, 0x5600);
+	KUNIT_EXPECT_LT(test, out.b, 0x5800);
+
+	/* == green 140 - bt709 enc == */
+	out.a = 0xffff;
+	out.r = 0x0;
+	out.g = 0x8c8c;
+	out.b = 0x0;
+
+	apply_3x4_matrix(&out, &test_matrix_3x4_bt709_enc);
+
+	/* Y 30 */
+	KUNIT_EXPECT_GT(test, out.r, 0x6400);
+	KUNIT_EXPECT_LT(test, out.r, 0x6600);
+
+	/* U 0 */
+	KUNIT_EXPECT_LT(test, out.g, 0x100);
+
+	/* V 0 */
+	KUNIT_EXPECT_LT(test, out.b, 0x100);
+
+
+	/* == blue 140 - bt709 enc == */
+	out.a = 0xffff;
+	out.r = 0x0;
+	out.g = 0x0;
+	out.b = 0x8c8c;
+
+	apply_3x4_matrix(&out, &test_matrix_3x4_bt709_enc);
+
+	/* Y 30 */
+	KUNIT_EXPECT_GT(test, out.r, 0x900);
+	KUNIT_EXPECT_LT(test, out.r, 0xB00);
+
+	/* U 61 */
+	KUNIT_EXPECT_GT(test, out.g, 0x3C00);
+	KUNIT_EXPECT_LT(test, out.g, 0x3E00);
+
+	/* V 0 */
+	KUNIT_EXPECT_LT(test, out.b, 0x100);
+
+}
+
 static struct kunit_case vkms_color_test_cases[] = {
 	KUNIT_CASE(vkms_color_test_get_lut_index),
 	KUNIT_CASE(vkms_color_test_lerp),
 	KUNIT_CASE(vkms_color_test_linear),
 	KUNIT_CASE(vkms_color_srgb_inv_srgb),
+	KUNIT_CASE(vkms_color_ctm_3x4_50_desat),
+	KUNIT_CASE(vkms_color_ctm_3x4_bt709),
 	{}
 };
 
diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c
index 8fe16d26d680..54fd00b49360 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -128,7 +128,8 @@ static void apply_lut(const struct vkms_crtc_state *crtc_state, struct line_buff
 	}
 }
 
-static void apply_3x4_matrix(struct pixel_argb_s32 *pixel, const struct drm_color_ctm_3x4 *matrix)
+VISIBLE_IF_KUNIT void apply_3x4_matrix(struct pixel_argb_s32 *pixel,
+				       const struct drm_color_ctm_3x4 *matrix)
 {
 	s64 rf, gf, bf;
 	s64 r, g, b;
@@ -156,6 +157,7 @@ static void apply_3x4_matrix(struct pixel_argb_s32 *pixel, const struct drm_colo
 	pixel->g = drm_fixp2int_round(gf);
 	pixel->b = drm_fixp2int_round(bf);
 }
+EXPORT_SYMBOL_IF_KUNIT(apply_3x4_matrix);
 
 static void apply_colorop(struct pixel_argb_s32 *pixel, struct drm_colorop *colorop)
 {
diff --git a/drivers/gpu/drm/vkms/vkms_composer.h b/drivers/gpu/drm/vkms/vkms_composer.h
index 67ae09913460..afef65a5c3ba 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.h
+++ b/drivers/gpu/drm/vkms/vkms_composer.h
@@ -21,6 +21,7 @@ u16 lerp_u16(u16 a, u16 b, s64 t);
 s64 get_lut_index(const struct vkms_color_lut *lut, u16 channel_value);
 u16 apply_lut_to_channel_value(const struct vkms_color_lut *lut, u16 channel_value,
 			       enum lut_channel channel);
+void apply_3x4_matrix(struct pixel_argb_s32 *pixel, const struct drm_color_ctm_3x4 *matrix);
 #endif
 
 #endif /* _VKMS_COMPOSER_H_ */
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 20/43] drm/colorop: pass plane_color_pipeline client cap to atomic check
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (18 preceding siblings ...)
  2025-03-26 23:47 ` [PATCH V8 19/43] drm/vkms: Add tests for CTM handling Alex Hung
@ 2025-03-26 23:47 ` Alex Hung
  2025-03-29 15:32   ` Simon Ser
  2025-03-26 23:47 ` [PATCH V8 21/43] drm/colorop: define a new macro for_each_new_colorop_in_state Alex Hung
                   ` (23 subsequent siblings)
  43 siblings, 1 reply; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:47 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

Drivers will need to know whether an atomic check/commit
originated from a client with DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE
so they can ignore deprecated properties, like COLOR_ENCODING
and COLOR_RANGE.

Pass the plane_color_pipeline bit to drm_atomic_state.

Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
v5:
 - Fix kernel docs

 drivers/gpu/drm/drm_atomic_uapi.c |  1 +
 include/drm/drm_atomic.h          | 18 ++++++++++++++++++
 2 files changed, 19 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index 52c6a4dfbc47..dcd12fc0bd8f 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -1600,6 +1600,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
 	drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
 	state->acquire_ctx = &ctx;
 	state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET);
+	state->plane_color_pipeline = file_priv->plane_color_pipeline;
 
 retry:
 	copied_objs = 0;
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 0f76ee3caa9d..2b088cef946a 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -464,6 +464,24 @@ struct drm_atomic_state {
 	 */
 	bool duplicated : 1;
 
+	/**
+	 * @plane_color_pipeline:
+	 *
+	 * Indicates whether this atomic state originated with a client that
+	 * set the DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE.
+	 *
+	 * Drivers and helper functions should use this to ignore legacy
+	 * properties that are incompatible with the drm_plane COLOR_PIPELINE
+	 * behavior, such as:
+	 *
+	 *  - COLOR_RANGE
+	 *  - COLOR_ENCODING
+	 *
+	 * or any other driver-specific properties that might affect pixel
+	 * values.
+	 */
+	bool plane_color_pipeline : 1;
+
 	/**
 	 * @colorops:
 	 *
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 21/43] drm/colorop: define a new macro for_each_new_colorop_in_state
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (19 preceding siblings ...)
  2025-03-26 23:47 ` [PATCH V8 20/43] drm/colorop: pass plane_color_pipeline client cap to atomic check Alex Hung
@ 2025-03-26 23:47 ` Alex Hung
  2025-03-26 23:47 ` [PATCH V8 22/43] drm/amd/display: Ignore deprecated props when plane_color_pipeline set Alex Hung
                   ` (22 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:47 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

Create a new macro for_each_new_colorop_in_state to access new
drm_colorop_state updated from uapi.

Reviewed-by: Simon Ser <contact@emersion.fr>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
 include/drm/drm_atomic.h | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 2b088cef946a..266b2e6d58ea 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -1066,6 +1066,26 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
 			      (new_colorop_state) = (__state)->colorops[__i].new_state, 1))
 
 
+/**
+ * for_each_new_colorop_in_state - iterate over all colorops in an atomic update
+ * @__state: &struct drm_atomic_state pointer
+ * @colorop: &struct drm_colorop iteration cursor
+ * @new_colorop_state: &struct drm_colorop_state iteration cursor for the new state
+ * @__i: int iteration cursor, for macro-internal use
+ *
+ * This iterates over all colorops in an atomic update, tracking new state. This is
+ * useful is useful in places where the state delta needs to be considered, for
+ * example in atomic check functions.
+ */
+#define for_each_new_colorop_in_state(__state, colorop, new_colorop_state, __i) \
+	for ((__i) = 0;							\
+	     (__i) < (__state)->dev->mode_config.num_colorop;	\
+	     (__i)++)							\
+		for_each_if ((__state)->colorops[__i].ptr &&		\
+			     ((colorop) = (__state)->colorops[__i].ptr,	\
+			      (void)(colorop) /* Only to avoid unused-but-set-variable warning */, \
+			      (new_colorop_state) = (__state)->colorops[__i].new_state, 1))
+
 /**
  * for_each_oldnew_plane_in_state - iterate over all planes in an atomic update
  * @__state: &struct drm_atomic_state pointer
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 22/43] drm/amd/display: Ignore deprecated props when plane_color_pipeline set
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (20 preceding siblings ...)
  2025-03-26 23:47 ` [PATCH V8 21/43] drm/colorop: define a new macro for_each_new_colorop_in_state Alex Hung
@ 2025-03-26 23:47 ` Alex Hung
  2025-03-26 23:47 ` [PATCH V8 23/43] drm/amd/display: Add bypass COLOR PIPELINE Alex Hung
                   ` (21 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:47 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

When the plane_color_pipeline bit is set we should ignore
deprecated properties, such as COLOR_RANGE and COLOR_ENCODING.

Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 6a54f1cfa125..b00f760afb29 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -5691,6 +5691,10 @@ fill_plane_color_attributes(const struct drm_plane_state *plane_state,
 
 	*color_space = COLOR_SPACE_SRGB;
 
+	/* Ignore properties when DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE is set */
+	if (plane_state->state && plane_state->state->plane_color_pipeline)
+		return 0;
+
 	/* DRM color properties only affect non-RGB formats. */
 	if (format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
 		return 0;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 23/43] drm/amd/display: Add bypass COLOR PIPELINE
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (21 preceding siblings ...)
  2025-03-26 23:47 ` [PATCH V8 22/43] drm/amd/display: Ignore deprecated props when plane_color_pipeline set Alex Hung
@ 2025-03-26 23:47 ` Alex Hung
  2025-03-26 23:47 ` [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane Alex Hung
                   ` (20 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:47 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

Add the default Bypass pipeline and ensure it passes the
kms_colorop test plane-XR30-XR30-bypass.

Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
index 0090e08d5057..9632b8b73e7e 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
@@ -1784,6 +1784,20 @@ dm_atomic_plane_get_property(struct drm_plane *plane,
 }
 #endif
 
+#define MAX_COLOR_PIPELINES 5
+
+static int
+dm_plane_init_colorops(struct drm_plane *plane)
+{
+	struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
+	int len = 0;
+
+	/* Create COLOR_PIPELINE property and attach */
+	drm_plane_create_color_pipeline_property(plane, pipelines, len);
+
+	return 0;
+}
+
 static const struct drm_plane_funcs dm_plane_funcs = {
 	.update_plane	= drm_atomic_helper_update_plane,
 	.disable_plane	= drm_atomic_helper_disable_plane,
@@ -1890,7 +1904,12 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
 
 #ifdef AMD_PRIVATE_COLOR
 	dm_atomic_plane_attach_color_mgmt_properties(dm, plane);
+#else
+	res = dm_plane_init_colorops(plane);
+	if (res)
+		return res;
 #endif
+
 	/* Create (reset) the plane state */
 	if (plane->funcs->reset)
 		plane->funcs->reset(plane);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (22 preceding siblings ...)
  2025-03-26 23:47 ` [PATCH V8 23/43] drm/amd/display: Add bypass COLOR PIPELINE Alex Hung
@ 2025-03-26 23:47 ` Alex Hung
  2025-03-30  9:48   ` Shengyu Qu
  2025-03-30 12:59   ` Shengyu Qu
  2025-03-26 23:47 ` [PATCH V8 25/43] drm/amd/display: Add support for sRGB EOTF in DEGAM block Alex Hung
                   ` (19 subsequent siblings)
  43 siblings, 2 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:47 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

cursor plane does not need to have color pipeline.

Signed-off-by: Alex Hung <alex.hung@amd.com>
---
v7:
 - Add a commit messages

 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
index 9632b8b73e7e..b5b9b0b5da63 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
@@ -1792,6 +1792,9 @@ dm_plane_init_colorops(struct drm_plane *plane)
 	struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
 	int len = 0;
 
+	if (plane->type == DRM_PLANE_TYPE_CURSOR)
+		return 0;
+
 	/* Create COLOR_PIPELINE property and attach */
 	drm_plane_create_color_pipeline_property(plane, pipelines, len);
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 25/43] drm/amd/display: Add support for sRGB EOTF in DEGAM block
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (23 preceding siblings ...)
  2025-03-26 23:47 ` [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane Alex Hung
@ 2025-03-26 23:47 ` Alex Hung
  2025-03-26 23:47 ` [PATCH V8 26/43] drm/amd/display: Add support for sRGB Inverse EOTF in SHAPER block Alex Hung
                   ` (18 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:47 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

Expose one 1D curve colorop with support for
DRM_COLOROP_1D_CURVE_SRGB_EOTF and program HW to perform
the sRGB transform when the colorop is not in bypass.

With this change the following IGT test passes:
kms_colorop --run plane-XR30-XR30-srgb_eotf

The color pipeline now consists of a single colorop:
1. 1D curve colorop w/ sRGB EOTF

Signed-off-by: Alex Hung <alex.hung@amd.com>
Co-developed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
v8:
 - Fix incorrect && by || in __set_colorop_in_tf_1d_curve (Leo Li)

v7:
 - Fix checkpatch warnings
  - Change switch "{ }" position
  - Delete double ";"
  - Delete "{ }" for single-line if-statement
  - Add a new line at EOF
  - Change SPDX-License-Identifier: GPL-2.0+ from // to /* */

v6:
 - cleanup if colorop alloc or init fails

 .../gpu/drm/amd/display/amdgpu_dm/Makefile    |  3 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 86 +++++++++++++++++++
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.c | 70 +++++++++++++++
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.h | 34 ++++++++
 .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   | 10 +++
 5 files changed, 202 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
 create mode 100644 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
index ab2a97e354da..46158d67ab12 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
@@ -38,7 +38,8 @@ AMDGPUDM = \
 	amdgpu_dm_pp_smu.o \
 	amdgpu_dm_psr.o \
 	amdgpu_dm_replay.o \
-	amdgpu_dm_wb.o
+	amdgpu_dm_wb.o \
+	amdgpu_dm_colorop.o
 
 ifdef CONFIG_DRM_AMD_DC_FP
 AMDGPUDM += dc_fpu.o
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index ebabfe3a512f..0b513ab5050f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -668,6 +668,18 @@ amdgpu_tf_to_dc_tf(enum amdgpu_transfer_function tf)
 	}
 }
 
+static enum dc_transfer_func_predefined
+amdgpu_colorop_tf_to_dc_tf(enum drm_colorop_curve_1d_type tf)
+{
+	switch (tf) {
+	case DRM_COLOROP_1D_CURVE_SRGB_EOTF:
+	case DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF:
+		return TRANSFER_FUNCTION_SRGB;
+	default:
+		return TRANSFER_FUNCTION_LINEAR;
+	}
+}
+
 static void __to_dc_lut3d_color(struct dc_rgb *rgb,
 				const struct drm_color_lut lut,
 				int bit_precision)
@@ -1137,6 +1149,59 @@ __set_dm_plane_degamma(struct drm_plane_state *plane_state,
 	return 0;
 }
 
+static int
+__set_colorop_in_tf_1d_curve(struct dc_plane_state *dc_plane_state,
+		       struct drm_colorop_state *colorop_state)
+{
+	struct dc_transfer_func *tf = &dc_plane_state->in_transfer_func;
+	struct drm_colorop *colorop = colorop_state->colorop;
+	struct drm_device *drm = colorop->dev;
+
+	if (colorop->type != DRM_COLOROP_1D_CURVE ||
+	    colorop_state->curve_1d_type != DRM_COLOROP_1D_CURVE_SRGB_EOTF)
+		return -EINVAL;
+
+	if (colorop_state->bypass) {
+		tf->type = TF_TYPE_BYPASS;
+		tf->tf = TRANSFER_FUNCTION_LINEAR;
+		return 0;
+	}
+
+	drm_dbg(drm, "Degamma colorop with ID: %d\n", colorop->base.id);
+
+	tf->type = TF_TYPE_PREDEFINED;
+	tf->tf = amdgpu_colorop_tf_to_dc_tf(colorop_state->curve_1d_type);
+
+	return 0;
+}
+
+static int
+__set_dm_plane_colorop_degamma(struct drm_plane_state *plane_state,
+			       struct dc_plane_state *dc_plane_state,
+			       struct drm_colorop *colorop)
+{
+	struct drm_colorop *old_colorop;
+	struct drm_colorop_state *colorop_state = NULL, *new_colorop_state;
+	struct drm_atomic_state *state = plane_state->state;
+	int i = 0;
+
+	old_colorop = colorop;
+
+	/* 1st op: 1d curve - degamma */
+	for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
+		if (new_colorop_state->colorop == old_colorop &&
+		    new_colorop_state->curve_1d_type == DRM_COLOROP_1D_CURVE_SRGB_EOTF) {
+			colorop_state = new_colorop_state;
+			break;
+		}
+	}
+
+	if (!colorop_state)
+		return -EINVAL;
+
+	return __set_colorop_in_tf_1d_curve(dc_plane_state, colorop_state);
+}
+
 static int
 amdgpu_dm_plane_set_color_properties(struct drm_plane_state *plane_state,
 				     struct dc_plane_state *dc_plane_state)
@@ -1187,6 +1252,24 @@ amdgpu_dm_plane_set_color_properties(struct drm_plane_state *plane_state,
 	return 0;
 }
 
+static int
+amdgpu_dm_plane_set_colorop_properties(struct drm_plane_state *plane_state,
+		       struct dc_plane_state *dc_plane_state)
+{
+	struct drm_colorop *colorop = plane_state->color_pipeline;
+	int ret;
+
+	/* 1D Curve - DEGAM TF */
+	if (!colorop)
+		return -EINVAL;
+
+	ret = __set_dm_plane_colorop_degamma(plane_state, dc_plane_state, colorop);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 /**
  * amdgpu_dm_update_plane_color_mgmt: Maps DRM color management to DC plane.
  * @crtc: amdgpu_dm crtc state
@@ -1283,5 +1366,8 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
 		dc_plane_state->input_csc_color_matrix.enable_adjustment = false;
 	}
 
+	if (!amdgpu_dm_plane_set_colorop_properties(plane_state, dc_plane_state))
+		return 0;
+
 	return amdgpu_dm_plane_set_color_properties(plane_state, dc_plane_state);
 }
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
new file mode 100644
index 000000000000..3be0cb19ebc7
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include <drm/drm_print.h>
+#include <drm/drm_plane.h>
+#include <drm/drm_property.h>
+#include <drm/drm_colorop.h>
+
+#include "amdgpu_dm_colorop.h"
+
+const u64 amdgpu_dm_supported_degam_tfs =
+	BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF);
+
+#define MAX_COLOR_PIPELINE_OPS 10
+
+int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list)
+{
+	struct drm_colorop *ops[MAX_COLOR_PIPELINE_OPS];
+	struct drm_device *dev = plane->dev;
+	int ret;
+	int i = 0;
+
+	memset(ops, 0, sizeof(ops));
+
+	/* 1D curve - DEGAM TF */
+	ops[i] = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
+	if (!ops[i]) {
+		DRM_ERROR("KMS: Failed to allocate colorop\n");
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	ret = drm_colorop_curve_1d_init(dev, ops[i], plane, amdgpu_dm_supported_degam_tfs);
+	if (ret)
+		goto cleanup;
+
+	list->type = ops[i]->base.id;
+	list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", ops[i]->base.id);
+
+	return 0;
+
+cleanup:
+	for (; i >= 0; i--)
+		kfree(ops[i]);
+
+	return ret;
+}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h
new file mode 100644
index 000000000000..3324e2a66079
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2023 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __AMDGPU_DM_COLOROP_H__
+#define __AMDGPU_DM_COLOROP_H__
+
+extern const u64 amdgpu_dm_supported_degam_tfs;
+
+int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list);
+
+#endif /* __AMDGPU_DM_COLOROP_H__*/
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
index b5b9b0b5da63..bf97957ad4a2 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
@@ -37,6 +37,7 @@
 #include "amdgpu_display.h"
 #include "amdgpu_dm_trace.h"
 #include "amdgpu_dm_plane.h"
+#include "amdgpu_dm_colorop.h"
 #include "gc/gc_11_0_0_offset.h"
 #include "gc/gc_11_0_0_sh_mask.h"
 
@@ -1791,10 +1792,19 @@ dm_plane_init_colorops(struct drm_plane *plane)
 {
 	struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
 	int len = 0;
+	int ret;
 
 	if (plane->type == DRM_PLANE_TYPE_CURSOR)
 		return 0;
 
+	/* initialize default pipeline */
+	ret = amdgpu_dm_initialize_default_pipeline(plane, &(pipelines[len]));
+	if (ret) {
+		DRM_ERROR("Failed to create color pipeline for plane %d: %d\n", plane->base.id, ret);
+		return ret;
+	}
+	len++;
+
 	/* Create COLOR_PIPELINE property and attach */
 	drm_plane_create_color_pipeline_property(plane, pipelines, len);
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 26/43] drm/amd/display: Add support for sRGB Inverse EOTF in SHAPER block
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (24 preceding siblings ...)
  2025-03-26 23:47 ` [PATCH V8 25/43] drm/amd/display: Add support for sRGB EOTF in DEGAM block Alex Hung
@ 2025-03-26 23:47 ` Alex Hung
  2025-03-26 23:47 ` [PATCH V8 27/43] drm/amd/display: Add support for sRGB EOTF in BLND block Alex Hung
                   ` (17 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:47 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

Expose a 2nd curve colorop with support for
DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF and program HW to
perform the sRGB Inverse EOTF on the shaper block
when the colorop is not in bypass.

With this change the follow IGT tests pass:
kms_colorop --run plane-XR30-XR30-srgb_inv_eotf
kms_colorop --run plane-XR30-XR30-srgb_eotf-srgb_inv_eotf

The color pipeline now consists of the following colorops:
1. 1D curve colorop w/ sRGB EOTF support
2. 1D curve colorop w/ sRGB Inverse EOTF support

Signed-off-by: Alex Hung <alex.hung@amd.com>
Co-developed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
v6:
 - don't pass uninitialized variable into __set_output_tf

 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 74 +++++++++++++++++++
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.c | 19 +++++
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.h |  1 +
 3 files changed, 94 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index 0b513ab5050f..4662d88885de 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -1202,6 +1202,68 @@ __set_dm_plane_colorop_degamma(struct drm_plane_state *plane_state,
 	return __set_colorop_in_tf_1d_curve(dc_plane_state, colorop_state);
 }
 
+static int
+__set_colorop_in_shaper_1d_curve(struct dc_plane_state *dc_plane_state,
+		       struct drm_colorop_state *colorop_state)
+{
+	struct dc_transfer_func *tf = &dc_plane_state->in_shaper_func;
+	struct drm_colorop *colorop = colorop_state->colorop;
+	struct drm_device *drm = colorop->dev;
+
+	if (colorop->type != DRM_COLOROP_1D_CURVE &&
+	    colorop_state->curve_1d_type != DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF)
+		return -EINVAL;
+
+	if (colorop_state->bypass) {
+		tf->type = TF_TYPE_BYPASS;
+		tf->tf = TRANSFER_FUNCTION_LINEAR;
+		return 0;
+	}
+
+	drm_dbg(drm, "Shaper colorop with ID: %d\n", colorop->base.id);
+
+	if (colorop->type == DRM_COLOROP_1D_CURVE) {
+		tf->type = TF_TYPE_DISTRIBUTED_POINTS;
+		tf->tf = amdgpu_colorop_tf_to_dc_tf(colorop_state->curve_1d_type);
+		tf->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
+		return __set_output_tf(tf, 0, 0, false);
+	}
+
+	return -EINVAL;
+}
+
+static int
+__set_dm_plane_colorop_shaper(struct drm_plane_state *plane_state,
+			      struct dc_plane_state *dc_plane_state,
+			      struct drm_colorop *colorop)
+{
+	struct drm_colorop *old_colorop;
+	struct drm_colorop_state *colorop_state = NULL, *new_colorop_state;
+	struct drm_atomic_state *state = plane_state->state;
+	int i = 0;
+
+	old_colorop = colorop;
+
+	/* 2nd op: 1d curve - shaper */
+	for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
+		if (new_colorop_state->colorop == old_colorop &&
+		    new_colorop_state->curve_1d_type == DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF) {
+			colorop_state = new_colorop_state;
+			break;
+		}
+
+		if (new_colorop_state->colorop == old_colorop) {
+			colorop_state = new_colorop_state;
+			break;
+		}
+	}
+
+	if (!colorop_state)
+		return -EINVAL;
+
+	return __set_colorop_in_shaper_1d_curve(dc_plane_state, colorop_state);
+}
+
 static int
 amdgpu_dm_plane_set_color_properties(struct drm_plane_state *plane_state,
 				     struct dc_plane_state *dc_plane_state)
@@ -1257,6 +1319,7 @@ amdgpu_dm_plane_set_colorop_properties(struct drm_plane_state *plane_state,
 		       struct dc_plane_state *dc_plane_state)
 {
 	struct drm_colorop *colorop = plane_state->color_pipeline;
+	struct drm_device *dev = plane_state->plane->dev;
 	int ret;
 
 	/* 1D Curve - DEGAM TF */
@@ -1267,6 +1330,17 @@ amdgpu_dm_plane_set_colorop_properties(struct drm_plane_state *plane_state,
 	if (ret)
 		return ret;
 
+	/* 1D Curve - SHAPER TF */
+	colorop = colorop->next;
+	if (!colorop) {
+		drm_dbg(dev, "no Shaper TF colorop found\n");
+		return -EINVAL;
+	}
+
+	ret = __set_dm_plane_colorop_shaper(plane_state, dc_plane_state, colorop);
+	if (ret)
+		return ret;
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
index 3be0cb19ebc7..718544b11863 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
@@ -34,6 +34,9 @@
 const u64 amdgpu_dm_supported_degam_tfs =
 	BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF);
 
+const u64 amdgpu_dm_supported_shaper_tfs =
+	BIT(DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF);
+
 #define MAX_COLOR_PIPELINE_OPS 10
 
 int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list)
@@ -60,6 +63,22 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
 	list->type = ops[i]->base.id;
 	list->name = kasprintf(GFP_KERNEL, "Color Pipeline %d", ops[i]->base.id);
 
+	i++;
+
+	/* 1D curve - SHAPER TF */
+	ops[i] = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
+	if (!ops[i]) {
+		DRM_ERROR("KMS: Failed to allocate colorop\n");
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	ret = drm_colorop_curve_1d_init(dev, ops[i], plane, amdgpu_dm_supported_shaper_tfs);
+	if (ret)
+		goto cleanup;
+
+	drm_colorop_set_next_property(ops[i-1], ops[i]);
+
 	return 0;
 
 cleanup:
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h
index 3324e2a66079..71cd27994528 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h
@@ -28,6 +28,7 @@
 #define __AMDGPU_DM_COLOROP_H__
 
 extern const u64 amdgpu_dm_supported_degam_tfs;
+extern const u64 amdgpu_dm_supported_shaper_tfs;
 
 int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list);
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 27/43] drm/amd/display: Add support for sRGB EOTF in BLND block
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (25 preceding siblings ...)
  2025-03-26 23:47 ` [PATCH V8 26/43] drm/amd/display: Add support for sRGB Inverse EOTF in SHAPER block Alex Hung
@ 2025-03-26 23:47 ` Alex Hung
  2025-03-26 23:47 ` [PATCH V8 28/43] drm/colorop: Add PQ 125 EOTF and its inverse Alex Hung
                   ` (16 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:47 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

Expose a 3rd 1D curve colorop, with support for
DRM_COLOROP_1D_CURVE_SRGB_EOTF and program the BLND block
to perform the sRGB transform when the colorop is not in
bypass

With this change the following IGT test passes:
kms_colorop --run plane-XR30-XR30-srgb_eotf-srgb_inv_eotf-srgb_eotf

The color pipeline now consists of the following colorops:
1. 1D curve colorop w/ sRGB EOTF support
2. 1D curve colorop w/ sRGB Inverse EOTF support
3. 1D curve colorop w/ sRGB EOTF support

Signed-off-by: Alex Hung <alex.hung@amd.com>
Co-developed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
v7:
 - Initialized uint32_t blend_size = 0 by default (kernel test robot)

 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 77 +++++++++++++++++++
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.c | 19 +++++
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.h |  1 +
 3 files changed, 97 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index 4662d88885de..7ce95ddf3851 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -1264,6 +1264,72 @@ __set_dm_plane_colorop_shaper(struct drm_plane_state *plane_state,
 	return __set_colorop_in_shaper_1d_curve(dc_plane_state, colorop_state);
 }
 
+
+static int
+__set_colorop_1d_curve_blend_tf_lut(struct dc_plane_state *dc_plane_state,
+				  struct drm_colorop_state *colorop_state)
+{
+
+	struct dc_transfer_func *tf = &dc_plane_state->blend_tf;
+	struct drm_colorop *colorop = colorop_state->colorop;
+	struct drm_device *drm = colorop->dev;
+	const struct drm_color_lut *blend_lut;
+	uint32_t blend_size = 0;
+
+	if (colorop->type != DRM_COLOROP_1D_CURVE &&
+	    colorop_state->curve_1d_type != DRM_COLOROP_1D_CURVE_SRGB_EOTF)
+		return -EINVAL;
+
+	if (colorop_state->bypass) {
+		tf->type = TF_TYPE_BYPASS;
+		tf->tf = TRANSFER_FUNCTION_LINEAR;
+		return 0;
+	}
+
+	drm_dbg(drm, "Blend colorop with ID: %d\n", colorop->base.id);
+
+	if (colorop->type == DRM_COLOROP_1D_CURVE) {
+		tf->type = TF_TYPE_DISTRIBUTED_POINTS;
+		tf->tf = amdgpu_colorop_tf_to_dc_tf(colorop_state->curve_1d_type);
+		tf->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
+		return __set_input_tf(NULL, tf, blend_lut, blend_size);
+	}
+
+	return -EINVAL;
+}
+
+static int
+__set_dm_plane_colorop_blend(struct drm_plane_state *plane_state,
+			     struct dc_plane_state *dc_plane_state,
+			     struct drm_colorop *colorop)
+{
+	struct drm_colorop *old_colorop;
+	struct drm_colorop_state *colorop_state = NULL, *new_colorop_state;
+	struct drm_atomic_state *state = plane_state->state;
+	int i = 0;
+
+	old_colorop = colorop;
+
+	/* 3nd op: 1d curve - blend */
+	for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
+		if (new_colorop_state->colorop == old_colorop &&
+		    new_colorop_state->curve_1d_type == DRM_COLOROP_1D_CURVE_SRGB_EOTF) {
+			colorop_state = new_colorop_state;
+			break;
+		}
+
+		if (new_colorop_state->colorop == old_colorop) {
+			colorop_state = new_colorop_state;
+			break;
+		}
+	}
+
+	if (!colorop_state)
+		return -EINVAL;
+
+	return __set_colorop_1d_curve_blend_tf_lut(dc_plane_state, colorop_state);
+}
+
 static int
 amdgpu_dm_plane_set_color_properties(struct drm_plane_state *plane_state,
 				     struct dc_plane_state *dc_plane_state)
@@ -1341,6 +1407,17 @@ amdgpu_dm_plane_set_colorop_properties(struct drm_plane_state *plane_state,
 	if (ret)
 		return ret;
 
+	/* 1D Curve - BLND TF */
+	colorop = colorop->next;
+	if (!colorop) {
+		drm_dbg(dev, "no Blend TF colorop found\n");
+		return -EINVAL;
+	}
+
+	ret = __set_dm_plane_colorop_blend(plane_state, dc_plane_state, colorop);
+	if (ret)
+		return ret;
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
index 718544b11863..c5154e1430f5 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
@@ -37,6 +37,9 @@ const u64 amdgpu_dm_supported_degam_tfs =
 const u64 amdgpu_dm_supported_shaper_tfs =
 	BIT(DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF);
 
+const u64 amdgpu_dm_supported_blnd_tfs =
+	BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF);
+
 #define MAX_COLOR_PIPELINE_OPS 10
 
 int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list)
@@ -79,6 +82,22 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
 
 	drm_colorop_set_next_property(ops[i-1], ops[i]);
 
+	i++;
+
+	/* 1D curve - BLND TF */
+	ops[i] = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
+	if (!ops[i]) {
+		DRM_ERROR("KMS: Failed to allocate colorop\n");
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	ret = drm_colorop_curve_1d_init(dev, ops[i], plane, amdgpu_dm_supported_blnd_tfs);
+	if (ret)
+		goto cleanup;
+
+	drm_colorop_set_next_property(ops[i-1], ops[i]);
+
 	return 0;
 
 cleanup:
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h
index 71cd27994528..2e1617ffc8ee 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.h
@@ -29,6 +29,7 @@
 
 extern const u64 amdgpu_dm_supported_degam_tfs;
 extern const u64 amdgpu_dm_supported_shaper_tfs;
+extern const u64 amdgpu_dm_supported_blnd_tfs;
 
 int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list);
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 28/43] drm/colorop: Add PQ 125 EOTF and its inverse
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (26 preceding siblings ...)
  2025-03-26 23:47 ` [PATCH V8 27/43] drm/amd/display: Add support for sRGB EOTF in BLND block Alex Hung
@ 2025-03-26 23:47 ` Alex Hung
  2025-03-29 14:48   ` Simon Ser
  2025-03-26 23:47 ` [PATCH V8 29/43] drm/amd/display: Enable support for PQ 125 EOTF and Inverse Alex Hung
                   ` (15 subsequent siblings)
  43 siblings, 1 reply; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:47 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

The PQ function defines a mapping of code values to nits (cd/m^2).
The max code value maps to 10,000 nits.

Windows DWM's canonical composition color space (CCCS)  defaults
to composing SDR contents to 80 nits and uses a float value of
1.0 to represent this. For this reason AMD HW hard-codes a PQ
function that is scaled by 125, yielding 80 nit PQ values for
1.0 and 10,000 nits at 125.0.

This patch introduces this scaled PQ EOTF and its inverse as
1D curve types.

Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
 drivers/gpu/drm/drm_colorop.c |  2 ++
 include/drm/drm_colorop.h     | 24 ++++++++++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index 8ab754f935e6..914fa0fa71d1 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -70,6 +70,8 @@ static const struct drm_prop_enum_list drm_colorop_type_enum_list[] = {
 static const char * const colorop_curve_1d_type_names[] = {
 	[DRM_COLOROP_1D_CURVE_SRGB_EOTF] = "sRGB EOTF",
 	[DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF] = "sRGB Inverse EOTF",
+	[DRM_COLOROP_1D_CURVE_PQ_125_EOTF] = "PQ 125 EOTF",
+	[DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF] = "PQ 125 Inverse EOTF",
 };
 
 
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index d9149c320bac..ce51ac407c70 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -59,6 +59,30 @@ enum drm_colorop_curve_1d_type {
 	 */
 	DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF,
 
+	/**
+	 * @DRM_COLOROP_1D_CURVE_PQ_125_EOTF:
+	 *
+	 * enum string "PQ 125 EOTF"
+	 *
+	 * The PQ transfer function, scaled by 125.0f, so that 10,000
+	 * nits correspond to 125.0f.
+	 *
+	 * Transfer characteristics of the PQ function as defined by
+	 * SMPTE ST 2084 (2014) for 10-, 12-, 14-, and 16-bit systems
+	 * and Rec. ITU-R BT.2100-2 perceptual quantization (PQ) system,
+	 * represented by H.273 TransferCharacteristics code point 16.
+	 */
+	DRM_COLOROP_1D_CURVE_PQ_125_EOTF,
+
+	/**
+	 * @DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF:
+	 *
+	 * enum string "PQ 125 Inverse EOTF"
+	 *
+	 * The inverse of DRM_COLOROP_1D_CURVE_PQ_125_EOTF.
+	 */
+	DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF,
+
 	/**
 	 * @DRM_COLOROP_1D_CURVE_COUNT:
 	 *
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 29/43] drm/amd/display: Enable support for PQ 125 EOTF and Inverse
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (27 preceding siblings ...)
  2025-03-26 23:47 ` [PATCH V8 28/43] drm/colorop: Add PQ 125 EOTF and its inverse Alex Hung
@ 2025-03-26 23:47 ` Alex Hung
  2025-03-26 23:47 ` [PATCH V8 30/43] drm/colorop: add BT2020/BT709 OETF and Inverse OETF Alex Hung
                   ` (14 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:47 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

This patchset enables support for the PQ_125 EOTF and its inverse
on all existing plane 1D curve colorops, i.e., on DEGAM, SHAPER,
and BLND blocks.

With this patchset the following IGT subtests are passing:
kms_colorop --run plane-XR30-XR30-pq_125_eotf
kms_colorop --run plane-XR30-XR30-pq_125_inv_eotf
kms_colorop --run plane-XR30-XR30-pq_125_eotf-pq_125_inv_eotf
kms_colorop --run plane-XR30-XR30-pq_125_eotf-pq_125_inv_eotf-pq_125_eotf

Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
v8: 
 - Move BIT(DRM_COLOROP_1D_CURVE_PQ_125_EOTF) in amdgpu_dm_supported_blnd_tfs
   from "drm/amd/display: Add support for BT.709 and BT.2020 TFs" (Leo Li)

 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 20 +++++++++++++------
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.c |  9 ++++++---
 2 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index 7ce95ddf3851..63044e0296cb 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -25,6 +25,7 @@
 #include "amdgpu.h"
 #include "amdgpu_mode.h"
 #include "amdgpu_dm.h"
+#include "amdgpu_dm_colorop.h"
 #include "dc.h"
 #include "modules/color/color_gamma.h"
 #include "basics/conversion.h"
@@ -675,6 +676,9 @@ amdgpu_colorop_tf_to_dc_tf(enum drm_colorop_curve_1d_type tf)
 	case DRM_COLOROP_1D_CURVE_SRGB_EOTF:
 	case DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF:
 		return TRANSFER_FUNCTION_SRGB;
+	case DRM_COLOROP_1D_CURVE_PQ_125_EOTF:
+	case DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF:
+		return TRANSFER_FUNCTION_PQ;
 	default:
 		return TRANSFER_FUNCTION_LINEAR;
 	}
@@ -1157,8 +1161,10 @@ __set_colorop_in_tf_1d_curve(struct dc_plane_state *dc_plane_state,
 	struct drm_colorop *colorop = colorop_state->colorop;
 	struct drm_device *drm = colorop->dev;
 
-	if (colorop->type != DRM_COLOROP_1D_CURVE ||
-	    colorop_state->curve_1d_type != DRM_COLOROP_1D_CURVE_SRGB_EOTF)
+	if (colorop->type != DRM_COLOROP_1D_CURVE)
+		return -EINVAL;
+
+	if (!(BIT(colorop_state->curve_1d_type) & amdgpu_dm_supported_degam_tfs))
 		return -EINVAL;
 
 	if (colorop_state->bypass) {
@@ -1190,7 +1196,7 @@ __set_dm_plane_colorop_degamma(struct drm_plane_state *plane_state,
 	/* 1st op: 1d curve - degamma */
 	for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
 		if (new_colorop_state->colorop == old_colorop &&
-		    new_colorop_state->curve_1d_type == DRM_COLOROP_1D_CURVE_SRGB_EOTF) {
+		    (BIT(new_colorop_state->curve_1d_type) & amdgpu_dm_supported_degam_tfs)) {
 			colorop_state = new_colorop_state;
 			break;
 		}
@@ -1210,8 +1216,10 @@ __set_colorop_in_shaper_1d_curve(struct dc_plane_state *dc_plane_state,
 	struct drm_colorop *colorop = colorop_state->colorop;
 	struct drm_device *drm = colorop->dev;
 
-	if (colorop->type != DRM_COLOROP_1D_CURVE &&
-	    colorop_state->curve_1d_type != DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF)
+	if (colorop->type != DRM_COLOROP_1D_CURVE)
+		return -EINVAL;
+
+	if (!(BIT(colorop_state->curve_1d_type) & amdgpu_dm_supported_shaper_tfs))
 		return -EINVAL;
 
 	if (colorop_state->bypass) {
@@ -1247,7 +1255,7 @@ __set_dm_plane_colorop_shaper(struct drm_plane_state *plane_state,
 	/* 2nd op: 1d curve - shaper */
 	for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
 		if (new_colorop_state->colorop == old_colorop &&
-		    new_colorop_state->curve_1d_type == DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF) {
+		    (BIT(new_colorop_state->curve_1d_type) & amdgpu_dm_supported_shaper_tfs)) {
 			colorop_state = new_colorop_state;
 			break;
 		}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
index c5154e1430f5..581f41907c79 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
@@ -32,13 +32,16 @@
 #include "amdgpu_dm_colorop.h"
 
 const u64 amdgpu_dm_supported_degam_tfs =
-	BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF);
+	BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) |
+	BIT(DRM_COLOROP_1D_CURVE_PQ_125_EOTF);
 
 const u64 amdgpu_dm_supported_shaper_tfs =
-	BIT(DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF);
+	BIT(DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF) |
+	BIT(DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF);
 
 const u64 amdgpu_dm_supported_blnd_tfs =
-	BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF);
+	BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) |
+	BIT(DRM_COLOROP_1D_CURVE_PQ_125_EOTF);
 
 #define MAX_COLOR_PIPELINE_OPS 10
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 30/43] drm/colorop: add BT2020/BT709 OETF and Inverse OETF
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (28 preceding siblings ...)
  2025-03-26 23:47 ` [PATCH V8 29/43] drm/amd/display: Enable support for PQ 125 EOTF and Inverse Alex Hung
@ 2025-03-26 23:47 ` Alex Hung
  2025-03-29 14:53   ` Simon Ser
  2025-03-26 23:47 ` [PATCH V8 31/43] drm/amd/display: Add support for BT.709 and BT.2020 TFs Alex Hung
                   ` (13 subsequent siblings)
  43 siblings, 1 reply; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:47 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

The BT.709 and BT.2020 OETFs are the same, the only difference
being that the BT.2020 variant is defined with more precision
for 10 and 12-bit per color encodings.

Both are used as encoding functions for video content, and are
therefore defined as OETF (opto-electronic transfer function)
instead of as EOTF (electro-optical transfer function).

Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
 drivers/gpu/drm/drm_colorop.c |  2 ++
 include/drm/drm_colorop.h     | 23 +++++++++++++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index 914fa0fa71d1..fcb4a8d0e38d 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -70,6 +70,8 @@ static const struct drm_prop_enum_list drm_colorop_type_enum_list[] = {
 static const char * const colorop_curve_1d_type_names[] = {
 	[DRM_COLOROP_1D_CURVE_SRGB_EOTF] = "sRGB EOTF",
 	[DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF] = "sRGB Inverse EOTF",
+	[DRM_COLOROP_1D_CURVE_BT2020_INV_OETF] = "BT.2020 Inverse OETF",
+	[DRM_COLOROP_1D_CURVE_BT2020_OETF] = "BT.2020 OETF",
 	[DRM_COLOROP_1D_CURVE_PQ_125_EOTF] = "PQ 125 EOTF",
 	[DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF] = "PQ 125 Inverse EOTF",
 };
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index ce51ac407c70..d3a60c1beed1 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -59,6 +59,29 @@ enum drm_colorop_curve_1d_type {
 	 */
 	DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF,
 
+	/**
+	 * @DRM_COLOROP_1D_CURVE_BT2020_INV_OETF:
+	 *
+	 * enum string "BT.2020 Inverse OETF"
+	 *
+	 * The inverse of &DRM_COLOROP_1D_CURVE_BT2020_OETF
+	 */
+	DRM_COLOROP_1D_CURVE_BT2020_INV_OETF,
+
+	/**
+	 * @DRM_COLOROP_1D_CURVE_BT2020_OETF:
+	 *
+	 * enum string "BT.2020 OETF"
+	 *
+	 * The BT.2020/BT.709 transfer function. The BT.709 and BT.2020
+	 * transfer functions are the same, the only difference is that
+	 * BT.2020 is defined with more precision for 10 and 12-bit
+	 * encodings.
+	 *
+	 *
+	 */
+	DRM_COLOROP_1D_CURVE_BT2020_OETF,
+
 	/**
 	 * @DRM_COLOROP_1D_CURVE_PQ_125_EOTF:
 	 *
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 31/43] drm/amd/display: Add support for BT.709 and BT.2020 TFs
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (29 preceding siblings ...)
  2025-03-26 23:47 ` [PATCH V8 30/43] drm/colorop: add BT2020/BT709 OETF and Inverse OETF Alex Hung
@ 2025-03-26 23:47 ` Alex Hung
  2025-03-26 23:47 ` [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type Alex Hung
                   ` (12 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:47 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

This adds support for the BT.709/BT.2020 transfer functions
on all current 1D curve plane colorops, i.e., on DEGAM, SHAPER,
and BLND blocks.

With this change the following IGT subtests pass:
kms_colorop --run plane-XR30-XR30-bt2020_inv_oetf
kms_colorop --run plane-XR30-XR30-bt2020_oetf

Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
v8: 
 - Move BIT(DRM_COLOROP_1D_CURVE_PQ_125_EOTF) in amdgpu_dm_supported_blnd_tfs
   to "drm/amd/display: Enable support for PQ 125 EOTF and Inverse" (Leo Li)

 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c   | 11 ++++++++---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c |  9 ++++++---
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index 63044e0296cb..1765402bc122 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -676,6 +676,9 @@ amdgpu_colorop_tf_to_dc_tf(enum drm_colorop_curve_1d_type tf)
 	case DRM_COLOROP_1D_CURVE_SRGB_EOTF:
 	case DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF:
 		return TRANSFER_FUNCTION_SRGB;
+	case DRM_COLOROP_1D_CURVE_BT2020_INV_OETF:
+	case DRM_COLOROP_1D_CURVE_BT2020_OETF:
+		return TRANSFER_FUNCTION_BT709;
 	case DRM_COLOROP_1D_CURVE_PQ_125_EOTF:
 	case DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF:
 		return TRANSFER_FUNCTION_PQ;
@@ -1284,8 +1287,10 @@ __set_colorop_1d_curve_blend_tf_lut(struct dc_plane_state *dc_plane_state,
 	const struct drm_color_lut *blend_lut;
 	uint32_t blend_size = 0;
 
-	if (colorop->type != DRM_COLOROP_1D_CURVE &&
-	    colorop_state->curve_1d_type != DRM_COLOROP_1D_CURVE_SRGB_EOTF)
+	if (colorop->type != DRM_COLOROP_1D_CURVE)
+		return -EINVAL;
+
+	if (!(BIT(colorop_state->curve_1d_type) & amdgpu_dm_supported_blnd_tfs))
 		return -EINVAL;
 
 	if (colorop_state->bypass) {
@@ -1321,7 +1326,7 @@ __set_dm_plane_colorop_blend(struct drm_plane_state *plane_state,
 	/* 3nd op: 1d curve - blend */
 	for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
 		if (new_colorop_state->colorop == old_colorop &&
-		    new_colorop_state->curve_1d_type == DRM_COLOROP_1D_CURVE_SRGB_EOTF) {
+		    (BIT(new_colorop_state->curve_1d_type) & amdgpu_dm_supported_blnd_tfs)) {
 			colorop_state = new_colorop_state;
 			break;
 		}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
index 581f41907c79..ff5828a1e8cd 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
@@ -33,15 +33,18 @@
 
 const u64 amdgpu_dm_supported_degam_tfs =
 	BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) |
-	BIT(DRM_COLOROP_1D_CURVE_PQ_125_EOTF);
+	BIT(DRM_COLOROP_1D_CURVE_PQ_125_EOTF) |
+	BIT(DRM_COLOROP_1D_CURVE_BT2020_INV_OETF);
 
 const u64 amdgpu_dm_supported_shaper_tfs =
 	BIT(DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF) |
-	BIT(DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF);
+	BIT(DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF) |
+	BIT(DRM_COLOROP_1D_CURVE_BT2020_OETF);
 
 const u64 amdgpu_dm_supported_blnd_tfs =
 	BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) |
-	BIT(DRM_COLOROP_1D_CURVE_PQ_125_EOTF);
+	BIT(DRM_COLOROP_1D_CURVE_PQ_125_EOTF) |
+	BIT(DRM_COLOROP_1D_CURVE_BT2020_INV_OETF);
 
 #define MAX_COLOR_PIPELINE_OPS 10
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (30 preceding siblings ...)
  2025-03-26 23:47 ` [PATCH V8 31/43] drm/amd/display: Add support for BT.709 and BT.2020 TFs Alex Hung
@ 2025-03-26 23:47 ` Alex Hung
  2025-03-29 14:55   ` Simon Ser
  2025-04-15  6:09   ` Shankar, Uma
  2025-03-26 23:47 ` [PATCH V8 33/43] drm/amd/display: add shaper and blend colorops for 1D Curve Custom LUT Alex Hung
                   ` (11 subsequent siblings)
  43 siblings, 2 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:47 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

We've previously introduced DRM_COLOROP_1D_CURVE for
pre-defined 1D curves. But we also have HW that supports
custom curves and userspace needs the ability to pass
custom curves, aka LUTs.

This patch introduces a new colorop type, called
DRM_COLOROP_1D_LUT that provides a SIZE property which
is used by a driver to advertise the supported SIZE
of the LUT, as well as a DATA property which userspace
uses to set the LUT.

DATA and size function in the same way as current drm_crtc
GAMMA and DEGAMMA LUTs.

Signed-off-by: Alex Hung <alex.hung@amd.com>
Co-developed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
v8:
 - Add DRM_MODE_PROP_ATOMIC to drm_property_create_range (Simon Ser)
 - Change "1D Curve Custom LUT" to "1D LUT" (Simon Ser)

v7:
 - Change "size" to "lut_size" (this affects multiple following commits)
 - Move "lut_size" from drm_colorop_state to drm_colorop
 - Modify other files accordingly (i.e. from drm_colorop_state->size
   to drm_colorop->lut_size)

v5:
 - Add kernel doc
 - Define SIZE in similar manner to GAMMA_SIZE on drm_crtc (Melissa)

 drivers/gpu/drm/drm_atomic.c      |  4 +++
 drivers/gpu/drm/drm_atomic_uapi.c |  5 ++++
 drivers/gpu/drm/drm_colorop.c     | 43 +++++++++++++++++++++++++++++++
 include/drm/drm_colorop.h         | 16 ++++++++++++
 include/uapi/drm/drm_mode.h       | 14 ++++++++++
 5 files changed, 82 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 5223cf363692..f713d177241d 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -793,6 +793,10 @@ static void drm_atomic_colorop_print_state(struct drm_printer *p,
 		drm_printf(p, "\tcurve_1d_type=%s\n",
 			   drm_get_colorop_curve_1d_type_name(state->curve_1d_type));
 		break;
+	case DRM_COLOROP_1D_LUT:
+		drm_printf(p, "\tsize=%d\n", colorop->lut_size);
+		drm_printf(p, "\tdata blob id=%d\n", state->data ? state->data->base.id : 0);
+		break;
 	case DRM_COLOROP_CTM_3X4:
 		drm_printf(p, "\tdata blob id=%d\n", state->data ? state->data->base.id : 0);
 		break;
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index dcd12fc0bd8f..dfd88a227da7 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -713,6 +713,9 @@ static int drm_atomic_color_set_data_property(struct drm_colorop *colorop,
 	bool replaced = false;
 
 	switch (colorop->type) {
+	case DRM_COLOROP_1D_LUT:
+		size = colorop->lut_size * sizeof(struct drm_color_lut);
+		break;
 	case DRM_COLOROP_CTM_3X4:
 		size = sizeof(struct drm_color_ctm_3x4);
 		break;
@@ -762,6 +765,8 @@ drm_atomic_colorop_get_property(struct drm_colorop *colorop,
 		*val = state->bypass;
 	} else if (property == colorop->curve_1d_type_property) {
 		*val = state->curve_1d_type;
+	} else if (property == colorop->lut_size_property) {
+		*val = colorop->lut_size;
 	} else if (property == colorop->data_property) {
 		*val = (state->data) ? state->data->base.id : 0;
 	} else {
diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index fcb4a8d0e38d..15ffbba60b3d 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -64,6 +64,7 @@
 
 static const struct drm_prop_enum_list drm_colorop_type_enum_list[] = {
 	{ DRM_COLOROP_1D_CURVE, "1D Curve" },
+	{ DRM_COLOROP_1D_LUT, "1D LUT" },
 	{ DRM_COLOROP_CTM_3X4, "3x4 Matrix"},
 };
 
@@ -225,6 +226,47 @@ static int drm_colorop_create_data_prop(struct drm_device *dev, struct drm_color
 	return 0;
 }
 
+/**
+ * drm_colorop_curve_1d_lut_init - Initialize a DRM_COLOROP_1D_LUT
+ *
+ * @dev: DRM device
+ * @colorop: The drm_colorop object to initialize
+ * @plane: The associated drm_plane
+ * @lut_size: LUT size supported by driver
+ * @return zero on success, -E value on failure
+ */
+int drm_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_colorop *colorop,
+				  struct drm_plane *plane, uint32_t lut_size)
+{
+	struct drm_property *prop;
+	int ret;
+
+	ret = drm_colorop_init(dev, colorop, plane, DRM_COLOROP_1D_LUT);
+	if (ret)
+		return ret;
+
+	/* initialize 1D LUT only attribute */
+	/* LUT size */
+	prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE | DRM_MODE_PROP_ATOMIC,
+					 "SIZE", 0, UINT_MAX);
+	if (!prop)
+		return -ENOMEM;
+
+	colorop->lut_size_property = prop;
+	drm_object_attach_property(&colorop->base, colorop->lut_size_property, lut_size);
+	colorop->lut_size = lut_size;
+
+	/* data */
+	ret = drm_colorop_create_data_prop(dev, colorop);
+	if (ret)
+		return ret;
+
+	drm_colorop_reset(colorop);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_colorop_curve_1d_lut_init);
+
 int drm_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop,
 			     struct drm_plane *plane)
 {
@@ -333,6 +375,7 @@ void drm_colorop_reset(struct drm_colorop *colorop)
 
 static const char * const colorop_type_name[] = {
 	[DRM_COLOROP_1D_CURVE] = "1D Curve",
+	[DRM_COLOROP_1D_LUT] = "1D LUT",
 	[DRM_COLOROP_CTM_3X4] = "3x4 Matrix",
 };
 
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index d3a60c1beed1..d66c76033343 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -259,6 +259,13 @@ struct drm_colorop {
 	 */
 	struct drm_property *bypass_property;
 
+	/**
+	 * @lut_size:
+	 *
+	 * Number of entries of the custom LUT. This should be read-only.
+	 */
+	uint32_t lut_size;
+
 	/**
 	 * @curve_1d_type_property:
 	 *
@@ -266,6 +273,13 @@ struct drm_colorop {
 	 */
 	struct drm_property *curve_1d_type_property;
 
+	/**
+	 * @lut_size_property:
+	 *
+	 * Size property for custom LUT from userspace.
+	 */
+	struct drm_property *lut_size_property;
+
 	/**
 	 * @data_property:
 	 *
@@ -310,6 +324,8 @@ static inline struct drm_colorop *drm_colorop_find(struct drm_device *dev,
 
 int drm_colorop_curve_1d_init(struct drm_device *dev, struct drm_colorop *colorop,
 			      struct drm_plane *plane, u64 supported_tfs);
+int drm_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_colorop *colorop,
+				  struct drm_plane *plane, uint32_t lut_size);
 int drm_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop,
 			     struct drm_plane *plane);
 
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 651bdf48b766..dde250dd7a51 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -890,6 +890,20 @@ enum drm_colorop_type {
 	 */
 	DRM_COLOROP_1D_CURVE,
 
+	/**
+	 * @DRM_COLOROP_1D_LUT:
+	 *
+	 * enum string "1D LUT"
+	 *
+	 * A simple 1D LUT of uniformly spaced &drm_color_lut entries,
+	 * packed into a blob via the DATA property. The driver's
+	 * expected LUT size is advertised via the SIZE property.
+	 *
+	 * The DATA blob is an array of struct drm_color_lut with size
+	 * of "lut_size".
+	 */
+	DRM_COLOROP_1D_LUT,
+
 	/**
 	 * @DRM_COLOROP_CTM_3X4:
 	 *
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 33/43] drm/amd/display: add shaper and blend colorops for 1D Curve Custom LUT
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (31 preceding siblings ...)
  2025-03-26 23:47 ` [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type Alex Hung
@ 2025-03-26 23:47 ` Alex Hung
  2025-03-26 23:47 ` [PATCH V8 34/43] drm/amd/display: add 3x4 matrix colorop Alex Hung
                   ` (10 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:47 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

This patch adds colorops for custom 1D LUTs in the SHAPER and
BLND HW blocks.

With this change the following IGT tests pass:
kms_colorop --run plane-XR30-XR30-srgb_inv_eotf_lut
kms_colorop --run plane-XR30-XR30-srgb_inv_eotf_lut-srgb_eotf_lut

The color pipeline now consists of the following colorops:
1. 1D curve colorop
2. 1D curve colorop
3. 1D LUT
4. 1D curve colorop
5. 1D LUT

The 1D curve colorops support sRGB, BT2020, and PQ scaled to 125.0.

Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
v8:
 - Return error when __set_output_tf fails (Leo Li)
 - 

v7:
 - Initialize uint32_t blend_size = 0 by default (kernel test robot)
 - Modify state->size to colorop->lut_size

 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 173 ++++++++++--------
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.c |  32 ++++
 2 files changed, 126 insertions(+), 79 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index 1765402bc122..7e81088804fe 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -1211,38 +1211,6 @@ __set_dm_plane_colorop_degamma(struct drm_plane_state *plane_state,
 	return __set_colorop_in_tf_1d_curve(dc_plane_state, colorop_state);
 }
 
-static int
-__set_colorop_in_shaper_1d_curve(struct dc_plane_state *dc_plane_state,
-		       struct drm_colorop_state *colorop_state)
-{
-	struct dc_transfer_func *tf = &dc_plane_state->in_shaper_func;
-	struct drm_colorop *colorop = colorop_state->colorop;
-	struct drm_device *drm = colorop->dev;
-
-	if (colorop->type != DRM_COLOROP_1D_CURVE)
-		return -EINVAL;
-
-	if (!(BIT(colorop_state->curve_1d_type) & amdgpu_dm_supported_shaper_tfs))
-		return -EINVAL;
-
-	if (colorop_state->bypass) {
-		tf->type = TF_TYPE_BYPASS;
-		tf->tf = TRANSFER_FUNCTION_LINEAR;
-		return 0;
-	}
-
-	drm_dbg(drm, "Shaper colorop with ID: %d\n", colorop->base.id);
-
-	if (colorop->type == DRM_COLOROP_1D_CURVE) {
-		tf->type = TF_TYPE_DISTRIBUTED_POINTS;
-		tf->tf = amdgpu_colorop_tf_to_dc_tf(colorop_state->curve_1d_type);
-		tf->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
-		return __set_output_tf(tf, 0, 0, false);
-	}
-
-	return -EINVAL;
-}
-
 static int
 __set_dm_plane_colorop_shaper(struct drm_plane_state *plane_state,
 			      struct dc_plane_state *dc_plane_state,
@@ -1251,64 +1219,66 @@ __set_dm_plane_colorop_shaper(struct drm_plane_state *plane_state,
 	struct drm_colorop *old_colorop;
 	struct drm_colorop_state *colorop_state = NULL, *new_colorop_state;
 	struct drm_atomic_state *state = plane_state->state;
-	int i = 0;
+	enum dc_transfer_func_predefined default_tf = TRANSFER_FUNCTION_LINEAR;
+	struct dc_transfer_func *tf = &dc_plane_state->in_shaper_func;
+	const struct drm_color_lut *shaper_lut;
+	struct drm_device *dev = colorop->dev;
+	uint32_t shaper_size;
+	int i = 0, ret = 0;
 
+	/* 1D Curve - SHAPER TF */
 	old_colorop = colorop;
-
-	/* 2nd op: 1d curve - shaper */
 	for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
 		if (new_colorop_state->colorop == old_colorop &&
 		    (BIT(new_colorop_state->curve_1d_type) & amdgpu_dm_supported_shaper_tfs)) {
 			colorop_state = new_colorop_state;
 			break;
 		}
-
-		if (new_colorop_state->colorop == old_colorop) {
-			colorop_state = new_colorop_state;
-			break;
-		}
 	}
 
-	if (!colorop_state)
-		return -EINVAL;
-
-	return __set_colorop_in_shaper_1d_curve(dc_plane_state, colorop_state);
-}
-
-
-static int
-__set_colorop_1d_curve_blend_tf_lut(struct dc_plane_state *dc_plane_state,
-				  struct drm_colorop_state *colorop_state)
-{
-
-	struct dc_transfer_func *tf = &dc_plane_state->blend_tf;
-	struct drm_colorop *colorop = colorop_state->colorop;
-	struct drm_device *drm = colorop->dev;
-	const struct drm_color_lut *blend_lut;
-	uint32_t blend_size = 0;
-
-	if (colorop->type != DRM_COLOROP_1D_CURVE)
-		return -EINVAL;
+	if (colorop_state && !colorop_state->bypass && colorop->type == DRM_COLOROP_1D_CURVE) {
+		drm_dbg(dev, "Shaper TF colorop with ID: %d\n", colorop->base.id);
+		tf->type = TF_TYPE_DISTRIBUTED_POINTS;
+		tf->tf = default_tf = amdgpu_colorop_tf_to_dc_tf(colorop_state->curve_1d_type);
+		tf->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
+		ret = __set_output_tf(tf, 0, 0, false);
+		if (ret)
+			return ret;
+	}
 
-	if (!(BIT(colorop_state->curve_1d_type) & amdgpu_dm_supported_blnd_tfs))
+	/* 1D LUT - SHAPER LUT */
+	colorop = old_colorop->next;
+	if (!colorop) {
+		drm_dbg(dev, "no Shaper LUT colorop found\n");
 		return -EINVAL;
-
-	if (colorop_state->bypass) {
-		tf->type = TF_TYPE_BYPASS;
-		tf->tf = TRANSFER_FUNCTION_LINEAR;
-		return 0;
 	}
 
-	drm_dbg(drm, "Blend colorop with ID: %d\n", colorop->base.id);
+	old_colorop = colorop;
+	for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
+		if (new_colorop_state->colorop == old_colorop &&
+		    new_colorop_state->colorop->type == DRM_COLOROP_1D_LUT) {
+			colorop_state = new_colorop_state;
+			break;
+		}
+	}
 
-	if (colorop->type == DRM_COLOROP_1D_CURVE) {
+	if (colorop_state && !colorop_state->bypass && colorop->type == DRM_COLOROP_1D_LUT) {
+		drm_dbg(dev, "Shaper LUT colorop with ID: %d\n", colorop->base.id);
 		tf->type = TF_TYPE_DISTRIBUTED_POINTS;
-		tf->tf = amdgpu_colorop_tf_to_dc_tf(colorop_state->curve_1d_type);
+		tf->tf = default_tf;
 		tf->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
-		return __set_input_tf(NULL, tf, blend_lut, blend_size);
+		shaper_lut = __extract_blob_lut(colorop_state->data, &shaper_size);
+		shaper_size = shaper_lut != NULL ? shaper_size : 0;
+
+		/* Custom LUT size must be the same as supported size */
+		if (shaper_size == colorop->lut_size) {
+			ret = __set_output_tf(tf, shaper_lut, shaper_size, false);
+			if (ret)
+				return ret;
+		}
 	}
 
-	return -EINVAL;
+	return 0;
 }
 
 static int
@@ -1319,28 +1289,63 @@ __set_dm_plane_colorop_blend(struct drm_plane_state *plane_state,
 	struct drm_colorop *old_colorop;
 	struct drm_colorop_state *colorop_state = NULL, *new_colorop_state;
 	struct drm_atomic_state *state = plane_state->state;
+	enum dc_transfer_func_predefined default_tf = TRANSFER_FUNCTION_LINEAR;
+	struct dc_transfer_func *tf = &dc_plane_state->blend_tf;
+	const struct drm_color_lut *blend_lut;
+	struct drm_device *dev = colorop->dev;
+	uint32_t blend_size;
 	int i = 0;
 
+	/* 1D Curve - BLND TF */
 	old_colorop = colorop;
-
-	/* 3nd op: 1d curve - blend */
 	for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
 		if (new_colorop_state->colorop == old_colorop &&
 		    (BIT(new_colorop_state->curve_1d_type) & amdgpu_dm_supported_blnd_tfs)) {
 			colorop_state = new_colorop_state;
 			break;
 		}
+	}
 
-		if (new_colorop_state->colorop == old_colorop) {
+	if (colorop_state && !colorop_state->bypass && colorop->type == DRM_COLOROP_1D_CURVE &&
+	    (BIT(colorop_state->curve_1d_type) & amdgpu_dm_supported_blnd_tfs)) {
+		drm_dbg(dev, "Blend TF colorop with ID: %d\n", colorop->base.id);
+		tf->type = TF_TYPE_DISTRIBUTED_POINTS;
+		tf->tf = default_tf = amdgpu_colorop_tf_to_dc_tf(colorop_state->curve_1d_type);
+		tf->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
+		__set_input_tf(NULL, tf, blend_lut, blend_size);
+	}
+
+	/* 1D Curve - BLND LUT */
+	colorop = old_colorop->next;
+	if (!colorop) {
+		drm_dbg(dev, "no Blend LUT colorop found\n");
+		return -EINVAL;
+	}
+
+	old_colorop = colorop;
+	for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
+		if (new_colorop_state->colorop == old_colorop &&
+		    new_colorop_state->colorop->type == DRM_COLOROP_1D_LUT) {
 			colorop_state = new_colorop_state;
 			break;
 		}
 	}
 
-	if (!colorop_state)
-		return -EINVAL;
+	if (colorop_state && !colorop_state->bypass && colorop->type == DRM_COLOROP_1D_LUT &&
+	    (BIT(colorop_state->curve_1d_type) & amdgpu_dm_supported_blnd_tfs)) {
+		drm_dbg(dev, "Blend LUT colorop with ID: %d\n", colorop->base.id);
+		tf->type = TF_TYPE_DISTRIBUTED_POINTS;
+		tf->tf = default_tf;
+		tf->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
+		blend_lut = __extract_blob_lut(colorop_state->data, &blend_size);
+		blend_size = blend_lut != NULL ? blend_size : 0;
 
-	return __set_colorop_1d_curve_blend_tf_lut(dc_plane_state, colorop_state);
+		/* Custom LUT size must be the same as supported size */
+		if (blend_size == colorop->lut_size)
+			__set_input_tf(NULL, tf, blend_lut, blend_size);
+	}
+
+	return 0;
 }
 
 static int
@@ -1409,7 +1414,7 @@ amdgpu_dm_plane_set_colorop_properties(struct drm_plane_state *plane_state,
 	if (ret)
 		return ret;
 
-	/* 1D Curve - SHAPER TF */
+	/* 1D Curve & LUT - SHAPER TF & LUT */
 	colorop = colorop->next;
 	if (!colorop) {
 		drm_dbg(dev, "no Shaper TF colorop found\n");
@@ -1420,7 +1425,12 @@ amdgpu_dm_plane_set_colorop_properties(struct drm_plane_state *plane_state,
 	if (ret)
 		return ret;
 
-	/* 1D Curve - BLND TF */
+	/* Shaper LUT colorop is already handled, just skip here */
+	colorop = colorop->next;
+	if (!colorop)
+		return -EINVAL;
+
+	/* 1D Curve & LUT - BLND TF & LUT */
 	colorop = colorop->next;
 	if (!colorop) {
 		drm_dbg(dev, "no Blend TF colorop found\n");
@@ -1431,6 +1441,11 @@ amdgpu_dm_plane_set_colorop_properties(struct drm_plane_state *plane_state,
 	if (ret)
 		return ret;
 
+	/* BLND LUT colorop is already handled, just skip here */
+	colorop = colorop->next;
+	if (!colorop)
+		return -EINVAL;
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
index ff5828a1e8cd..8a5e15083f11 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
@@ -29,6 +29,7 @@
 #include <drm/drm_property.h>
 #include <drm/drm_colorop.h>
 
+#include "amdgpu.h"
 #include "amdgpu_dm_colorop.h"
 
 const u64 amdgpu_dm_supported_degam_tfs =
@@ -90,6 +91,22 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
 
 	i++;
 
+	/* 1D LUT - SHAPER LUT */
+	ops[i] = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
+	if (!ops[i]) {
+		DRM_ERROR("KMS: Failed to allocate colorop\n");
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	ret = drm_colorop_curve_1d_lut_init(dev, ops[i], plane, MAX_COLOR_LUT_ENTRIES);
+	if (ret)
+		goto cleanup;
+
+	drm_colorop_set_next_property(ops[i-1], ops[i]);
+
+	i++;
+
 	/* 1D curve - BLND TF */
 	ops[i] = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
 	if (!ops[i]) {
@@ -104,6 +121,21 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
 
 	drm_colorop_set_next_property(ops[i-1], ops[i]);
 
+	i++;
+
+	/* 1D LUT - BLND LUT */
+	ops[i] = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
+	if (!ops[i]) {
+		DRM_ERROR("KMS: Failed to allocate colorop\n");
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	ret = drm_colorop_curve_1d_lut_init(dev, ops[i], plane, MAX_COLOR_LUT_ENTRIES);
+	if (ret)
+		goto cleanup;
+
+	drm_colorop_set_next_property(ops[i-1], ops[i]);
 	return 0;
 
 cleanup:
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 34/43] drm/amd/display: add 3x4 matrix colorop
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (32 preceding siblings ...)
  2025-03-26 23:47 ` [PATCH V8 33/43] drm/amd/display: add shaper and blend colorops for 1D Curve Custom LUT Alex Hung
@ 2025-03-26 23:47 ` Alex Hung
  2025-03-26 23:47 ` [PATCH V8 35/43] drm/colorop: Add mutliplier type Alex Hung
                   ` (9 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:47 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

This adds support for a 3x4 color transformation matrix.

With this change the following IGT tests pass:
kms_colorop --run plane-XR30-XR30-ctm_3x4_50_desat
kms_colorop --run plane-XR30-XR30-ctm_3x4_overdrive
kms_colorop --run plane-XR30-XR30-ctm_3x4_oversaturate
kms_colorop --run plane-XR30-XR30-ctm_3x4_bt709_enc
kms_colorop --run plane-XR30-XR30-ctm_3x4_bt709_dec

The color pipeline now consists of the following colorops:
1. 1D curve colorop
2. 3x4 CTM
3. 1D curve colorop
4. 1D LUT
5. 1D curve colorop
6. 1D LUT

Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
v8:
 - Return -EINVAL when drm_color_ctm_3x4's size mismatches (Leo Li)

v7:
 - Change %lu to %zu for sizeof() when In drm_warn

v6:
 - fix warnings in dbg prints

 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 52 +++++++++++++++++++
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.c | 16 ++++++
 2 files changed, 68 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index 7e81088804fe..8a9404339da0 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -1211,6 +1211,47 @@ __set_dm_plane_colorop_degamma(struct drm_plane_state *plane_state,
 	return __set_colorop_in_tf_1d_curve(dc_plane_state, colorop_state);
 }
 
+static int
+__set_dm_plane_colorop_3x4_matrix(struct drm_plane_state *plane_state,
+				  struct dc_plane_state *dc_plane_state,
+				  struct drm_colorop *colorop)
+{
+	struct drm_colorop *old_colorop;
+	struct drm_colorop_state *colorop_state = NULL, *new_colorop_state;
+	struct drm_atomic_state *state = plane_state->state;
+	const struct drm_device *dev = colorop->dev;
+	const struct drm_property_blob *blob;
+	struct drm_color_ctm_3x4 *ctm = NULL;
+	int i = 0;
+
+	/* 3x4 matrix */
+	old_colorop = colorop;
+	for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
+		if (new_colorop_state->colorop == old_colorop &&
+		    new_colorop_state->colorop->type == DRM_COLOROP_CTM_3X4) {
+			colorop_state = new_colorop_state;
+			break;
+		}
+	}
+
+	if (colorop_state && !colorop_state->bypass && colorop->type == DRM_COLOROP_CTM_3X4) {
+		drm_dbg(dev, "3x4 matrix colorop with ID: %d\n", colorop->base.id);
+		blob = colorop_state->data;
+		if (blob->length == sizeof(struct drm_color_ctm_3x4)) {
+			ctm = blob ? (struct drm_color_ctm_3x4 *) blob->data : NULL;
+			__drm_ctm_3x4_to_dc_matrix(ctm, dc_plane_state->gamut_remap_matrix.matrix);
+			dc_plane_state->gamut_remap_matrix.enable_remap = true;
+			dc_plane_state->input_csc_color_matrix.enable_adjustment = false;
+		} else {
+			drm_warn(dev, "blob->length (%lu) isn't equal to drm_color_ctm_3x4 (%zu)\n",
+				 blob->length, sizeof(struct drm_color_ctm_3x4));
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
 static int
 __set_dm_plane_colorop_shaper(struct drm_plane_state *plane_state,
 			      struct dc_plane_state *dc_plane_state,
@@ -1414,6 +1455,17 @@ amdgpu_dm_plane_set_colorop_properties(struct drm_plane_state *plane_state,
 	if (ret)
 		return ret;
 
+	/* 3x4 matrix */
+	colorop = colorop->next;
+	if (!colorop) {
+		drm_dbg(dev, "no 3x4 matrix colorop found\n");
+		return -EINVAL;
+	}
+
+	ret = __set_dm_plane_colorop_3x4_matrix(plane_state, dc_plane_state, colorop);
+	if (ret)
+		return ret;
+
 	/* 1D Curve & LUT - SHAPER TF & LUT */
 	colorop = colorop->next;
 	if (!colorop) {
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
index 8a5e15083f11..9a9386bf85ec 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
@@ -75,6 +75,22 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
 
 	i++;
 
+	/* 3x4 matrix */
+	ops[i] = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
+	if (!ops[i]) {
+		DRM_ERROR("KMS: Failed to allocate colorop\n");
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	ret = drm_colorop_ctm_3x4_init(dev, ops[i], plane);
+	if (ret)
+		goto cleanup;
+
+	drm_colorop_set_next_property(ops[i-1], ops[i]);
+
+	i++;
+
 	/* 1D curve - SHAPER TF */
 	ops[i] = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
 	if (!ops[i]) {
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 35/43] drm/colorop: Add mutliplier type
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (33 preceding siblings ...)
  2025-03-26 23:47 ` [PATCH V8 34/43] drm/amd/display: add 3x4 matrix colorop Alex Hung
@ 2025-03-26 23:47 ` Alex Hung
  2025-03-26 23:47 ` [PATCH V8 36/43] drm/amd/display: add multiplier colorop Alex Hung
                   ` (8 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:47 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

This introduces a new drm_colorop_type: DRM_COLOROP_MULTIPLIER.

It's a simple multiplier to all pixel values. The value is
specified via a S31.32 fixed point provided via the
"MULTIPLIER" property.

Reviewed-by: Simon Ser <contact@emersion.fr>
Signed-off-by: Alex Hung <alex.hung@amd.com>
---
v7:
 - Modify size_property to lut_size_property

 drivers/gpu/drm/drm_atomic.c      |  3 +++
 drivers/gpu/drm/drm_atomic_uapi.c |  4 ++++
 drivers/gpu/drm/drm_colorop.c     | 33 +++++++++++++++++++++++++++++++
 include/drm/drm_colorop.h         | 16 +++++++++++++++
 include/uapi/drm/drm_mode.h       | 11 +++++++++++
 5 files changed, 67 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index f713d177241d..a04f1c98fef9 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -800,6 +800,9 @@ static void drm_atomic_colorop_print_state(struct drm_printer *p,
 	case DRM_COLOROP_CTM_3X4:
 		drm_printf(p, "\tdata blob id=%d\n", state->data ? state->data->base.id : 0);
 		break;
+	case DRM_COLOROP_MULTIPLIER:
+		drm_printf(p, "\tmultiplier=%llu\n", state->multiplier);
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index dfd88a227da7..947c18e8bf9b 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -740,6 +740,8 @@ static int drm_atomic_colorop_set_property(struct drm_colorop *colorop,
 		state->bypass = val;
 	} else if (property == colorop->curve_1d_type_property) {
 		state->curve_1d_type = val;
+	} else if (property == colorop->multiplier_property) {
+		state->multiplier = val;
 	} else if (property == colorop->data_property) {
 		return drm_atomic_color_set_data_property(colorop, state,
 							  property, val);
@@ -765,6 +767,8 @@ drm_atomic_colorop_get_property(struct drm_colorop *colorop,
 		*val = state->bypass;
 	} else if (property == colorop->curve_1d_type_property) {
 		*val = state->curve_1d_type;
+	} else if (property == colorop->multiplier_property) {
+		*val = state->multiplier;
 	} else if (property == colorop->lut_size_property) {
 		*val = colorop->lut_size;
 	} else if (property == colorop->data_property) {
diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index 15ffbba60b3d..45aa7b059e35 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -66,6 +66,7 @@ static const struct drm_prop_enum_list drm_colorop_type_enum_list[] = {
 	{ DRM_COLOROP_1D_CURVE, "1D Curve" },
 	{ DRM_COLOROP_1D_LUT, "1D LUT" },
 	{ DRM_COLOROP_CTM_3X4, "3x4 Matrix"},
+	{ DRM_COLOROP_MULTIPLIER, "Multiplier"},
 };
 
 static const char * const colorop_curve_1d_type_names[] = {
@@ -286,6 +287,37 @@ int drm_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop
 }
 EXPORT_SYMBOL(drm_colorop_ctm_3x4_init);
 
+/**
+ * drm_colorop_mult_init - Initialize a DRM_COLOROP_MULTIPLIER
+ *
+ * @dev: DRM device
+ * @colorop: The drm_colorop object to initialize
+ * @plane: The associated drm_plane
+ * @return zero on success, -E value on failure
+ */
+int drm_colorop_mult_init(struct drm_device *dev, struct drm_colorop *colorop,
+			      struct drm_plane *plane)
+{
+	struct drm_property *prop;
+	int ret;
+
+	ret = drm_colorop_init(dev, colorop, plane, DRM_COLOROP_MULTIPLIER);
+	if (ret)
+		return ret;
+
+	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, "MULTIPLIER", 0, U64_MAX);
+	if (!prop)
+		return -ENOMEM;
+
+	colorop->multiplier_property = prop;
+	drm_object_attach_property(&colorop->base, colorop->multiplier_property, 0);
+
+	drm_colorop_reset(colorop);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_colorop_mult_init);
+
 static void __drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop,
 							struct drm_colorop_state *state)
 {
@@ -377,6 +409,7 @@ static const char * const colorop_type_name[] = {
 	[DRM_COLOROP_1D_CURVE] = "1D Curve",
 	[DRM_COLOROP_1D_LUT] = "1D LUT",
 	[DRM_COLOROP_CTM_3X4] = "3x4 Matrix",
+	[DRM_COLOROP_MULTIPLIER] = "Multiplier",
 };
 
 const char *drm_get_colorop_type_name(enum drm_colorop_type type)
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index d66c76033343..159e6d52e8b1 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -146,6 +146,13 @@ struct drm_colorop_state {
 	 */
 	enum drm_colorop_curve_1d_type curve_1d_type;
 
+	/**
+	 * @multiplier:
+	 *
+	 * Multiplier to 'gain' the plane. Format is S31.32 sign-magnitude.
+	 */
+	uint64_t multiplier;
+
 	/**
 	 * @data:
 	 *
@@ -273,6 +280,13 @@ struct drm_colorop {
 	 */
 	struct drm_property *curve_1d_type_property;
 
+	/**
+	 * @multiplier_property:
+	 *
+	 * Multiplier property for plane gain
+	 */
+	struct drm_property *multiplier_property;
+
 	/**
 	 * @lut_size_property:
 	 *
@@ -328,6 +342,8 @@ int drm_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_colorop *co
 				  struct drm_plane *plane, uint32_t lut_size);
 int drm_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop,
 			     struct drm_plane *plane);
+int drm_colorop_mult_init(struct drm_device *dev, struct drm_colorop *colorop,
+			      struct drm_plane *plane);
 
 struct drm_colorop_state *
 drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop);
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index dde250dd7a51..fa5e1ddaf4f0 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -919,6 +919,17 @@ enum drm_colorop_type {
 	 * | B |   | 8  9  10 12 |   | B |
 	 */
 	DRM_COLOROP_CTM_3X4,
+
+	/**
+	 * @DRM_COLOROP_MULTIPLIER:
+	 *
+	 * enum string "Multiplier"
+	 *
+	 * A simple multiplier, applied to all color values. The
+	 * multiplier is specified as a S31.32 via the MULTIPLIER
+	 * property.
+	 */
+	DRM_COLOROP_MULTIPLIER,
 };
 
 /**
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 36/43] drm/amd/display: add multiplier colorop
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (34 preceding siblings ...)
  2025-03-26 23:47 ` [PATCH V8 35/43] drm/colorop: Add mutliplier type Alex Hung
@ 2025-03-26 23:47 ` Alex Hung
  2025-03-26 23:47 ` [PATCH V8 37/43] drm/amd/display: Swap matrix and multiplier Alex Hung
                   ` (7 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:47 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

This adds support for a multiplier. This multiplier is
programmed via the HDR Multiplier in DCN.

With this change the following IGT tests pass:
kms_colorop --run plane-XR30-XR30-multiply_125
kms_colorop --run plane-XR30-XR30-multiply_inv_125

The color pipeline now consists of the following colorops:
1. 1D curve colorop
2. 3x4 CTM
3. Multiplier
4. 1D curve colorop
5. 1D LUT
6. 1D curve colorop
7. 1D LUT

Signed-off-by: Alex Hung <alex.hung@amd.com>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 40 +++++++++++++++++++
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.c | 16 ++++++++
 2 files changed, 56 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index 8a9404339da0..e3ae0c32da2b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -1252,6 +1252,35 @@ __set_dm_plane_colorop_3x4_matrix(struct drm_plane_state *plane_state,
 	return 0;
 }
 
+static int
+__set_dm_plane_colorop_multiplier(struct drm_plane_state *plane_state,
+				  struct dc_plane_state *dc_plane_state,
+				  struct drm_colorop *colorop)
+{
+	struct drm_colorop *old_colorop;
+	struct drm_colorop_state *colorop_state = NULL, *new_colorop_state;
+	struct drm_atomic_state *state = plane_state->state;
+	const struct drm_device *dev = colorop->dev;
+	int i = 0;
+
+	/* Multiplier */
+	old_colorop = colorop;
+	for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
+		if (new_colorop_state->colorop == old_colorop &&
+		    new_colorop_state->colorop->type == DRM_COLOROP_MULTIPLIER) {
+			colorop_state = new_colorop_state;
+			break;
+		}
+	}
+
+	if (colorop_state && !colorop_state->bypass && colorop->type == DRM_COLOROP_MULTIPLIER) {
+		drm_dbg(dev, "Multiplier colorop with ID: %d\n", colorop->base.id);
+		dc_plane_state->hdr_mult = amdgpu_dm_fixpt_from_s3132(colorop_state->multiplier);
+	}
+
+	return 0;
+}
+
 static int
 __set_dm_plane_colorop_shaper(struct drm_plane_state *plane_state,
 			      struct dc_plane_state *dc_plane_state,
@@ -1466,6 +1495,17 @@ amdgpu_dm_plane_set_colorop_properties(struct drm_plane_state *plane_state,
 	if (ret)
 		return ret;
 
+	/* Multiplier */
+	colorop = colorop->next;
+	if (!colorop) {
+		drm_dbg(dev, "no multiplier colorop found\n");
+		return -EINVAL;
+	}
+
+	ret = __set_dm_plane_colorop_multiplier(plane_state, dc_plane_state, colorop);
+	if (ret)
+		return ret;
+
 	/* 1D Curve & LUT - SHAPER TF & LUT */
 	colorop = colorop->next;
 	if (!colorop) {
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
index 9a9386bf85ec..33156531d751 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
@@ -91,6 +91,22 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
 
 	i++;
 
+	/* Multiplier */
+	ops[i] = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
+	if (!ops[i]) {
+		DRM_ERROR("KMS: Failed to allocate colorop\n");
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	ret = drm_colorop_mult_init(dev, ops[i], plane);
+	if (ret)
+		goto cleanup;
+
+	drm_colorop_set_next_property(ops[i-1], ops[i]);
+
+	i++;
+
 	/* 1D curve - SHAPER TF */
 	ops[i] = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
 	if (!ops[i]) {
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 37/43] drm/amd/display: Swap matrix and multiplier
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (35 preceding siblings ...)
  2025-03-26 23:47 ` [PATCH V8 36/43] drm/amd/display: add multiplier colorop Alex Hung
@ 2025-03-26 23:47 ` Alex Hung
  2025-03-26 23:47 ` [PATCH V8 38/43] drm/colorop: Define LUT_1D interpolation Alex Hung
                   ` (6 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:47 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

Swap the order of matrix and multiplier as designed in hardware.

Signed-off-by: Alex Hung <alex.hung@amd.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c  | 12 ++++++------
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c    |  8 ++++----
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index e3ae0c32da2b..1bf40f39bd0c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -1484,25 +1484,25 @@ amdgpu_dm_plane_set_colorop_properties(struct drm_plane_state *plane_state,
 	if (ret)
 		return ret;
 
-	/* 3x4 matrix */
+	/* Multiplier */
 	colorop = colorop->next;
 	if (!colorop) {
-		drm_dbg(dev, "no 3x4 matrix colorop found\n");
+		drm_dbg(dev, "no multiplier colorop found\n");
 		return -EINVAL;
 	}
 
-	ret = __set_dm_plane_colorop_3x4_matrix(plane_state, dc_plane_state, colorop);
+	ret = __set_dm_plane_colorop_multiplier(plane_state, dc_plane_state, colorop);
 	if (ret)
 		return ret;
 
-	/* Multiplier */
+	/* 3x4 matrix */
 	colorop = colorop->next;
 	if (!colorop) {
-		drm_dbg(dev, "no multiplier colorop found\n");
+		drm_dbg(dev, "no 3x4 matrix colorop found\n");
 		return -EINVAL;
 	}
 
-	ret = __set_dm_plane_colorop_multiplier(plane_state, dc_plane_state, colorop);
+	ret = __set_dm_plane_colorop_3x4_matrix(plane_state, dc_plane_state, colorop);
 	if (ret)
 		return ret;
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
index 33156531d751..d0777691862b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
@@ -75,7 +75,7 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
 
 	i++;
 
-	/* 3x4 matrix */
+	/* Multiplier */
 	ops[i] = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
 	if (!ops[i]) {
 		DRM_ERROR("KMS: Failed to allocate colorop\n");
@@ -83,7 +83,7 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
 		goto cleanup;
 	}
 
-	ret = drm_colorop_ctm_3x4_init(dev, ops[i], plane);
+	ret = drm_colorop_mult_init(dev, ops[i], plane);
 	if (ret)
 		goto cleanup;
 
@@ -91,7 +91,7 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
 
 	i++;
 
-	/* Multiplier */
+	/* 3x4 matrix */
 	ops[i] = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
 	if (!ops[i]) {
 		DRM_ERROR("KMS: Failed to allocate colorop\n");
@@ -99,7 +99,7 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
 		goto cleanup;
 	}
 
-	ret = drm_colorop_mult_init(dev, ops[i], plane);
+	ret = drm_colorop_ctm_3x4_init(dev, ops[i], plane);
 	if (ret)
 		goto cleanup;
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 38/43] drm/colorop: Define LUT_1D interpolation
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (36 preceding siblings ...)
  2025-03-26 23:47 ` [PATCH V8 37/43] drm/amd/display: Swap matrix and multiplier Alex Hung
@ 2025-03-26 23:47 ` Alex Hung
  2025-03-26 23:47 ` [PATCH V8 39/43] drm/colorop: allow non-bypass colorops Alex Hung
                   ` (5 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:47 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

We want to make sure userspace is aware of the 1D LUT
interpolation. While linear interpolation is common it
might not be supported on all HW. Give driver implementers
a way to specify their interpolation.

Reviewed-by: Simon Ser <contact@emersion.fr>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
v7:
 - Fix a checkpatch long-line warning
 - Modify state->size to colorop->lut_size

 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.c |  6 ++--
 drivers/gpu/drm/drm_atomic.c                  |  2 ++
 drivers/gpu/drm/drm_colorop.c                 | 36 ++++++++++++++++++-
 include/drm/drm_colorop.h                     | 19 +++++++++-
 include/uapi/drm/drm_mode.h                   | 13 +++++++
 5 files changed, 72 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
index d0777691862b..92c9f3fb0254 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
@@ -131,7 +131,8 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
 		goto cleanup;
 	}
 
-	ret = drm_colorop_curve_1d_lut_init(dev, ops[i], plane, MAX_COLOR_LUT_ENTRIES);
+	ret = drm_colorop_curve_1d_lut_init(dev, ops[i], plane, MAX_COLOR_LUT_ENTRIES,
+					    DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR);
 	if (ret)
 		goto cleanup;
 
@@ -163,7 +164,8 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
 		goto cleanup;
 	}
 
-	ret = drm_colorop_curve_1d_lut_init(dev, ops[i], plane, MAX_COLOR_LUT_ENTRIES);
+	ret = drm_colorop_curve_1d_lut_init(dev, ops[i], plane, MAX_COLOR_LUT_ENTRIES,
+					    DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR);
 	if (ret)
 		goto cleanup;
 
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index a04f1c98fef9..9420fb9b8a46 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -795,6 +795,8 @@ static void drm_atomic_colorop_print_state(struct drm_printer *p,
 		break;
 	case DRM_COLOROP_1D_LUT:
 		drm_printf(p, "\tsize=%d\n", colorop->lut_size);
+		drm_printf(p, "\tinterpolation=%s\n",
+			   drm_get_colorop_lut1d_interpolation_name(colorop->lut1d_interpolation));
 		drm_printf(p, "\tdata blob id=%d\n", state->data ? state->data->base.id : 0);
 		break;
 	case DRM_COLOROP_CTM_3X4:
diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index 45aa7b059e35..7360ca4d2325 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -78,6 +78,9 @@ static const char * const colorop_curve_1d_type_names[] = {
 	[DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF] = "PQ 125 Inverse EOTF",
 };
 
+static const struct drm_prop_enum_list drm_colorop_lut1d_interpolation_list[] = {
+	{ DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR, "Linear" },
+};
 
 /* Init Helpers */
 
@@ -234,10 +237,12 @@ static int drm_colorop_create_data_prop(struct drm_device *dev, struct drm_color
  * @colorop: The drm_colorop object to initialize
  * @plane: The associated drm_plane
  * @lut_size: LUT size supported by driver
+ * @lut1d_interpolation: 1D LUT interpolation type
  * @return zero on success, -E value on failure
  */
 int drm_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_colorop *colorop,
-				  struct drm_plane *plane, uint32_t lut_size)
+				  struct drm_plane *plane, uint32_t lut_size,
+				  enum drm_colorop_lut1d_interpolation_type lut1d_interpolation)
 {
 	struct drm_property *prop;
 	int ret;
@@ -257,6 +262,17 @@ int drm_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_colorop *co
 	drm_object_attach_property(&colorop->base, colorop->lut_size_property, lut_size);
 	colorop->lut_size = lut_size;
 
+	/* Interpolation */
+	prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, "LUT1D_INTERPOLATION",
+					drm_colorop_lut1d_interpolation_list,
+					ARRAY_SIZE(drm_colorop_lut1d_interpolation_list));
+	if (!prop)
+		return -ENOMEM;
+
+	colorop->lut1d_interpolation_property = prop;
+	drm_object_attach_property(&colorop->base, prop, lut1d_interpolation);
+	colorop->lut1d_interpolation = lut1d_interpolation;
+
 	/* data */
 	ret = drm_colorop_create_data_prop(dev, colorop);
 	if (ret)
@@ -411,6 +427,9 @@ static const char * const colorop_type_name[] = {
 	[DRM_COLOROP_CTM_3X4] = "3x4 Matrix",
 	[DRM_COLOROP_MULTIPLIER] = "Multiplier",
 };
+static const char * const colorop_lut1d_interpolation_name[] = {
+	[DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR] = "Linear",
+};
 
 const char *drm_get_colorop_type_name(enum drm_colorop_type type)
 {
@@ -428,6 +447,21 @@ const char *drm_get_colorop_curve_1d_type_name(enum drm_colorop_curve_1d_type ty
 	return colorop_curve_1d_type_names[type];
 }
 
+/**
+ * drm_get_colorop_lut1d_interpolation_name: return a string for interpolation type
+ * @type: interpolation type to compute name of
+ *
+ * In contrast to the other drm_get_*_name functions this one here returns a
+ * const pointer and hence is threadsafe.
+ */
+const char *drm_get_colorop_lut1d_interpolation_name(enum drm_colorop_lut1d_interpolation_type type)
+{
+	if (WARN_ON(type >= ARRAY_SIZE(colorop_lut1d_interpolation_name)))
+		return "unknown";
+
+	return colorop_lut1d_interpolation_name[type];
+}
+
 /**
  * drm_colorop_set_next_property - sets the next pointer
  * @colorop: drm colorop
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index 159e6d52e8b1..86694d45d1d1 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -273,6 +273,21 @@ struct drm_colorop {
 	 */
 	uint32_t lut_size;
 
+	/**
+	 * @lut1d_interpolation:
+	 *
+	 * Read-only
+	 * Interpolation for DRM_COLOROP_1D_LUT
+	 */
+	enum drm_colorop_lut1d_interpolation_type lut1d_interpolation;
+
+	/**
+	 * @lut1d_interpolation_property:
+	 *
+	 * Read-only property for DRM_COLOROP_1D_LUT interpolation
+	 */
+	struct drm_property *lut1d_interpolation_property;
+
 	/**
 	 * @curve_1d_type_property:
 	 *
@@ -339,7 +354,8 @@ static inline struct drm_colorop *drm_colorop_find(struct drm_device *dev,
 int drm_colorop_curve_1d_init(struct drm_device *dev, struct drm_colorop *colorop,
 			      struct drm_plane *plane, u64 supported_tfs);
 int drm_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_colorop *colorop,
-				  struct drm_plane *plane, uint32_t lut_size);
+				  struct drm_plane *plane, uint32_t lut_size,
+				  enum drm_colorop_lut1d_interpolation_type lut1d_interpolation);
 int drm_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop,
 			     struct drm_plane *plane);
 int drm_colorop_mult_init(struct drm_device *dev, struct drm_colorop *colorop,
@@ -393,6 +409,7 @@ const char *drm_get_colorop_type_name(enum drm_colorop_type type);
  * const pointer and hence is threadsafe.
  */
 const char *drm_get_colorop_curve_1d_type_name(enum drm_colorop_curve_1d_type type);
+const char *drm_get_colorop_lut1d_interpolation_name(enum drm_colorop_lut1d_interpolation_type type);
 
 void drm_colorop_set_next_property(struct drm_colorop *colorop, struct drm_colorop *next);
 
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index fa5e1ddaf4f0..d76c8ffe5408 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -932,6 +932,19 @@ enum drm_colorop_type {
 	DRM_COLOROP_MULTIPLIER,
 };
 
+/**
+ * enum drm_colorop_lut1d_interpolation_type - type of interpolation for 1D LUTs
+ */
+enum drm_colorop_lut1d_interpolation_type {
+	/**
+	 * @DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR:
+	 *
+	 * Linear interpolation. Values between points of the LUT will be
+	 * linearly interpolated.
+	 */
+	DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR,
+};
+
 /**
  * struct drm_plane_size_hint - Plane size hints
  * @width: The width of the plane in pixel
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 39/43] drm/colorop: allow non-bypass colorops
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (37 preceding siblings ...)
  2025-03-26 23:47 ` [PATCH V8 38/43] drm/colorop: Define LUT_1D interpolation Alex Hung
@ 2025-03-26 23:47 ` Alex Hung
  2025-03-29 15:41   ` Simon Ser
  2025-03-26 23:47 ` [PATCH V8 40/43] drm/colorop: Add 3D LUT support to color pipeline Alex Hung
                   ` (4 subsequent siblings)
  43 siblings, 1 reply; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:47 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

Not all HW will be able to do bypass on all color
operations. Introduce an 'allow_bypass' boolean for
all colorop init functions and only create the BYPASS
property when it's true.

Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.c | 22 +++++---
 drivers/gpu/drm/drm_atomic.c                  |  3 +-
 drivers/gpu/drm/drm_colorop.c                 | 53 ++++++++++++-------
 drivers/gpu/drm/vkms/vkms_colorop.c           |  8 +--
 include/drm/drm_colorop.h                     | 10 ++--
 5 files changed, 61 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
index 92c9f3fb0254..ec94ff887886 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
@@ -66,7 +66,9 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
 		goto cleanup;
 	}
 
-	ret = drm_colorop_curve_1d_init(dev, ops[i], plane, amdgpu_dm_supported_degam_tfs);
+	ret = drm_colorop_curve_1d_init(dev, ops[i], plane,
+					amdgpu_dm_supported_degam_tfs,
+					true);
 	if (ret)
 		goto cleanup;
 
@@ -83,7 +85,7 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
 		goto cleanup;
 	}
 
-	ret = drm_colorop_mult_init(dev, ops[i], plane);
+	ret = drm_colorop_mult_init(dev, ops[i], plane, true);
 	if (ret)
 		goto cleanup;
 
@@ -99,7 +101,7 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
 		goto cleanup;
 	}
 
-	ret = drm_colorop_ctm_3x4_init(dev, ops[i], plane);
+	ret = drm_colorop_ctm_3x4_init(dev, ops[i], plane, true);
 	if (ret)
 		goto cleanup;
 
@@ -115,7 +117,9 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
 		goto cleanup;
 	}
 
-	ret = drm_colorop_curve_1d_init(dev, ops[i], plane, amdgpu_dm_supported_shaper_tfs);
+	ret = drm_colorop_curve_1d_init(dev, ops[i], plane,
+					amdgpu_dm_supported_shaper_tfs,
+					true);
 	if (ret)
 		goto cleanup;
 
@@ -132,7 +136,8 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
 	}
 
 	ret = drm_colorop_curve_1d_lut_init(dev, ops[i], plane, MAX_COLOR_LUT_ENTRIES,
-					    DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR);
+					    DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR,
+					    true);
 	if (ret)
 		goto cleanup;
 
@@ -148,7 +153,9 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
 		goto cleanup;
 	}
 
-	ret = drm_colorop_curve_1d_init(dev, ops[i], plane, amdgpu_dm_supported_blnd_tfs);
+	ret = drm_colorop_curve_1d_init(dev, ops[i], plane,
+					amdgpu_dm_supported_blnd_tfs,
+					true);
 	if (ret)
 		goto cleanup;
 
@@ -165,7 +172,8 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
 	}
 
 	ret = drm_colorop_curve_1d_lut_init(dev, ops[i], plane, MAX_COLOR_LUT_ENTRIES,
-					    DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR);
+					    DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR,
+					    true);
 	if (ret)
 		goto cleanup;
 
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 9420fb9b8a46..0efb0ead204a 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -786,7 +786,8 @@ static void drm_atomic_colorop_print_state(struct drm_printer *p,
 
 	drm_printf(p, "colorop[%u]:\n", colorop->base.id);
 	drm_printf(p, "\ttype=%s\n", drm_get_colorop_type_name(colorop->type));
-	drm_printf(p, "\tbypass=%u\n", state->bypass);
+	if (colorop->bypass_property)
+		drm_printf(p, "\tbypass=%u\n", state->bypass);
 
 	switch (colorop->type) {
 	case DRM_COLOROP_1D_CURVE:
diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index 7360ca4d2325..e03706e7179b 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -85,7 +85,8 @@ static const struct drm_prop_enum_list drm_colorop_lut1d_interpolation_list[] =
 /* Init Helpers */
 
 static int drm_colorop_init(struct drm_device *dev, struct drm_colorop *colorop,
-			    struct drm_plane *plane, enum drm_colorop_type type)
+			    struct drm_plane *plane, enum drm_colorop_type type,
+			    bool allow_bypass)
 {
 	struct drm_mode_config *config = &dev->mode_config;
 	struct drm_property *prop;
@@ -121,16 +122,18 @@ static int drm_colorop_init(struct drm_device *dev, struct drm_colorop *colorop,
 				   colorop->type_property,
 				   colorop->type);
 
-	/* bypass */
-	prop = drm_property_create_bool(dev, DRM_MODE_PROP_ATOMIC,
-					"BYPASS");
-	if (!prop)
-		return -ENOMEM;
-
-	colorop->bypass_property = prop;
-	drm_object_attach_property(&colorop->base,
-				   colorop->bypass_property,
-				   1);
+	if (allow_bypass) {
+		/* bypass */
+		prop = drm_property_create_bool(dev, DRM_MODE_PROP_ATOMIC,
+						"BYPASS");
+		if (!prop)
+			return -ENOMEM;
+
+		colorop->bypass_property = prop;
+		drm_object_attach_property(&colorop->base,
+					colorop->bypass_property,
+					1);
+	}
 
 	/* next */
 	prop = drm_property_create_object(dev, DRM_MODE_PROP_IMMUTABLE | DRM_MODE_PROP_ATOMIC,
@@ -154,10 +157,13 @@ static int drm_colorop_init(struct drm_device *dev, struct drm_colorop *colorop,
  * @supported_tfs: A bitfield of supported drm_colorop_curve_1d_init enum values,
  *                 created using BIT(curve_type) and combined with the OR '|'
  *                 operator.
+ * @allow_bypass: true if BYPASS property should be created, false if bypass of
+ *                this colorop is not possible
  * @return zero on success, -E value on failure
  */
 int drm_colorop_curve_1d_init(struct drm_device *dev, struct drm_colorop *colorop,
-			      struct drm_plane *plane, u64 supported_tfs)
+			      struct drm_plane *plane, u64 supported_tfs,
+			      bool allow_bypass)
 {
 	struct drm_prop_enum_list enum_list[DRM_COLOROP_1D_CURVE_COUNT];
 	int i, len;
@@ -178,7 +184,8 @@ int drm_colorop_curve_1d_init(struct drm_device *dev, struct drm_colorop *coloro
 		return -EINVAL;
 	}
 
-	ret = drm_colorop_init(dev, colorop, plane, DRM_COLOROP_1D_CURVE);
+	ret = drm_colorop_init(dev, colorop, plane, DRM_COLOROP_1D_CURVE,
+			       allow_bypass);
 	if (ret)
 		return ret;
 
@@ -238,16 +245,20 @@ static int drm_colorop_create_data_prop(struct drm_device *dev, struct drm_color
  * @plane: The associated drm_plane
  * @lut_size: LUT size supported by driver
  * @lut1d_interpolation: 1D LUT interpolation type
+ * @allow_bypass: true if BYPASS property should be created, false if bypass of
+ *                this colorop is not possible
  * @return zero on success, -E value on failure
  */
 int drm_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_colorop *colorop,
 				  struct drm_plane *plane, uint32_t lut_size,
-				  enum drm_colorop_lut1d_interpolation_type lut1d_interpolation)
+				  enum drm_colorop_lut1d_interpolation_type lut1d_interpolation,
+				  bool allow_bypass)
 {
 	struct drm_property *prop;
 	int ret;
 
-	ret = drm_colorop_init(dev, colorop, plane, DRM_COLOROP_1D_LUT);
+	ret = drm_colorop_init(dev, colorop, plane, DRM_COLOROP_1D_LUT,
+			       allow_bypass);
 	if (ret)
 		return ret;
 
@@ -285,11 +296,12 @@ int drm_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_colorop *co
 EXPORT_SYMBOL(drm_colorop_curve_1d_lut_init);
 
 int drm_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop,
-			     struct drm_plane *plane)
+			     struct drm_plane *plane, bool allow_bypass)
 {
 	int ret;
 
-	ret = drm_colorop_init(dev, colorop, plane, DRM_COLOROP_CTM_3X4);
+	ret = drm_colorop_init(dev, colorop, plane, DRM_COLOROP_CTM_3X4,
+			       allow_bypass);
 	if (ret)
 		return ret;
 
@@ -309,15 +321,18 @@ EXPORT_SYMBOL(drm_colorop_ctm_3x4_init);
  * @dev: DRM device
  * @colorop: The drm_colorop object to initialize
  * @plane: The associated drm_plane
+ * @allow_bypass: true if BYPASS property should be created, false if bypass of
+ *                this colorop is not possible
  * @return zero on success, -E value on failure
  */
 int drm_colorop_mult_init(struct drm_device *dev, struct drm_colorop *colorop,
-			      struct drm_plane *plane)
+			      struct drm_plane *plane, bool allow_bypass)
 {
 	struct drm_property *prop;
 	int ret;
 
-	ret = drm_colorop_init(dev, colorop, plane, DRM_COLOROP_MULTIPLIER);
+	ret = drm_colorop_init(dev, colorop, plane, DRM_COLOROP_MULTIPLIER,
+			       allow_bypass);
 	if (ret)
 		return ret;
 
diff --git a/drivers/gpu/drm/vkms/vkms_colorop.c b/drivers/gpu/drm/vkms/vkms_colorop.c
index 0fbb9262bfc5..a2f548a4b84d 100644
--- a/drivers/gpu/drm/vkms/vkms_colorop.c
+++ b/drivers/gpu/drm/vkms/vkms_colorop.c
@@ -31,7 +31,7 @@ static int vkms_initialize_color_pipeline(struct drm_plane *plane, struct drm_pr
 		goto cleanup;
 	}
 
-	ret = drm_colorop_curve_1d_init(dev, ops[i], plane, supported_tfs);
+	ret = drm_colorop_curve_1d_init(dev, ops[i], plane, supported_tfs, true);
 	if (ret)
 		goto cleanup;
 
@@ -48,7 +48,7 @@ static int vkms_initialize_color_pipeline(struct drm_plane *plane, struct drm_pr
 		goto cleanup;
 	}
 
-	ret = drm_colorop_ctm_3x4_init(dev, ops[i], plane);
+	ret = drm_colorop_ctm_3x4_init(dev, ops[i], plane, true);
 	if (ret)
 		goto cleanup;
 
@@ -64,7 +64,7 @@ static int vkms_initialize_color_pipeline(struct drm_plane *plane, struct drm_pr
 		goto cleanup;
 	}
 
-	ret = drm_colorop_ctm_3x4_init(dev, ops[i], plane);
+	ret = drm_colorop_ctm_3x4_init(dev, ops[i], plane, true);
 	if (ret)
 		goto cleanup;
 
@@ -80,7 +80,7 @@ static int vkms_initialize_color_pipeline(struct drm_plane *plane, struct drm_pr
 		goto cleanup;
 	}
 
-	ret = drm_colorop_curve_1d_init(dev, ops[i], plane, supported_tfs);
+	ret = drm_colorop_curve_1d_init(dev, ops[i], plane, supported_tfs, true);
 	if (ret)
 		goto cleanup;
 
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index 86694d45d1d1..c89d5eb44856 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -352,14 +352,16 @@ static inline struct drm_colorop *drm_colorop_find(struct drm_device *dev,
 }
 
 int drm_colorop_curve_1d_init(struct drm_device *dev, struct drm_colorop *colorop,
-			      struct drm_plane *plane, u64 supported_tfs);
+			      struct drm_plane *plane, u64 supported_tfs,
+			      bool allow_bypass);
 int drm_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_colorop *colorop,
 				  struct drm_plane *plane, uint32_t lut_size,
-				  enum drm_colorop_lut1d_interpolation_type lut1d_interpolation);
+				  enum drm_colorop_lut1d_interpolation_type lut1d_interpolation,
+				  bool allow_bypass);
 int drm_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop,
-			     struct drm_plane *plane);
+			     struct drm_plane *plane, bool allow_bypass);
 int drm_colorop_mult_init(struct drm_device *dev, struct drm_colorop *colorop,
-			      struct drm_plane *plane);
+			      struct drm_plane *plane, bool allow_bypass);
 
 struct drm_colorop_state *
 drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 40/43] drm/colorop: Add 3D LUT support to color pipeline
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (38 preceding siblings ...)
  2025-03-26 23:47 ` [PATCH V8 39/43] drm/colorop: allow non-bypass colorops Alex Hung
@ 2025-03-26 23:47 ` Alex Hung
  2025-03-29 14:57   ` Simon Ser
                     ` (2 more replies)
  2025-03-26 23:47 ` [PATCH V8 41/43] drm/amd/display: add 3D LUT colorop Alex Hung
                   ` (3 subsequent siblings)
  43 siblings, 3 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:47 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

It is to be used to enable HDR by allowing userpace to create and pass
3D LUTs to kernel and hardware.

new drm_colorop_type: DRM_COLOROP_3D_LUT.

Signed-off-by: Alex Hung <alex.hung@amd.com>
---
v8:
 - Fix typo in subject (Simon Ser)
 - Update documentation for DRM_COLOROP_3D_LUT (Simon Ser)
 - Delete empty lines (Simon Ser)

v7:
 - Simplify 3D LUT by removing lut_3d_modes and related functions (Simon Ser)

 drivers/gpu/drm/drm_atomic.c      |  6 +++
 drivers/gpu/drm/drm_atomic_uapi.c |  6 +++
 drivers/gpu/drm/drm_colorop.c     | 72 +++++++++++++++++++++++++++++++
 include/drm/drm_colorop.h         | 21 +++++++++
 include/uapi/drm/drm_mode.h       | 33 ++++++++++++++
 5 files changed, 138 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 0efb0ead204a..ef47a06344f3 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -806,6 +806,12 @@ static void drm_atomic_colorop_print_state(struct drm_printer *p,
 	case DRM_COLOROP_MULTIPLIER:
 		drm_printf(p, "\tmultiplier=%llu\n", state->multiplier);
 		break;
+	case DRM_COLOROP_3D_LUT:
+		drm_printf(p, "\tsize=%d\n", colorop->lut_size);
+		drm_printf(p, "\tinterpolation=%s\n",
+			   drm_get_colorop_lut3d_interpolation_name(colorop->lut3d_interpolation));
+		drm_printf(p, "\tdata blob id=%d\n", state->data ? state->data->base.id : 0);
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index 947c18e8bf9b..d5d464b4d0f6 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -719,6 +719,10 @@ static int drm_atomic_color_set_data_property(struct drm_colorop *colorop,
 	case DRM_COLOROP_CTM_3X4:
 		size = sizeof(struct drm_color_ctm_3x4);
 		break;
+	case DRM_COLOROP_3D_LUT:
+		size = colorop->lut_size * colorop->lut_size * colorop->lut_size *
+		       sizeof(struct drm_color_lut);
+		break;
 	default:
 		/* should never get here */
 		return -EINVAL;
@@ -771,6 +775,8 @@ drm_atomic_colorop_get_property(struct drm_colorop *colorop,
 		*val = state->multiplier;
 	} else if (property == colorop->lut_size_property) {
 		*val = colorop->lut_size;
+	} else if (property == colorop->lut3d_interpolation_property) {
+		*val = colorop->lut3d_interpolation;
 	} else if (property == colorop->data_property) {
 		*val = (state->data) ? state->data->base.id : 0;
 	} else {
diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index e03706e7179b..224c6be237d2 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -67,6 +67,7 @@ static const struct drm_prop_enum_list drm_colorop_type_enum_list[] = {
 	{ DRM_COLOROP_1D_LUT, "1D LUT" },
 	{ DRM_COLOROP_CTM_3X4, "3x4 Matrix"},
 	{ DRM_COLOROP_MULTIPLIER, "Multiplier"},
+	{ DRM_COLOROP_3D_LUT, "3D LUT"},
 };
 
 static const char * const colorop_curve_1d_type_names[] = {
@@ -82,6 +83,11 @@ static const struct drm_prop_enum_list drm_colorop_lut1d_interpolation_list[] =
 	{ DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR, "Linear" },
 };
 
+
+static const struct drm_prop_enum_list drm_colorop_lut3d_interpolation_list[] = {
+	{ DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL, "Tetrahedral" },
+};
+
 /* Init Helpers */
 
 static int drm_colorop_init(struct drm_device *dev, struct drm_colorop *colorop,
@@ -349,6 +355,51 @@ int drm_colorop_mult_init(struct drm_device *dev, struct drm_colorop *colorop,
 }
 EXPORT_SYMBOL(drm_colorop_mult_init);
 
+int drm_colorop_3dlut_init(struct drm_device *dev, struct drm_colorop *colorop,
+			   struct drm_plane *plane,
+			   uint32_t lut_size,
+			   enum drm_colorop_lut3d_interpolation_type interpolation,
+			   bool allow_bypass)
+{
+	struct drm_property *prop;
+	int ret;
+
+	ret = drm_colorop_init(dev, colorop, plane, DRM_COLOROP_3D_LUT, allow_bypass);
+	if (ret)
+		return ret;
+
+	/* LUT size */
+	prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE  | DRM_MODE_PROP_ATOMIC,
+					 "SIZE", 0, UINT_MAX);
+	if (!prop)
+		return -ENOMEM;
+
+	colorop->lut_size_property = prop;
+	drm_object_attach_property(&colorop->base, colorop->lut_size_property, lut_size);
+	colorop->lut_size = lut_size;
+
+	/* interpolation */
+	prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, "LUT3D_INTERPOLATION",
+					drm_colorop_lut3d_interpolation_list,
+					ARRAY_SIZE(drm_colorop_lut3d_interpolation_list));
+	if (!prop)
+		return -ENOMEM;
+
+	colorop->lut3d_interpolation_property = prop;
+	drm_object_attach_property(&colorop->base, prop, interpolation);
+	colorop->lut3d_interpolation = interpolation;
+
+	/* data */
+	ret = drm_colorop_create_data_prop(dev, colorop);
+	if (ret)
+		return ret;
+
+	drm_colorop_reset(colorop);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_colorop_3dlut_init);
+
 static void __drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop,
 							struct drm_colorop_state *state)
 {
@@ -441,7 +492,13 @@ static const char * const colorop_type_name[] = {
 	[DRM_COLOROP_1D_LUT] = "1D LUT",
 	[DRM_COLOROP_CTM_3X4] = "3x4 Matrix",
 	[DRM_COLOROP_MULTIPLIER] = "Multiplier",
+	[DRM_COLOROP_3D_LUT] = "3D LUT",
 };
+
+static const char * const colorop_lu3d_interpolation_name[] = {
+	[DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL] = "Tetrahedral",
+};
+
 static const char * const colorop_lut1d_interpolation_name[] = {
 	[DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR] = "Linear",
 };
@@ -477,6 +534,21 @@ const char *drm_get_colorop_lut1d_interpolation_name(enum drm_colorop_lut1d_inte
 	return colorop_lut1d_interpolation_name[type];
 }
 
+/**
+ * drm_get_colorop_lut3d_interpolation_name - return a string for interpolation type
+ * @type: interpolation type to compute name of
+ *
+ * In contrast to the other drm_get_*_name functions this one here returns a
+ * const pointer and hence is threadsafe.
+ */
+const char *drm_get_colorop_lut3d_interpolation_name(enum drm_colorop_lut3d_interpolation_type type)
+{
+	if (WARN_ON(type >= ARRAY_SIZE(colorop_lu3d_interpolation_name)))
+		return "unknown";
+
+	return colorop_lu3d_interpolation_name[type];
+}
+
 /**
  * drm_colorop_set_next_property - sets the next pointer
  * @colorop: drm colorop
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index c89d5eb44856..e999d5ceb8a5 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -281,6 +281,14 @@ struct drm_colorop {
 	 */
 	enum drm_colorop_lut1d_interpolation_type lut1d_interpolation;
 
+	/**
+	 * @lut3d_interpolation:
+	 *
+	 * Read-only
+	 * Interpolation for DRM_COLOROP_3D_LUT
+	 */
+	enum drm_colorop_lut3d_interpolation_type lut3d_interpolation;
+
 	/**
 	 * @lut1d_interpolation_property:
 	 *
@@ -309,6 +317,13 @@ struct drm_colorop {
 	 */
 	struct drm_property *lut_size_property;
 
+	/**
+	 * @lut3d_interpolation_property:
+	 *
+	 * Read-only property for DRM_COLOROP_3D_LUT interpolation
+	 */
+	struct drm_property *lut3d_interpolation_property;
+
 	/**
 	 * @data_property:
 	 *
@@ -362,6 +377,11 @@ int drm_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop
 			     struct drm_plane *plane, bool allow_bypass);
 int drm_colorop_mult_init(struct drm_device *dev, struct drm_colorop *colorop,
 			      struct drm_plane *plane, bool allow_bypass);
+int drm_colorop_3dlut_init(struct drm_device *dev, struct drm_colorop *colorop,
+			   struct drm_plane *plane,
+			   uint32_t lut_size,
+			   enum drm_colorop_lut3d_interpolation_type interpolation,
+			   bool allow_bypass);
 
 struct drm_colorop_state *
 drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop);
@@ -412,6 +432,7 @@ const char *drm_get_colorop_type_name(enum drm_colorop_type type);
  */
 const char *drm_get_colorop_curve_1d_type_name(enum drm_colorop_curve_1d_type type);
 const char *drm_get_colorop_lut1d_interpolation_name(enum drm_colorop_lut1d_interpolation_type type);
+const char *drm_get_colorop_lut3d_interpolation_name(enum drm_colorop_lut3d_interpolation_type type);
 
 void drm_colorop_set_next_property(struct drm_colorop *colorop, struct drm_colorop *next);
 
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index d76c8ffe5408..88fafbdeb2a2 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -930,6 +930,39 @@ enum drm_colorop_type {
 	 * property.
 	 */
 	DRM_COLOROP_MULTIPLIER,
+
+	/**
+	 * @DRM_COLOROP_3D_LUT:
+	 *
+	 * enum string "3D LUT"
+	 *
+	 * A 3D LUT of &drm_color_lut entries,
+	 * packed into a blob via the DATA property. The driver's expected
+	 * LUT size is advertised via the SIZE property, i.e., a 3D LUT with
+	 * 17x17x17 entries will have SIZE set to 17.
+	 *
+	 * The DATA blob is a 3D array of struct drm_color_lut with dimension
+	 * length of "lut_size".
+	 * The LUT elements are traversed like so:
+	 *
+	 *   for R in range 0..n
+	 *     for G in range 0..n
+	 *       for B in range 0..n
+	 *         color = lut3d[R][G][B]
+	 */
+	DRM_COLOROP_3D_LUT,
+};
+
+/**
+ * enum drm_colorop_lut3d_interpolation_type - type of 3DLUT interpolation
+ */
+enum drm_colorop_lut3d_interpolation_type {
+	/**
+	 * @DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL:
+	 *
+	 * Tetrahedral 3DLUT interpolation
+	 */
+	DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL,
 };
 
 /**
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 41/43] drm/amd/display: add 3D LUT colorop
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (39 preceding siblings ...)
  2025-03-26 23:47 ` [PATCH V8 40/43] drm/colorop: Add 3D LUT support to color pipeline Alex Hung
@ 2025-03-26 23:47 ` Alex Hung
  2025-03-26 23:47 ` [PATCH V8 42/43] drm/amd/display: Add AMD color pipeline doc Alex Hung
                   ` (2 subsequent siblings)
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:47 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

This adds support for a 3D LUT.

The color pipeline now consists of the following colorops:
1. 1D curve colorop
2. Multiplier
3. 3x4 CTM
4. 1D curve colorop
5. 1D LUT
6. 3D LUT
7. 1D curve colorop
8. 1D LUT

Signed-off-by: Alex Hung <alex.hung@amd.com>
---
v8:
 - Set initialized to 0 and return when drm_lut3d_size is 0 (Harry Wentland)
 - Rework tf->type = TF_TYPE_BYPASS for shaper (Harry Wentland & Leo Li)

v7:
 - Simplify 3D LUT according to drm_colorop changes (Simon Ser)

 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 94 +++++++++++++++++++
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.c | 19 ++++
 2 files changed, 113 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index 1bf40f39bd0c..a4b6bb7b409f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -1293,6 +1293,7 @@ __set_dm_plane_colorop_shaper(struct drm_plane_state *plane_state,
 	struct dc_transfer_func *tf = &dc_plane_state->in_shaper_func;
 	const struct drm_color_lut *shaper_lut;
 	struct drm_device *dev = colorop->dev;
+	bool enabled = false;
 	uint32_t shaper_size;
 	int i = 0, ret = 0;
 
@@ -1314,6 +1315,7 @@ __set_dm_plane_colorop_shaper(struct drm_plane_state *plane_state,
 		ret = __set_output_tf(tf, 0, 0, false);
 		if (ret)
 			return ret;
+		enabled = true;
 	}
 
 	/* 1D LUT - SHAPER LUT */
@@ -1345,6 +1347,87 @@ __set_dm_plane_colorop_shaper(struct drm_plane_state *plane_state,
 			ret = __set_output_tf(tf, shaper_lut, shaper_size, false);
 			if (ret)
 				return ret;
+			enabled = true;
+		}
+	}
+
+	if (!enabled)
+		tf->type = TF_TYPE_BYPASS;
+
+	return 0;
+}
+
+/* __set_colorop_3dlut - set DRM 3D LUT to DC stream
+ * @drm_lut3d: user 3D LUT
+ * @drm_lut3d_size: size of 3D LUT
+ * @lut3d: DC 3D LUT
+ *
+ * Map user 3D LUT data to DC 3D LUT and all necessary bits to program it
+ * on DCN accordingly.
+ */
+static void __set_colorop_3dlut(const struct drm_color_lut *drm_lut3d,
+				uint32_t drm_lut3d_size,
+				struct dc_3dlut *lut)
+{
+	if (!drm_lut3d_size) {
+		lut->state.bits.initialized = 0;
+		return;
+	}
+
+	/* Only supports 17x17x17 3D LUT (12-bit) now */
+	lut->lut_3d.use_12bits = true;
+	lut->lut_3d.use_tetrahedral_9 = false;
+
+	lut->state.bits.initialized = 1;
+	__drm_3dlut_to_dc_3dlut(drm_lut3d, drm_lut3d_size, &lut->lut_3d,
+				lut->lut_3d.use_tetrahedral_9, 12);
+
+}
+
+static int
+__set_dm_plane_colorop_3dlut(struct drm_plane_state *plane_state,
+			     struct dc_plane_state *dc_plane_state,
+			     struct drm_colorop *colorop)
+{
+	struct drm_colorop *old_colorop;
+	struct drm_colorop_state *colorop_state = NULL, *new_colorop_state;
+	struct dc_transfer_func *tf = &dc_plane_state->in_shaper_func;
+	struct drm_atomic_state *state = plane_state->state;
+	const struct amdgpu_device *adev = drm_to_adev(colorop->dev);
+	const struct drm_device *dev = colorop->dev;
+	const struct drm_color_lut *lut3d;
+	uint32_t lut3d_size;
+	int i = 0, ret = 0;
+
+	/* 3D LUT */
+	old_colorop = colorop;
+	for_each_new_colorop_in_state(state, colorop, new_colorop_state, i) {
+		if (new_colorop_state->colorop == old_colorop &&
+		    new_colorop_state->colorop->type == DRM_COLOROP_3D_LUT) {
+			colorop_state = new_colorop_state;
+			break;
+		}
+	}
+
+	if (colorop_state && !colorop_state->bypass && colorop->type == DRM_COLOROP_3D_LUT) {
+		if (!adev->dm.dc->caps.color.dpp.hw_3d_lut) {
+			drm_dbg(dev, "3D LUT is not supported by hardware\n");
+			return -EINVAL;
+		}
+
+		drm_dbg(dev, "3D LUT colorop with ID: %d\n", colorop->base.id);
+		lut3d = __extract_blob_lut(colorop_state->data, &lut3d_size);
+		lut3d_size = lut3d != NULL ? lut3d_size : 0;
+		__set_colorop_3dlut(lut3d, lut3d_size, &dc_plane_state->lut3d_func);
+
+		/* 3D LUT requires shaper. If shaper colorop is bypassed, enable shaper curve
+		 * with TRANSFER_FUNCTION_LINEAR
+		 */
+		if (tf->type == TF_TYPE_BYPASS) {
+			tf->type = TF_TYPE_DISTRIBUTED_POINTS;
+			tf->tf = TRANSFER_FUNCTION_LINEAR;
+			tf->sdr_ref_white_level = SDR_WHITE_LEVEL_INIT_VALUE;
+			ret = __set_output_tf(tf, NULL, 0, false);
 		}
 	}
 
@@ -1522,6 +1605,17 @@ amdgpu_dm_plane_set_colorop_properties(struct drm_plane_state *plane_state,
 	if (!colorop)
 		return -EINVAL;
 
+	/* 3D LUT */
+	colorop = colorop->next;
+	if (!colorop) {
+		drm_dbg(dev, "no 3D LUT colorop found\n");
+		return -EINVAL;
+	}
+
+	ret = __set_dm_plane_colorop_3dlut(plane_state, dc_plane_state, colorop);
+	if (ret)
+		return ret;
+
 	/* 1D Curve & LUT - BLND TF & LUT */
 	colorop = colorop->next;
 	if (!colorop) {
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
index ec94ff887886..e03e6044f937 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
@@ -49,6 +49,8 @@ const u64 amdgpu_dm_supported_blnd_tfs =
 
 #define MAX_COLOR_PIPELINE_OPS 10
 
+#define LUT3D_SIZE		17
+
 int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list)
 {
 	struct drm_colorop *ops[MAX_COLOR_PIPELINE_OPS];
@@ -145,6 +147,23 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
 
 	i++;
 
+	/* 3D LUT */
+	ops[i] = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
+	if (!ops[i]) {
+		DRM_ERROR("KMS: Failed to allocate colorop\n");
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	ret = drm_colorop_3dlut_init(dev, ops[i], plane, LUT3D_SIZE,
+				     DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL, true);
+	if (ret)
+		goto cleanup;
+
+	drm_colorop_set_next_property(ops[i-1], ops[i]);
+
+	i++;
+
 	/* 1D curve - BLND TF */
 	ops[i] = kzalloc(sizeof(struct drm_colorop), GFP_KERNEL);
 	if (!ops[i]) {
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 42/43] drm/amd/display: Add AMD color pipeline doc
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (40 preceding siblings ...)
  2025-03-26 23:47 ` [PATCH V8 41/43] drm/amd/display: add 3D LUT colorop Alex Hung
@ 2025-03-26 23:47 ` Alex Hung
  2025-03-26 23:47 ` [PATCH V8 43/43] drm/colorop: Add destroy functions for color pipeline Alex Hung
  2025-03-29 15:51 ` [PATCH V8 00/43] Color Pipeline API w/ VKMS Simon Ser
  43 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:47 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

From: Harry Wentland <harry.wentland@amd.com>

Add kernel doc for AMD color pipeline.

Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 122 +++++++++++++++---
 1 file changed, 102 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
index a4b6bb7b409f..6caec63f001b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -33,6 +33,32 @@
 /**
  * DOC: overview
  *
+ * We have three types of color management in the AMD display driver.
+ * 1. the legacy &drm_crtc DEGAMMA, CTM, and GAMMA properties
+ * 2. AMD driver private color management on &drm_plane and &drm_crtc
+ * 3. AMD plane color pipeline
+ *
+ * The CRTC properties are the original color management. When they were
+ * implemented per-plane color management was not a thing yet. Because
+ * of that we could get away with plumbing the DEGAMMA and CTM
+ * properties to pre-blending HW functions. This is incompatible with
+ * per-plane color management, such as via the AMD private properties or
+ * the new drm_plane color pipeline. The only compatible CRTC property
+ * with per-plane color management is the GAMMA property as it is
+ * applied post-blending.
+ *
+ * The AMD driver private color management properties are only exposed
+ * when the kernel is built explicitly with -DAMD_PRIVATE_COLOR. They
+ * are temporary building blocks on the path to full-fledged &drm_plane
+ * and &drm_crtc color pipelines and lay the driver's groundwork for the
+ * color pipelines.
+ *
+ * The AMD plane color pipeline describes AMD's &drm_colorops via the
+ * &drm_plane's COLOR_PIPELINE property.
+ *
+ * drm_crtc Properties
+ * -------------------
+ *
  * The DC interface to HW gives us the following color management blocks
  * per pipe (surface):
  *
@@ -43,33 +69,89 @@
  * - Surface regamma LUT (normalized)
  * - Output CSC (normalized)
  *
- * But these aren't a direct mapping to DRM color properties. The current DRM
- * interface exposes CRTC degamma, CRTC CTM and CRTC regamma while our hardware
- * is essentially giving:
+ * But these aren't a direct mapping to DRM color properties. The
+ * current DRM interface exposes CRTC degamma, CRTC CTM and CRTC regamma
+ * while our hardware is essentially giving:
  *
  * Plane CTM -> Plane degamma -> Plane CTM -> Plane regamma -> Plane CTM
  *
- * The input gamma LUT block isn't really applicable here since it operates
- * on the actual input data itself rather than the HW fp representation. The
- * input and output CSC blocks are technically available to use as part of
- * the DC interface but are typically used internally by DC for conversions
- * between color spaces. These could be blended together with user
- * adjustments in the future but for now these should remain untouched.
+ * The input gamma LUT block isn't really applicable here since it
+ * operates on the actual input data itself rather than the HW fp
+ * representation. The input and output CSC blocks are technically
+ * available to use as part of the DC interface but are typically used
+ * internally by DC for conversions between color spaces. These could be
+ * blended together with user adjustments in the future but for now
+ * these should remain untouched.
+ *
+ * The pipe blending also happens after these blocks so we don't
+ * actually support any CRTC props with correct blending with multiple
+ * planes - but we can still support CRTC color management properties in
+ * DM in most single plane cases correctly with clever management of the
+ * DC interface in DM.
+ *
+ * As per DRM documentation, blocks should be in hardware bypass when
+ * their respective property is set to NULL. A linear DGM/RGM LUT should
+ * also considered as putting the respective block into bypass mode.
+ *
+ * This means that the following configuration is assumed to be the
+ * default:
+ *
+ * Plane DGM Bypass -> Plane CTM Bypass -> Plane RGM Bypass -> ... CRTC
+ * DGM Bypass -> CRTC CTM Bypass -> CRTC RGM Bypass
+ *
+ * AMD Private Color Management on drm_plane
+ * -----------------------------------------
+ *
+ * The AMD private color management properties on a &drm_plane are:
+ *
+ * - AMD_PLANE_DEGAMMA_LUT
+ * - AMD_PLANE_DEGAMMA_LUT_SIZE
+ * - AMD_PLANE_DEGAMMA_TF
+ * - AMD_PLANE_HDR_MULT
+ * - AMD_PLANE_CTM
+ * - AMD_PLANE_SHAPER_LUT
+ * - AMD_PLANE_SHAPER_LUT_SIZE
+ * - AMD_PLANE_SHAPER_TF
+ * - AMD_PLANE_LUT3D
+ * - AMD_PLANE_LUT3D_SIZE
+ * - AMD_PLANE_BLEND_LUT
+ * - AMD_PLANE_BLEND_LUT_SIZE
+ * - AMD_PLANE_BLEND_TF
+ *
+ * The AMD private color management property on a &drm_crtc is:
+ *
+ * - AMD_CRTC_REGAMMA_TF
+ *
+ * Use of these properties is discouraged.
+ *
+ * AMD plane color pipeline
+ * ------------------------
+ *
+ * The AMD &drm_plane color pipeline is advertised for DCN generations
+ * 3.0 and newer. It exposes these elements in this order:
+ *
+ * 1. 1D curve colorop
+ * 2. Multiplier
+ * 3. 3x4 CTM
+ * 4. 1D curve colorop
+ * 5. 1D LUT
+ * 6. 3D LUT
+ * 7. 1D curve colorop
+ * 8. 1D LUT
+ *
+ * The multiplier (#2) is a simple multiplier that is applied to all
+ * channels.
+ *
+ * The 3x4 CTM (#3) is a simple 3x4 matrix.
  *
- * The pipe blending also happens after these blocks so we don't actually
- * support any CRTC props with correct blending with multiple planes - but we
- * can still support CRTC color management properties in DM in most single
- * plane cases correctly with clever management of the DC interface in DM.
+ * #1, and #7 are non-linear to linear curves. #4 is a linear to
+ * non-linear curve. They support sRGB, PQ, and BT.709/BT.2020 EOTFs or
+ * their inverse.
  *
- * As per DRM documentation, blocks should be in hardware bypass when their
- * respective property is set to NULL. A linear DGM/RGM LUT should also
- * considered as putting the respective block into bypass mode.
+ * The 1D LUTs (#5 and #8) are plain 4096 entry LUTs.
  *
- * This means that the following
- * configuration is assumed to be the default:
+ * The 3DLUT (#6) is a tetrahedrally interpolated 17 cube LUT.
  *
- * Plane DGM Bypass -> Plane CTM Bypass -> Plane RGM Bypass -> ...
- * CRTC DGM Bypass -> CRTC CTM Bypass -> CRTC RGM Bypass
  */
 
 #define MAX_DRM_LUT_VALUE 0xFFFF
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* [PATCH V8 43/43] drm/colorop: Add destroy functions for color pipeline
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (41 preceding siblings ...)
  2025-03-26 23:47 ` [PATCH V8 42/43] drm/amd/display: Add AMD color pipeline doc Alex Hung
@ 2025-03-26 23:47 ` Alex Hung
  2025-03-29 15:48   ` Simon Ser
  2025-03-29 15:51 ` [PATCH V8 00/43] Color Pipeline API w/ VKMS Simon Ser
  43 siblings, 1 reply; 128+ messages in thread
From: Alex Hung @ 2025-03-26 23:47 UTC (permalink / raw)
  To: dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, alex.hung, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

The functions are to clean up color pipeline when a device driver
fails to create its color pipeline.

Signed-off-by: Alex Hung <alex.hung@amd.com>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_colorop.c |  3 +-
 drivers/gpu/drm/drm_colorop.c                 | 41 +++++++++++++++++++
 drivers/gpu/drm/vkms/vkms_colorop.c           |  3 +-
 include/drm/drm_colorop.h                     |  2 +
 4 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
index e03e6044f937..80173f00dfd0 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
@@ -200,8 +200,7 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
 	return 0;
 
 cleanup:
-	for (; i >= 0; i--)
-		kfree(ops[i]);
+	drm_colorop_pipeline_destroy(plane);
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
index 224c6be237d2..5845527201d2 100644
--- a/drivers/gpu/drm/drm_colorop.c
+++ b/drivers/gpu/drm/drm_colorop.c
@@ -154,6 +154,47 @@ static int drm_colorop_init(struct drm_device *dev, struct drm_colorop *colorop,
 	return ret;
 }
 
+/**
+ * drm_colorop_cleanup - Cleanup a drm_colorop object in color_pipeline
+ *
+ * @colorop: The drm_colorop object to be cleaned
+ */
+static void drm_colorop_cleanup(struct drm_colorop *colorop)
+{
+	struct drm_device *dev = colorop->dev;
+	struct drm_mode_config *config = &dev->mode_config;
+
+	list_del(&colorop->head);
+	config->num_colorop--;
+
+	if (colorop->state && colorop->state->data) {
+		drm_property_blob_put(colorop->state->data);
+		colorop->state->data = NULL;
+	}
+
+	kfree(colorop->state);
+	kfree(colorop);
+}
+
+/**
+ * drm_colorop_pipeline_destroy - Helper for color pipeline destruction
+ *
+ * @plane: - The drm_plane structure containing the color_pipeline
+ *
+ * Provides a default color pipeline destroy handler for a planes.
+ */
+void drm_colorop_pipeline_destroy(struct drm_plane *plane)
+{
+	struct drm_device *dev = plane->dev;
+	struct drm_mode_config *config = &dev->mode_config;
+	struct drm_colorop *colorop, *next;
+
+	list_for_each_entry_safe(colorop, next, &config->colorop_list, head) {
+		drm_colorop_cleanup(colorop);
+	}
+}
+EXPORT_SYMBOL(drm_colorop_pipeline_destroy);
+
 /**
  * drm_colorop_curve_1d_init - Initialize a DRM_COLOROP_1D_CURVE
  *
diff --git a/drivers/gpu/drm/vkms/vkms_colorop.c b/drivers/gpu/drm/vkms/vkms_colorop.c
index a2f548a4b84d..801e7ad6ad79 100644
--- a/drivers/gpu/drm/vkms/vkms_colorop.c
+++ b/drivers/gpu/drm/vkms/vkms_colorop.c
@@ -89,8 +89,7 @@ static int vkms_initialize_color_pipeline(struct drm_plane *plane, struct drm_pr
 	return 0;
 
 cleanup:
-	for (; i >= 0; i--)
-		kfree(ops[i]);
+	drm_colorop_pipeline_destroy(plane);
 
 	return ret;
 }
diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
index e999d5ceb8a5..e1f7c91e8db1 100644
--- a/include/drm/drm_colorop.h
+++ b/include/drm/drm_colorop.h
@@ -366,6 +366,8 @@ static inline struct drm_colorop *drm_colorop_find(struct drm_device *dev,
 	return mo ? obj_to_colorop(mo) : NULL;
 }
 
+void drm_colorop_pipeline_destroy(struct drm_plane *plane);
+
 int drm_colorop_curve_1d_init(struct drm_device *dev, struct drm_colorop *colorop,
 			      struct drm_plane *plane, u64 supported_tfs,
 			      bool allow_bypass);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 08/43] drm/colorop: Add NEXT property
  2025-03-26 23:46 ` [PATCH V8 08/43] drm/colorop: Add NEXT property Alex Hung
@ 2025-03-27 23:26   ` Simon Ser
  0 siblings, 0 replies; 128+ messages in thread
From: Simon Ser @ 2025-03-27 23:26 UTC (permalink / raw)
  To: Alex Hung
  Cc: dri-devel, amd-gfx, wayland-devel, harry.wentland, leo.liu,
	ville.syrjala, pekka.paalanen, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

Reviewed-by: Simon Ser <contact@emersion.fr>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 09/43] drm/colorop: Add atomic state print for drm_colorop
  2025-03-26 23:46 ` [PATCH V8 09/43] drm/colorop: Add atomic state print for drm_colorop Alex Hung
@ 2025-03-27 23:29   ` Simon Ser
  0 siblings, 0 replies; 128+ messages in thread
From: Simon Ser @ 2025-03-27 23:29 UTC (permalink / raw)
  To: Alex Hung
  Cc: dri-devel, amd-gfx, wayland-devel, harry.wentland, leo.liu,
	ville.syrjala, pekka.paalanen, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

Reviewed-by: Simon Ser <contact@emersion.fr>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 10/43] drm/plane: Add COLOR PIPELINE property
  2025-03-26 23:46 ` [PATCH V8 10/43] drm/plane: Add COLOR PIPELINE property Alex Hung
@ 2025-03-29 14:33   ` Simon Ser
  0 siblings, 0 replies; 128+ messages in thread
From: Simon Ser @ 2025-03-29 14:33 UTC (permalink / raw)
  To: Alex Hung
  Cc: dri-devel, amd-gfx, wayland-devel, harry.wentland, leo.liu,
	ville.syrjala, pekka.paalanen, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

Two nits below, regardless:

Reviewed-by: Simon Ser <contact@emersion.fr>

> +	} else if (property == plane->color_pipeline_property) {
> +		/* find DRM colorop object */
> +		struct drm_colorop *colorop = NULL;
> +
> +		colorop = drm_colorop_find(dev, file_priv, val);
> +
> +		if (val && !colorop)
> +			return -EACCES;
> +
> +		/* set it on drm_plane_state */
> +		drm_atomic_set_colorop_for_plane(state, colorop);

Nit: I don't think these comments are especially useful, the names of the
functions are clear enough.

> +int drm_plane_create_color_pipeline_property(struct drm_plane *plane,
> +					     const struct drm_prop_enum_list *pipelines,
> +					     const int num_pipelines)

Nit: in general we don't mark non-pointer arguments as const: the function
cannot mutate the caller's value anyways.

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 11/43] drm/colorop: Introduce DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE
  2025-03-26 23:46 ` [PATCH V8 11/43] drm/colorop: Introduce DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE Alex Hung
@ 2025-03-29 14:37   ` Simon Ser
  2025-04-01  1:42   ` Shengyu Qu
  1 sibling, 0 replies; 128+ messages in thread
From: Simon Ser @ 2025-03-29 14:37 UTC (permalink / raw)
  To: Alex Hung
  Cc: dri-devel, amd-gfx, wayland-devel, harry.wentland, leo.liu,
	ville.syrjala, pekka.paalanen, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

Reviewed-by: Simon Ser <contact@emersion.fr>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 12/43] Documentation/gpu: document drm_colorop
  2025-03-26 23:46 ` [PATCH V8 12/43] Documentation/gpu: document drm_colorop Alex Hung
@ 2025-03-29 14:40   ` Simon Ser
  0 siblings, 0 replies; 128+ messages in thread
From: Simon Ser @ 2025-03-29 14:40 UTC (permalink / raw)
  To: Alex Hung
  Cc: dri-devel, amd-gfx, wayland-devel, harry.wentland, leo.liu,
	ville.syrjala, pekka.paalanen, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

Reviewed-by: Simon Ser <contact@emersion.fr>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 28/43] drm/colorop: Add PQ 125 EOTF and its inverse
  2025-03-26 23:47 ` [PATCH V8 28/43] drm/colorop: Add PQ 125 EOTF and its inverse Alex Hung
@ 2025-03-29 14:48   ` Simon Ser
  0 siblings, 0 replies; 128+ messages in thread
From: Simon Ser @ 2025-03-29 14:48 UTC (permalink / raw)
  To: Alex Hung
  Cc: dri-devel, amd-gfx, wayland-devel, harry.wentland, leo.liu,
	ville.syrjala, pekka.paalanen, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

Reviewed-by: Simon Ser <contact@emersion.fr>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 30/43] drm/colorop: add BT2020/BT709 OETF and Inverse OETF
  2025-03-26 23:47 ` [PATCH V8 30/43] drm/colorop: add BT2020/BT709 OETF and Inverse OETF Alex Hung
@ 2025-03-29 14:53   ` Simon Ser
  0 siblings, 0 replies; 128+ messages in thread
From: Simon Ser @ 2025-03-29 14:53 UTC (permalink / raw)
  To: Alex Hung
  Cc: dri-devel, amd-gfx, wayland-devel, harry.wentland, leo.liu,
	ville.syrjala, pekka.paalanen, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

Note, this patch adds new values in the middle of the enum. This is in
general a breaking uAPI change: all enum values afterwards will get
re-numbered.

Maybe this patch should come before the PQ 125 one. In this series it
shouldn't matter either way because we're also introducing the enum, but
(1) who knows what/how distros might end up cherry-picking (2) future
patches might take inspiration from this one.

With that fixed:

Reviewed-by: Simon Ser <contact@emersion.fr>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type
  2025-03-26 23:47 ` [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type Alex Hung
@ 2025-03-29 14:55   ` Simon Ser
  2025-04-15  6:09   ` Shankar, Uma
  1 sibling, 0 replies; 128+ messages in thread
From: Simon Ser @ 2025-03-29 14:55 UTC (permalink / raw)
  To: Alex Hung
  Cc: dri-devel, amd-gfx, wayland-devel, harry.wentland, leo.liu,
	ville.syrjala, pekka.paalanen, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

Reviewed-by: Simon Ser <contact@emersion.fr>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 40/43] drm/colorop: Add 3D LUT support to color pipeline
  2025-03-26 23:47 ` [PATCH V8 40/43] drm/colorop: Add 3D LUT support to color pipeline Alex Hung
@ 2025-03-29 14:57   ` Simon Ser
  2025-04-25 13:50   ` Leandro Ribeiro
  2025-05-17  1:22   ` Xaver Hugl
  2 siblings, 0 replies; 128+ messages in thread
From: Simon Ser @ 2025-03-29 14:57 UTC (permalink / raw)
  To: Alex Hung
  Cc: dri-devel, amd-gfx, wayland-devel, harry.wentland, leo.liu,
	ville.syrjala, pekka.paalanen, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

Reviewed-by: Simon Ser <contact@emersion.fr>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 03/43] drm/doc/rfc: Describe why prescriptive color pipeline is needed
  2025-03-26 23:46 ` [PATCH V8 03/43] drm/doc/rfc: Describe why prescriptive color pipeline is needed Alex Hung
@ 2025-03-29 15:26   ` Simon Ser
  2025-04-01  0:10     ` Alex Hung
  2025-03-31 16:24   ` Shengyu Qu
  1 sibling, 1 reply; 128+ messages in thread
From: Simon Ser @ 2025-03-29 15:26 UTC (permalink / raw)
  To: Alex Hung
  Cc: dri-devel, amd-gfx, wayland-devel, harry.wentland, leo.liu,
	ville.syrjala, pekka.paalanen, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

Thanks a lot for these docs, very well written. I especially like the
"Driver Implementer's Guide" section.

A few minor comments below, regardless:

Reviewed-by: Simon Ser <contact@emersion.fr>

> +What problem are we solving?
> +============================
> +
> +We would like to support pre-, and post-blending complex color
> +transformations in display controller hardware in order to allow for
> +HW-supported HDR use-cases, as well as to provide support to
> +color-managed applications, such as video or image editors.
> +
> +It is possible to support an HDR output on HW supporting the Colorspace
> +and HDR Metadata drm_connector properties, but that requires the
> +compositor or application to render and compose the content into one
> +final buffer intended for display. Doing so is costly.
> +
> +Most modern display HW offers various 1D LUTs, 3D LUTs, matrices, and other
> +operations to support color transformations. These operations are often
> +implemented in fixed-function HW and therefore much more power efficient than
> +performing similar operations via shaders or CPU.
> +
> +We would like to make use of this HW functionality to support complex color
> +transformations with no, or minimal CPU or shader load.

I would also highlight that we need to seamlessly switch between HW
fixed-function blocks and shaders/CPU with no visible difference. Depending on
the content being displayed we might need to fallback to shaders/CPU at any
time. (A classic example would be a new notification popup preventing us from
leveraging KMS planes.)

> +An example of a drm_colorop object might look like one of these::
> +
> +    /* 1D enumerated curve */
> +    Color operation 42
> +    ├─ "TYPE": immutable enum {1D enumerated curve, 1D LUT, 3x3 matrix, 3x4 matrix, 3D LUT, etc.} = 1D enumerated curve
> +    ├─ "BYPASS": bool {true, false}
> +    ├─ "CURVE_1D_TYPE": enum {sRGB EOTF, sRGB inverse EOTF, PQ EOTF, PQ inverse EOTF, …}
> +    └─ "NEXT": immutable color operation ID = 43
> +
> +    /* custom 4k entry 1D LUT */
> +    Color operation 52
> +    ├─ "TYPE": immutable enum {1D enumerated curve, 1D LUT, 3x3 matrix, 3x4 matrix, 3D LUT, etc.} = 1D LUT
> +    ├─ "BYPASS": bool {true, false}
> +    ├─ "SIZE": immutable range = 4096
> +    ├─ "DATA": blob
> +    └─ "NEXT": immutable color operation ID = 0
> +
> +    /* 17^3 3D LUT */
> +    Color operation 72
> +    ├─ "TYPE": immutable enum {1D enumerated curve, 1D LUT, 3x3 matrix, 3x4 matrix, 3D LUT, etc.} = 3D LUT
> +    ├─ "BYPASS": bool {true, false}
> +    ├─ "3DLUT_MODES": read-only blob of supported 3DLUT modes
> +    ├─ "3DLUT_MODE_INDEX": index of selected 3DLUT mode

Nit: the 3D LUT modes have been dropped from the initial patch series.

> +    ├─ "DATA": blob
> +    └─ "NEXT": immutable color operation ID = 73

[...]

> +Color Pipeline Discovery
> +========================
> +
> +A DRM client wanting color management on a drm_plane will:
> +
> +1. Get the COLOR_PIPELINE property of the plane
> +2. iterate all COLOR_PIPELINE enum values
> +3. for each enum value walk the color pipeline (via the NEXT pointers)
> +   and see if the available color operations are suitable for the
> +   desired color management operations
> +
> +If userspace encounters an unknown or unsuitable color operation during
> +discovery it does not need to reject the entire color pipeline outright,
> +as long as the unknown or unsuitable colorop has a "BYPASS" property.
> +Drivers will ensure that a bypassed block does not have any effect.
> +
> +An example of chained properties to define an AMD pre-blending color
> +pipeline might look like this::
> +
> +    Plane 10
> +    ├─ "TYPE" (immutable) = Primary
> +    └─ "COLOR_PIPELINE": enum {0, 44} = 0
> +
> +    Color operation 44
> +    ├─ "TYPE" (immutable) = 1D enumerated curve
> +    ├─ "BYPASS": bool
> +    ├─ "CURVE_1D_TYPE": enum {sRGB EOTF, PQ EOTF} = sRGB EOTF
> +    └─ "NEXT" (immutable) = 45
> +
> +    Color operation 45
> +    ├─ "TYPE" (immutable) = 3x4 Matrix
> +    ├─ "BYPASS": bool
> +    ├─ "DATA": blob
> +    └─ "NEXT" (immutable) = 46
> +
> +    Color operation 46
> +    ├─ "TYPE" (immutable) = 1D enumerated curve
> +    ├─ "BYPASS": bool
> +    ├─ "CURVE_1D_TYPE": enum {sRGB Inverse EOTF, PQ Inverse EOTF} = sRGB EOTF
> +    └─ "NEXT" (immutable) = 47
> +
> +    Color operation 47
> +    ├─ "TYPE" (immutable) = 1D LUT
> +    ├─ "SIZE": immutable range = 4096
> +    ├─ "DATA": blob
> +    └─ "NEXT" (immutable) = 48
> +
> +    Color operation 48
> +    ├─ "TYPE" (immutable) = 3D LUT
> +    ├─ "3DLUT_MODE_INDEX": 0

Ditto

> +    ├─ "DATA": blob
> +    └─ "NEXT" (immutable) = 49
> +
> +    Color operation 49
> +    ├─ "TYPE" (immutable) = 1D enumerated curve
> +    ├─ "BYPASS": bool
> +    ├─ "CURVE_1D_TYPE": enum {sRGB EOTF, PQ EOTF} = sRGB EOTF
> +    └─ "NEXT" (immutable) = 0
> +
> +
> +Color Pipeline Programming
> +==========================
> +
> +Once a DRM client has found a suitable pipeline it will:
> +
> +1. Set the COLOR_PIPELINE enum value to the one pointing at the first
> +   drm_colorop object of the desired pipeline
> +2. Set the properties for all drm_colorop objects in the pipeline to the
> +   desired values, setting BYPASS to true for unused drm_colorop blocks,
> +   and false for enabled drm_colorop blocks
> +3. Perform (TEST_ONLY or not) atomic commit with all the other KMS
> +   states it wishes to change
> +
> +To configure the pipeline for an HDR10 PQ plane and blending in linear
> +space, a compositor might perform an atomic commit with the following
> +property values::
> +
> +    Plane 10
> +    └─ "COLOR_PIPELINE" = 42
> +
> +    Color operation 42
> +    └─ "BYPASS" = true
> +
> +    Color operation 44
> +    └─ "BYPASS" = true
> +
> +    Color operation 45
> +    └─ "BYPASS" = true
> +
> +    Color operation 46
> +    └─ "BYPASS" = true
> +
> +    Color operation 47
> +    ├─ "LUT_3D_DATA" = Gamut mapping + tone mapping + night mode

I think this is just named "DATA" now?

> +    └─ "BYPASS" = false
> +
> +    Color operation 48
> +    ├─ "CURVE_1D_TYPE" = PQ EOTF
> +    └─ "BYPASS" = false

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 20/43] drm/colorop: pass plane_color_pipeline client cap to atomic check
  2025-03-26 23:47 ` [PATCH V8 20/43] drm/colorop: pass plane_color_pipeline client cap to atomic check Alex Hung
@ 2025-03-29 15:32   ` Simon Ser
  0 siblings, 0 replies; 128+ messages in thread
From: Simon Ser @ 2025-03-29 15:32 UTC (permalink / raw)
  To: Alex Hung
  Cc: dri-devel, amd-gfx, wayland-devel, harry.wentland, leo.liu,
	ville.syrjala, pekka.paalanen, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

Reviewed-by: Simon Ser <contact@emersion.fr>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 39/43] drm/colorop: allow non-bypass colorops
  2025-03-26 23:47 ` [PATCH V8 39/43] drm/colorop: allow non-bypass colorops Alex Hung
@ 2025-03-29 15:41   ` Simon Ser
  0 siblings, 0 replies; 128+ messages in thread
From: Simon Ser @ 2025-03-29 15:41 UTC (permalink / raw)
  To: Alex Hung
  Cc: dri-devel, amd-gfx, wayland-devel, harry.wentland, leo.liu,
	ville.syrjala, pekka.paalanen, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

I'm personally not a fan of such boolean function arguments, especially
when caller and callee are far apart. From the caller side, the meaning
of the boolean argument is not immediately clear.

I would prefer a "flags" argument, which can take a e.g.
DRM_COLOROP_FLAG_ALLOW_BYPASS value.

But I'm not feeling strongly about this.

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 43/43] drm/colorop: Add destroy functions for color pipeline
  2025-03-26 23:47 ` [PATCH V8 43/43] drm/colorop: Add destroy functions for color pipeline Alex Hung
@ 2025-03-29 15:48   ` Simon Ser
  2025-04-01  2:42     ` Alex Hung
  0 siblings, 1 reply; 128+ messages in thread
From: Simon Ser @ 2025-03-29 15:48 UTC (permalink / raw)
  To: Alex Hung
  Cc: dri-devel, amd-gfx, wayland-devel, harry.wentland, leo.liu,
	ville.syrjala, pekka.paalanen, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

I would prefer these functions to be introduced together with the
patches adding functions to create objects and adding the new fields.
That way it's easier to check the symmetry and at no point in the
series there are memory leaks.

Additionally, I would avoid using the name "cleanup", which seems to
have different semantics: for instance drm_plane_cleanup() doesn't kfree
the pointer. "destroy" seems more appropriate here.

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 00/43] Color Pipeline API w/ VKMS
  2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
                   ` (42 preceding siblings ...)
  2025-03-26 23:47 ` [PATCH V8 43/43] drm/colorop: Add destroy functions for color pipeline Alex Hung
@ 2025-03-29 15:51 ` Simon Ser
  43 siblings, 0 replies; 128+ messages in thread
From: Simon Ser @ 2025-03-29 15:51 UTC (permalink / raw)
  To: Alex Hung
  Cc: dri-devel, amd-gfx, wayland-devel, harry.wentland, leo.liu,
	ville.syrjala, pekka.paalanen, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet, Arthur Grillo

Thanks a lot for sending the updated series, Alex! I've looked at all
of the core DRM patches and they all look pretty close to being R-b'ed.
I don't think I'd have time to look at vkms or amdgpu patches. Let me
know if I missed anything!

Simon

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-03-26 23:47 ` [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane Alex Hung
@ 2025-03-30  9:48   ` Shengyu Qu
  2025-03-30 12:59   ` Shengyu Qu
  1 sibling, 0 replies; 128+ messages in thread
From: Shengyu Qu @ 2025-03-30  9:48 UTC (permalink / raw)
  To: Alex Hung, dri-devel, amd-gfx
  Cc: wiagn233, wayland-devel, harry.wentland, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet


[-- Attachment #1.1.1: Type: text/plain, Size: 1192 bytes --]

Hi,

Do we really need to disable cursor plane color pipeline support? I 
don't think we need to disable that if it is supported, since there 
might be some user-defined colored cursor icon.

Best regards,
Shengyu

在 2025/3/27 7:47, Alex Hung 写道:
> cursor plane does not need to have color pipeline.
> 
> Signed-off-by: Alex Hung <alex.hung@amd.com>
> ---
> v7:
>   - Add a commit messages
> 
>   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 3 +++
>   1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> index 9632b8b73e7e..b5b9b0b5da63 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> @@ -1792,6 +1792,9 @@ dm_plane_init_colorops(struct drm_plane *plane)
>   	struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
>   	int len = 0;
>   
> +	if (plane->type == DRM_PLANE_TYPE_CURSOR)
> +		return 0;
> +
>   	/* Create COLOR_PIPELINE property and attach */
>   	drm_plane_create_color_pipeline_property(plane, pipelines, len);
>   


[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 6977 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-03-26 23:47 ` [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane Alex Hung
  2025-03-30  9:48   ` Shengyu Qu
@ 2025-03-30 12:59   ` Shengyu Qu
  2025-03-31 14:28     ` Alex Hung
  1 sibling, 1 reply; 128+ messages in thread
From: Shengyu Qu @ 2025-03-30 12:59 UTC (permalink / raw)
  To: Alex Hung, dri-devel, amd-gfx
  Cc: wiagn233, wayland-devel, harry.wentland, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet


[-- Attachment #1.1.1: Type: text/plain, Size: 1291 bytes --]

Hi,

Do we really need to disable cursor plane color pipeline support? I 
don't think we need to disable that if it is supported, since there 
might be some user-defined colored cursor icon.

Best regards,
Shengyu

For some unknown reason, seems my mail is not shown in the mail list 
archive, so I resent it.

在 2025/3/27 7:47, Alex Hung 写道:
> cursor plane does not need to have color pipeline.
> 
> Signed-off-by: Alex Hung <alex.hung@amd.com>
> ---
> v7:
>   - Add a commit messages
> 
>   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 3 +++
>   1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> index 9632b8b73e7e..b5b9b0b5da63 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
> @@ -1792,6 +1792,9 @@ dm_plane_init_colorops(struct drm_plane *plane)
>   	struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
>   	int len = 0;
>   
> +	if (plane->type == DRM_PLANE_TYPE_CURSOR)
> +		return 0;
> +
>   	/* Create COLOR_PIPELINE property and attach */
>   	drm_plane_create_color_pipeline_property(plane, pipelines, len);
>   


[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 6977 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-03-30 12:59   ` Shengyu Qu
@ 2025-03-31 14:28     ` Alex Hung
  2025-03-31 15:43       ` Shengyu Qu
  0 siblings, 1 reply; 128+ messages in thread
From: Alex Hung @ 2025-03-31 14:28 UTC (permalink / raw)
  To: Shengyu Qu, dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet



On 3/30/25 06:59, Shengyu Qu wrote:
> Hi,
> 
> Do we really need to disable cursor plane color pipeline support? I 
> don't think we need to disable that if it is supported, since there 
> might be some user-defined colored cursor icon.

This patch applies to AMD hardware only: 
https://elixir.bootlin.com/linux/v6.13/source/Documentation/gpu/amdgpu/display/mpo-overview.rst#L101

> 
> Best regards,
> Shengyu
> 
> For some unknown reason, seems my mail is not shown in the mail list 
> archive, so I resent it.
> 
> 在 2025/3/27 7:47, Alex Hung 写道:
>> cursor plane does not need to have color pipeline.
>>
>> Signed-off-by: Alex Hung <alex.hung@amd.com>
>> ---
>> v7:
>>   - Add a commit messages
>>
>>   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 3 +++
>>   1 file changed, 3 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c 
>> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>> index 9632b8b73e7e..b5b9b0b5da63 100644
>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>> @@ -1792,6 +1792,9 @@ dm_plane_init_colorops(struct drm_plane *plane)
>>       struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
>>       int len = 0;
>> +    if (plane->type == DRM_PLANE_TYPE_CURSOR)
>> +        return 0;
>> +
>>       /* Create COLOR_PIPELINE property and attach */
>>       drm_plane_create_color_pipeline_property(plane, pipelines, len);
> 


^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-03-31 14:28     ` Alex Hung
@ 2025-03-31 15:43       ` Shengyu Qu
  2025-03-31 16:06         ` Alex Hung
  0 siblings, 1 reply; 128+ messages in thread
From: Shengyu Qu @ 2025-03-31 15:43 UTC (permalink / raw)
  To: Alex Hung, dri-devel, amd-gfx
  Cc: wiagn233, wayland-devel, harry.wentland, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet


[-- Attachment #1.1.1: Type: text/plain, Size: 1978 bytes --]

Hi,

Thanks for reply. So currently we have to apply color conversion on the 
background plane of the cursor to do some color space conversion. What 
would happen if cursor and background plane needs different conversion 
config? Or we just give the cursor a dedicated plane?

Best regards,
Shengyu

在 2025/3/31 22:28, Alex Hung 写道:
> 
> 
> On 3/30/25 06:59, Shengyu Qu wrote:
>> Hi,
>>
>> Do we really need to disable cursor plane color pipeline support? I 
>> don't think we need to disable that if it is supported, since there 
>> might be some user-defined colored cursor icon.
> 
> This patch applies to AMD hardware only: https://elixir.bootlin.com/ 
> linux/v6.13/source/Documentation/gpu/amdgpu/display/mpo-overview.rst#L101
> 
>>
>> Best regards,
>> Shengyu
>>
>> For some unknown reason, seems my mail is not shown in the mail list 
>> archive, so I resent it.
>>
>> 在 2025/3/27 7:47, Alex Hung 写道:
>>> cursor plane does not need to have color pipeline.
>>>
>>> Signed-off-by: Alex Hung <alex.hung@amd.com>
>>> ---
>>> v7:
>>>   - Add a commit messages
>>>
>>>   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 3 +++
>>>   1 file changed, 3 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c 
>>> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>>> index 9632b8b73e7e..b5b9b0b5da63 100644
>>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>>> @@ -1792,6 +1792,9 @@ dm_plane_init_colorops(struct drm_plane *plane)
>>>       struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
>>>       int len = 0;
>>> +    if (plane->type == DRM_PLANE_TYPE_CURSOR)
>>> +        return 0;
>>> +
>>>       /* Create COLOR_PIPELINE property and attach */
>>>       drm_plane_create_color_pipeline_property(plane, pipelines, len);
>>
> 


[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 6977 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-03-31 15:43       ` Shengyu Qu
@ 2025-03-31 16:06         ` Alex Hung
  2025-03-31 16:12           ` Shengyu Qu
  0 siblings, 1 reply; 128+ messages in thread
From: Alex Hung @ 2025-03-31 16:06 UTC (permalink / raw)
  To: Shengyu Qu, dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet



On 3/31/25 09:43, Shengyu Qu wrote:
> Hi,
> 
> Thanks for reply. So currently we have to apply color conversion on the 
> background plane of the cursor to do some color space conversion. What 
> would happen if cursor and background plane needs different conversion 
> config? Or we just give the cursor a dedicated plane?

This scenario is not supported on AMD hardware, but software cursors on 
other plane types won't be affected.

> 
> Best regards,
> Shengyu
> 
> 在 2025/3/31 22:28, Alex Hung 写道:
>>
>>
>> On 3/30/25 06:59, Shengyu Qu wrote:
>>> Hi,
>>>
>>> Do we really need to disable cursor plane color pipeline support? I 
>>> don't think we need to disable that if it is supported, since there 
>>> might be some user-defined colored cursor icon.
>>
>> This patch applies to AMD hardware only: https://elixir.bootlin.com/ 
>> linux/v6.13/source/Documentation/gpu/amdgpu/display/mpo-overview.rst#L101
>>
>>>
>>> Best regards,
>>> Shengyu
>>>
>>> For some unknown reason, seems my mail is not shown in the mail list 
>>> archive, so I resent it.
>>>
>>> 在 2025/3/27 7:47, Alex Hung 写道:
>>>> cursor plane does not need to have color pipeline.
>>>>
>>>> Signed-off-by: Alex Hung <alex.hung@amd.com>
>>>> ---
>>>> v7:
>>>>   - Add a commit messages
>>>>
>>>>   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 3 +++
>>>>   1 file changed, 3 insertions(+)
>>>>
>>>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c 
>>>> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>>>> index 9632b8b73e7e..b5b9b0b5da63 100644
>>>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>>>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>>>> @@ -1792,6 +1792,9 @@ dm_plane_init_colorops(struct drm_plane *plane)
>>>>       struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
>>>>       int len = 0;
>>>> +    if (plane->type == DRM_PLANE_TYPE_CURSOR)
>>>> +        return 0;
>>>> +
>>>>       /* Create COLOR_PIPELINE property and attach */
>>>>       drm_plane_create_color_pipeline_property(plane, pipelines, len);
>>>
>>
> 


^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-03-31 16:06         ` Alex Hung
@ 2025-03-31 16:12           ` Shengyu Qu
  2025-03-31 16:26             ` Alex Hung
  0 siblings, 1 reply; 128+ messages in thread
From: Shengyu Qu @ 2025-03-31 16:12 UTC (permalink / raw)
  To: Alex Hung, dri-devel, amd-gfx
  Cc: wiagn233, wayland-devel, harry.wentland, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet


[-- Attachment #1.1.1: Type: text/plain, Size: 2490 bytes --]

So currently we have to hope the compositor won't use 
DRM_PLANE_TYPE_CURSOR planes at all.... Why do we still register 
DRM_PLANE_TYPE_CURSOR in the driver?

在 2025/4/1 0:06, Alex Hung 写道:
> 
> 
> On 3/31/25 09:43, Shengyu Qu wrote:
>> Hi,
>>
>> Thanks for reply. So currently we have to apply color conversion on 
>> the background plane of the cursor to do some color space conversion. 
>> What would happen if cursor and background plane needs different 
>> conversion config? Or we just give the cursor a dedicated plane?
> 
> This scenario is not supported on AMD hardware, but software cursors on 
> other plane types won't be affected.
> 
>>
>> Best regards,
>> Shengyu
>>
>> 在 2025/3/31 22:28, Alex Hung 写道:
>>>
>>>
>>> On 3/30/25 06:59, Shengyu Qu wrote:
>>>> Hi,
>>>>
>>>> Do we really need to disable cursor plane color pipeline support? I 
>>>> don't think we need to disable that if it is supported, since there 
>>>> might be some user-defined colored cursor icon.
>>>
>>> This patch applies to AMD hardware only: https://elixir.bootlin.com/ 
>>> linux/v6.13/source/Documentation/gpu/amdgpu/display/mpo- 
>>> overview.rst#L101
>>>
>>>>
>>>> Best regards,
>>>> Shengyu
>>>>
>>>> For some unknown reason, seems my mail is not shown in the mail list 
>>>> archive, so I resent it.
>>>>
>>>> 在 2025/3/27 7:47, Alex Hung 写道:
>>>>> cursor plane does not need to have color pipeline.
>>>>>
>>>>> Signed-off-by: Alex Hung <alex.hung@amd.com>
>>>>> ---
>>>>> v7:
>>>>>   - Add a commit messages
>>>>>
>>>>>   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 3 +++
>>>>>   1 file changed, 3 insertions(+)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/ 
>>>>> amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/ 
>>>>> amdgpu_dm_plane.c
>>>>> index 9632b8b73e7e..b5b9b0b5da63 100644
>>>>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>>>>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>>>>> @@ -1792,6 +1792,9 @@ dm_plane_init_colorops(struct drm_plane *plane)
>>>>>       struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
>>>>>       int len = 0;
>>>>> +    if (plane->type == DRM_PLANE_TYPE_CURSOR)
>>>>> +        return 0;
>>>>> +
>>>>>       /* Create COLOR_PIPELINE property and attach */
>>>>>       drm_plane_create_color_pipeline_property(plane, pipelines, len);
>>>>
>>>
>>
> 


[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 6977 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 03/43] drm/doc/rfc: Describe why prescriptive color pipeline is needed
  2025-03-26 23:46 ` [PATCH V8 03/43] drm/doc/rfc: Describe why prescriptive color pipeline is needed Alex Hung
  2025-03-29 15:26   ` Simon Ser
@ 2025-03-31 16:24   ` Shengyu Qu
  2025-03-31 16:41     ` Alex Hung
  1 sibling, 1 reply; 128+ messages in thread
From: Shengyu Qu @ 2025-03-31 16:24 UTC (permalink / raw)
  To: Alex Hung, dri-devel, amd-gfx
  Cc: wiagn233, wayland-devel, harry.wentland, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet


[-- Attachment #1.1.1: Type: text/plain, Size: 19165 bytes --]



在 2025/3/27 7:46, Alex Hung 写道:
> From: Harry Wentland <harry.wentland@amd.com>
> 
> Add documentation for color pipeline API.
> 
> Signed-off-by: Alex Hung <alex.hung@amd.com>
> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
> ---
> v8:
>   - Fix typo "definint" -> "defining"
> 
> v7:
>   - Add a commit messages
> 
> v5:
>   - Don't require BYPASS to succeed (Sebastian)
>   - use DATA for 1D and 3D LUT types (Sebastian)
>   - update 3DLUT ops to use 3DLUT_MODES and 3DLUT_MODE_INDEX
>   - Add section on drm_colorop extensibility
>   - Add color_pipeline.rst to RFC toc tree
> 
> v4:
>   - Drop IOCTL docs since we dropped the IOCTLs (Pekka)
>   - Clarify reading and setting of COLOR_PIPELINE prop (Pekka)
>   - Add blurb about not requiring to reject a pipeline due to
>     incompatible ops, as long as op can be bypassed (Pekka)
>   - Dropped informational strings (such as input CSC) as they're
>     not actually intended to be advertised (Pekka)
> 
> v3:
>   - Describe DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE (Sebastian)
>   - Ask for clear documentation of colorop behavior (Sebastian)
> 
> v2:
>   - Update colorop visualizations to match reality (Sebastian, Alex Hung)
>   - Updated wording (Pekka)
>   - Change BYPASS wording to make it non-mandatory (Sebastian)
>   - Drop cover-letter-like paragraph from COLOR_PIPELINE Plane Property
>     section (Pekka)
>   - Use PQ EOTF instead of its inverse in Pipeline Programming example (Melissa)
>   - Add "Driver Implementer's Guide" section (Pekka)
>   - Add "Driver Forward/Backward Compatibility" section (Sebastian, Pekka)
> 
>   Documentation/gpu/rfc/color_pipeline.rst | 378 +++++++++++++++++++++++
>   Documentation/gpu/rfc/index.rst          |   3 +
>   2 files changed, 381 insertions(+)
>   create mode 100644 Documentation/gpu/rfc/color_pipeline.rst
> 
> diff --git a/Documentation/gpu/rfc/color_pipeline.rst b/Documentation/gpu/rfc/color_pipeline.rst
> new file mode 100644
> index 000000000000..58bcc2a5ffd8
> --- /dev/null
> +++ b/Documentation/gpu/rfc/color_pipeline.rst
> @@ -0,0 +1,378 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +
> +========================
> +Linux Color Pipeline API
> +========================
> +
> +What problem are we solving?
> +============================
> +
> +We would like to support pre-, and post-blending complex color
> +transformations in display controller hardware in order to allow for
> +HW-supported HDR use-cases, as well as to provide support to
> +color-managed applications, such as video or image editors.
> +
> +It is possible to support an HDR output on HW supporting the Colorspace
> +and HDR Metadata drm_connector properties, but that requires the
> +compositor or application to render and compose the content into one
> +final buffer intended for display. Doing so is costly.
> +
> +Most modern display HW offers various 1D LUTs, 3D LUTs, matrices, and other
> +operations to support color transformations. These operations are often
> +implemented in fixed-function HW and therefore much more power efficient than
> +performing similar operations via shaders or CPU.
> +
> +We would like to make use of this HW functionality to support complex color
> +transformations with no, or minimal CPU or shader load.
> +
> +
> +How are other OSes solving this problem?
> +========================================
> +
> +The most widely supported use-cases regard HDR content, whether video or
> +gaming.
> +
> +Most OSes will specify the source content format (color gamut, encoding transfer
> +function, and other metadata, such as max and average light levels) to a driver.
> +Drivers will then program their fixed-function HW accordingly to map from a
> +source content buffer's space to a display's space.
> +
> +When fixed-function HW is not available the compositor will assemble a shader to
> +ask the GPU to perform the transformation from the source content format to the
> +display's format.
> +
> +A compositor's mapping function and a driver's mapping function are usually
> +entirely separate concepts. On OSes where a HW vendor has no insight into
> +closed-source compositor code such a vendor will tune their color management
> +code to visually match the compositor's. On other OSes, where both mapping
> +functions are open to an implementer they will ensure both mappings match.
> +
> +This results in mapping algorithm lock-in, meaning that no-one alone can
> +experiment with or introduce new mapping algorithms and achieve
> +consistent results regardless of which implementation path is taken.
> +
> +Why is Linux different?
> +=======================
> +
> +Unlike other OSes, where there is one compositor for one or more drivers, on
> +Linux we have a many-to-many relationship. Many compositors; many drivers.
> +In addition each compositor vendor or community has their own view of how
> +color management should be done. This is what makes Linux so beautiful.
> +
> +This means that a HW vendor can now no longer tune their driver to one
> +compositor, as tuning it to one could make it look fairly different from
> +another compositor's color mapping.
> +
> +We need a better solution.
> +
> +
> +Descriptive API
> +===============
> +
> +An API that describes the source and destination colorspaces is a descriptive
> +API. It describes the input and output color spaces but does not describe
> +how precisely they should be mapped. Such a mapping includes many minute
> +design decision that can greatly affect the look of the final result.
> +
> +It is not feasible to describe such mapping with enough detail to ensure the
> +same result from each implementation. In fact, these mappings are a very active
> +research area.
> +
> +
> +Prescriptive API
> +================
> +
> +A prescriptive API describes not the source and destination colorspaces. It
> +instead prescribes a recipe for how to manipulate pixel values to arrive at the
> +desired outcome.
> +
> +This recipe is generally an ordered list of straight-forward operations,
> +with clear mathematical definitions, such as 1D LUTs, 3D LUTs, matrices,
> +or other operations that can be described in a precise manner.
> +
> +
> +The Color Pipeline API
> +======================
> +
> +HW color management pipelines can significantly differ between HW
> +vendors in terms of availability, ordering, and capabilities of HW
> +blocks. This makes a common definition of color management blocks and
> +their ordering nigh impossible. Instead we are defining an API that
> +allows user space to discover the HW capabilities in a generic manner,
> +agnostic of specific drivers and hardware.
> +
> +
> +drm_colorop Object
> +==================
> +
> +To support the definition of color pipelines we define the DRM core
> +object type drm_colorop. Individual drm_colorop objects will be chained
> +via the NEXT property of a drm_colorop to constitute a color pipeline.
> +Each drm_colorop object is unique, i.e., even if multiple color
> +pipelines have the same operation they won't share the same drm_colorop
> +object to describe that operation.
> +
> +Note that drivers are not expected to map drm_colorop objects statically
> +to specific HW blocks. The mapping of drm_colorop objects is entirely a
> +driver-internal detail and can be as dynamic or static as a driver needs
> +it to be. See more in the Driver Implementation Guide section below.
> +
> +Each drm_colorop has three core properties:
> +
> +TYPE: An enumeration property, defining the type of transformation, such as
> +* enumerated curve
> +* custom (uniform) 1D LUT
> +* 3x3 matrix
> +* 3x4 matrix
> +* 3D LUT
> +* etc.
> +
> +Depending on the type of transformation other properties will describe
> +more details.
> +
> +BYPASS: A boolean property that can be used to easily put a block into
> +bypass mode. The BYPASS property is not mandatory for a colorop, as long
> +as the entire pipeline can get bypassed by setting the COLOR_PIPELINE on
> +a plane to '0'.
> +
> +NEXT: The ID of the next drm_colorop in a color pipeline, or 0 if this
> +drm_colorop is the last in the chain.
> +
> +An example of a drm_colorop object might look like one of these::
> +
> +    /* 1D enumerated curve */
> +    Color operation 42
> +    ├─ "TYPE": immutable enum {1D enumerated curve, 1D LUT, 3x3 matrix, 3x4 matrix, 3D LUT, etc.} = 1D enumerated curve
> +    ├─ "BYPASS": bool {true, false}
> +    ├─ "CURVE_1D_TYPE": enum {sRGB EOTF, sRGB inverse EOTF, PQ EOTF, PQ inverse EOTF, …}
> +    └─ "NEXT": immutable color operation ID = 43
> +
> +    /* custom 4k entry 1D LUT */
> +    Color operation 52
> +    ├─ "TYPE": immutable enum {1D enumerated curve, 1D LUT, 3x3 matrix, 3x4 matrix, 3D LUT, etc.} = 1D LUT
> +    ├─ "BYPASS": bool {true, false}
> +    ├─ "SIZE": immutable range = 4096
> +    ├─ "DATA": blob
> +    └─ "NEXT": immutable color operation ID = 0
> +
> +    /* 17^3 3D LUT */
> +    Color operation 72
> +    ├─ "TYPE": immutable enum {1D enumerated curve, 1D LUT, 3x3 matrix, 3x4 matrix, 3D LUT, etc.} = 3D LUT
> +    ├─ "BYPASS": bool {true, false}
> +    ├─ "3DLUT_MODES": read-only blob of supported 3DLUT modes
> +    ├─ "3DLUT_MODE_INDEX": index of selected 3DLUT mode
> +    ├─ "DATA": blob
> +    └─ "NEXT": immutable color operation ID = 73
> +
> +drm_colorop extensibility
> +-------------------------
> +
> +Unlike existing DRM core objects, like &drm_plane, drm_colorop is not
> +extensible. This simplifies implementations and keeps all functionality
> +for managing &drm_colorop objects in the DRM core.
> +
> +If there is a need one may introduce a simple &drm_colorop_funcs
> +function table in the future, for example to support an IN_FORMATS
> +property on a &drm_colorop.
> +
> +If a driver requires the ability to create a driver-specific colorop
> +object they will need to add &drm_colorop func table support with
> +support for the usual functions, like destroy, atomic_duplicate_state,
> +and atomic_destroy_state.
As far as I know, there are multiple embedded SOCs(with mainline linux 
support) that support colorops which are not exist in current func list. 
Why don't we just make the api extensible now? It would make the 
API/code more simple when adding colorops.

> +
> +
> +COLOR_PIPELINE Plane Property
> +=============================
> +
> +Color Pipelines are created by a driver and advertised via a new
> +COLOR_PIPELINE enum property on each plane. Values of the property
> +always include object id 0, which is the default and means all color
> +processing is disabled. Additional values will be the object IDs of the
> +first drm_colorop in a pipeline. A driver can create and advertise none,
> +one, or more possible color pipelines. A DRM client will select a color
> +pipeline by setting the COLOR PIPELINE to the respective value.
> +
> +NOTE: Many DRM clients will set enumeration properties via the string
> +value, often hard-coding it. Since this enumeration is generated based
> +on the colorop object IDs it is important to perform the Color Pipeline
> +Discovery, described below, instead of hard-coding color pipeline
> +assignment. Drivers might generate the enum strings dynamically.
> +Hard-coded strings might only work for specific drivers on a specific
> +pieces of HW. Color Pipeline Discovery can work universally, as long as
> +drivers implement the required color operations.
> +
> +The COLOR_PIPELINE property is only exposed when the
> +DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE is set. Drivers shall ignore any
> +existing pre-blend color operations when this cap is set, such as
> +COLOR_RANGE and COLOR_ENCODING. If drivers want to support COLOR_RANGE
> +or COLOR_ENCODING functionality when the color pipeline client cap is
> +set, they are expected to expose colorops in the pipeline to allow for
> +the appropriate color transformation.
> +
> +Setting of the COLOR_PIPELINE plane property or drm_colorop properties
> +is only allowed for userspace that sets this client cap.
> +
> +An example of a COLOR_PIPELINE property on a plane might look like this::
> +
> +    Plane 10
> +    ├─ "TYPE": immutable enum {Overlay, Primary, Cursor} = Primary
> +    ├─ …
> +    └─ "COLOR_PIPELINE": enum {0, 42, 52} = 0
> +
> +
> +Color Pipeline Discovery
> +========================
> +
> +A DRM client wanting color management on a drm_plane will:
> +
> +1. Get the COLOR_PIPELINE property of the plane
> +2. iterate all COLOR_PIPELINE enum values
> +3. for each enum value walk the color pipeline (via the NEXT pointers)
> +   and see if the available color operations are suitable for the
> +   desired color management operations
> +
> +If userspace encounters an unknown or unsuitable color operation during
> +discovery it does not need to reject the entire color pipeline outright,
> +as long as the unknown or unsuitable colorop has a "BYPASS" property.
> +Drivers will ensure that a bypassed block does not have any effect.
> +
> +An example of chained properties to define an AMD pre-blending color
> +pipeline might look like this::
> +
> +    Plane 10
> +    ├─ "TYPE" (immutable) = Primary
> +    └─ "COLOR_PIPELINE": enum {0, 44} = 0
> +
> +    Color operation 44
> +    ├─ "TYPE" (immutable) = 1D enumerated curve
> +    ├─ "BYPASS": bool
> +    ├─ "CURVE_1D_TYPE": enum {sRGB EOTF, PQ EOTF} = sRGB EOTF
> +    └─ "NEXT" (immutable) = 45
> +
> +    Color operation 45
> +    ├─ "TYPE" (immutable) = 3x4 Matrix
> +    ├─ "BYPASS": bool
> +    ├─ "DATA": blob
> +    └─ "NEXT" (immutable) = 46
> +
> +    Color operation 46
> +    ├─ "TYPE" (immutable) = 1D enumerated curve
> +    ├─ "BYPASS": bool
> +    ├─ "CURVE_1D_TYPE": enum {sRGB Inverse EOTF, PQ Inverse EOTF} = sRGB EOTF
> +    └─ "NEXT" (immutable) = 47
> +
> +    Color operation 47
> +    ├─ "TYPE" (immutable) = 1D LUT
> +    ├─ "SIZE": immutable range = 4096
> +    ├─ "DATA": blob
> +    └─ "NEXT" (immutable) = 48
> +
> +    Color operation 48
> +    ├─ "TYPE" (immutable) = 3D LUT
> +    ├─ "3DLUT_MODE_INDEX": 0
> +    ├─ "DATA": blob
> +    └─ "NEXT" (immutable) = 49
> +
> +    Color operation 49
> +    ├─ "TYPE" (immutable) = 1D enumerated curve
> +    ├─ "BYPASS": bool
> +    ├─ "CURVE_1D_TYPE": enum {sRGB EOTF, PQ EOTF} = sRGB EOTF
> +    └─ "NEXT" (immutable) = 0
> +
> +
> +Color Pipeline Programming
> +==========================
> +
> +Once a DRM client has found a suitable pipeline it will:
> +
> +1. Set the COLOR_PIPELINE enum value to the one pointing at the first
> +   drm_colorop object of the desired pipeline
> +2. Set the properties for all drm_colorop objects in the pipeline to the
> +   desired values, setting BYPASS to true for unused drm_colorop blocks,
> +   and false for enabled drm_colorop blocks
> +3. Perform (TEST_ONLY or not) atomic commit with all the other KMS
> +   states it wishes to change
> +
> +To configure the pipeline for an HDR10 PQ plane and blending in linear
> +space, a compositor might perform an atomic commit with the following
> +property values::
> +
> +    Plane 10
> +    └─ "COLOR_PIPELINE" = 42
> +
> +    Color operation 42
> +    └─ "BYPASS" = true
> +
> +    Color operation 44
> +    └─ "BYPASS" = true
> +
> +    Color operation 45
> +    └─ "BYPASS" = true
> +
> +    Color operation 46
> +    └─ "BYPASS" = true
> +
> +    Color operation 47
> +    ├─ "LUT_3D_DATA" = Gamut mapping + tone mapping + night mode
> +    └─ "BYPASS" = false
> +
> +    Color operation 48
> +    ├─ "CURVE_1D_TYPE" = PQ EOTF
> +    └─ "BYPASS" = false
> +
> +
> +Driver Implementer's Guide
> +==========================
> +
> +What does this all mean for driver implementations? As noted above the
> +colorops can map to HW directly but don't need to do so. Here are some
> +suggestions on how to think about creating your color pipelines:
> +
> +- Try to expose pipelines that use already defined colorops, even if
> +  your hardware pipeline is split differently. This allows existing
> +  userspace to immediately take advantage of the hardware.
> +
> +- Additionally, try to expose your actual hardware blocks as colorops.
> +  Define new colorop types where you believe it can offer significant
> +  benefits if userspace learns to program them.
> +
> +- Avoid defining new colorops for compound operations with very narrow
> +  scope. If you have a hardware block for a special operation that
> +  cannot be split further, you can expose that as a new colorop type.
> +  However, try to not define colorops for "use cases", especially if
> +  they require you to combine multiple hardware blocks.
> +
> +- Design new colorops as prescriptive, not descriptive; by the
> +  mathematical formula, not by the assumed input and output.
> +
> +A defined colorop type must be deterministic. The exact behavior of the
> +colorop must be documented entirely, whether via a mathematical formula
> +or some other description. Its operation can depend only on its
> +properties and input and nothing else, allowed error tolerance
> +notwithstanding.
> +
> +
> +Driver Forward/Backward Compatibility
> +=====================================
> +
> +As this is uAPI drivers can't regress color pipelines that have been
> +introduced for a given HW generation. New HW generations are free to
> +abandon color pipelines advertised for previous generations.
> +Nevertheless, it can be beneficial to carry support for existing color
> +pipelines forward as those will likely already have support in DRM
> +clients.
> +
> +Introducing new colorops to a pipeline is fine, as long as they can be
> +bypassed or are purely informational. DRM clients implementing support
> +for the pipeline can always skip unknown properties as long as they can
> +be confident that doing so will not cause unexpected results.
> +
> +If a new colorop doesn't fall into one of the above categories
> +(bypassable or informational) the modified pipeline would be unusable
> +for user space. In this case a new pipeline should be defined.
> +
> +
> +References
> +==========
> +
> +1. https://lore.kernel.org/dri-devel/QMers3awXvNCQlyhWdTtsPwkp5ie9bze_hD5nAccFW7a_RXlWjYB7MoUW_8CKLT2bSQwIXVi5H6VULYIxCdgvryZoAoJnC5lZgyK1QWn488=@emersion.fr/
> \ No newline at end of file
> diff --git a/Documentation/gpu/rfc/index.rst b/Documentation/gpu/rfc/index.rst
> index 396e535377fb..ef19b0ba2a3e 100644
> --- a/Documentation/gpu/rfc/index.rst
> +++ b/Documentation/gpu/rfc/index.rst
> @@ -35,3 +35,6 @@ host such documentation:
>   .. toctree::
>   
>       i915_vm_bind.rst
> +
> +.. toctree::
> +    color_pipeline.rst
> \ No newline at end of file


[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 6977 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-03-31 16:12           ` Shengyu Qu
@ 2025-03-31 16:26             ` Alex Hung
  2025-03-31 16:31               ` Shengyu Qu
  0 siblings, 1 reply; 128+ messages in thread
From: Alex Hung @ 2025-03-31 16:26 UTC (permalink / raw)
  To: Shengyu Qu, dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet



On 3/31/25 10:12, Shengyu Qu wrote:
> So currently we have to hope the compositor won't use 
> DRM_PLANE_TYPE_CURSOR planes at all.... Why do we still register 
> DRM_PLANE_TYPE_CURSOR in the driver?

I am not sure what your question is. A compositor can choose or skip any 
hardware features, but this discussion is out of the scope.

> 
> 在 2025/4/1 0:06, Alex Hung 写道:
>>
>>
>> On 3/31/25 09:43, Shengyu Qu wrote:
>>> Hi,
>>>
>>> Thanks for reply. So currently we have to apply color conversion on 
>>> the background plane of the cursor to do some color space conversion. 
>>> What would happen if cursor and background plane needs different 
>>> conversion config? Or we just give the cursor a dedicated plane?
>>
>> This scenario is not supported on AMD hardware, but software cursors 
>> on other plane types won't be affected.
>>
>>>
>>> Best regards,
>>> Shengyu
>>>
>>> 在 2025/3/31 22:28, Alex Hung 写道:
>>>>
>>>>
>>>> On 3/30/25 06:59, Shengyu Qu wrote:
>>>>> Hi,
>>>>>
>>>>> Do we really need to disable cursor plane color pipeline support? I 
>>>>> don't think we need to disable that if it is supported, since there 
>>>>> might be some user-defined colored cursor icon.
>>>>
>>>> This patch applies to AMD hardware only: https://elixir.bootlin.com/ 
>>>> linux/v6.13/source/Documentation/gpu/amdgpu/display/mpo- 
>>>> overview.rst#L101
>>>>
>>>>>
>>>>> Best regards,
>>>>> Shengyu
>>>>>
>>>>> For some unknown reason, seems my mail is not shown in the mail 
>>>>> list archive, so I resent it.
>>>>>
>>>>> 在 2025/3/27 7:47, Alex Hung 写道:
>>>>>> cursor plane does not need to have color pipeline.
>>>>>>
>>>>>> Signed-off-by: Alex Hung <alex.hung@amd.com>
>>>>>> ---
>>>>>> v7:
>>>>>>   - Add a commit messages
>>>>>>
>>>>>>   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 3 +++
>>>>>>   1 file changed, 3 insertions(+)
>>>>>>
>>>>>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/ 
>>>>>> amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/ 
>>>>>> amdgpu_dm_plane.c
>>>>>> index 9632b8b73e7e..b5b9b0b5da63 100644
>>>>>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>>>>>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>>>>>> @@ -1792,6 +1792,9 @@ dm_plane_init_colorops(struct drm_plane *plane)
>>>>>>       struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
>>>>>>       int len = 0;
>>>>>> +    if (plane->type == DRM_PLANE_TYPE_CURSOR)
>>>>>> +        return 0;
>>>>>> +
>>>>>>       /* Create COLOR_PIPELINE property and attach */
>>>>>>       drm_plane_create_color_pipeline_property(plane, pipelines, 
>>>>>> len);
>>>>>
>>>>
>>>
>>
> 


^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-03-31 16:26             ` Alex Hung
@ 2025-03-31 16:31               ` Shengyu Qu
  2025-03-31 16:34                 ` Alex Hung
  0 siblings, 1 reply; 128+ messages in thread
From: Shengyu Qu @ 2025-03-31 16:31 UTC (permalink / raw)
  To: Alex Hung, dri-devel, amd-gfx
  Cc: wiagn233, wayland-devel, harry.wentland, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet


[-- Attachment #1.1.1: Type: text/plain, Size: 3059 bytes --]

Sorry for vague expression. I mean that I think we shouldn't register 
DRM_PLANE_TYPE_CURSOR in the driver, as we don't have actual hardware 
support.

在 2025/4/1 0:26, Alex Hung 写道:
> 
> 
> On 3/31/25 10:12, Shengyu Qu wrote:
>> So currently we have to hope the compositor won't use 
>> DRM_PLANE_TYPE_CURSOR planes at all.... Why do we still register 
>> DRM_PLANE_TYPE_CURSOR in the driver?
> 
> I am not sure what your question is. A compositor can choose or skip any 
> hardware features, but this discussion is out of the scope.
> 
>>
>> 在 2025/4/1 0:06, Alex Hung 写道:
>>>
>>>
>>> On 3/31/25 09:43, Shengyu Qu wrote:
>>>> Hi,
>>>>
>>>> Thanks for reply. So currently we have to apply color conversion on 
>>>> the background plane of the cursor to do some color space 
>>>> conversion. What would happen if cursor and background plane needs 
>>>> different conversion config? Or we just give the cursor a dedicated 
>>>> plane?
>>>
>>> This scenario is not supported on AMD hardware, but software cursors 
>>> on other plane types won't be affected.
>>>
>>>>
>>>> Best regards,
>>>> Shengyu
>>>>
>>>> 在 2025/3/31 22:28, Alex Hung 写道:
>>>>>
>>>>>
>>>>> On 3/30/25 06:59, Shengyu Qu wrote:
>>>>>> Hi,
>>>>>>
>>>>>> Do we really need to disable cursor plane color pipeline support? 
>>>>>> I don't think we need to disable that if it is supported, since 
>>>>>> there might be some user-defined colored cursor icon.
>>>>>
>>>>> This patch applies to AMD hardware only: https:// 
>>>>> elixir.bootlin.com/ linux/v6.13/source/Documentation/gpu/amdgpu/ 
>>>>> display/mpo- overview.rst#L101
>>>>>
>>>>>>
>>>>>> Best regards,
>>>>>> Shengyu
>>>>>>
>>>>>> For some unknown reason, seems my mail is not shown in the mail 
>>>>>> list archive, so I resent it.
>>>>>>
>>>>>> 在 2025/3/27 7:47, Alex Hung 写道:
>>>>>>> cursor plane does not need to have color pipeline.
>>>>>>>
>>>>>>> Signed-off-by: Alex Hung <alex.hung@amd.com>
>>>>>>> ---
>>>>>>> v7:
>>>>>>>   - Add a commit messages
>>>>>>>
>>>>>>>   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 3 +++
>>>>>>>   1 file changed, 3 insertions(+)
>>>>>>>
>>>>>>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/ 
>>>>>>> amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/ 
>>>>>>> amdgpu_dm_plane.c
>>>>>>> index 9632b8b73e7e..b5b9b0b5da63 100644
>>>>>>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>>>>>>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>>>>>>> @@ -1792,6 +1792,9 @@ dm_plane_init_colorops(struct drm_plane 
>>>>>>> *plane)
>>>>>>>       struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
>>>>>>>       int len = 0;
>>>>>>> +    if (plane->type == DRM_PLANE_TYPE_CURSOR)
>>>>>>> +        return 0;
>>>>>>> +
>>>>>>>       /* Create COLOR_PIPELINE property and attach */
>>>>>>>       drm_plane_create_color_pipeline_property(plane, pipelines, 
>>>>>>> len);
>>>>>>
>>>>>
>>>>
>>>
>>
> 


[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 6977 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-03-31 16:31               ` Shengyu Qu
@ 2025-03-31 16:34                 ` Alex Hung
  2025-03-31 16:50                   ` Shengyu Qu
  0 siblings, 1 reply; 128+ messages in thread
From: Alex Hung @ 2025-03-31 16:34 UTC (permalink / raw)
  To: Shengyu Qu, dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet



On 3/31/25 10:31, Shengyu Qu wrote:
> Sorry for vague expression. I mean that I think we shouldn't register 
> DRM_PLANE_TYPE_CURSOR in the driver, as we don't have actual hardware 
> support.

This is not true. AMD has hardware cursor support.

> 
> 在 2025/4/1 0:26, Alex Hung 写道:
>>
>>
>> On 3/31/25 10:12, Shengyu Qu wrote:
>>> So currently we have to hope the compositor won't use 
>>> DRM_PLANE_TYPE_CURSOR planes at all.... Why do we still register 
>>> DRM_PLANE_TYPE_CURSOR in the driver?
>>
>> I am not sure what your question is. A compositor can choose or skip 
>> any hardware features, but this discussion is out of the scope.
>>
>>>
>>> 在 2025/4/1 0:06, Alex Hung 写道:
>>>>
>>>>
>>>> On 3/31/25 09:43, Shengyu Qu wrote:
>>>>> Hi,
>>>>>
>>>>> Thanks for reply. So currently we have to apply color conversion on 
>>>>> the background plane of the cursor to do some color space 
>>>>> conversion. What would happen if cursor and background plane needs 
>>>>> different conversion config? Or we just give the cursor a dedicated 
>>>>> plane?
>>>>
>>>> This scenario is not supported on AMD hardware, but software cursors 
>>>> on other plane types won't be affected.
>>>>
>>>>>
>>>>> Best regards,
>>>>> Shengyu
>>>>>
>>>>> 在 2025/3/31 22:28, Alex Hung 写道:
>>>>>>
>>>>>>
>>>>>> On 3/30/25 06:59, Shengyu Qu wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> Do we really need to disable cursor plane color pipeline support? 
>>>>>>> I don't think we need to disable that if it is supported, since 
>>>>>>> there might be some user-defined colored cursor icon.
>>>>>>
>>>>>> This patch applies to AMD hardware only: https:// 
>>>>>> elixir.bootlin.com/ linux/v6.13/source/Documentation/gpu/amdgpu/ 
>>>>>> display/mpo- overview.rst#L101
>>>>>>
>>>>>>>
>>>>>>> Best regards,
>>>>>>> Shengyu
>>>>>>>
>>>>>>> For some unknown reason, seems my mail is not shown in the mail 
>>>>>>> list archive, so I resent it.
>>>>>>>
>>>>>>> 在 2025/3/27 7:47, Alex Hung 写道:
>>>>>>>> cursor plane does not need to have color pipeline.
>>>>>>>>
>>>>>>>> Signed-off-by: Alex Hung <alex.hung@amd.com>
>>>>>>>> ---
>>>>>>>> v7:
>>>>>>>>   - Add a commit messages
>>>>>>>>
>>>>>>>>   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 3 +++
>>>>>>>>   1 file changed, 3 insertions(+)
>>>>>>>>
>>>>>>>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/ 
>>>>>>>> amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/ 
>>>>>>>> amdgpu_dm_plane.c
>>>>>>>> index 9632b8b73e7e..b5b9b0b5da63 100644
>>>>>>>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>>>>>>>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>>>>>>>> @@ -1792,6 +1792,9 @@ dm_plane_init_colorops(struct drm_plane 
>>>>>>>> *plane)
>>>>>>>>       struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
>>>>>>>>       int len = 0;
>>>>>>>> +    if (plane->type == DRM_PLANE_TYPE_CURSOR)
>>>>>>>> +        return 0;
>>>>>>>> +
>>>>>>>>       /* Create COLOR_PIPELINE property and attach */
>>>>>>>>       drm_plane_create_color_pipeline_property(plane, pipelines, 
>>>>>>>> len);
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
> 


^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 03/43] drm/doc/rfc: Describe why prescriptive color pipeline is needed
  2025-03-31 16:24   ` Shengyu Qu
@ 2025-03-31 16:41     ` Alex Hung
  2025-03-31 16:54       ` Shengyu Qu
  0 siblings, 1 reply; 128+ messages in thread
From: Alex Hung @ 2025-03-31 16:41 UTC (permalink / raw)
  To: Shengyu Qu, dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet



On 3/31/25 10:24, Shengyu Qu wrote:
> 
> 
> 在 2025/3/27 7:46, Alex Hung 写道:
>> From: Harry Wentland <harry.wentland@amd.com>
>>
>> Add documentation for color pipeline API.
>>
>> Signed-off-by: Alex Hung <alex.hung@amd.com>
>> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
>> ---
>> v8:
>>   - Fix typo "definint" -> "defining"
>>
>> v7:
>>   - Add a commit messages
>>
>> v5:
>>   - Don't require BYPASS to succeed (Sebastian)
>>   - use DATA for 1D and 3D LUT types (Sebastian)
>>   - update 3DLUT ops to use 3DLUT_MODES and 3DLUT_MODE_INDEX
>>   - Add section on drm_colorop extensibility
>>   - Add color_pipeline.rst to RFC toc tree
>>
>> v4:
>>   - Drop IOCTL docs since we dropped the IOCTLs (Pekka)
>>   - Clarify reading and setting of COLOR_PIPELINE prop (Pekka)
>>   - Add blurb about not requiring to reject a pipeline due to
>>     incompatible ops, as long as op can be bypassed (Pekka)
>>   - Dropped informational strings (such as input CSC) as they're
>>     not actually intended to be advertised (Pekka)
>>
>> v3:
>>   - Describe DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE (Sebastian)
>>   - Ask for clear documentation of colorop behavior (Sebastian)
>>
>> v2:
>>   - Update colorop visualizations to match reality (Sebastian, Alex Hung)
>>   - Updated wording (Pekka)
>>   - Change BYPASS wording to make it non-mandatory (Sebastian)
>>   - Drop cover-letter-like paragraph from COLOR_PIPELINE Plane Property
>>     section (Pekka)
>>   - Use PQ EOTF instead of its inverse in Pipeline Programming example 
>> (Melissa)
>>   - Add "Driver Implementer's Guide" section (Pekka)
>>   - Add "Driver Forward/Backward Compatibility" section (Sebastian, 
>> Pekka)
>>
>>   Documentation/gpu/rfc/color_pipeline.rst | 378 +++++++++++++++++++++++
>>   Documentation/gpu/rfc/index.rst          |   3 +
>>   2 files changed, 381 insertions(+)
>>   create mode 100644 Documentation/gpu/rfc/color_pipeline.rst
>>
>> diff --git a/Documentation/gpu/rfc/color_pipeline.rst b/Documentation/ 
>> gpu/rfc/color_pipeline.rst
>> new file mode 100644
>> index 000000000000..58bcc2a5ffd8
>> --- /dev/null
>> +++ b/Documentation/gpu/rfc/color_pipeline.rst
>> @@ -0,0 +1,378 @@
>> +.. SPDX-License-Identifier: GPL-2.0
>> +
>> +========================
>> +Linux Color Pipeline API
>> +========================
>> +
>> +What problem are we solving?
>> +============================
>> +
>> +We would like to support pre-, and post-blending complex color
>> +transformations in display controller hardware in order to allow for
>> +HW-supported HDR use-cases, as well as to provide support to
>> +color-managed applications, such as video or image editors.
>> +
>> +It is possible to support an HDR output on HW supporting the Colorspace
>> +and HDR Metadata drm_connector properties, but that requires the
>> +compositor or application to render and compose the content into one
>> +final buffer intended for display. Doing so is costly.
>> +
>> +Most modern display HW offers various 1D LUTs, 3D LUTs, matrices, and 
>> other
>> +operations to support color transformations. These operations are often
>> +implemented in fixed-function HW and therefore much more power 
>> efficient than
>> +performing similar operations via shaders or CPU.
>> +
>> +We would like to make use of this HW functionality to support complex 
>> color
>> +transformations with no, or minimal CPU or shader load.
>> +
>> +
>> +How are other OSes solving this problem?
>> +========================================
>> +
>> +The most widely supported use-cases regard HDR content, whether video or
>> +gaming.
>> +
>> +Most OSes will specify the source content format (color gamut, 
>> encoding transfer
>> +function, and other metadata, such as max and average light levels) 
>> to a driver.
>> +Drivers will then program their fixed-function HW accordingly to map 
>> from a
>> +source content buffer's space to a display's space.
>> +
>> +When fixed-function HW is not available the compositor will assemble 
>> a shader to
>> +ask the GPU to perform the transformation from the source content 
>> format to the
>> +display's format.
>> +
>> +A compositor's mapping function and a driver's mapping function are 
>> usually
>> +entirely separate concepts. On OSes where a HW vendor has no insight 
>> into
>> +closed-source compositor code such a vendor will tune their color 
>> management
>> +code to visually match the compositor's. On other OSes, where both 
>> mapping
>> +functions are open to an implementer they will ensure both mappings 
>> match.
>> +
>> +This results in mapping algorithm lock-in, meaning that no-one alone can
>> +experiment with or introduce new mapping algorithms and achieve
>> +consistent results regardless of which implementation path is taken.
>> +
>> +Why is Linux different?
>> +=======================
>> +
>> +Unlike other OSes, where there is one compositor for one or more 
>> drivers, on
>> +Linux we have a many-to-many relationship. Many compositors; many 
>> drivers.
>> +In addition each compositor vendor or community has their own view of 
>> how
>> +color management should be done. This is what makes Linux so beautiful.
>> +
>> +This means that a HW vendor can now no longer tune their driver to one
>> +compositor, as tuning it to one could make it look fairly different from
>> +another compositor's color mapping.
>> +
>> +We need a better solution.
>> +
>> +
>> +Descriptive API
>> +===============
>> +
>> +An API that describes the source and destination colorspaces is a 
>> descriptive
>> +API. It describes the input and output color spaces but does not 
>> describe
>> +how precisely they should be mapped. Such a mapping includes many minute
>> +design decision that can greatly affect the look of the final result.
>> +
>> +It is not feasible to describe such mapping with enough detail to 
>> ensure the
>> +same result from each implementation. In fact, these mappings are a 
>> very active
>> +research area.
>> +
>> +
>> +Prescriptive API
>> +================
>> +
>> +A prescriptive API describes not the source and destination 
>> colorspaces. It
>> +instead prescribes a recipe for how to manipulate pixel values to 
>> arrive at the
>> +desired outcome.
>> +
>> +This recipe is generally an ordered list of straight-forward operations,
>> +with clear mathematical definitions, such as 1D LUTs, 3D LUTs, matrices,
>> +or other operations that can be described in a precise manner.
>> +
>> +
>> +The Color Pipeline API
>> +======================
>> +
>> +HW color management pipelines can significantly differ between HW
>> +vendors in terms of availability, ordering, and capabilities of HW
>> +blocks. This makes a common definition of color management blocks and
>> +their ordering nigh impossible. Instead we are defining an API that
>> +allows user space to discover the HW capabilities in a generic manner,
>> +agnostic of specific drivers and hardware.
>> +
>> +
>> +drm_colorop Object
>> +==================
>> +
>> +To support the definition of color pipelines we define the DRM core
>> +object type drm_colorop. Individual drm_colorop objects will be chained
>> +via the NEXT property of a drm_colorop to constitute a color pipeline.
>> +Each drm_colorop object is unique, i.e., even if multiple color
>> +pipelines have the same operation they won't share the same drm_colorop
>> +object to describe that operation.
>> +
>> +Note that drivers are not expected to map drm_colorop objects statically
>> +to specific HW blocks. The mapping of drm_colorop objects is entirely a
>> +driver-internal detail and can be as dynamic or static as a driver needs
>> +it to be. See more in the Driver Implementation Guide section below.
>> +
>> +Each drm_colorop has three core properties:
>> +
>> +TYPE: An enumeration property, defining the type of transformation, 
>> such as
>> +* enumerated curve
>> +* custom (uniform) 1D LUT
>> +* 3x3 matrix
>> +* 3x4 matrix
>> +* 3D LUT
>> +* etc.
>> +
>> +Depending on the type of transformation other properties will describe
>> +more details.
>> +
>> +BYPASS: A boolean property that can be used to easily put a block into
>> +bypass mode. The BYPASS property is not mandatory for a colorop, as long
>> +as the entire pipeline can get bypassed by setting the COLOR_PIPELINE on
>> +a plane to '0'.
>> +
>> +NEXT: The ID of the next drm_colorop in a color pipeline, or 0 if this
>> +drm_colorop is the last in the chain.
>> +
>> +An example of a drm_colorop object might look like one of these::
>> +
>> +    /* 1D enumerated curve */
>> +    Color operation 42
>> +    ├─ "TYPE": immutable enum {1D enumerated curve, 1D LUT, 3x3 
>> matrix, 3x4 matrix, 3D LUT, etc.} = 1D enumerated curve
>> +    ├─ "BYPASS": bool {true, false}
>> +    ├─ "CURVE_1D_TYPE": enum {sRGB EOTF, sRGB inverse EOTF, PQ EOTF, 
>> PQ inverse EOTF, …}
>> +    └─ "NEXT": immutable color operation ID = 43
>> +
>> +    /* custom 4k entry 1D LUT */
>> +    Color operation 52
>> +    ├─ "TYPE": immutable enum {1D enumerated curve, 1D LUT, 3x3 
>> matrix, 3x4 matrix, 3D LUT, etc.} = 1D LUT
>> +    ├─ "BYPASS": bool {true, false}
>> +    ├─ "SIZE": immutable range = 4096
>> +    ├─ "DATA": blob
>> +    └─ "NEXT": immutable color operation ID = 0
>> +
>> +    /* 17^3 3D LUT */
>> +    Color operation 72
>> +    ├─ "TYPE": immutable enum {1D enumerated curve, 1D LUT, 3x3 
>> matrix, 3x4 matrix, 3D LUT, etc.} = 3D LUT
>> +    ├─ "BYPASS": bool {true, false}
>> +    ├─ "3DLUT_MODES": read-only blob of supported 3DLUT modes
>> +    ├─ "3DLUT_MODE_INDEX": index of selected 3DLUT mode
>> +    ├─ "DATA": blob
>> +    └─ "NEXT": immutable color operation ID = 73
>> +
>> +drm_colorop extensibility
>> +-------------------------
>> +
>> +Unlike existing DRM core objects, like &drm_plane, drm_colorop is not
>> +extensible. This simplifies implementations and keeps all functionality
>> +for managing &drm_colorop objects in the DRM core.
>> +
>> +If there is a need one may introduce a simple &drm_colorop_funcs
>> +function table in the future, for example to support an IN_FORMATS
>> +property on a &drm_colorop.
>> +
>> +If a driver requires the ability to create a driver-specific colorop
>> +object they will need to add &drm_colorop func table support with
>> +support for the usual functions, like destroy, atomic_duplicate_state,
>> +and atomic_destroy_state.
> As far as I know, there are multiple embedded SOCs(with mainline linux 
> support) that support colorops which are not exist in current func list. 
> Why don't we just make the api extensible now? It would make the API/ 
> code more simple when adding colorops.

Any vendor can create their color pipeline(s) and add new colorop 
objects accordingly. This patchset creates an AMD-specific color 
pipeline and colorop objects (for an obvious reason) as an demonstration 
and other vendors are working on their own too.

The following paragraphs should answer your questions.

> 
>> +
>> +
>> +COLOR_PIPELINE Plane Property
>> +=============================
>> +
>> +Color Pipelines are created by a driver and advertised via a new
>> +COLOR_PIPELINE enum property on each plane. Values of the property
>> +always include object id 0, which is the default and means all color
>> +processing is disabled. Additional values will be the object IDs of the
>> +first drm_colorop in a pipeline. A driver can create and advertise none,
>> +one, or more possible color pipelines. A DRM client will select a color
>> +pipeline by setting the COLOR PIPELINE to the respective value.
>> +
>> +NOTE: Many DRM clients will set enumeration properties via the string
>> +value, often hard-coding it. Since this enumeration is generated based
>> +on the colorop object IDs it is important to perform the Color Pipeline
>> +Discovery, described below, instead of hard-coding color pipeline
>> +assignment. Drivers might generate the enum strings dynamically.
>> +Hard-coded strings might only work for specific drivers on a specific
>> +pieces of HW. Color Pipeline Discovery can work universally, as long as
>> +drivers implement the required color operations.
>> +
>> +The COLOR_PIPELINE property is only exposed when the
>> +DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE is set. Drivers shall ignore any
>> +existing pre-blend color operations when this cap is set, such as
>> +COLOR_RANGE and COLOR_ENCODING. If drivers want to support COLOR_RANGE
>> +or COLOR_ENCODING functionality when the color pipeline client cap is
>> +set, they are expected to expose colorops in the pipeline to allow for
>> +the appropriate color transformation.
>> +
>> +Setting of the COLOR_PIPELINE plane property or drm_colorop properties
>> +is only allowed for userspace that sets this client cap.
>> +
>> +An example of a COLOR_PIPELINE property on a plane might look like 
>> this::
>> +
>> +    Plane 10
>> +    ├─ "TYPE": immutable enum {Overlay, Primary, Cursor} = Primary
>> +    ├─ …
>> +    └─ "COLOR_PIPELINE": enum {0, 42, 52} = 0
>> +
>> +
>> +Color Pipeline Discovery
>> +========================
>> +
>> +A DRM client wanting color management on a drm_plane will:
>> +
>> +1. Get the COLOR_PIPELINE property of the plane
>> +2. iterate all COLOR_PIPELINE enum values
>> +3. for each enum value walk the color pipeline (via the NEXT pointers)
>> +   and see if the available color operations are suitable for the
>> +   desired color management operations
>> +
>> +If userspace encounters an unknown or unsuitable color operation during
>> +discovery it does not need to reject the entire color pipeline outright,
>> +as long as the unknown or unsuitable colorop has a "BYPASS" property.
>> +Drivers will ensure that a bypassed block does not have any effect.
>> +
>> +An example of chained properties to define an AMD pre-blending color
>> +pipeline might look like this::
>> +
>> +    Plane 10
>> +    ├─ "TYPE" (immutable) = Primary
>> +    └─ "COLOR_PIPELINE": enum {0, 44} = 0
>> +
>> +    Color operation 44
>> +    ├─ "TYPE" (immutable) = 1D enumerated curve
>> +    ├─ "BYPASS": bool
>> +    ├─ "CURVE_1D_TYPE": enum {sRGB EOTF, PQ EOTF} = sRGB EOTF
>> +    └─ "NEXT" (immutable) = 45
>> +
>> +    Color operation 45
>> +    ├─ "TYPE" (immutable) = 3x4 Matrix
>> +    ├─ "BYPASS": bool
>> +    ├─ "DATA": blob
>> +    └─ "NEXT" (immutable) = 46
>> +
>> +    Color operation 46
>> +    ├─ "TYPE" (immutable) = 1D enumerated curve
>> +    ├─ "BYPASS": bool
>> +    ├─ "CURVE_1D_TYPE": enum {sRGB Inverse EOTF, PQ Inverse EOTF} = 
>> sRGB EOTF
>> +    └─ "NEXT" (immutable) = 47
>> +
>> +    Color operation 47
>> +    ├─ "TYPE" (immutable) = 1D LUT
>> +    ├─ "SIZE": immutable range = 4096
>> +    ├─ "DATA": blob
>> +    └─ "NEXT" (immutable) = 48
>> +
>> +    Color operation 48
>> +    ├─ "TYPE" (immutable) = 3D LUT
>> +    ├─ "3DLUT_MODE_INDEX": 0
>> +    ├─ "DATA": blob
>> +    └─ "NEXT" (immutable) = 49
>> +
>> +    Color operation 49
>> +    ├─ "TYPE" (immutable) = 1D enumerated curve
>> +    ├─ "BYPASS": bool
>> +    ├─ "CURVE_1D_TYPE": enum {sRGB EOTF, PQ EOTF} = sRGB EOTF
>> +    └─ "NEXT" (immutable) = 0
>> +
>> +
>> +Color Pipeline Programming
>> +==========================
>> +
>> +Once a DRM client has found a suitable pipeline it will:
>> +
>> +1. Set the COLOR_PIPELINE enum value to the one pointing at the first
>> +   drm_colorop object of the desired pipeline
>> +2. Set the properties for all drm_colorop objects in the pipeline to the
>> +   desired values, setting BYPASS to true for unused drm_colorop blocks,
>> +   and false for enabled drm_colorop blocks
>> +3. Perform (TEST_ONLY or not) atomic commit with all the other KMS
>> +   states it wishes to change
>> +
>> +To configure the pipeline for an HDR10 PQ plane and blending in linear
>> +space, a compositor might perform an atomic commit with the following
>> +property values::
>> +
>> +    Plane 10
>> +    └─ "COLOR_PIPELINE" = 42
>> +
>> +    Color operation 42
>> +    └─ "BYPASS" = true
>> +
>> +    Color operation 44
>> +    └─ "BYPASS" = true
>> +
>> +    Color operation 45
>> +    └─ "BYPASS" = true
>> +
>> +    Color operation 46
>> +    └─ "BYPASS" = true
>> +
>> +    Color operation 47
>> +    ├─ "LUT_3D_DATA" = Gamut mapping + tone mapping + night mode
>> +    └─ "BYPASS" = false
>> +
>> +    Color operation 48
>> +    ├─ "CURVE_1D_TYPE" = PQ EOTF
>> +    └─ "BYPASS" = false
>> +
>> +
>> +Driver Implementer's Guide
>> +==========================
>> +
>> +What does this all mean for driver implementations? As noted above the
>> +colorops can map to HW directly but don't need to do so. Here are some
>> +suggestions on how to think about creating your color pipelines:
>> +
>> +- Try to expose pipelines that use already defined colorops, even if
>> +  your hardware pipeline is split differently. This allows existing
>> +  userspace to immediately take advantage of the hardware.
>> +
>> +- Additionally, try to expose your actual hardware blocks as colorops.
>> +  Define new colorop types where you believe it can offer significant
>> +  benefits if userspace learns to program them.
>> +
>> +- Avoid defining new colorops for compound operations with very narrow
>> +  scope. If you have a hardware block for a special operation that
>> +  cannot be split further, you can expose that as a new colorop type.
>> +  However, try to not define colorops for "use cases", especially if
>> +  they require you to combine multiple hardware blocks.
>> +
>> +- Design new colorops as prescriptive, not descriptive; by the
>> +  mathematical formula, not by the assumed input and output.
>> +
>> +A defined colorop type must be deterministic. The exact behavior of the
>> +colorop must be documented entirely, whether via a mathematical formula
>> +or some other description. Its operation can depend only on its
>> +properties and input and nothing else, allowed error tolerance
>> +notwithstanding.
>> +
>> +
>> +Driver Forward/Backward Compatibility
>> +=====================================
>> +
>> +As this is uAPI drivers can't regress color pipelines that have been
>> +introduced for a given HW generation. New HW generations are free to
>> +abandon color pipelines advertised for previous generations.
>> +Nevertheless, it can be beneficial to carry support for existing color
>> +pipelines forward as those will likely already have support in DRM
>> +clients.
>> +
>> +Introducing new colorops to a pipeline is fine, as long as they can be
>> +bypassed or are purely informational. DRM clients implementing support
>> +for the pipeline can always skip unknown properties as long as they can
>> +be confident that doing so will not cause unexpected results.
>> +
>> +If a new colorop doesn't fall into one of the above categories
>> +(bypassable or informational) the modified pipeline would be unusable
>> +for user space. In this case a new pipeline should be defined.
>> +
>> +
>> +References
>> +==========
>> +
>> +1. https://lore.kernel.org/dri-devel/ 
>> QMers3awXvNCQlyhWdTtsPwkp5ie9bze_hD5nAccFW7a_RXlWjYB7MoUW_8CKLT2bSQwIXVi5H6VULYIxCdgvryZoAoJnC5lZgyK1QWn488=@emersion.fr/
>> \ No newline at end of file
>> diff --git a/Documentation/gpu/rfc/index.rst b/Documentation/gpu/rfc/ 
>> index.rst
>> index 396e535377fb..ef19b0ba2a3e 100644
>> --- a/Documentation/gpu/rfc/index.rst
>> +++ b/Documentation/gpu/rfc/index.rst
>> @@ -35,3 +35,6 @@ host such documentation:
>>   .. toctree::
>>       i915_vm_bind.rst
>> +
>> +.. toctree::
>> +    color_pipeline.rst
>> \ No newline at end of file
> 


^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-03-31 16:34                 ` Alex Hung
@ 2025-03-31 16:50                   ` Shengyu Qu
  2025-03-31 17:04                     ` Shengyu Qu
  0 siblings, 1 reply; 128+ messages in thread
From: Shengyu Qu @ 2025-03-31 16:50 UTC (permalink / raw)
  To: Alex Hung, dri-devel, amd-gfx
  Cc: wiagn233, wayland-devel, harry.wentland, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet


[-- Attachment #1.1.1: Type: text/plain, Size: 3671 bytes --]

Thanks, I mistook about the MPO document. Maybe we should also disable 
colorop on the background plane of the cursor plane? So that compositors 
would do sw color convertion on both cursor plane and background plane, 
which should keep cursor display correctly.

在 2025/4/1 0:34, Alex Hung 写道:
> 
> 
> On 3/31/25 10:31, Shengyu Qu wrote:
>> Sorry for vague expression. I mean that I think we shouldn't register 
>> DRM_PLANE_TYPE_CURSOR in the driver, as we don't have actual hardware 
>> support.
> 
> This is not true. AMD has hardware cursor support.
> 
>>
>> 在 2025/4/1 0:26, Alex Hung 写道:
>>>
>>>
>>> On 3/31/25 10:12, Shengyu Qu wrote:
>>>> So currently we have to hope the compositor won't use 
>>>> DRM_PLANE_TYPE_CURSOR planes at all.... Why do we still register 
>>>> DRM_PLANE_TYPE_CURSOR in the driver?
>>>
>>> I am not sure what your question is. A compositor can choose or skip 
>>> any hardware features, but this discussion is out of the scope.
>>>
>>>>
>>>> 在 2025/4/1 0:06, Alex Hung 写道:
>>>>>
>>>>>
>>>>> On 3/31/25 09:43, Shengyu Qu wrote:
>>>>>> Hi,
>>>>>>
>>>>>> Thanks for reply. So currently we have to apply color conversion 
>>>>>> on the background plane of the cursor to do some color space 
>>>>>> conversion. What would happen if cursor and background plane needs 
>>>>>> different conversion config? Or we just give the cursor a 
>>>>>> dedicated plane?
>>>>>
>>>>> This scenario is not supported on AMD hardware, but software 
>>>>> cursors on other plane types won't be affected.
>>>>>
>>>>>>
>>>>>> Best regards,
>>>>>> Shengyu
>>>>>>
>>>>>> 在 2025/3/31 22:28, Alex Hung 写道:
>>>>>>>
>>>>>>>
>>>>>>> On 3/30/25 06:59, Shengyu Qu wrote:
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> Do we really need to disable cursor plane color pipeline 
>>>>>>>> support? I don't think we need to disable that if it is 
>>>>>>>> supported, since there might be some user-defined colored cursor 
>>>>>>>> icon.
>>>>>>>
>>>>>>> This patch applies to AMD hardware only: https:// 
>>>>>>> elixir.bootlin.com/ linux/v6.13/source/Documentation/gpu/amdgpu/ 
>>>>>>> display/mpo- overview.rst#L101
>>>>>>>
>>>>>>>>
>>>>>>>> Best regards,
>>>>>>>> Shengyu
>>>>>>>>
>>>>>>>> For some unknown reason, seems my mail is not shown in the mail 
>>>>>>>> list archive, so I resent it.
>>>>>>>>
>>>>>>>> 在 2025/3/27 7:47, Alex Hung 写道:
>>>>>>>>> cursor plane does not need to have color pipeline.
>>>>>>>>>
>>>>>>>>> Signed-off-by: Alex Hung <alex.hung@amd.com>
>>>>>>>>> ---
>>>>>>>>> v7:
>>>>>>>>>   - Add a commit messages
>>>>>>>>>
>>>>>>>>>   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 3 +++
>>>>>>>>>   1 file changed, 3 insertions(+)
>>>>>>>>>
>>>>>>>>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/ 
>>>>>>>>> amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/ 
>>>>>>>>> amdgpu_dm_plane.c
>>>>>>>>> index 9632b8b73e7e..b5b9b0b5da63 100644
>>>>>>>>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>>>>>>>>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>>>>>>>>> @@ -1792,6 +1792,9 @@ dm_plane_init_colorops(struct drm_plane 
>>>>>>>>> *plane)
>>>>>>>>>       struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
>>>>>>>>>       int len = 0;
>>>>>>>>> +    if (plane->type == DRM_PLANE_TYPE_CURSOR)
>>>>>>>>> +        return 0;
>>>>>>>>> +
>>>>>>>>>       /* Create COLOR_PIPELINE property and attach */
>>>>>>>>>       drm_plane_create_color_pipeline_property(plane, 
>>>>>>>>> pipelines, len);
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
> 


[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 6977 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 03/43] drm/doc/rfc: Describe why prescriptive color pipeline is needed
  2025-03-31 16:41     ` Alex Hung
@ 2025-03-31 16:54       ` Shengyu Qu
  0 siblings, 0 replies; 128+ messages in thread
From: Shengyu Qu @ 2025-03-31 16:54 UTC (permalink / raw)
  To: Alex Hung, dri-devel, amd-gfx
  Cc: wiagn233, wayland-devel, harry.wentland, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet


[-- Attachment #1.1.1: Type: text/plain, Size: 21121 bytes --]

You are right. Sorry for the noise.

在 2025/4/1 0:41, Alex Hung 写道:
> 
> 
> On 3/31/25 10:24, Shengyu Qu wrote:
>>
>>
>> 在 2025/3/27 7:46, Alex Hung 写道:
>>> From: Harry Wentland <harry.wentland@amd.com>
>>>
>>> Add documentation for color pipeline API.
>>>
>>> Signed-off-by: Alex Hung <alex.hung@amd.com>
>>> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
>>> ---
>>> v8:
>>>   - Fix typo "definint" -> "defining"
>>>
>>> v7:
>>>   - Add a commit messages
>>>
>>> v5:
>>>   - Don't require BYPASS to succeed (Sebastian)
>>>   - use DATA for 1D and 3D LUT types (Sebastian)
>>>   - update 3DLUT ops to use 3DLUT_MODES and 3DLUT_MODE_INDEX
>>>   - Add section on drm_colorop extensibility
>>>   - Add color_pipeline.rst to RFC toc tree
>>>
>>> v4:
>>>   - Drop IOCTL docs since we dropped the IOCTLs (Pekka)
>>>   - Clarify reading and setting of COLOR_PIPELINE prop (Pekka)
>>>   - Add blurb about not requiring to reject a pipeline due to
>>>     incompatible ops, as long as op can be bypassed (Pekka)
>>>   - Dropped informational strings (such as input CSC) as they're
>>>     not actually intended to be advertised (Pekka)
>>>
>>> v3:
>>>   - Describe DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE (Sebastian)
>>>   - Ask for clear documentation of colorop behavior (Sebastian)
>>>
>>> v2:
>>>   - Update colorop visualizations to match reality (Sebastian, Alex 
>>> Hung)
>>>   - Updated wording (Pekka)
>>>   - Change BYPASS wording to make it non-mandatory (Sebastian)
>>>   - Drop cover-letter-like paragraph from COLOR_PIPELINE Plane Property
>>>     section (Pekka)
>>>   - Use PQ EOTF instead of its inverse in Pipeline Programming 
>>> example (Melissa)
>>>   - Add "Driver Implementer's Guide" section (Pekka)
>>>   - Add "Driver Forward/Backward Compatibility" section (Sebastian, 
>>> Pekka)
>>>
>>>   Documentation/gpu/rfc/color_pipeline.rst | 378 +++++++++++++++++++++++
>>>   Documentation/gpu/rfc/index.rst          |   3 +
>>>   2 files changed, 381 insertions(+)
>>>   create mode 100644 Documentation/gpu/rfc/color_pipeline.rst
>>>
>>> diff --git a/Documentation/gpu/rfc/color_pipeline.rst b/ 
>>> Documentation/ gpu/rfc/color_pipeline.rst
>>> new file mode 100644
>>> index 000000000000..58bcc2a5ffd8
>>> --- /dev/null
>>> +++ b/Documentation/gpu/rfc/color_pipeline.rst
>>> @@ -0,0 +1,378 @@
>>> +.. SPDX-License-Identifier: GPL-2.0
>>> +
>>> +========================
>>> +Linux Color Pipeline API
>>> +========================
>>> +
>>> +What problem are we solving?
>>> +============================
>>> +
>>> +We would like to support pre-, and post-blending complex color
>>> +transformations in display controller hardware in order to allow for
>>> +HW-supported HDR use-cases, as well as to provide support to
>>> +color-managed applications, such as video or image editors.
>>> +
>>> +It is possible to support an HDR output on HW supporting the Colorspace
>>> +and HDR Metadata drm_connector properties, but that requires the
>>> +compositor or application to render and compose the content into one
>>> +final buffer intended for display. Doing so is costly.
>>> +
>>> +Most modern display HW offers various 1D LUTs, 3D LUTs, matrices, 
>>> and other
>>> +operations to support color transformations. These operations are often
>>> +implemented in fixed-function HW and therefore much more power 
>>> efficient than
>>> +performing similar operations via shaders or CPU.
>>> +
>>> +We would like to make use of this HW functionality to support 
>>> complex color
>>> +transformations with no, or minimal CPU or shader load.
>>> +
>>> +
>>> +How are other OSes solving this problem?
>>> +========================================
>>> +
>>> +The most widely supported use-cases regard HDR content, whether 
>>> video or
>>> +gaming.
>>> +
>>> +Most OSes will specify the source content format (color gamut, 
>>> encoding transfer
>>> +function, and other metadata, such as max and average light levels) 
>>> to a driver.
>>> +Drivers will then program their fixed-function HW accordingly to map 
>>> from a
>>> +source content buffer's space to a display's space.
>>> +
>>> +When fixed-function HW is not available the compositor will assemble 
>>> a shader to
>>> +ask the GPU to perform the transformation from the source content 
>>> format to the
>>> +display's format.
>>> +
>>> +A compositor's mapping function and a driver's mapping function are 
>>> usually
>>> +entirely separate concepts. On OSes where a HW vendor has no insight 
>>> into
>>> +closed-source compositor code such a vendor will tune their color 
>>> management
>>> +code to visually match the compositor's. On other OSes, where both 
>>> mapping
>>> +functions are open to an implementer they will ensure both mappings 
>>> match.
>>> +
>>> +This results in mapping algorithm lock-in, meaning that no-one alone 
>>> can
>>> +experiment with or introduce new mapping algorithms and achieve
>>> +consistent results regardless of which implementation path is taken.
>>> +
>>> +Why is Linux different?
>>> +=======================
>>> +
>>> +Unlike other OSes, where there is one compositor for one or more 
>>> drivers, on
>>> +Linux we have a many-to-many relationship. Many compositors; many 
>>> drivers.
>>> +In addition each compositor vendor or community has their own view 
>>> of how
>>> +color management should be done. This is what makes Linux so beautiful.
>>> +
>>> +This means that a HW vendor can now no longer tune their driver to one
>>> +compositor, as tuning it to one could make it look fairly different 
>>> from
>>> +another compositor's color mapping.
>>> +
>>> +We need a better solution.
>>> +
>>> +
>>> +Descriptive API
>>> +===============
>>> +
>>> +An API that describes the source and destination colorspaces is a 
>>> descriptive
>>> +API. It describes the input and output color spaces but does not 
>>> describe
>>> +how precisely they should be mapped. Such a mapping includes many 
>>> minute
>>> +design decision that can greatly affect the look of the final result.
>>> +
>>> +It is not feasible to describe such mapping with enough detail to 
>>> ensure the
>>> +same result from each implementation. In fact, these mappings are a 
>>> very active
>>> +research area.
>>> +
>>> +
>>> +Prescriptive API
>>> +================
>>> +
>>> +A prescriptive API describes not the source and destination 
>>> colorspaces. It
>>> +instead prescribes a recipe for how to manipulate pixel values to 
>>> arrive at the
>>> +desired outcome.
>>> +
>>> +This recipe is generally an ordered list of straight-forward 
>>> operations,
>>> +with clear mathematical definitions, such as 1D LUTs, 3D LUTs, 
>>> matrices,
>>> +or other operations that can be described in a precise manner.
>>> +
>>> +
>>> +The Color Pipeline API
>>> +======================
>>> +
>>> +HW color management pipelines can significantly differ between HW
>>> +vendors in terms of availability, ordering, and capabilities of HW
>>> +blocks. This makes a common definition of color management blocks and
>>> +their ordering nigh impossible. Instead we are defining an API that
>>> +allows user space to discover the HW capabilities in a generic manner,
>>> +agnostic of specific drivers and hardware.
>>> +
>>> +
>>> +drm_colorop Object
>>> +==================
>>> +
>>> +To support the definition of color pipelines we define the DRM core
>>> +object type drm_colorop. Individual drm_colorop objects will be chained
>>> +via the NEXT property of a drm_colorop to constitute a color pipeline.
>>> +Each drm_colorop object is unique, i.e., even if multiple color
>>> +pipelines have the same operation they won't share the same drm_colorop
>>> +object to describe that operation.
>>> +
>>> +Note that drivers are not expected to map drm_colorop objects 
>>> statically
>>> +to specific HW blocks. The mapping of drm_colorop objects is entirely a
>>> +driver-internal detail and can be as dynamic or static as a driver 
>>> needs
>>> +it to be. See more in the Driver Implementation Guide section below.
>>> +
>>> +Each drm_colorop has three core properties:
>>> +
>>> +TYPE: An enumeration property, defining the type of transformation, 
>>> such as
>>> +* enumerated curve
>>> +* custom (uniform) 1D LUT
>>> +* 3x3 matrix
>>> +* 3x4 matrix
>>> +* 3D LUT
>>> +* etc.
>>> +
>>> +Depending on the type of transformation other properties will describe
>>> +more details.
>>> +
>>> +BYPASS: A boolean property that can be used to easily put a block into
>>> +bypass mode. The BYPASS property is not mandatory for a colorop, as 
>>> long
>>> +as the entire pipeline can get bypassed by setting the 
>>> COLOR_PIPELINE on
>>> +a plane to '0'.
>>> +
>>> +NEXT: The ID of the next drm_colorop in a color pipeline, or 0 if this
>>> +drm_colorop is the last in the chain.
>>> +
>>> +An example of a drm_colorop object might look like one of these::
>>> +
>>> +    /* 1D enumerated curve */
>>> +    Color operation 42
>>> +    ├─ "TYPE": immutable enum {1D enumerated curve, 1D LUT, 3x3 
>>> matrix, 3x4 matrix, 3D LUT, etc.} = 1D enumerated curve
>>> +    ├─ "BYPASS": bool {true, false}
>>> +    ├─ "CURVE_1D_TYPE": enum {sRGB EOTF, sRGB inverse EOTF, PQ EOTF, 
>>> PQ inverse EOTF, …}
>>> +    └─ "NEXT": immutable color operation ID = 43
>>> +
>>> +    /* custom 4k entry 1D LUT */
>>> +    Color operation 52
>>> +    ├─ "TYPE": immutable enum {1D enumerated curve, 1D LUT, 3x3 
>>> matrix, 3x4 matrix, 3D LUT, etc.} = 1D LUT
>>> +    ├─ "BYPASS": bool {true, false}
>>> +    ├─ "SIZE": immutable range = 4096
>>> +    ├─ "DATA": blob
>>> +    └─ "NEXT": immutable color operation ID = 0
>>> +
>>> +    /* 17^3 3D LUT */
>>> +    Color operation 72
>>> +    ├─ "TYPE": immutable enum {1D enumerated curve, 1D LUT, 3x3 
>>> matrix, 3x4 matrix, 3D LUT, etc.} = 3D LUT
>>> +    ├─ "BYPASS": bool {true, false}
>>> +    ├─ "3DLUT_MODES": read-only blob of supported 3DLUT modes
>>> +    ├─ "3DLUT_MODE_INDEX": index of selected 3DLUT mode
>>> +    ├─ "DATA": blob
>>> +    └─ "NEXT": immutable color operation ID = 73
>>> +
>>> +drm_colorop extensibility
>>> +-------------------------
>>> +
>>> +Unlike existing DRM core objects, like &drm_plane, drm_colorop is not
>>> +extensible. This simplifies implementations and keeps all functionality
>>> +for managing &drm_colorop objects in the DRM core.
>>> +
>>> +If there is a need one may introduce a simple &drm_colorop_funcs
>>> +function table in the future, for example to support an IN_FORMATS
>>> +property on a &drm_colorop.
>>> +
>>> +If a driver requires the ability to create a driver-specific colorop
>>> +object they will need to add &drm_colorop func table support with
>>> +support for the usual functions, like destroy, atomic_duplicate_state,
>>> +and atomic_destroy_state.
>> As far as I know, there are multiple embedded SOCs(with mainline linux 
>> support) that support colorops which are not exist in current func 
>> list. Why don't we just make the api extensible now? It would make the 
>> API/ code more simple when adding colorops.
> 
> Any vendor can create their color pipeline(s) and add new colorop 
> objects accordingly. This patchset creates an AMD-specific color 
> pipeline and colorop objects (for an obvious reason) as an demonstration 
> and other vendors are working on their own too.
> 
> The following paragraphs should answer your questions.
> 
>>
>>> +
>>> +
>>> +COLOR_PIPELINE Plane Property
>>> +=============================
>>> +
>>> +Color Pipelines are created by a driver and advertised via a new
>>> +COLOR_PIPELINE enum property on each plane. Values of the property
>>> +always include object id 0, which is the default and means all color
>>> +processing is disabled. Additional values will be the object IDs of the
>>> +first drm_colorop in a pipeline. A driver can create and advertise 
>>> none,
>>> +one, or more possible color pipelines. A DRM client will select a color
>>> +pipeline by setting the COLOR PIPELINE to the respective value.
>>> +
>>> +NOTE: Many DRM clients will set enumeration properties via the string
>>> +value, often hard-coding it. Since this enumeration is generated based
>>> +on the colorop object IDs it is important to perform the Color Pipeline
>>> +Discovery, described below, instead of hard-coding color pipeline
>>> +assignment. Drivers might generate the enum strings dynamically.
>>> +Hard-coded strings might only work for specific drivers on a specific
>>> +pieces of HW. Color Pipeline Discovery can work universally, as long as
>>> +drivers implement the required color operations.
>>> +
>>> +The COLOR_PIPELINE property is only exposed when the
>>> +DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE is set. Drivers shall ignore any
>>> +existing pre-blend color operations when this cap is set, such as
>>> +COLOR_RANGE and COLOR_ENCODING. If drivers want to support COLOR_RANGE
>>> +or COLOR_ENCODING functionality when the color pipeline client cap is
>>> +set, they are expected to expose colorops in the pipeline to allow for
>>> +the appropriate color transformation.
>>> +
>>> +Setting of the COLOR_PIPELINE plane property or drm_colorop properties
>>> +is only allowed for userspace that sets this client cap.
>>> +
>>> +An example of a COLOR_PIPELINE property on a plane might look like 
>>> this::
>>> +
>>> +    Plane 10
>>> +    ├─ "TYPE": immutable enum {Overlay, Primary, Cursor} = Primary
>>> +    ├─ …
>>> +    └─ "COLOR_PIPELINE": enum {0, 42, 52} = 0
>>> +
>>> +
>>> +Color Pipeline Discovery
>>> +========================
>>> +
>>> +A DRM client wanting color management on a drm_plane will:
>>> +
>>> +1. Get the COLOR_PIPELINE property of the plane
>>> +2. iterate all COLOR_PIPELINE enum values
>>> +3. for each enum value walk the color pipeline (via the NEXT pointers)
>>> +   and see if the available color operations are suitable for the
>>> +   desired color management operations
>>> +
>>> +If userspace encounters an unknown or unsuitable color operation during
>>> +discovery it does not need to reject the entire color pipeline 
>>> outright,
>>> +as long as the unknown or unsuitable colorop has a "BYPASS" property.
>>> +Drivers will ensure that a bypassed block does not have any effect.
>>> +
>>> +An example of chained properties to define an AMD pre-blending color
>>> +pipeline might look like this::
>>> +
>>> +    Plane 10
>>> +    ├─ "TYPE" (immutable) = Primary
>>> +    └─ "COLOR_PIPELINE": enum {0, 44} = 0
>>> +
>>> +    Color operation 44
>>> +    ├─ "TYPE" (immutable) = 1D enumerated curve
>>> +    ├─ "BYPASS": bool
>>> +    ├─ "CURVE_1D_TYPE": enum {sRGB EOTF, PQ EOTF} = sRGB EOTF
>>> +    └─ "NEXT" (immutable) = 45
>>> +
>>> +    Color operation 45
>>> +    ├─ "TYPE" (immutable) = 3x4 Matrix
>>> +    ├─ "BYPASS": bool
>>> +    ├─ "DATA": blob
>>> +    └─ "NEXT" (immutable) = 46
>>> +
>>> +    Color operation 46
>>> +    ├─ "TYPE" (immutable) = 1D enumerated curve
>>> +    ├─ "BYPASS": bool
>>> +    ├─ "CURVE_1D_TYPE": enum {sRGB Inverse EOTF, PQ Inverse EOTF} = 
>>> sRGB EOTF
>>> +    └─ "NEXT" (immutable) = 47
>>> +
>>> +    Color operation 47
>>> +    ├─ "TYPE" (immutable) = 1D LUT
>>> +    ├─ "SIZE": immutable range = 4096
>>> +    ├─ "DATA": blob
>>> +    └─ "NEXT" (immutable) = 48
>>> +
>>> +    Color operation 48
>>> +    ├─ "TYPE" (immutable) = 3D LUT
>>> +    ├─ "3DLUT_MODE_INDEX": 0
>>> +    ├─ "DATA": blob
>>> +    └─ "NEXT" (immutable) = 49
>>> +
>>> +    Color operation 49
>>> +    ├─ "TYPE" (immutable) = 1D enumerated curve
>>> +    ├─ "BYPASS": bool
>>> +    ├─ "CURVE_1D_TYPE": enum {sRGB EOTF, PQ EOTF} = sRGB EOTF
>>> +    └─ "NEXT" (immutable) = 0
>>> +
>>> +
>>> +Color Pipeline Programming
>>> +==========================
>>> +
>>> +Once a DRM client has found a suitable pipeline it will:
>>> +
>>> +1. Set the COLOR_PIPELINE enum value to the one pointing at the first
>>> +   drm_colorop object of the desired pipeline
>>> +2. Set the properties for all drm_colorop objects in the pipeline to 
>>> the
>>> +   desired values, setting BYPASS to true for unused drm_colorop 
>>> blocks,
>>> +   and false for enabled drm_colorop blocks
>>> +3. Perform (TEST_ONLY or not) atomic commit with all the other KMS
>>> +   states it wishes to change
>>> +
>>> +To configure the pipeline for an HDR10 PQ plane and blending in linear
>>> +space, a compositor might perform an atomic commit with the following
>>> +property values::
>>> +
>>> +    Plane 10
>>> +    └─ "COLOR_PIPELINE" = 42
>>> +
>>> +    Color operation 42
>>> +    └─ "BYPASS" = true
>>> +
>>> +    Color operation 44
>>> +    └─ "BYPASS" = true
>>> +
>>> +    Color operation 45
>>> +    └─ "BYPASS" = true
>>> +
>>> +    Color operation 46
>>> +    └─ "BYPASS" = true
>>> +
>>> +    Color operation 47
>>> +    ├─ "LUT_3D_DATA" = Gamut mapping + tone mapping + night mode
>>> +    └─ "BYPASS" = false
>>> +
>>> +    Color operation 48
>>> +    ├─ "CURVE_1D_TYPE" = PQ EOTF
>>> +    └─ "BYPASS" = false
>>> +
>>> +
>>> +Driver Implementer's Guide
>>> +==========================
>>> +
>>> +What does this all mean for driver implementations? As noted above the
>>> +colorops can map to HW directly but don't need to do so. Here are some
>>> +suggestions on how to think about creating your color pipelines:
>>> +
>>> +- Try to expose pipelines that use already defined colorops, even if
>>> +  your hardware pipeline is split differently. This allows existing
>>> +  userspace to immediately take advantage of the hardware.
>>> +
>>> +- Additionally, try to expose your actual hardware blocks as colorops.
>>> +  Define new colorop types where you believe it can offer significant
>>> +  benefits if userspace learns to program them.
>>> +
>>> +- Avoid defining new colorops for compound operations with very narrow
>>> +  scope. If you have a hardware block for a special operation that
>>> +  cannot be split further, you can expose that as a new colorop type.
>>> +  However, try to not define colorops for "use cases", especially if
>>> +  they require you to combine multiple hardware blocks.
>>> +
>>> +- Design new colorops as prescriptive, not descriptive; by the
>>> +  mathematical formula, not by the assumed input and output.
>>> +
>>> +A defined colorop type must be deterministic. The exact behavior of the
>>> +colorop must be documented entirely, whether via a mathematical formula
>>> +or some other description. Its operation can depend only on its
>>> +properties and input and nothing else, allowed error tolerance
>>> +notwithstanding.
>>> +
>>> +
>>> +Driver Forward/Backward Compatibility
>>> +=====================================
>>> +
>>> +As this is uAPI drivers can't regress color pipelines that have been
>>> +introduced for a given HW generation. New HW generations are free to
>>> +abandon color pipelines advertised for previous generations.
>>> +Nevertheless, it can be beneficial to carry support for existing color
>>> +pipelines forward as those will likely already have support in DRM
>>> +clients.
>>> +
>>> +Introducing new colorops to a pipeline is fine, as long as they can be
>>> +bypassed or are purely informational. DRM clients implementing support
>>> +for the pipeline can always skip unknown properties as long as they can
>>> +be confident that doing so will not cause unexpected results.
>>> +
>>> +If a new colorop doesn't fall into one of the above categories
>>> +(bypassable or informational) the modified pipeline would be unusable
>>> +for user space. In this case a new pipeline should be defined.
>>> +
>>> +
>>> +References
>>> +==========
>>> +
>>> +1. https://lore.kernel.org/dri-devel/ 
>>> QMers3awXvNCQlyhWdTtsPwkp5ie9bze_hD5nAccFW7a_RXlWjYB7MoUW_8CKLT2bSQwIXVi5H6VULYIxCdgvryZoAoJnC5lZgyK1QWn488=@emersion.fr/
>>> \ No newline at end of file
>>> diff --git a/Documentation/gpu/rfc/index.rst b/Documentation/gpu/rfc/ 
>>> index.rst
>>> index 396e535377fb..ef19b0ba2a3e 100644
>>> --- a/Documentation/gpu/rfc/index.rst
>>> +++ b/Documentation/gpu/rfc/index.rst
>>> @@ -35,3 +35,6 @@ host such documentation:
>>>   .. toctree::
>>>       i915_vm_bind.rst
>>> +
>>> +.. toctree::
>>> +    color_pipeline.rst
>>> \ No newline at end of file
>>
> 


[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 6977 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-03-31 16:50                   ` Shengyu Qu
@ 2025-03-31 17:04                     ` Shengyu Qu
  2025-03-31 17:42                       ` Alex Hung
  0 siblings, 1 reply; 128+ messages in thread
From: Shengyu Qu @ 2025-03-31 17:04 UTC (permalink / raw)
  To: Alex Hung, dri-devel, amd-gfx
  Cc: wiagn233, wayland-devel, harry.wentland, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet


[-- Attachment #1.1.1: Type: text/plain, Size: 4104 bytes --]

Or we can add some kind of "linked with" info to plane's COLOR_PIPELINE 
property, to let userspace know that cursor plane and background plane 
share the same colorop config. So that userspace could do extra 
conversion on cursor image data to avoid display wrong cursor color.

在 2025/4/1 0:50, Shengyu Qu 写道:
> Thanks, I mistook about the MPO document. Maybe we should also disable 
> colorop on the background plane of the cursor plane? So that compositors 
> would do sw color convertion on both cursor plane and background plane, 
> which should keep cursor display correctly.
> 
> 在 2025/4/1 0:34, Alex Hung 写道:
>>
>>
>> On 3/31/25 10:31, Shengyu Qu wrote:
>>> Sorry for vague expression. I mean that I think we shouldn't register 
>>> DRM_PLANE_TYPE_CURSOR in the driver, as we don't have actual hardware 
>>> support.
>>
>> This is not true. AMD has hardware cursor support.
>>
>>>
>>> 在 2025/4/1 0:26, Alex Hung 写道:
>>>>
>>>>
>>>> On 3/31/25 10:12, Shengyu Qu wrote:
>>>>> So currently we have to hope the compositor won't use 
>>>>> DRM_PLANE_TYPE_CURSOR planes at all.... Why do we still register 
>>>>> DRM_PLANE_TYPE_CURSOR in the driver?
>>>>
>>>> I am not sure what your question is. A compositor can choose or skip 
>>>> any hardware features, but this discussion is out of the scope.
>>>>
>>>>>
>>>>> 在 2025/4/1 0:06, Alex Hung 写道:
>>>>>>
>>>>>>
>>>>>> On 3/31/25 09:43, Shengyu Qu wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> Thanks for reply. So currently we have to apply color conversion 
>>>>>>> on the background plane of the cursor to do some color space 
>>>>>>> conversion. What would happen if cursor and background plane 
>>>>>>> needs different conversion config? Or we just give the cursor a 
>>>>>>> dedicated plane?
>>>>>>
>>>>>> This scenario is not supported on AMD hardware, but software 
>>>>>> cursors on other plane types won't be affected.
>>>>>>
>>>>>>>
>>>>>>> Best regards,
>>>>>>> Shengyu
>>>>>>>
>>>>>>> 在 2025/3/31 22:28, Alex Hung 写道:
>>>>>>>>
>>>>>>>>
>>>>>>>> On 3/30/25 06:59, Shengyu Qu wrote:
>>>>>>>>> Hi,
>>>>>>>>>
>>>>>>>>> Do we really need to disable cursor plane color pipeline 
>>>>>>>>> support? I don't think we need to disable that if it is 
>>>>>>>>> supported, since there might be some user-defined colored 
>>>>>>>>> cursor icon.
>>>>>>>>
>>>>>>>> This patch applies to AMD hardware only: https:// 
>>>>>>>> elixir.bootlin.com/ linux/v6.13/source/Documentation/gpu/amdgpu/ 
>>>>>>>> display/mpo- overview.rst#L101
>>>>>>>>
>>>>>>>>>
>>>>>>>>> Best regards,
>>>>>>>>> Shengyu
>>>>>>>>>
>>>>>>>>> For some unknown reason, seems my mail is not shown in the mail 
>>>>>>>>> list archive, so I resent it.
>>>>>>>>>
>>>>>>>>> 在 2025/3/27 7:47, Alex Hung 写道:
>>>>>>>>>> cursor plane does not need to have color pipeline.
>>>>>>>>>>
>>>>>>>>>> Signed-off-by: Alex Hung <alex.hung@amd.com>
>>>>>>>>>> ---
>>>>>>>>>> v7:
>>>>>>>>>>   - Add a commit messages
>>>>>>>>>>
>>>>>>>>>>   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 3 +++
>>>>>>>>>>   1 file changed, 3 insertions(+)
>>>>>>>>>>
>>>>>>>>>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/ 
>>>>>>>>>> amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/ 
>>>>>>>>>> amdgpu_dm_plane.c
>>>>>>>>>> index 9632b8b73e7e..b5b9b0b5da63 100644
>>>>>>>>>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>>>>>>>>>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>>>>>>>>>> @@ -1792,6 +1792,9 @@ dm_plane_init_colorops(struct drm_plane 
>>>>>>>>>> *plane)
>>>>>>>>>>       struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
>>>>>>>>>>       int len = 0;
>>>>>>>>>> +    if (plane->type == DRM_PLANE_TYPE_CURSOR)
>>>>>>>>>> +        return 0;
>>>>>>>>>> +
>>>>>>>>>>       /* Create COLOR_PIPELINE property and attach */
>>>>>>>>>>       drm_plane_create_color_pipeline_property(plane, 
>>>>>>>>>> pipelines, len);
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
> 


[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 6977 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-03-31 17:04                     ` Shengyu Qu
@ 2025-03-31 17:42                       ` Alex Hung
  2025-03-31 18:53                         ` Xaver Hugl
                                           ` (2 more replies)
  0 siblings, 3 replies; 128+ messages in thread
From: Alex Hung @ 2025-03-31 17:42 UTC (permalink / raw)
  To: Shengyu Qu, dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet



On 3/31/25 11:04, Shengyu Qu wrote:
> Or we can add some kind of "linked with" info to plane's COLOR_PIPELINE 
> property, to let userspace know that cursor plane and background plane 
> share the same colorop config. So that userspace could do extra 
> conversion on cursor image data to avoid display wrong cursor color.

That's over-complicate and makes little sense for both device drivers 
and userspace applications.

If any planes share same colorop config, a device driver exposes the 
same color pipeline with the same colorops.

If a plane does not support color pipeline or a driver doesn't want to 
support it, there is no color pipeline and no color objects.

Again it is up to compositors or apps to determine how color pipeline 
and colorops are used (or not). For example, both primary plane and 
overlay plane have the same color pipeline, HDR can be enabled only on 
overlay but not on primary.

> 
> 在 2025/4/1 0:50, Shengyu Qu 写道:
>> Thanks, I mistook about the MPO document. Maybe we should also disable 
>> colorop on the background plane of the cursor plane? So that 
>> compositors would do sw color convertion on both cursor plane and 
>> background plane, which should keep cursor display correctly.

Cursor plane has no color pipeline and thus it has no colorop either. It 
inherits color processing from its parent plane.

You can create a color pipeline for cursor plane for your hardware. If 
none of existing colorop matches your need, new colorop can be defined.


>>
>> 在 2025/4/1 0:34, Alex Hung 写道:
>>>
>>>
>>> On 3/31/25 10:31, Shengyu Qu wrote:
>>>> Sorry for vague expression. I mean that I think we shouldn't 
>>>> register DRM_PLANE_TYPE_CURSOR in the driver, as we don't have 
>>>> actual hardware support.
>>>
>>> This is not true. AMD has hardware cursor support.
>>>
>>>>
>>>> 在 2025/4/1 0:26, Alex Hung 写道:
>>>>>
>>>>>
>>>>> On 3/31/25 10:12, Shengyu Qu wrote:
>>>>>> So currently we have to hope the compositor won't use 
>>>>>> DRM_PLANE_TYPE_CURSOR planes at all.... Why do we still register 
>>>>>> DRM_PLANE_TYPE_CURSOR in the driver?
>>>>>
>>>>> I am not sure what your question is. A compositor can choose or 
>>>>> skip any hardware features, but this discussion is out of the scope.
>>>>>
>>>>>>
>>>>>> 在 2025/4/1 0:06, Alex Hung 写道:
>>>>>>>
>>>>>>>
>>>>>>> On 3/31/25 09:43, Shengyu Qu wrote:
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> Thanks for reply. So currently we have to apply color conversion 
>>>>>>>> on the background plane of the cursor to do some color space 
>>>>>>>> conversion. What would happen if cursor and background plane 
>>>>>>>> needs different conversion config? Or we just give the cursor a 
>>>>>>>> dedicated plane?
>>>>>>>
>>>>>>> This scenario is not supported on AMD hardware, but software 
>>>>>>> cursors on other plane types won't be affected.
>>>>>>>
>>>>>>>>
>>>>>>>> Best regards,
>>>>>>>> Shengyu
>>>>>>>>
>>>>>>>> 在 2025/3/31 22:28, Alex Hung 写道:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On 3/30/25 06:59, Shengyu Qu wrote:
>>>>>>>>>> Hi,
>>>>>>>>>>
>>>>>>>>>> Do we really need to disable cursor plane color pipeline 
>>>>>>>>>> support? I don't think we need to disable that if it is 
>>>>>>>>>> supported, since there might be some user-defined colored 
>>>>>>>>>> cursor icon.
>>>>>>>>>
>>>>>>>>> This patch applies to AMD hardware only: https:// 
>>>>>>>>> elixir.bootlin.com/ linux/v6.13/source/Documentation/gpu/ 
>>>>>>>>> amdgpu/ display/mpo- overview.rst#L101
>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Best regards,
>>>>>>>>>> Shengyu
>>>>>>>>>>
>>>>>>>>>> For some unknown reason, seems my mail is not shown in the 
>>>>>>>>>> mail list archive, so I resent it.
>>>>>>>>>>
>>>>>>>>>> 在 2025/3/27 7:47, Alex Hung 写道:
>>>>>>>>>>> cursor plane does not need to have color pipeline.
>>>>>>>>>>>
>>>>>>>>>>> Signed-off-by: Alex Hung <alex.hung@amd.com>
>>>>>>>>>>> ---
>>>>>>>>>>> v7:
>>>>>>>>>>>   - Add a commit messages
>>>>>>>>>>>
>>>>>>>>>>>   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 3 
>>>>>>>>>>> +++
>>>>>>>>>>>   1 file changed, 3 insertions(+)
>>>>>>>>>>>
>>>>>>>>>>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/ 
>>>>>>>>>>> amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/ 
>>>>>>>>>>> amdgpu_dm_plane.c
>>>>>>>>>>> index 9632b8b73e7e..b5b9b0b5da63 100644
>>>>>>>>>>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>>>>>>>>>>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>>>>>>>>>>> @@ -1792,6 +1792,9 @@ dm_plane_init_colorops(struct drm_plane 
>>>>>>>>>>> *plane)
>>>>>>>>>>>       struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
>>>>>>>>>>>       int len = 0;
>>>>>>>>>>> +    if (plane->type == DRM_PLANE_TYPE_CURSOR)
>>>>>>>>>>> +        return 0;
>>>>>>>>>>> +
>>>>>>>>>>>       /* Create COLOR_PIPELINE property and attach */
>>>>>>>>>>>       drm_plane_create_color_pipeline_property(plane, 
>>>>>>>>>>> pipelines, len);
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
> 


^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-03-31 17:42                       ` Alex Hung
@ 2025-03-31 18:53                         ` Xaver Hugl
  2025-04-01  0:28                           ` Alex Hung
  2025-04-01 15:45                           ` Melissa Wen
  2025-04-01  1:04                         ` Shengyu Qu
  2025-04-01  9:56                         ` Michel Dänzer
  2 siblings, 2 replies; 128+ messages in thread
From: Xaver Hugl @ 2025-03-31 18:53 UTC (permalink / raw)
  To: Alex Hung
  Cc: Shengyu Qu, dri-devel, amd-gfx, wayland-devel, harry.wentland,
	leo.liu, ville.syrjala, pekka.paalanen, contact, mwen, jadahl,
	sebastian.wick, shashank.sharma, agoins, joshua, mdaenzer,
	aleixpol, victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

> Cursor plane has no color pipeline and thus it has no colorop either. It
> inherits color processing from its parent plane.

Just to be sure: That means amdgpu will reject atomic commits that try
to set a color pipeline on the primary plane while showing the cursor
plane on top of it? Just like with scaling?

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 03/43] drm/doc/rfc: Describe why prescriptive color pipeline is needed
  2025-03-29 15:26   ` Simon Ser
@ 2025-04-01  0:10     ` Alex Hung
  2025-04-01  7:26       ` Simon Ser
  0 siblings, 1 reply; 128+ messages in thread
From: Alex Hung @ 2025-04-01  0:10 UTC (permalink / raw)
  To: Simon Ser
  Cc: dri-devel, amd-gfx, wayland-devel, harry.wentland, leo.liu,
	ville.syrjala, pekka.paalanen, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet



On 3/29/25 09:26, Simon Ser wrote:
> I would also highlight that we need to seamlessly switch between HW
> fixed-function blocks and shaders/CPU with no visible difference. Depending on
> the content being displayed we might need to fallback to shaders/CPU at any
> time. (A classic example would be a new notification popup preventing us from
> leveraging KMS planes.)

Yes that would be the goal.

Is there any part of the docs that still need revising to clarify this?

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-03-31 18:53                         ` Xaver Hugl
@ 2025-04-01  0:28                           ` Alex Hung
  2025-04-01 15:04                             ` Xaver Hugl
  2025-04-01 15:45                           ` Melissa Wen
  1 sibling, 1 reply; 128+ messages in thread
From: Alex Hung @ 2025-04-01  0:28 UTC (permalink / raw)
  To: Xaver Hugl
  Cc: Shengyu Qu, dri-devel, amd-gfx, wayland-devel, harry.wentland,
	leo.liu, ville.syrjala, pekka.paalanen, contact, mwen, jadahl,
	sebastian.wick, shashank.sharma, agoins, joshua, mdaenzer,
	aleixpol, victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet



On 3/31/25 12:53, Xaver Hugl wrote:
>> Cursor plane has no color pipeline and thus it has no colorop either. It
>> inherits color processing from its parent plane.
> 
> Just to be sure: That means amdgpu will reject atomic commits that try
> to set a color pipeline on the primary plane while showing the cursor
> plane on top of it? Just like with scaling?


In theory that should be the case, and I will investigate and confirm 
it. Is this a beavhiour expected by a compositor?

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-03-31 17:42                       ` Alex Hung
  2025-03-31 18:53                         ` Xaver Hugl
@ 2025-04-01  1:04                         ` Shengyu Qu
  2025-04-01  1:24                           ` Alex Hung
  2025-04-01  9:56                         ` Michel Dänzer
  2 siblings, 1 reply; 128+ messages in thread
From: Shengyu Qu @ 2025-04-01  1:04 UTC (permalink / raw)
  To: Alex Hung, dri-devel, amd-gfx
  Cc: wiagn233, wayland-devel, harry.wentland, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet


[-- Attachment #1.1.1: Type: text/plain, Size: 5864 bytes --]



在 2025/4/1 1:42, Alex Hung 写道:
> 
> 
> On 3/31/25 11:04, Shengyu Qu wrote:
>> Or we can add some kind of "linked with" info to plane's 
>> COLOR_PIPELINE property, to let userspace know that cursor plane and 
>> background plane share the same colorop config. So that userspace 
>> could do extra conversion on cursor image data to avoid display wrong 
>> cursor color.
> 
> That's over-complicate and makes little sense for both device drivers 
> and userspace applications.
> 
> If any planes share same colorop config, a device driver exposes the 
> same color pipeline with the same colorops.
> 
> If a plane does not support color pipeline or a driver doesn't want to 
> support it, there is no color pipeline and no color objects.
My understanding is that currently the driver would just report no 
colorop support on cursor plane and actually implement the background 
plane's colorop on cursor?

> 
> Again it is up to compositors or apps to determine how color pipeline 
> and colorops are used (or not). For example, both primary plane and 
> overlay plane have the same color pipeline, HDR can be enabled only on 
> overlay but not on primary.
Still this is the cleanest way to let compositors know and deal with 
this special cursor plane behavior. Or if compositors want to use all 
planes with hw colorop + MPO(for power saving or sth.), they have to 
detect the gpu they are running on and apply a quirk for this. That's a 
"dirty" implementation.

> 
>>
>> 在 2025/4/1 0:50, Shengyu Qu 写道:
>>> Thanks, I mistook about the MPO document. Maybe we should also 
>>> disable colorop on the background plane of the cursor plane? So that 
>>> compositors would do sw color convertion on both cursor plane and 
>>> background plane, which should keep cursor display correctly.
> 
> Cursor plane has no color pipeline and thus it has no colorop either. It 
> inherits color processing from its parent plane.
> 
> You can create a color pipeline for cursor plane for your hardware. If 
> none of existing colorop matches your need, new colorop can be defined.
> 
> 
>>>
>>> 在 2025/4/1 0:34, Alex Hung 写道:
>>>>
>>>>
>>>> On 3/31/25 10:31, Shengyu Qu wrote:
>>>>> Sorry for vague expression. I mean that I think we shouldn't 
>>>>> register DRM_PLANE_TYPE_CURSOR in the driver, as we don't have 
>>>>> actual hardware support.
>>>>
>>>> This is not true. AMD has hardware cursor support.
>>>>
>>>>>
>>>>> 在 2025/4/1 0:26, Alex Hung 写道:
>>>>>>
>>>>>>
>>>>>> On 3/31/25 10:12, Shengyu Qu wrote:
>>>>>>> So currently we have to hope the compositor won't use 
>>>>>>> DRM_PLANE_TYPE_CURSOR planes at all.... Why do we still register 
>>>>>>> DRM_PLANE_TYPE_CURSOR in the driver?
>>>>>>
>>>>>> I am not sure what your question is. A compositor can choose or 
>>>>>> skip any hardware features, but this discussion is out of the scope.
>>>>>>
>>>>>>>
>>>>>>> 在 2025/4/1 0:06, Alex Hung 写道:
>>>>>>>>
>>>>>>>>
>>>>>>>> On 3/31/25 09:43, Shengyu Qu wrote:
>>>>>>>>> Hi,
>>>>>>>>>
>>>>>>>>> Thanks for reply. So currently we have to apply color 
>>>>>>>>> conversion on the background plane of the cursor to do some 
>>>>>>>>> color space conversion. What would happen if cursor and 
>>>>>>>>> background plane needs different conversion config? Or we just 
>>>>>>>>> give the cursor a dedicated plane?
>>>>>>>>
>>>>>>>> This scenario is not supported on AMD hardware, but software 
>>>>>>>> cursors on other plane types won't be affected.
>>>>>>>>
>>>>>>>>>
>>>>>>>>> Best regards,
>>>>>>>>> Shengyu
>>>>>>>>>
>>>>>>>>> 在 2025/3/31 22:28, Alex Hung 写道:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On 3/30/25 06:59, Shengyu Qu wrote:
>>>>>>>>>>> Hi,
>>>>>>>>>>>
>>>>>>>>>>> Do we really need to disable cursor plane color pipeline 
>>>>>>>>>>> support? I don't think we need to disable that if it is 
>>>>>>>>>>> supported, since there might be some user-defined colored 
>>>>>>>>>>> cursor icon.
>>>>>>>>>>
>>>>>>>>>> This patch applies to AMD hardware only: https:// 
>>>>>>>>>> elixir.bootlin.com/ linux/v6.13/source/Documentation/gpu/ 
>>>>>>>>>> amdgpu/ display/mpo- overview.rst#L101
>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Best regards,
>>>>>>>>>>> Shengyu
>>>>>>>>>>>
>>>>>>>>>>> For some unknown reason, seems my mail is not shown in the 
>>>>>>>>>>> mail list archive, so I resent it.
>>>>>>>>>>>
>>>>>>>>>>> 在 2025/3/27 7:47, Alex Hung 写道:
>>>>>>>>>>>> cursor plane does not need to have color pipeline.
>>>>>>>>>>>>
>>>>>>>>>>>> Signed-off-by: Alex Hung <alex.hung@amd.com>
>>>>>>>>>>>> ---
>>>>>>>>>>>> v7:
>>>>>>>>>>>>   - Add a commit messages
>>>>>>>>>>>>
>>>>>>>>>>>>   drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 
>>>>>>>>>>>> 3 +++
>>>>>>>>>>>>   1 file changed, 3 insertions(+)
>>>>>>>>>>>>
>>>>>>>>>>>> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/ 
>>>>>>>>>>>> amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/ 
>>>>>>>>>>>> amdgpu_dm_plane.c
>>>>>>>>>>>> index 9632b8b73e7e..b5b9b0b5da63 100644
>>>>>>>>>>>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>>>>>>>>>>>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
>>>>>>>>>>>> @@ -1792,6 +1792,9 @@ dm_plane_init_colorops(struct 
>>>>>>>>>>>> drm_plane *plane)
>>>>>>>>>>>>       struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES];
>>>>>>>>>>>>       int len = 0;
>>>>>>>>>>>> +    if (plane->type == DRM_PLANE_TYPE_CURSOR)
>>>>>>>>>>>> +        return 0;
>>>>>>>>>>>> +
>>>>>>>>>>>>       /* Create COLOR_PIPELINE property and attach */
>>>>>>>>>>>>       drm_plane_create_color_pipeline_property(plane, 
>>>>>>>>>>>> pipelines, len);
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
> 


[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 6977 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-04-01  1:04                         ` Shengyu Qu
@ 2025-04-01  1:24                           ` Alex Hung
  0 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-04-01  1:24 UTC (permalink / raw)
  To: Shengyu Qu, dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet



On 3/31/25 19:04, Shengyu Qu wrote:
>>
> My understanding is that currently the driver would just report no 
> colorop support on cursor plane and actually implement the background 
> plane's colorop on cursor?

No.

> 
>>
>> Again it is up to compositors or apps to determine how color pipeline 
>> and colorops are used (or not). For example, both primary plane and 
>> overlay plane have the same color pipeline, HDR can be enabled only on 
>> overlay but not on primary.
> Still this is the cleanest way to let compositors know and deal with 
> this special cursor plane behavior. Or if compositors want to use all 
> planes with hw colorop + MPO(for power saving or sth.), they have to 
> detect the gpu they are running on and apply a quirk for this. That's a 
> "dirty" implementation.

Unrelated to color pipeline.

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 11/43] drm/colorop: Introduce DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE
  2025-03-26 23:46 ` [PATCH V8 11/43] drm/colorop: Introduce DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE Alex Hung
  2025-03-29 14:37   ` Simon Ser
@ 2025-04-01  1:42   ` Shengyu Qu
  1 sibling, 0 replies; 128+ messages in thread
From: Shengyu Qu @ 2025-04-01  1:42 UTC (permalink / raw)
  To: Alex Hung, dri-devel, amd-gfx
  Cc: wiagn233, wayland-devel, harry.wentland, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet


[-- Attachment #1.1.1: Type: text/plain, Size: 5598 bytes --]



在 2025/3/27 7:46, Alex Hung 写道:
> From: Harry Wentland <harry.wentland@amd.com>
> 
> With the introduction of the pre-blending color pipeline we
> can no longer have color operations that don't have a clear
> position in the color pipeline. We deprecate all existing
> plane properties. For upstream drivers those are:
>   - COLOR_ENCODING
>   - COLOR_RANGE
> 
> Drivers are expected to ignore these properties when
> programming the HW. DRM clients that don't register with
don't?
Seems conflict with change note below.

> DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE will not be allowed to
> set the COLOR_ENCODING and COLOR_RANGE properties.
> 
> Setting of the COLOR_PIPELINE plane property or drm_colorop
> properties is only allowed for userspace that sets this
> client cap.
> 
> Signed-off-by: Alex Hung <alex.hung@amd.com>
> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
> ---
> v8:
>   - Disallow setting of COLOR_RANGE and COLOR_ENCODING when
>     DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE is set
> 
> v5:
>   - Fix kernel docs
> 
> v4:
>   - Don't block setting of COLOR_RANGE and COLOR_ENCODING
>     when client cap is set
> 
> 
>   drivers/gpu/drm/drm_atomic_uapi.c | 23 ++++++++++++++++++++++-
>   drivers/gpu/drm/drm_ioctl.c       |  7 +++++++
>   include/drm/drm_file.h            |  7 +++++++
>   include/uapi/drm/drm.h            | 15 +++++++++++++++
>   4 files changed, 51 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
> index 5738b1c18755..e0b4b122ef6b 100644
> --- a/drivers/gpu/drm/drm_atomic_uapi.c
> +++ b/drivers/gpu/drm/drm_atomic_uapi.c
> @@ -567,10 +567,26 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane,
>   	} else if (property == plane->zpos_property) {
>   		state->zpos = val;
>   	} else if (property == plane->color_encoding_property) {
> +		if (file_priv->plane_color_pipeline) {
> +			drm_dbg_atomic(dev,
> +				       "Setting COLOR_ENCODING plane property not permitted with DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE client cap\n");
> +			return -EINVAL;
> +		}
>   		state->color_encoding = val;
>   	} else if (property == plane->color_range_property) {
> +		if (file_priv->plane_color_pipeline) {
> +			drm_dbg_atomic(dev,
> +				       "Setting COLOR_RANGE plane property not permitted with DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE client cap\n");
> +			return -EINVAL;
> +		}
>   		state->color_range = val;
>   	} else if (property == plane->color_pipeline_property) {
> +		if (!file_priv->plane_color_pipeline) {
> +			drm_dbg_atomic(dev,
> +				       "Setting COLOR_PIPELINE plane property not permitted unless DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE is set\n");
> +			return -EINVAL;
> +		}
> +
>   		/* find DRM colorop object */
>   		struct drm_colorop *colorop = NULL;
>   
> @@ -1197,6 +1213,12 @@ int drm_atomic_set_property(struct drm_atomic_state *state,
>   		break;
>   	}
>   	case DRM_MODE_OBJECT_COLOROP: {
> +		if (!file_priv->plane_color_pipeline) {
> +			drm_dbg_atomic(prop->dev,
> +				       "[OBJECT:%d] is a colorop but DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE not set\n",
> +				       obj->id);
> +			ret = -EINVAL;
> +		}
>   		struct drm_colorop *colorop = obj_to_colorop(obj);
>   		struct drm_colorop_state *colorop_state;
>   
> @@ -1209,7 +1231,6 @@ int drm_atomic_set_property(struct drm_atomic_state *state,
>   		ret = drm_atomic_colorop_set_property(colorop,
>   				colorop_state, file_priv,
>   				prop, prop_value);
> -
>   		break;
>   	}
>   	default:
> diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
> index f593dc569d31..5c89c586da7c 100644
> --- a/drivers/gpu/drm/drm_ioctl.c
> +++ b/drivers/gpu/drm/drm_ioctl.c
> @@ -373,6 +373,13 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
>   			return -EINVAL;
>   		file_priv->supports_virtualized_cursor_plane = req->value;
>   		break;
> +	case DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE:
> +		if (!file_priv->atomic)
> +			return -EINVAL;
> +		if (req->value > 1)
> +			return -EINVAL;
> +		file_priv->plane_color_pipeline = req->value;
> +		break;
>   	default:
>   		return -EINVAL;
>   	}
> diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h
> index 94d365b22505..86929ca667aa 100644
> --- a/include/drm/drm_file.h
> +++ b/include/drm/drm_file.h
> @@ -206,6 +206,13 @@ struct drm_file {
>   	 */
>   	bool writeback_connectors;
>   
> +	/**
> +	 * @plane_color_pipeline:
> +	 *
> +	 * True if client understands plane color pipelines
> +	 */
> +	bool plane_color_pipeline;
> +
>   	/**
>   	 * @was_master:
>   	 *
> diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
> index 7fba37b94401..3d12fbab066f 100644
> --- a/include/uapi/drm/drm.h
> +++ b/include/uapi/drm/drm.h
> @@ -875,6 +875,21 @@ struct drm_get_cap {
>    */
>   #define DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT	6
>   
> +/**
> + * DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE
> + *
> + * If set to 1 the DRM core will allow setting the COLOR_PIPELINE
> + * property on a &drm_plane, as well as drm_colorop properties.
> + *
> + * Setting of these plane properties will be rejected when this client
> + * cap is set:
> + * - COLOR_ENCODING
> + * - COLOR_RANGE
> + *
> + * The client must enable &DRM_CLIENT_CAP_ATOMIC first.
> + */
> +#define DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE	7
> +
>   /* DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */
>   struct drm_set_client_cap {
>   	__u64 capability;


[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 6977 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 43/43] drm/colorop: Add destroy functions for color pipeline
  2025-03-29 15:48   ` Simon Ser
@ 2025-04-01  2:42     ` Alex Hung
  2025-04-10 16:18       ` Simon Ser
  0 siblings, 1 reply; 128+ messages in thread
From: Alex Hung @ 2025-04-01  2:42 UTC (permalink / raw)
  To: Simon Ser
  Cc: dri-devel, amd-gfx, wayland-devel, harry.wentland, leo.liu,
	ville.syrjala, pekka.paalanen, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet



On 3/29/25 09:48, Simon Ser wrote:
> I would prefer these functions to be introduced together with the
> patches adding functions to create objects and adding the new fields.
> That way it's easier to check the symmetry and at no point in the
> series there are memory leaks.

The object creation and new fields are introduced in different patches. 
I divided this patch by introducing these functions in a patch, and 2. 
adding callers when needed to avoid memory leaks.

> 
> Additionally, I would avoid using the name "cleanup", which seems to
> have different semantics: for instance drm_plane_cleanup() doesn't kfree
> the pointer. "destroy" seems more appropriate here.

How about the following changes, i.e., freeing pointer is moved out of 
the cleanup function, and keeping the names.

@@ -173,7 +173,6 @@ static void drm_colorop_cleanup(struct drm_colorop 
*colorop)
         }

         kfree(colorop->state);
-       kfree(colorop);
  }

  /**
@@ -191,6 +190,7 @@ void drm_colorop_pipeline_destroy(struct drm_plane 
*plane)

         list_for_each_entry_safe(colorop, next, &config->colorop_list, 
head) {
                 drm_colorop_cleanup(colorop);
+               kfree(colorop);
         }
  }



^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 03/43] drm/doc/rfc: Describe why prescriptive color pipeline is needed
  2025-04-01  0:10     ` Alex Hung
@ 2025-04-01  7:26       ` Simon Ser
  0 siblings, 0 replies; 128+ messages in thread
From: Simon Ser @ 2025-04-01  7:26 UTC (permalink / raw)
  To: Alex Hung
  Cc: dri-devel, amd-gfx, wayland-devel, harry.wentland, leo.liu,
	ville.syrjala, pekka.paalanen, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

On Tuesday, April 1st, 2025 at 02:10, Alex Hung <alex.hung@amd.com> wrote:

> On 3/29/25 09:26, Simon Ser wrote:
> 
> > I would also highlight that we need to seamlessly switch between HW
> > fixed-function blocks and shaders/CPU with no visible difference. Depending on
> > the content being displayed we might need to fallback to shaders/CPU at any
> > time. (A classic example would be a new notification popup preventing us from
> > leveraging KMS planes.)
> 
> Yes that would be the goal.
> 
> Is there any part of the docs that still need revising to clarify this?

I haven't seen this point mentioned in the current docs.

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-03-31 17:42                       ` Alex Hung
  2025-03-31 18:53                         ` Xaver Hugl
  2025-04-01  1:04                         ` Shengyu Qu
@ 2025-04-01  9:56                         ` Michel Dänzer
  2025-04-01 12:32                           ` Shengyu Qu
  2 siblings, 1 reply; 128+ messages in thread
From: Michel Dänzer @ 2025-04-01  9:56 UTC (permalink / raw)
  To: Alex Hung, Shengyu Qu, dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, aleixpol, xaver.hugl, victoria,
	daniel, uma.shankar, quic_naseer, quic_cbraga, quic_abhinavk,
	marcan, Liviu.Dudau, sashamcintosh, chaitanya.kumar.borah,
	louis.chauvet

On 2025-03-31 19:42, Alex Hung wrote:
> On 3/31/25 11:04, Shengyu Qu wrote:
>> Or we can add some kind of "linked with" info to plane's COLOR_PIPELINE property, to let userspace know that cursor plane and background plane share the same colorop config. So that userspace could do extra conversion on cursor image data to avoid display wrong cursor color.
> 
> That's over-complicate and makes little sense for both device drivers and userspace applications.
> 
> If any planes share same colorop config, a device driver exposes the same color pipeline with the same colorops.
> 
> If a plane does not support color pipeline or a driver doesn't want to support it, there is no color pipeline and no color objects.

I suspect using the cursor plane is generally higher priority for Wayland compositors than using overlay planes, because the former is critical for a responsive user experience.

This requires that the amdgpu DC driver backs the cursor plane with a dedicated HW plane though (as it's already doing in some cases), to either fully support color pipelines for the cursor plane, or at least provide proper "no color pipeline" behaviour for it. Letting the effective behaviour be determined by the other planes which happen to be behind the cursor plane isn't usable for Wayland compositors.


-- 
Earthling Michel Dänzer       \        GNOME / Xwayland / Mesa developer
https://redhat.com             \               Libre software enthusiast

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-04-01  9:56                         ` Michel Dänzer
@ 2025-04-01 12:32                           ` Shengyu Qu
  2025-04-01 14:11                             ` Michel Dänzer
  0 siblings, 1 reply; 128+ messages in thread
From: Shengyu Qu @ 2025-04-01 12:32 UTC (permalink / raw)
  To: Michel Dänzer, Alex Hung, dri-devel, amd-gfx
  Cc: wiagn233, wayland-devel, harry.wentland, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, aleixpol, xaver.hugl, victoria,
	daniel, uma.shankar, quic_naseer, quic_cbraga, quic_abhinavk,
	marcan, Liviu.Dudau, sashamcintosh, chaitanya.kumar.borah,
	louis.chauvet


[-- Attachment #1.1.1: Type: text/plain, Size: 1820 bytes --]

Btw what's your opinion about this, Xaver?

在 2025/4/1 17:56, Michel Dänzer 写道:
> On 2025-03-31 19:42, Alex Hung wrote:
>> On 3/31/25 11:04, Shengyu Qu wrote:
>>> Or we can add some kind of "linked with" info to plane's COLOR_PIPELINE property, to let userspace know that cursor plane and background plane share the same colorop config. So that userspace could do extra conversion on cursor image data to avoid display wrong cursor color.
>>
>> That's over-complicate and makes little sense for both device drivers and userspace applications.
>>
>> If any planes share same colorop config, a device driver exposes the same color pipeline with the same colorops.
>>
>> If a plane does not support color pipeline or a driver doesn't want to support it, there is no color pipeline and no color objects.
> 
> I suspect using the cursor plane is generally higher priority for Wayland compositors than using overlay planes, because the former is critical for a responsive user experience.
> 
> This requires that the amdgpu DC driver backs the cursor plane with a dedicated HW plane though (as it's already doing in some cases), to either fully support color pipelines for the cursor plane, or at least provide proper "no color pipeline" behaviour for it. Letting the effective behaviour be determined by the other planes which happen to be behind the cursor plane isn't usable for Wayland compositors.
Current behavior is just disable colorop for both background plane and 
cursor plane. I'm not sure how much planes does the hardware support, 
but if there are too less planes to use, maybe we still need to make use 
of the cursor background plane in the compositor. And then how to deal 
with colorop of cursor and background plane while saving as much power 
as possible becomes a problem.


[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 6977 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-04-01 12:32                           ` Shengyu Qu
@ 2025-04-01 14:11                             ` Michel Dänzer
  2025-04-01 15:45                               ` Shengyu Qu
  2025-04-01 16:24                               ` Shengyu Qu
  0 siblings, 2 replies; 128+ messages in thread
From: Michel Dänzer @ 2025-04-01 14:11 UTC (permalink / raw)
  To: Shengyu Qu, Alex Hung, dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, aleixpol, xaver.hugl, victoria,
	daniel, uma.shankar, quic_naseer, quic_cbraga, quic_abhinavk,
	marcan, Liviu.Dudau, sashamcintosh, chaitanya.kumar.borah,
	louis.chauvet

On 2025-04-01 14:32, Shengyu Qu wrote:
> 在 2025/4/1 17:56, Michel Dänzer 写道:
>> On 2025-03-31 19:42, Alex Hung wrote:
>>> On 3/31/25 11:04, Shengyu Qu wrote:
>>>> Or we can add some kind of "linked with" info to plane's COLOR_PIPELINE property, to let userspace know that cursor plane and background plane share the same colorop config. So that userspace could do extra conversion on cursor image data to avoid display wrong cursor color.
>>>
>>> That's over-complicate and makes little sense for both device drivers and userspace applications.
>>>
>>> If any planes share same colorop config, a device driver exposes the same color pipeline with the same colorops.
>>>
>>> If a plane does not support color pipeline or a driver doesn't want to support it, there is no color pipeline and no color objects.
>>
>> I suspect using the cursor plane is generally higher priority for Wayland compositors than using overlay planes, because the former is critical for a responsive user experience.
>>
>> This requires that the amdgpu DC driver backs the cursor plane with a dedicated HW plane though (as it's already doing in some cases), to either fully support color pipelines for the cursor plane, or at least provide proper "no color pipeline" behaviour for it. Letting the effective behaviour be determined by the other planes which happen to be behind the cursor plane isn't usable for Wayland compositors.
> Current behavior is just disable colorop for both background plane and cursor plane. 

Are you saying the color pipeline is implicitly disabled for any KMS planes which happen to be overlapped by the cursor plane?

That sounds like a no go.


> I'm not sure how much planes does the hardware support, but if there are too less planes to use, maybe we still need to make use of the cursor background plane in the compositor.

If the HW has too few planes to allow both the cursor & overlay planes to work correctly (regardless of their dimensions), the driver should not allow enabling both kinds of planes at the same time.


-- 
Earthling Michel Dänzer       \        GNOME / Xwayland / Mesa developer
https://redhat.com             \               Libre software enthusiast

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-04-01  0:28                           ` Alex Hung
@ 2025-04-01 15:04                             ` Xaver Hugl
  0 siblings, 0 replies; 128+ messages in thread
From: Xaver Hugl @ 2025-04-01 15:04 UTC (permalink / raw)
  To: Alex Hung
  Cc: Shengyu Qu, dri-devel, amd-gfx, wayland-devel, harry.wentland,
	leo.liu, ville.syrjala, pekka.paalanen, contact, mwen, jadahl,
	sebastian.wick, shashank.sharma, agoins, joshua, mdaenzer,
	aleixpol, victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

Am Di., 1. Apr. 2025 um 02:29 Uhr schrieb Alex Hung <alex.hung@amd.com>:
>
>
>
> On 3/31/25 12:53, Xaver Hugl wrote:
> >> Cursor plane has no color pipeline and thus it has no colorop either. It
> >> inherits color processing from its parent plane.
> >
> > Just to be sure: That means amdgpu will reject atomic commits that try
> > to set a color pipeline on the primary plane while showing the cursor
> > plane on top of it? Just like with scaling?
>
>
> In theory that should be the case, and I will investigate and confirm
> it. Is this a beavhiour expected by a compositor?

It's not just an expectation, the API requires it. If you were to
apply a color pipeline to a plane that doesn't have any, or not apply
one that is set, then that would be incredibly broken. Commits where
that would happen must never ever pass atomic tests.

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 06/43] drm/colorop: Add 1D Curve subtype
  2025-03-26 23:46 ` [PATCH V8 06/43] drm/colorop: Add 1D Curve subtype Alex Hung
@ 2025-04-01 15:14   ` Daniel Stone
  2025-04-01 19:53     ` Simon Ser
  0 siblings, 1 reply; 128+ messages in thread
From: Daniel Stone @ 2025-04-01 15:14 UTC (permalink / raw)
  To: Alex Hung
  Cc: dri-devel, amd-gfx, wayland-devel, harry.wentland, leo.liu,
	ville.syrjala, pekka.paalanen, contact, mwen, jadahl,
	sebastian.wick, shashank.sharma, agoins, joshua, mdaenzer,
	aleixpol, xaver.hugl, victoria, daniel, uma.shankar, quic_naseer,
	quic_cbraga, quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

Hi Alex,

On Wed, 26 Mar 2025 at 23:50, Alex Hung <alex.hung@amd.com> wrote:
> +static int drm_colorop_init(struct drm_device *dev, struct drm_colorop *colorop,
> +                           struct drm_plane *plane, enum drm_colorop_type type)
> +{
> +       struct drm_mode_config *config = &dev->mode_config;
> +       struct drm_property *prop;
> +       int ret = 0;
> +
> +       ret = drm_mode_object_add(dev, &colorop->base, DRM_MODE_OBJECT_COLOROP);
> +       if (ret)
> +               return ret;
> +
> +       colorop->base.properties = &colorop->properties;
> +       colorop->dev = dev;
> +       colorop->type = type;
> +       colorop->plane = plane;

'plane' seems really incongruous here. The colorop can be created for
any number of planes, but we're setting it to always be bound to a
single plane at init, and that can only be changed later.

I can see the sense in allowing different pipelines to move between
different planes, but then it shouldn't be set at init time. I think
you want to just drop the 'plane' argument here, and only set the
plane during an atomic commit when actually switching the state.

It would also be helpful for userspace to know how color pipelines
could be used, and to back that up with igt. Questions I have whilst
reading this:

1. Is it guaranteed that, if any plane on a device supports the
COLOR_PIPELINE property, all planes will support COLOR_PIPELINE?
(Given the amdgpu cursor-plane discussion, it looks like no, which is
unfortunate but oh well.)

2. Is it guaranteed that, if a COLOR_PIPELINE property exists on a
plane, that BYPASS will be one of the supported values? (The current
implementation does this, which seems sensible, but if the plan is to
not make this a uAPI invariant, e.g. to support planes with mandatory
CM steps, this should probably be explicitly documented.)

3. Can a given color pipeline potentially be used on different planes,
i.e. a colorop used to represent a separate hardware processing block
which may be used on any plane but only one plane at a time? (This
should be documented either way, and if they are unique per plane, igt
should enforce this.)

3. Can a given color pipeline be active on multiple planes at a time?
(If so, the implementation definitely needs rethinking: the colorop
would need to have a list of planes.)

4. Can a given color pipeline be active on multiple planes on multiple
CRTCs at a time?

5. For a given colorop property, is it an invariant that the colorop
will only appear in one color pipeline at a time? (I believe so, but
this probably needs documenting and/or igt.)

Either way, I suspect that clorop->plane is the wrong thing to do, and
that it maybe wants to be a list of planes in the drm_colorop_state?

Cheers,
Daniel

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-04-01 14:11                             ` Michel Dänzer
@ 2025-04-01 15:45                               ` Shengyu Qu
  2025-04-01 19:45                                 ` Harry Wentland
  2025-04-01 16:24                               ` Shengyu Qu
  1 sibling, 1 reply; 128+ messages in thread
From: Shengyu Qu @ 2025-04-01 15:45 UTC (permalink / raw)
  To: Michel Dänzer, Alex Hung, dri-devel, amd-gfx
  Cc: wiagn233, wayland-devel, harry.wentland, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, aleixpol, xaver.hugl, victoria,
	daniel, uma.shankar, quic_naseer, quic_cbraga, quic_abhinavk,
	marcan, Liviu.Dudau, sashamcintosh, chaitanya.kumar.borah,
	louis.chauvet


[-- Attachment #1.1.1: Type: text/plain, Size: 2308 bytes --]



在 2025/4/1 22:11, Michel Dänzer 写道:
> On 2025-04-01 14:32, Shengyu Qu wrote:
>> 在 2025/4/1 17:56, Michel Dänzer 写道:
>>> On 2025-03-31 19:42, Alex Hung wrote:
>>>> On 3/31/25 11:04, Shengyu Qu wrote:
>>>>> Or we can add some kind of "linked with" info to plane's COLOR_PIPELINE property, to let userspace know that cursor plane and background plane share the same colorop config. So that userspace could do extra conversion on cursor image data to avoid display wrong cursor color.
>>>>
>>>> That's over-complicate and makes little sense for both device drivers and userspace applications.
>>>>
>>>> If any planes share same colorop config, a device driver exposes the same color pipeline with the same colorops.
>>>>
>>>> If a plane does not support color pipeline or a driver doesn't want to support it, there is no color pipeline and no color objects.
>>>
>>> I suspect using the cursor plane is generally higher priority for Wayland compositors than using overlay planes, because the former is critical for a responsive user experience.
>>>
>>> This requires that the amdgpu DC driver backs the cursor plane with a dedicated HW plane though (as it's already doing in some cases), to either fully support color pipelines for the cursor plane, or at least provide proper "no color pipeline" behaviour for it. Letting the effective behaviour be determined by the other planes which happen to be behind the cursor plane isn't usable for Wayland compositors.
>> Current behavior is just disable colorop for both background plane and cursor plane.
> 
> Are you saying the color pipeline is implicitly disabled for any KMS planes which happen to be overlapped by the cursor plane?
According to this mail, I think so(unless I mistook about the meaning 
again):
https://lists.freedesktop.org/archives/amd-gfx/2025-April/122257.html

> 
> That sounds like a no go.
> 
> 
>> I'm not sure how much planes does the hardware support, but if there are too less planes to use, maybe we still need to make use of the cursor background plane in the compositor.
> 
> If the HW has too few planes to allow both the cursor & overlay planes to work correctly (regardless of their dimensions), the driver should not allow enabling both kinds of planes at the same time.
> 
> 


[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 6977 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-03-31 18:53                         ` Xaver Hugl
  2025-04-01  0:28                           ` Alex Hung
@ 2025-04-01 15:45                           ` Melissa Wen
  2025-04-01 19:39                             ` Harry Wentland
  1 sibling, 1 reply; 128+ messages in thread
From: Melissa Wen @ 2025-04-01 15:45 UTC (permalink / raw)
  To: Xaver Hugl
  Cc: Alex Hung, Shengyu Qu, dri-devel, amd-gfx, wayland-devel,
	harry.wentland, leo.liu, ville.syrjala, pekka.paalanen, contact,
	jadahl, sebastian.wick, shashank.sharma, agoins, joshua, mdaenzer,
	aleixpol, victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

On 03/31, Xaver Hugl wrote:
> > Cursor plane has no color pipeline and thus it has no colorop either. It
> > inherits color processing from its parent plane.
> 
> Just to be sure: That means amdgpu will reject atomic commits that try
> to set a color pipeline on the primary plane while showing the cursor
> plane on top of it? Just like with scaling?

Isn't AMD driver resorting to overlay cursor mode when scaling?

In addition, isn't it a case of using overlay cursor mode when setting a
color pipeline for cursor?

Melissa

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-04-01 14:11                             ` Michel Dänzer
  2025-04-01 15:45                               ` Shengyu Qu
@ 2025-04-01 16:24                               ` Shengyu Qu
  1 sibling, 0 replies; 128+ messages in thread
From: Shengyu Qu @ 2025-04-01 16:24 UTC (permalink / raw)
  To: Michel Dänzer, Alex Hung, dri-devel, amd-gfx
  Cc: wiagn233, wayland-devel, harry.wentland, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, aleixpol, xaver.hugl, victoria,
	daniel, uma.shankar, quic_naseer, quic_cbraga, quic_abhinavk,
	marcan, Liviu.Dudau, sashamcintosh, chaitanya.kumar.borah,
	louis.chauvet


[-- Attachment #1.1.1: Type: text/plain, Size: 2447 bytes --]



在 2025/4/1 22:11, Michel Dänzer 写道:
> On 2025-04-01 14:32, Shengyu Qu wrote:
>> 在 2025/4/1 17:56, Michel Dänzer 写道:
>>> On 2025-03-31 19:42, Alex Hung wrote:
>>>> On 3/31/25 11:04, Shengyu Qu wrote:
>>>>> Or we can add some kind of "linked with" info to plane's COLOR_PIPELINE property, to let userspace know that cursor plane and background plane share the same colorop config. So that userspace could do extra conversion on cursor image data to avoid display wrong cursor color.
>>>>
>>>> That's over-complicate and makes little sense for both device drivers and userspace applications.
>>>>
>>>> If any planes share same colorop config, a device driver exposes the same color pipeline with the same colorops.
>>>>
>>>> If a plane does not support color pipeline or a driver doesn't want to support it, there is no color pipeline and no color objects.
>>>
>>> I suspect using the cursor plane is generally higher priority for Wayland compositors than using overlay planes, because the former is critical for a responsive user experience.
>>>
>>> This requires that the amdgpu DC driver backs the cursor plane with a dedicated HW plane though (as it's already doing in some cases), to either fully support color pipelines for the cursor plane, or at least provide proper "no color pipeline" behaviour for it. Letting the effective behaviour be determined by the other planes which happen to be behind the cursor plane isn't usable for Wayland compositors.
>> Current behavior is just disable colorop for both background plane and cursor plane.
> 
> Are you saying the color pipeline is implicitly disabled for any KMS planes which happen to be overlapped by the cursor plane?
Forget about my previous mail. Background plane means the parent plane 
of cursor plane, which is described here:
https://docs.kernel.org/next/gpu/amdgpu/display/mpo-overview.html
Not mean the plane that is overlapped by cursor plane, since only one 
plane is affected by cursor plane.

> 
> That sounds like a no go.
> 
> 
>> I'm not sure how much planes does the hardware support, but if there are too less planes to use, maybe we still need to make use of the cursor background plane in the compositor.
> 
> If the HW has too few planes to allow both the cursor & overlay planes to work correctly (regardless of their dimensions), the driver should not allow enabling both kinds of planes at the same time.
> 
> 


[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 6977 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-04-01 15:45                           ` Melissa Wen
@ 2025-04-01 19:39                             ` Harry Wentland
  0 siblings, 0 replies; 128+ messages in thread
From: Harry Wentland @ 2025-04-01 19:39 UTC (permalink / raw)
  To: Melissa Wen, Xaver Hugl
  Cc: Alex Hung, Shengyu Qu, dri-devel, amd-gfx, wayland-devel, leo.liu,
	ville.syrjala, pekka.paalanen, contact, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, victoria,
	daniel, uma.shankar, quic_naseer, quic_cbraga, quic_abhinavk,
	marcan, Liviu.Dudau, sashamcintosh, chaitanya.kumar.borah,
	louis.chauvet



On 2025-04-01 11:45, Melissa Wen wrote:
> On 03/31, Xaver Hugl wrote:
>>> Cursor plane has no color pipeline and thus it has no colorop either. It
>>> inherits color processing from its parent plane.
>>
>> Just to be sure: That means amdgpu will reject atomic commits that try
>> to set a color pipeline on the primary plane while showing the cursor
>> plane on top of it? Just like with scaling?
> 
> Isn't AMD driver resorting to overlay cursor mode when scaling?
> 
> In addition, isn't it a case of using overlay cursor mode when setting a
> color pipeline for cursor?
> 

Yes, AMD driver is using the overlay cursor (entire dedicated
HW pipe) for the cursor when the cursor scaling doesn't match
the underlying plane.

The same thing can be done for color operations but it's not
implemented yet.

Harry

> Melissa


^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-04-01 15:45                               ` Shengyu Qu
@ 2025-04-01 19:45                                 ` Harry Wentland
  2025-04-02  3:47                                   ` Qu Shengyu
  0 siblings, 1 reply; 128+ messages in thread
From: Harry Wentland @ 2025-04-01 19:45 UTC (permalink / raw)
  To: Shengyu Qu, Michel Dänzer, Alex Hung, dri-devel, amd-gfx
  Cc: wayland-devel, leo.liu, ville.syrjala, pekka.paalanen, contact,
	mwen, jadahl, sebastian.wick, shashank.sharma, agoins, joshua,
	aleixpol, xaver.hugl, victoria, daniel, uma.shankar, quic_naseer,
	quic_cbraga, quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet



On 2025-04-01 11:45, Shengyu Qu wrote:
> 
> 
> 在 2025/4/1 22:11, Michel Dänzer 写道:
>> On 2025-04-01 14:32, Shengyu Qu wrote:
>>> 在 2025/4/1 17:56, Michel Dänzer 写道:
>>>> On 2025-03-31 19:42, Alex Hung wrote:
>>>>> On 3/31/25 11:04, Shengyu Qu wrote:
>>>>>> Or we can add some kind of "linked with" info to plane's COLOR_PIPELINE property, to let userspace know that cursor plane and background plane share the same colorop config. So that userspace could do extra conversion on cursor image data to avoid display wrong cursor color.
>>>>>
>>>>> That's over-complicate and makes little sense for both device drivers and userspace applications.
>>>>>
>>>>> If any planes share same colorop config, a device driver exposes the same color pipeline with the same colorops.
>>>>>
>>>>> If a plane does not support color pipeline or a driver doesn't want to support it, there is no color pipeline and no color objects.
>>>>
>>>> I suspect using the cursor plane is generally higher priority for Wayland compositors than using overlay planes, because the former is critical for a responsive user experience.
>>>>
>>>> This requires that the amdgpu DC driver backs the cursor plane with a dedicated HW plane though (as it's already doing in some cases), to either fully support color pipelines for the cursor plane, or at least provide proper "no color pipeline" behaviour for it. Letting the effective behaviour be determined by the other planes which happen to be behind the cursor plane isn't usable for Wayland compositors.
>>> Current behavior is just disable colorop for both background plane and cursor plane.
>>
>> Are you saying the color pipeline is implicitly disabled for any KMS planes which happen to be overlapped by the cursor plane?
> According to this mail, I think so(unless I mistook about the meaning again):
> https://lists.freedesktop.org/archives/amd-gfx/2025-April/122257.html
> 

No, that's not what this is saying.

What this says is that when a compositor tries to enable
an color pipeline on a plane on AMD HW and a cursor on
top of that plane the driver will reject that commit.

A compositor can then either not set a color pipeline,
or not set the cursor plane.

There's no "implicit disabling" going on. Everything is 
explicit.

I'm having a hard time trying to understand where your
questions are coming from. Are you implementing a compositor?
Are you trying to build a power-efficient system using AMD
HW? Something else? If you could expand on that it might help
us answer them better.

Harry

>>
>> That sounds like a no go.
>>
>>
>>> I'm not sure how much planes does the hardware support, but if there are too less planes to use, maybe we still need to make use of the cursor background plane in the compositor.
>>
>> If the HW has too few planes to allow both the cursor & overlay planes to work correctly (regardless of their dimensions), the driver should not allow enabling both kinds of planes at the same time.
>>
>>
> 


^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 06/43] drm/colorop: Add 1D Curve subtype
  2025-04-01 15:14   ` Daniel Stone
@ 2025-04-01 19:53     ` Simon Ser
  2025-04-01 21:02       ` Harry Wentland
  2025-04-08 16:40       ` Daniel Stone
  0 siblings, 2 replies; 128+ messages in thread
From: Simon Ser @ 2025-04-01 19:53 UTC (permalink / raw)
  To: Daniel Stone
  Cc: Alex Hung, dri-devel, amd-gfx, wayland-devel, harry.wentland,
	leo.liu, ville.syrjala, pekka.paalanen, mwen, jadahl,
	sebastian.wick, shashank.sharma, agoins, joshua, mdaenzer,
	aleixpol, xaver.hugl, victoria, daniel, uma.shankar, quic_naseer,
	quic_cbraga, quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet






On Tuesday, April 1st, 2025 at 17:14, Daniel Stone <daniel@fooishbar.org> wrote:

> 
> 
> Hi Alex,
> 
> On Wed, 26 Mar 2025 at 23:50, Alex Hung alex.hung@amd.com wrote:
> 
> > +static int drm_colorop_init(struct drm_device *dev, struct drm_colorop *colorop,
> > + struct drm_plane *plane, enum drm_colorop_type type)
> > +{
> > + struct drm_mode_config *config = &dev->mode_config;
> > + struct drm_property *prop;
> > + int ret = 0;
> > +
> > + ret = drm_mode_object_add(dev, &colorop->base, DRM_MODE_OBJECT_COLOROP);
> > + if (ret)
> > + return ret;
> > +
> > + colorop->base.properties = &colorop->properties;
> > + colorop->dev = dev;
> > + colorop->type = type;
> > + colorop->plane = plane;
> 
> 'plane' seems really incongruous here. The colorop can be created for
> any number of planes, but we're setting it to always be bound to a
> single plane at init, and that can only be changed later.

I don't think the current design allows a single colorop to be re-used
between planes? I think as-is, drivers create one set of colorops per
plane and never share them between different planes?

> 1. Is it guaranteed that, if any plane on a device supports the
> COLOR_PIPELINE property, all planes will support COLOR_PIPELINE?
> (Given the amdgpu cursor-plane discussion, it looks like no, which is
> unfortunate but oh well.)

I don't think so. (They could all expose a COLOR_PIPELINE with the only
choice as the zero bypass pipeline, but that sounds silly.)

> 2. Is it guaranteed that, if a COLOR_PIPELINE property exists on a
> plane, that BYPASS will be one of the supported values? (The current
> implementation does this, which seems sensible, but if the plan is to
> not make this a uAPI invariant, e.g. to support planes with mandatory
> CM steps, this should probably be explicitly documented.)

Yes. This is a hard requirement, mentioned in the design doc IIRC.

> 3. Can a given color pipeline potentially be used on different planes,
> i.e. a colorop used to represent a separate hardware processing block
> which may be used on any plane but only one plane at a time? (This
> should be documented either way, and if they are unique per plane, igt
> should enforce this.)

Right now, I don't think so. Could be a future extension I suppose, but
I think we need to properly sit down and think about all of the possible
consequences. Maybe using the same pipeline ID isn't the best uAPI here.

> 3. Can a given color pipeline be active on multiple planes at a time?
> (If so, the implementation definitely needs rethinking: the colorop
> would need to have a list of planes.)

I don't think so.

> 4. Can a given color pipeline be active on multiple planes on multiple
> CRTCs at a time?

Ditto.

> 5. For a given colorop property, is it an invariant that the colorop
> will only appear in one color pipeline at a time? (I believe so, but
> this probably needs documenting and/or igt.)

I don't really understand why that would matter to user-space.

> Either way, I suspect that clorop->plane is the wrong thing to do, and
> that it maybe wants to be a list of planes in the drm_colorop_state?

I don't think so, for a given plane, there can only be a single pipeline
active at a time.

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 06/43] drm/colorop: Add 1D Curve subtype
  2025-04-01 19:53     ` Simon Ser
@ 2025-04-01 21:02       ` Harry Wentland
  2025-04-08 16:40       ` Daniel Stone
  1 sibling, 0 replies; 128+ messages in thread
From: Harry Wentland @ 2025-04-01 21:02 UTC (permalink / raw)
  To: Simon Ser, Daniel Stone
  Cc: Alex Hung, dri-devel, amd-gfx, wayland-devel, leo.liu,
	ville.syrjala, pekka.paalanen, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet



On 2025-04-01 15:53, Simon Ser wrote:
> 
> 
> 
> 
> 
> On Tuesday, April 1st, 2025 at 17:14, Daniel Stone <daniel@fooishbar.org> wrote:
> 
>>
>>
>> Hi Alex,
>>
>> On Wed, 26 Mar 2025 at 23:50, Alex Hung alex.hung@amd.com wrote:
>>
>>> +static int drm_colorop_init(struct drm_device *dev, struct drm_colorop *colorop,
>>> + struct drm_plane *plane, enum drm_colorop_type type)
>>> +{
>>> + struct drm_mode_config *config = &dev->mode_config;
>>> + struct drm_property *prop;
>>> + int ret = 0;
>>> +
>>> + ret = drm_mode_object_add(dev, &colorop->base, DRM_MODE_OBJECT_COLOROP);
>>> + if (ret)
>>> + return ret;
>>> +
>>> + colorop->base.properties = &colorop->properties;
>>> + colorop->dev = dev;
>>> + colorop->type = type;
>>> + colorop->plane = plane;
>>
>> 'plane' seems really incongruous here. The colorop can be created for
>> any number of planes, but we're setting it to always be bound to a
>> single plane at init, and that can only be changed later.
> 
> I don't think the current design allows a single colorop to be re-used
> between planes? I think as-is, drivers create one set of colorops per
> plane and never share them between different planes?
> 

Yeah, with the current design a colorop always belongs to a plane.

In the future when we introduce crtc colorops they could be
associated with a single crtc instead.

>> 1. Is it guaranteed that, if any plane on a device supports the
>> COLOR_PIPELINE property, all planes will support COLOR_PIPELINE?
>> (Given the amdgpu cursor-plane discussion, it looks like no, which is
>> unfortunate but oh well.)
> 
> I don't think so. (They could all expose a COLOR_PIPELINE with the only
> choice as the zero bypass pipeline, but that sounds silly.)
> 

Correct.

>> 2. Is it guaranteed that, if a COLOR_PIPELINE property exists on a
>> plane, that BYPASS will be one of the supported values? (The current
>> implementation does this, which seems sensible, but if the plan is to
>> not make this a uAPI invariant, e.g. to support planes with mandatory
>> CM steps, this should probably be explicitly documented.)
> 
> Yes. This is a hard requirement, mentioned in the design doc IIRC.
> 

If this wasn't the case then those pipes would be doing undefined
things with current implementations.

>> 3. Can a given color pipeline potentially be used on different planes,
>> i.e. a colorop used to represent a separate hardware processing block
>> which may be used on any plane but only one plane at a time? (This
>> should be documented either way, and if they are unique per plane, igt
>> should enforce this.)
> 
> Right now, I don't think so. Could be a future extension I suppose, but
> I think we need to properly sit down and think about all of the possible
> consequences. Maybe using the same pipeline ID isn't the best uAPI here.
> 

I think it'd be easier to tie a colorop to a single pipeline, which is
tied to a single plane. I'd imagine HW is rarely designed to allow
arbitrary routing of individual HW blocks. Muxes are costly.

>> 3. Can a given color pipeline be active on multiple planes at a time?
>> (If so, the implementation definitely needs rethinking: the colorop
>> would need to have a list of planes.)
> 
> I don't think so.
> 

It's tied specifically to a single plane.

Harry

>> 4. Can a given color pipeline be active on multiple planes on multiple
>> CRTCs at a time?
> 
> Ditto.
> 
>> 5. For a given colorop property, is it an invariant that the colorop
>> will only appear in one color pipeline at a time? (I believe so, but
>> this probably needs documenting and/or igt.)
> 
> I don't really understand why that would matter to user-space.
> 
>> Either way, I suspect that clorop->plane is the wrong thing to do, and
>> that it maybe wants to be a list of planes in the drm_colorop_state?
> 
> I don't think so, for a given plane, there can only be a single pipeline
> active at a time.


^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane
  2025-04-01 19:45                                 ` Harry Wentland
@ 2025-04-02  3:47                                   ` Qu Shengyu
  0 siblings, 0 replies; 128+ messages in thread
From: Qu Shengyu @ 2025-04-02  3:47 UTC (permalink / raw)
  To: Harry Wentland
  Cc: Michel Dänzer, Alex Hung, dri-devel@lists.freedesktop.org,
	amd-gfx@lists.freedesktop.org,
	wayland-devel@lists.freedesktop.org, leo.liu@amd.com,
	ville.syrjala@linux.intel.com, pekka.paalanen@collabora.com,
	contact@emersion.fr, mwen@igalia.com, jadahl@redhat.com,
	sebastian.wick@redhat.com, shashank.sharma@amd.com,
	agoins@nvidia.com, joshua@froggi.es, aleixpol@kde.org,
	xaver.hugl@gmail.com, victoria@system76.com, daniel@ffwll.ch,
	uma.shankar@intel.com, quic_naseer@quicinc.com,
	quic_cbraga@quicinc.com, quic_abhinavk@quicinc.com,
	marcan@marcan.st, liviu.dudau@arm.com, sashamcintosh@google.com,
	chaitanya.kumar.borah@intel.com, louis.chauvet@bootlin.com

Hi,

Thanks for reply. It solves my question. Seems it’s not clearly described in the document. Maybe you can add more information to documentation in next version of patch?


> 在 2025年4月2日,03:45,Harry Wentland <harry.wentland@amd.com> 写道:
> 
> 
> On 2025-04-01 11:45, Shengyu Qu wrote:
>> 
>> 
>> 在 2025/4/1 22:11, Michel Dänzer 写道:
>>> On 2025-04-01 14:32, Shengyu Qu wrote:
>>>> 在 2025/4/1 17:56, Michel Dänzer 写道:
>>>>> On 2025-03-31 19:42, Alex Hung wrote:
>>>>>> On 3/31/25 11:04, Shengyu Qu wrote:
>>>>>>> Or we can add some kind of "linked with" info to plane's COLOR_PIPELINE property, to let userspace know that cursor plane and background plane share the same colorop config. So that userspace could do extra conversion on cursor image data to avoid display wrong cursor color.
>>>>>> That's over-complicate and makes little sense for both device drivers and userspace applications.
>>>>>> If any planes share same colorop config, a device driver exposes the same color pipeline with the same colorops.
>>>>>> If a plane does not support color pipeline or a driver doesn't want to support it, there is no color pipeline and no color objects.
>>>>> I suspect using the cursor plane is generally higher priority for Wayland compositors than using overlay planes, because the former is critical for a responsive user experience.
>>>>> This requires that the amdgpu DC driver backs the cursor plane with a dedicated HW plane though (as it's already doing in some cases), to either fully support color pipelines for the cursor plane, or at least provide proper "no color pipeline" behaviour for it. Letting the effective behaviour be determined by the other planes which happen to be behind the cursor plane isn't usable for Wayland compositors.
>>>> Current behavior is just disable colorop for both background plane and cursor plane.
>>> Are you saying the color pipeline is implicitly disabled for any KMS planes which happen to be overlapped by the cursor plane?
>> According to this mail, I think so(unless I mistook about the meaning again):
>> https://lists.freedesktop.org/archives/amd-gfx/2025-April/122257.html
> 
> No, that's not what this is saying.
> 
> What this says is that when a compositor tries to enable
> an color pipeline on a plane on AMD HW and a cursor on
> top of that plane the driver will reject that commit.
> 
> A compositor can then either not set a color pipeline,
> or not set the cursor plane.
> 
> There's no "implicit disabling" going on. Everything is
> explicit.
> 
> I'm having a hard time trying to understand where your
> questions are coming from. Are you implementing a compositor?
> Are you trying to build a power-efficient system using AMD
> HW? Something else? If you could expand on that it might help
> us answer them better.
The question basically comes from I hope that all planes(including cursor’s parent plane)could use hw colorop to reduce power consumption. But current code implementation won’t support applying colorop to cursor’s parent plane.

That “linked with” I mentioned in previous email is a try to come up with a solution for this issue.

Best regards,
Shengyu 

> 
> Harry
> 
>>> That sounds like a no go.
>>>> I'm not sure how much planes does the hardware support, but if there are too less planes to use, maybe we still need to make use of the cursor background plane in the compositor.
>>> If the HW has too few planes to allow both the cursor & overlay planes to work correctly (regardless of their dimensions), the driver should not allow enabling both kinds of planes at the same time.

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 06/43] drm/colorop: Add 1D Curve subtype
  2025-04-01 19:53     ` Simon Ser
  2025-04-01 21:02       ` Harry Wentland
@ 2025-04-08 16:40       ` Daniel Stone
  2025-04-08 17:30         ` Harry Wentland
                           ` (2 more replies)
  1 sibling, 3 replies; 128+ messages in thread
From: Daniel Stone @ 2025-04-08 16:40 UTC (permalink / raw)
  To: Simon Ser
  Cc: Alex Hung, dri-devel, amd-gfx, wayland-devel, harry.wentland,
	leo.liu, ville.syrjala, pekka.paalanen, mwen, jadahl,
	sebastian.wick, shashank.sharma, agoins, joshua, mdaenzer,
	aleixpol, xaver.hugl, victoria, daniel, uma.shankar, quic_naseer,
	quic_cbraga, quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

Hi there,

On Tue, 1 Apr 2025 at 20:53, Simon Ser <contact@emersion.fr> wrote:
> On Tuesday, April 1st, 2025 at 17:14, Daniel Stone <daniel@fooishbar.org> wrote:
> > 'plane' seems really incongruous here. The colorop can be created for
> > any number of planes, but we're setting it to always be bound to a
> > single plane at init, and that can only be changed later.
>
> I don't think the current design allows a single colorop to be re-used
> between planes? I think as-is, drivers create one set of colorops per
> plane and never share them between different planes?

OK, Harry's reply cleared that up perfectly - the flexibility that's
there at the moment is about being able to reuse colorops for CRTCs in
post-blend ops (great!), not shared between planes.

> > 1. Is it guaranteed that, if any plane on a device supports the
> > COLOR_PIPELINE property, all planes will support COLOR_PIPELINE?
> > (Given the amdgpu cursor-plane discussion, it looks like no, which is
> > unfortunate but oh well.)
>
> I don't think so. (They could all expose a COLOR_PIPELINE with the only
> choice as the zero bypass pipeline, but that sounds silly.)

Works for me: so any planes could not have colour pipelines, and the
result would be undefined (well, less defined) colour.

> > 2. Is it guaranteed that, if a COLOR_PIPELINE property exists on a
> > plane, that BYPASS will be one of the supported values? (The current
> > implementation does this, which seems sensible, but if the plan is to
> > not make this a uAPI invariant, e.g. to support planes with mandatory
> > CM steps, this should probably be explicitly documented.)
>
> Yes. This is a hard requirement, mentioned in the design doc IIRC.

Nice. I guess that's kind of implicit given pre-colorop behaviour
expectations. We'd probably need a client cap analogous to universal
planes to expose planes with mandatory colorop steps. This should
probably be enforced with igt.

> > 3. Can a given color pipeline potentially be used on different planes,
> > i.e. a colorop used to represent a separate hardware processing block
> > which may be used on any plane but only one plane at a time? (This
> > should be documented either way, and if they are unique per plane, igt
> > should enforce this.)
>
> Right now, I don't think so. Could be a future extension I suppose, but
> I think we need to properly sit down and think about all of the possible
> consequences. Maybe using the same pipeline ID isn't the best uAPI here.

I'm with you on this. I think if we were trying to express a single
color-transformation block which was shared between multiple planes
(MTK is probably the closest to this conceptually from what I've
seen), having an immutable COLOR_PIPELINE_SHARED = { ids... } property
would be the best way to achieve this.

> > 3. Can a given color pipeline be active on multiple planes at a time?
> > (If so, the implementation definitely needs rethinking: the colorop
> > would need to have a list of planes.)
>
> I don't think so.

Great. But probably needs igt.

> > 4. Can a given color pipeline be active on multiple planes on multiple
> > CRTCs at a time?
>
> Ditto.

Ditto.

> > 5. For a given colorop property, is it an invariant that the colorop
> > will only appear in one color pipeline at a time? (I believe so, but
> > this probably needs documenting and/or igt.)
>
> I don't really understand why that would matter to user-space.

Plane A: COLOR_PIPELINE@123 = { 1D_CURVE@456 }
Plane B: COLOR_PIPELINE@789 = { 1D_CURVE@456 }

If userspace wasn't defensive about this, it would program the curve
for 456 twice, and unless they were the same you'd get undesirable
results.

The existing implementation is fine here, I think it just needs better
igt to codify the expectations we all have.

> > Either way, I suspect that clorop->plane is the wrong thing to do, and
> > that it maybe wants to be a list of planes in the drm_colorop_state?
>
> I don't think so, for a given plane, there can only be a single pipeline
> active at a time.

Yeah, again that was just not having grasped that the colorop not
being derived from the plane was actually about allowing for it to be
attached to a single CRTC instead, rather than potentially multiple
planes. I have no concerns around this.

As it stands, I've gone through the implementation pretty thoroughly,
as well as our use of it in Weston. I'm happy with how it looks for
pre-blend, and I'm even happier that the implementation is written to
apply easily to apply to post-blend CRTC pipelines.

With the suggested uAPI doc fixes and igt additions, this series is:
Reviewed-by: Daniel Stone <daniels@collabora.com>

Thanks everyone for the immense amount of work that's gone into this. :)

Cheers,
Daniel

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 06/43] drm/colorop: Add 1D Curve subtype
  2025-04-08 16:40       ` Daniel Stone
@ 2025-04-08 17:30         ` Harry Wentland
  2025-04-08 18:28           ` Daniel Stone
  2025-04-10  7:53           ` Pipeline vs. no pipeline (Re: [PATCH V8 06/43] drm/colorop: Add 1D Curve subtype) Pekka Paalanen
  2025-04-10 10:05         ` [PATCH V8 06/43] drm/colorop: Add 1D Curve subtype Simon Ser
  2025-04-15 11:12         ` Borah, Chaitanya Kumar
  2 siblings, 2 replies; 128+ messages in thread
From: Harry Wentland @ 2025-04-08 17:30 UTC (permalink / raw)
  To: Daniel Stone, Simon Ser
  Cc: Alex Hung, dri-devel, amd-gfx, wayland-devel, leo.liu,
	ville.syrjala, pekka.paalanen, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet



On 2025-04-08 12:40, Daniel Stone wrote:
> Hi there,
> 
> On Tue, 1 Apr 2025 at 20:53, Simon Ser <contact@emersion.fr> wrote:
>> On Tuesday, April 1st, 2025 at 17:14, Daniel Stone <daniel@fooishbar.org> wrote:
>>> 'plane' seems really incongruous here. The colorop can be created for
>>> any number of planes, but we're setting it to always be bound to a
>>> single plane at init, and that can only be changed later.
>>
>> I don't think the current design allows a single colorop to be re-used
>> between planes? I think as-is, drivers create one set of colorops per
>> plane and never share them between different planes?
> 
> OK, Harry's reply cleared that up perfectly - the flexibility that's
> there at the moment is about being able to reuse colorops for CRTCs in
> post-blend ops (great!), not shared between planes.
> 

Just to make sure we're talking about the same thing:

The design intent is to allow drm_colorops on a crtc (once we implement
that), not to be able to share the same drm_colorop between a plane and
crtc.

>>> 1. Is it guaranteed that, if any plane on a device supports the
>>> COLOR_PIPELINE property, all planes will support COLOR_PIPELINE?
>>> (Given the amdgpu cursor-plane discussion, it looks like no, which is
>>> unfortunate but oh well.)
>>
>> I don't think so. (They could all expose a COLOR_PIPELINE with the only
>> choice as the zero bypass pipeline, but that sounds silly.)
> 
> Works for me: so any planes could not have colour pipelines, and the
> result would be undefined (well, less defined) colour.

Yes, basically it would be what we have now (without color pipelines).

> 
>>> 2. Is it guaranteed that, if a COLOR_PIPELINE property exists on a
>>> plane, that BYPASS will be one of the supported values? (The current
>>> implementation does this, which seems sensible, but if the plan is to
>>> not make this a uAPI invariant, e.g. to support planes with mandatory
>>> CM steps, this should probably be explicitly documented.)
>>
>> Yes. This is a hard requirement, mentioned in the design doc IIRC.
> 
> Nice. I guess that's kind of implicit given pre-colorop behaviour
> expectations. We'd probably need a client cap analogous to universal
> planes to expose planes with mandatory colorop steps. This should
> probably be enforced with igt.
> 

Yes.

The API allows for the option of non-bypassable individual
colorops, but the pipeline as a whole must support bypass
currently.

>>> 3. Can a given color pipeline potentially be used on different planes,
>>> i.e. a colorop used to represent a separate hardware processing block
>>> which may be used on any plane but only one plane at a time? (This
>>> should be documented either way, and if they are unique per plane, igt
>>> should enforce this.)
>>
>> Right now, I don't think so. Could be a future extension I suppose, but
>> I think we need to properly sit down and think about all of the possible
>> consequences. Maybe using the same pipeline ID isn't the best uAPI here.
> 
> I'm with you on this. I think if we were trying to express a single
> color-transformation block which was shared between multiple planes
> (MTK is probably the closest to this conceptually from what I've
> seen), having an immutable COLOR_PIPELINE_SHARED = { ids... } property
> would be the best way to achieve this.
> 
>>> 3. Can a given color pipeline be active on multiple planes at a time?
>>> (If so, the implementation definitely needs rethinking: the colorop
>>> would need to have a list of planes.)
>>
>> I don't think so.
> 
> Great. But probably needs igt.
> 

Right, otherwise a driver dev might implement colorops in a way that
breaks this. Though, if DRM helpers are used it should be fairly safe,
I would think.

>>> 4. Can a given color pipeline be active on multiple planes on multiple
>>> CRTCs at a time?
>>
>> Ditto.
> 
> Ditto.
> 
>>> 5. For a given colorop property, is it an invariant that the colorop
>>> will only appear in one color pipeline at a time? (I believe so, but
>>> this probably needs documenting and/or igt.)
>>
>> I don't really understand why that would matter to user-space.
> 
> Plane A: COLOR_PIPELINE@123 = { 1D_CURVE@456 }
> Plane B: COLOR_PIPELINE@789 = { 1D_CURVE@456 }
> 

Yeah, a simple IGT test that parses all color pipelines and checks
that colorops don't occur in multiple pipelines is needed.

> If userspace wasn't defensive about this, it would program the curve
> for 456 twice, and unless they were the same you'd get undesirable
> results.
> 
> The existing implementation is fine here, I think it just needs better
> igt to codify the expectations we all have.
> 
>>> Either way, I suspect that clorop->plane is the wrong thing to do, and
>>> that it maybe wants to be a list of planes in the drm_colorop_state?
>>
>> I don't think so, for a given plane, there can only be a single pipeline
>> active at a time.
> 
> Yeah, again that was just not having grasped that the colorop not
> being derived from the plane was actually about allowing for it to be
> attached to a single CRTC instead, rather than potentially multiple
> planes. I have no concerns around this.
> 
> As it stands, I've gone through the implementation pretty thoroughly,
> as well as our use of it in Weston. I'm happy with how it looks for
> pre-blend, and I'm even happier that the implementation is written to
> apply easily to apply to post-blend CRTC pipelines.
> 
> With the suggested uAPI doc fixes and igt additions, this series is:
> Reviewed-by: Daniel Stone <daniels@collabora.com>
> 
> Thanks everyone for the immense amount of work that's gone into this. :)
> 

Thanks, Daniel. It wouldn't have been possible without the help
from many. And the hackfests really helped.

Harry

> Cheers,
> Daniel


^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 06/43] drm/colorop: Add 1D Curve subtype
  2025-04-08 17:30         ` Harry Wentland
@ 2025-04-08 18:28           ` Daniel Stone
  2025-04-10  7:53           ` Pipeline vs. no pipeline (Re: [PATCH V8 06/43] drm/colorop: Add 1D Curve subtype) Pekka Paalanen
  1 sibling, 0 replies; 128+ messages in thread
From: Daniel Stone @ 2025-04-08 18:28 UTC (permalink / raw)
  To: Harry Wentland
  Cc: Simon Ser, Alex Hung, dri-devel, amd-gfx, wayland-devel, leo.liu,
	ville.syrjala, pekka.paalanen, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

Hi Harry,

On Tue, 8 Apr 2025 at 18:30, Harry Wentland <harry.wentland@amd.com> wrote:
> On 2025-04-08 12:40, Daniel Stone wrote:
> > OK, Harry's reply cleared that up perfectly - the flexibility that's
> > there at the moment is about being able to reuse colorops for CRTCs in
> > post-blend ops (great!), not shared between planes.
>
> Just to make sure we're talking about the same thing:
>
> The design intent is to allow drm_colorops on a crtc (once we implement
> that), not to be able to share the same drm_colorop between a plane and
> crtc.

Right, that's my understanding here.

Cheers,
Daniel

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Pipeline vs. no pipeline (Re: [PATCH V8 06/43] drm/colorop: Add 1D Curve subtype)
  2025-04-08 17:30         ` Harry Wentland
  2025-04-08 18:28           ` Daniel Stone
@ 2025-04-10  7:53           ` Pekka Paalanen
  2025-04-15 15:29             ` Harry Wentland
  1 sibling, 1 reply; 128+ messages in thread
From: Pekka Paalanen @ 2025-04-10  7:53 UTC (permalink / raw)
  To: Harry Wentland
  Cc: Daniel Stone, Simon Ser, Alex Hung, dri-devel, amd-gfx,
	wayland-devel, leo.liu, ville.syrjala, mwen, jadahl,
	sebastian.wick, shashank.sharma, agoins, joshua, mdaenzer,
	aleixpol, xaver.hugl, victoria, daniel, uma.shankar, quic_naseer,
	quic_cbraga, quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

[-- Attachment #1: Type: text/plain, Size: 2407 bytes --]

On Tue, 8 Apr 2025 13:30:46 -0400
Harry Wentland <harry.wentland@amd.com> wrote:

> On 2025-04-08 12:40, Daniel Stone wrote:
> > Hi there,
> > 
> > On Tue, 1 Apr 2025 at 20:53, Simon Ser <contact@emersion.fr> wrote:  
> >> On Tuesday, April 1st, 2025 at 17:14, Daniel Stone <daniel@fooishbar.org> wrote:  

...

> >>> 1. Is it guaranteed that, if any plane on a device supports the
> >>> COLOR_PIPELINE property, all planes will support COLOR_PIPELINE?
> >>> (Given the amdgpu cursor-plane discussion, it looks like no, which is
> >>> unfortunate but oh well.)  
> >>
> >> I don't think so. (They could all expose a COLOR_PIPELINE with the only
> >> choice as the zero bypass pipeline, but that sounds silly.)  
> > 
> > Works for me: so any planes could not have colour pipelines, and the
> > result would be undefined (well, less defined) colour.  
> 
> Yes, basically it would be what we have now (without color pipelines).

Hi,

I see Alex wrote:

> In order to support YUV we'll need to add COLOR_ENCODING and COLOR_RANGE
> support to the color pipeline. I have sketched these out already but
> don't have it all hooked up yet. This should not hinder adoption of this
> API for gaming use-cases.

Was it considered to be able to lift the full-range RGB restriction
from the color pipelines, eventually leading to the possibility of
scanning out limited-range YCbCr bit-identical, giving userspace access
to the sub-black and super-white ranges for e.g. BT.814 purposes?

These questions are pointing in the direction of a bypass
COLOR_PIPELINE being different from no COLOR_PIPELINE. I assume a
bypass pipeline needs to shovel values through unchanged, while
"without color pipelines" would need the old COLOR_ENCODING and
COLOR_RANGE properties.

That reminds me of yet another question: if the framebuffer is limited
range, and it's not converted to full-range at the start of a color
pipeline, how will the sub-black and super-white ranges be represented?
Will they be negative and greater than 1.0 values, respectively? This
would be meaningful for the colorops being defined now, as I assume
people might implicitly limit their thinking to the [0.0, 1.0] range,
or at least exclude negative values.

The 3x4 CTM colorop is not yet explicit on whether it clamps its inputs
or outputs. Should all colorops be explicit about it?


Thanks,
pq

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 06/43] drm/colorop: Add 1D Curve subtype
  2025-04-08 16:40       ` Daniel Stone
  2025-04-08 17:30         ` Harry Wentland
@ 2025-04-10 10:05         ` Simon Ser
  2025-04-15 11:12         ` Borah, Chaitanya Kumar
  2 siblings, 0 replies; 128+ messages in thread
From: Simon Ser @ 2025-04-10 10:05 UTC (permalink / raw)
  To: Daniel Stone
  Cc: Alex Hung, dri-devel, amd-gfx, wayland-devel, harry.wentland,
	leo.liu, ville.syrjala, pekka.paalanen, mwen, jadahl,
	sebastian.wick, shashank.sharma, agoins, joshua, mdaenzer,
	aleixpol, xaver.hugl, victoria, daniel, uma.shankar, quic_naseer,
	quic_cbraga, quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

On Tuesday, April 8th, 2025 at 18:40, Daniel Stone <daniel@fooishbar.org> wrote:

> > > 5. For a given colorop property, is it an invariant that the colorop
> > > will only appear in one color pipeline at a time? (I believe so, but
> > > this probably needs documenting and/or igt.)
> > 
> > I don't really understand why that would matter to user-space.
> 
> Plane A: COLOR_PIPELINE@123 = { 1D_CURVE@456 }
> Plane B: COLOR_PIPELINE@789 = { 1D_CURVE@456 }
> 
> If userspace wasn't defensive about this, it would program the curve
> for 456 twice, and unless they were the same you'd get undesirable
> results.
> 
> The existing implementation is fine here, I think it just needs better
> igt to codify the expectations we all have.

Oh right, the same pipeline can definitely not be used on two different
planes, because KMS properties are set on the colorop objects by
user-space to configure the pipeline.

> > > Either way, I suspect that clorop->plane is the wrong thing to do, and
> > > that it maybe wants to be a list of planes in the drm_colorop_state?
> > 
> > I don't think so, for a given plane, there can only be a single pipeline
> > active at a time.
> 
> Yeah, again that was just not having grasped that the colorop not
> being derived from the plane was actually about allowing for it to be
> attached to a single CRTC instead, rather than potentially multiple
> planes. I have no concerns around this.
> 
> As it stands, I've gone through the implementation pretty thoroughly,
> as well as our use of it in Weston. I'm happy with how it looks for
> pre-blend, and I'm even happier that the implementation is written to
> apply easily to apply to post-blend CRTC pipelines.

Sweet!

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 43/43] drm/colorop: Add destroy functions for color pipeline
  2025-04-01  2:42     ` Alex Hung
@ 2025-04-10 16:18       ` Simon Ser
  0 siblings, 0 replies; 128+ messages in thread
From: Simon Ser @ 2025-04-10 16:18 UTC (permalink / raw)
  To: Alex Hung
  Cc: dri-devel, amd-gfx, wayland-devel, harry.wentland, leo.liu,
	ville.syrjala, pekka.paalanen, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

On Tuesday, April 1st, 2025 at 04:42, Alex Hung <alex.hung@amd.com> wrote:

> On 3/29/25 09:48, Simon Ser wrote:
> 
> > I would prefer these functions to be introduced together with the
> > patches adding functions to create objects and adding the new fields.
> > That way it's easier to check the symmetry and at no point in the
> > series there are memory leaks.
> 
> The object creation and new fields are introduced in different patches.
> I divided this patch by introducing these functions in a patch, and 2.
> adding callers when needed to avoid memory leaks.

Could we introduce the destructor together with the function creating a
colorop, as a thin kfree() wrapper, and add cleanup for new fields in
that destructor in the same commit where the new fields are introduced?

> > Additionally, I would avoid using the name "cleanup", which seems to
> > have different semantics: for instance drm_plane_cleanup() doesn't kfree
> > the pointer. "destroy" seems more appropriate here.
> 
> How about the following changes, i.e., freeing pointer is moved out of
> the cleanup function, and keeping the names.

I don't really see the upside, because (1) the creator function allocates
(so there is an asymmetry between the creator and destructor) and (2) all
callers of the destructor function will always want to kfree(), but I'd be
fine with that.

^ permalink raw reply	[flat|nested] 128+ messages in thread

* RE: [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type
  2025-03-26 23:47 ` [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type Alex Hung
  2025-03-29 14:55   ` Simon Ser
@ 2025-04-15  6:09   ` Shankar, Uma
  2025-04-15  6:16     ` Simon Ser
  1 sibling, 1 reply; 128+ messages in thread
From: Shankar, Uma @ 2025-04-15  6:09 UTC (permalink / raw)
  To: Alex Hung, dri-devel@lists.freedesktop.org,
	amd-gfx@lists.freedesktop.org, intel-gfx@lists.freedesktop.org
  Cc: wayland-devel@lists.freedesktop.org, harry.wentland@amd.com,
	leo.liu@amd.com, ville.syrjala@linux.intel.com,
	pekka.paalanen@collabora.com, contact@emersion.fr,
	mwen@igalia.com, jadahl@redhat.com, sebastian.wick@redhat.com,
	shashank.sharma@amd.com, agoins@nvidia.com, joshua@froggi.es,
	mdaenzer@redhat.com, aleixpol@kde.org, xaver.hugl@gmail.com,
	victoria@system76.com, daniel@ffwll.ch, quic_naseer@quicinc.com,
	quic_cbraga@quicinc.com, quic_abhinavk@quicinc.com,
	marcan@marcan.st, Liviu.Dudau@arm.com, sashamcintosh@google.com,
	Borah, Chaitanya Kumar, louis.chauvet@bootlin.com



> -----Original Message-----
> From: Alex Hung <alex.hung@amd.com>
> Sent: Thursday, March 27, 2025 5:17 AM
> To: dri-devel@lists.freedesktop.org; amd-gfx@lists.freedesktop.org
> Cc: wayland-devel@lists.freedesktop.org; harry.wentland@amd.com;
> alex.hung@amd.com; leo.liu@amd.com; ville.syrjala@linux.intel.com;
> pekka.paalanen@collabora.com; contact@emersion.fr; mwen@igalia.com;
> jadahl@redhat.com; sebastian.wick@redhat.com; shashank.sharma@amd.com;
> agoins@nvidia.com; joshua@froggi.es; mdaenzer@redhat.com;
> aleixpol@kde.org; xaver.hugl@gmail.com; victoria@system76.com;
> daniel@ffwll.ch; Shankar, Uma <uma.shankar@intel.com>;
> quic_naseer@quicinc.com; quic_cbraga@quicinc.com;
> quic_abhinavk@quicinc.com; marcan@marcan.st; Liviu.Dudau@arm.com;
> sashamcintosh@google.com; Borah, Chaitanya Kumar
> <chaitanya.kumar.borah@intel.com>; louis.chauvet@bootlin.com
> Subject: [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type
> 
> We've previously introduced DRM_COLOROP_1D_CURVE for pre-defined 1D
> curves. But we also have HW that supports custom curves and userspace needs
> the ability to pass custom curves, aka LUTs.
> 
> This patch introduces a new colorop type, called DRM_COLOROP_1D_LUT that
> provides a SIZE property which is used by a driver to advertise the supported SIZE
> of the LUT, as well as a DATA property which userspace uses to set the LUT.
> 
> DATA and size function in the same way as current drm_crtc GAMMA and
> DEGAMMA LUTs.

Thanks Alex and Harry for driving this forward.
We want to have just one change in the way we expose the hardware capabilities else
all looks good in general.

To expose the capabilities of 1D Lut (of any kind), we can use a generic
implementation which covers the distribution of LUT samples along with size and
precision in a common color op. Something like below:

struct drm_color_lut_range {
	       __u32 flags;
	       __u16 count;
	       __s32 start, end;
	       __u32 norm_factor;

	       struct {
	               __u16 intp;
	               __u16 fracp;
	       } precision;
	};

The idea is to expose the lut distribution covering the entire color range from 0 to 1.0.
The underlying implementation in hardware can have just 1 segment covering the full range
OR a complex LUT distribution in Hardware like PWL, multi segmented etc.

To explain the usage with some real life example
------------------------------------------------

1. Conventional 1D LUT with just one segment

		|---|---|------------------------------------|
		0   1   2                                   1024


	- Hardware Description: A color block with a LUT linearly interpolating and
				covering range from 0 to 1.0
					- Number of segments - 1
					- Number of samples in LUT 1024
					- Precision of LUT samples in HW 0.10
					- Normalization Factor - Max value to represent 1.0
						 in terms of smallest step size which is 1024.

	In this case, it will be represented by the following structure.

	struct drm_color_lut_range lut_1024[] = {
			.start = 0 .end = (1 << 10);
			.normalization_factor = 1024;
			.count = 1024;
			.precision {
				.int_comp = 0;
				.fractional_comp = 10;
			}
		}

2. Piece Wise Linear 1D LUT

	  |---|---|------------------------------------|
	  0   1   2                                                32
                |       \
                |          \
                |             \
                |                \
	  0                   \
                |---|---|--...---|
	 0   1   2            8

	- Hardware Description: A color block with a LUT linearly interpolating and
				covering range from 0 to 1.0
					- Number of segments 2
					- Number of samples
						- segment 1 - 9 (covers range from 0 to 1/32)
						- segment 2 - 30 (covers range from 2/32 to 1.0)
					- Precision of LUT samples in HW 0.24
					- Normalization Factor - Max value to represent 1.0
						 in terms of smallest step size which is 8*32.

		struct drm_color_lut_range lut_pwl[] = {
		        /* segment 1 */
		        {
				.count = 9,
				.start = 0, .end = 8,
				.norm_factor = 8*32,
				.precision = {
					.intp = 0,
					.fracp = 24,
				},
			},
		        /* segment 2 */
			{
				.count = 30,
				.start = 8*2, .end = 8*32,
				.norm_factor = 8*32,
				.precision = {
					.intp = 0,
					.fracp = 24,
				},
		        },
		}

We can add and modify the relevant fields to be exposed in the capability structure as per
the community feedback, but this should be able to cover all the 1d LUT aspects and generically
expose the entire hardware block to userspace.

With this info, userspace will be able to compute the LUT samples for any specific usecase and we
may not need any exclusive "SIZE" or separate 1D lut property and just have this common property
which exposes hardware lut capabilities through "struct drm_color_lut_range"

Please refer to below links explaining the implementation:
[1] https://patchwork.freedesktop.org/patch/642652/?series=129812&rev=4
[2] https://patchwork.freedesktop.org/patch/642591/?series=129812&rev=4
[3] https://patchwork.freedesktop.org/patch/642597/?series=129812&rev=4

Regards,
Uma Shankar

> Signed-off-by: Alex Hung <alex.hung@amd.com>
> Co-developed-by: Harry Wentland <harry.wentland@amd.com>
> Signed-off-by: Harry Wentland <harry.wentland@amd.com>
> ---
> v8:
>  - Add DRM_MODE_PROP_ATOMIC to drm_property_create_range (Simon Ser)
>  - Change "1D Curve Custom LUT" to "1D LUT" (Simon Ser)
> 
> v7:
>  - Change "size" to "lut_size" (this affects multiple following commits)
>  - Move "lut_size" from drm_colorop_state to drm_colorop
>  - Modify other files accordingly (i.e. from drm_colorop_state->size
>    to drm_colorop->lut_size)
> 
> v5:
>  - Add kernel doc
>  - Define SIZE in similar manner to GAMMA_SIZE on drm_crtc (Melissa)
> 
>  drivers/gpu/drm/drm_atomic.c      |  4 +++
>  drivers/gpu/drm/drm_atomic_uapi.c |  5 ++++
>  drivers/gpu/drm/drm_colorop.c     | 43 +++++++++++++++++++++++++++++++
>  include/drm/drm_colorop.h         | 16 ++++++++++++
>  include/uapi/drm/drm_mode.h       | 14 ++++++++++
>  5 files changed, 82 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> index 5223cf363692..f713d177241d 100644
> --- a/drivers/gpu/drm/drm_atomic.c
> +++ b/drivers/gpu/drm/drm_atomic.c
> @@ -793,6 +793,10 @@ static void drm_atomic_colorop_print_state(struct
> drm_printer *p,
>  		drm_printf(p, "\tcurve_1d_type=%s\n",
>  			   drm_get_colorop_curve_1d_type_name(state-
> >curve_1d_type));
>  		break;
> +	case DRM_COLOROP_1D_LUT:
> +		drm_printf(p, "\tsize=%d\n", colorop->lut_size);
> +		drm_printf(p, "\tdata blob id=%d\n", state->data ? state->data-
> >base.id : 0);
> +		break;
>  	case DRM_COLOROP_CTM_3X4:
>  		drm_printf(p, "\tdata blob id=%d\n", state->data ? state->data-
> >base.id : 0);
>  		break;
> diff --git a/drivers/gpu/drm/drm_atomic_uapi.c
> b/drivers/gpu/drm/drm_atomic_uapi.c
> index dcd12fc0bd8f..dfd88a227da7 100644
> --- a/drivers/gpu/drm/drm_atomic_uapi.c
> +++ b/drivers/gpu/drm/drm_atomic_uapi.c
> @@ -713,6 +713,9 @@ static int drm_atomic_color_set_data_property(struct
> drm_colorop *colorop,
>  	bool replaced = false;
> 
>  	switch (colorop->type) {
> +	case DRM_COLOROP_1D_LUT:
> +		size = colorop->lut_size * sizeof(struct drm_color_lut);
> +		break;
>  	case DRM_COLOROP_CTM_3X4:
>  		size = sizeof(struct drm_color_ctm_3x4);
>  		break;
> @@ -762,6 +765,8 @@ drm_atomic_colorop_get_property(struct drm_colorop
> *colorop,
>  		*val = state->bypass;
>  	} else if (property == colorop->curve_1d_type_property) {
>  		*val = state->curve_1d_type;
> +	} else if (property == colorop->lut_size_property) {
> +		*val = colorop->lut_size;
>  	} else if (property == colorop->data_property) {
>  		*val = (state->data) ? state->data->base.id : 0;
>  	} else {
> diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
> index fcb4a8d0e38d..15ffbba60b3d 100644
> --- a/drivers/gpu/drm/drm_colorop.c
> +++ b/drivers/gpu/drm/drm_colorop.c
> @@ -64,6 +64,7 @@
> 
>  static const struct drm_prop_enum_list drm_colorop_type_enum_list[] = {
>  	{ DRM_COLOROP_1D_CURVE, "1D Curve" },
> +	{ DRM_COLOROP_1D_LUT, "1D LUT" },
>  	{ DRM_COLOROP_CTM_3X4, "3x4 Matrix"},
>  };
> 
> @@ -225,6 +226,47 @@ static int drm_colorop_create_data_prop(struct
> drm_device *dev, struct drm_color
>  	return 0;
>  }
> 
> +/**
> + * drm_colorop_curve_1d_lut_init - Initialize a DRM_COLOROP_1D_LUT
> + *
> + * @dev: DRM device
> + * @colorop: The drm_colorop object to initialize
> + * @plane: The associated drm_plane
> + * @lut_size: LUT size supported by driver
> + * @return zero on success, -E value on failure  */ int
> +drm_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_colorop
> *colorop,
> +				  struct drm_plane *plane, uint32_t lut_size) {
> +	struct drm_property *prop;
> +	int ret;
> +
> +	ret = drm_colorop_init(dev, colorop, plane, DRM_COLOROP_1D_LUT);
> +	if (ret)
> +		return ret;
> +
> +	/* initialize 1D LUT only attribute */
> +	/* LUT size */
> +	prop = drm_property_create_range(dev,
> DRM_MODE_PROP_IMMUTABLE | DRM_MODE_PROP_ATOMIC,
> +					 "SIZE", 0, UINT_MAX);
> +	if (!prop)
> +		return -ENOMEM;
> +
> +	colorop->lut_size_property = prop;
> +	drm_object_attach_property(&colorop->base, colorop-
> >lut_size_property, lut_size);
> +	colorop->lut_size = lut_size;
> +
> +	/* data */
> +	ret = drm_colorop_create_data_prop(dev, colorop);
> +	if (ret)
> +		return ret;
> +
> +	drm_colorop_reset(colorop);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(drm_colorop_curve_1d_lut_init);
> +
>  int drm_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop
> *colorop,
>  			     struct drm_plane *plane)
>  {
> @@ -333,6 +375,7 @@ void drm_colorop_reset(struct drm_colorop *colorop)
> 
>  static const char * const colorop_type_name[] = {
>  	[DRM_COLOROP_1D_CURVE] = "1D Curve",
> +	[DRM_COLOROP_1D_LUT] = "1D LUT",
>  	[DRM_COLOROP_CTM_3X4] = "3x4 Matrix",
>  };
> 
> diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h index
> d3a60c1beed1..d66c76033343 100644
> --- a/include/drm/drm_colorop.h
> +++ b/include/drm/drm_colorop.h
> @@ -259,6 +259,13 @@ struct drm_colorop {
>  	 */
>  	struct drm_property *bypass_property;
> 
> +	/**
> +	 * @lut_size:
> +	 *
> +	 * Number of entries of the custom LUT. This should be read-only.
> +	 */
> +	uint32_t lut_size;
> +
>  	/**
>  	 * @curve_1d_type_property:
>  	 *
> @@ -266,6 +273,13 @@ struct drm_colorop {
>  	 */
>  	struct drm_property *curve_1d_type_property;
> 
> +	/**
> +	 * @lut_size_property:
> +	 *
> +	 * Size property for custom LUT from userspace.
> +	 */
> +	struct drm_property *lut_size_property;
> +
>  	/**
>  	 * @data_property:
>  	 *
> @@ -310,6 +324,8 @@ static inline struct drm_colorop *drm_colorop_find(struct
> drm_device *dev,
> 
>  int drm_colorop_curve_1d_init(struct drm_device *dev, struct drm_colorop
> *colorop,
>  			      struct drm_plane *plane, u64 supported_tfs);
> +int drm_colorop_curve_1d_lut_init(struct drm_device *dev, struct drm_colorop
> *colorop,
> +				  struct drm_plane *plane, uint32_t lut_size);
>  int drm_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop
> *colorop,
>  			     struct drm_plane *plane);
> 
> diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
> index 651bdf48b766..dde250dd7a51 100644
> --- a/include/uapi/drm/drm_mode.h
> +++ b/include/uapi/drm/drm_mode.h
> @@ -890,6 +890,20 @@ enum drm_colorop_type {
>  	 */
>  	DRM_COLOROP_1D_CURVE,
> 
> +	/**
> +	 * @DRM_COLOROP_1D_LUT:
> +	 *
> +	 * enum string "1D LUT"
> +	 *
> +	 * A simple 1D LUT of uniformly spaced &drm_color_lut entries,
> +	 * packed into a blob via the DATA property. The driver's
> +	 * expected LUT size is advertised via the SIZE property.
> +	 *
> +	 * The DATA blob is an array of struct drm_color_lut with size
> +	 * of "lut_size".
> +	 */
> +	DRM_COLOROP_1D_LUT,
> +
>  	/**
>  	 * @DRM_COLOROP_CTM_3X4:
>  	 *
> --
> 2.43.0


^ permalink raw reply	[flat|nested] 128+ messages in thread

* RE: [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type
  2025-04-15  6:09   ` Shankar, Uma
@ 2025-04-15  6:16     ` Simon Ser
  2025-04-15  6:40       ` Shankar, Uma
  0 siblings, 1 reply; 128+ messages in thread
From: Simon Ser @ 2025-04-15  6:16 UTC (permalink / raw)
  To: Shankar, Uma
  Cc: Alex Hung, dri-devel@lists.freedesktop.org,
	amd-gfx@lists.freedesktop.org, intel-gfx@lists.freedesktop.org,
	wayland-devel@lists.freedesktop.org, harry.wentland@amd.com,
	leo.liu@amd.com, ville.syrjala@linux.intel.com,
	pekka.paalanen@collabora.com, mwen@igalia.com, jadahl@redhat.com,
	sebastian.wick@redhat.com, shashank.sharma@amd.com,
	agoins@nvidia.com, joshua@froggi.es, mdaenzer@redhat.com,
	aleixpol@kde.org, xaver.hugl@gmail.com, victoria@system76.com,
	daniel@ffwll.ch, quic_naseer@quicinc.com, quic_cbraga@quicinc.com,
	quic_abhinavk@quicinc.com, marcan@marcan.st, Liviu.Dudau@arm.com,
	sashamcintosh@google.com, Borah, Chaitanya Kumar,
	louis.chauvet@bootlin.com

On Tuesday, April 15th, 2025 at 08:09, Shankar, Uma <uma.shankar@intel.com> wrote:

> We want to have just one change in the way we expose the hardware capabilities else
> all looks good in general.

I would really recommend leaving this as a follow-up extension. It's a
complicated addition that requires more discussion.

^ permalink raw reply	[flat|nested] 128+ messages in thread

* RE: [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type
  2025-04-15  6:16     ` Simon Ser
@ 2025-04-15  6:40       ` Shankar, Uma
  2025-04-15 15:05         ` Harry Wentland
  0 siblings, 1 reply; 128+ messages in thread
From: Shankar, Uma @ 2025-04-15  6:40 UTC (permalink / raw)
  To: Simon Ser
  Cc: Alex Hung, dri-devel@lists.freedesktop.org,
	amd-gfx@lists.freedesktop.org, intel-gfx@lists.freedesktop.org,
	wayland-devel@lists.freedesktop.org, harry.wentland@amd.com,
	leo.liu@amd.com, ville.syrjala@linux.intel.com,
	pekka.paalanen@collabora.com, mwen@igalia.com, jadahl@redhat.com,
	sebastian.wick@redhat.com, shashank.sharma@amd.com,
	agoins@nvidia.com, joshua@froggi.es, mdaenzer@redhat.com,
	aleixpol@kde.org, xaver.hugl@gmail.com, victoria@system76.com,
	daniel@ffwll.ch, quic_naseer@quicinc.com, quic_cbraga@quicinc.com,
	quic_abhinavk@quicinc.com, marcan@marcan.st, Liviu.Dudau@arm.com,
	sashamcintosh@google.com, Borah, Chaitanya Kumar,
	louis.chauvet@bootlin.com



> -----Original Message-----
> From: Simon Ser <contact@emersion.fr>
> Sent: Tuesday, April 15, 2025 11:47 AM
> To: Shankar, Uma <uma.shankar@intel.com>
> Cc: Alex Hung <alex.hung@amd.com>; dri-devel@lists.freedesktop.org; amd-
> gfx@lists.freedesktop.org; intel-gfx@lists.freedesktop.org; wayland-
> devel@lists.freedesktop.org; harry.wentland@amd.com; leo.liu@amd.com;
> ville.syrjala@linux.intel.com; pekka.paalanen@collabora.com;
> mwen@igalia.com; jadahl@redhat.com; sebastian.wick@redhat.com;
> shashank.sharma@amd.com; agoins@nvidia.com; joshua@froggi.es;
> mdaenzer@redhat.com; aleixpol@kde.org; xaver.hugl@gmail.com;
> victoria@system76.com; daniel@ffwll.ch; quic_naseer@quicinc.com;
> quic_cbraga@quicinc.com; quic_abhinavk@quicinc.com; marcan@marcan.st;
> Liviu.Dudau@arm.com; sashamcintosh@google.com; Borah, Chaitanya Kumar
> <chaitanya.kumar.borah@intel.com>; louis.chauvet@bootlin.com
> Subject: RE: [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type
> 
> On Tuesday, April 15th, 2025 at 08:09, Shankar, Uma <uma.shankar@intel.com>
> wrote:
> 
> > We want to have just one change in the way we expose the hardware
> > capabilities else all looks good in general.
> 
> I would really recommend leaving this as a follow-up extension. It's a complicated
> addition that requires more discussion.

Hi Simon,
We have tried to solve the complex part and made it simple to understand and implement
along with a reference implementation [1] (can also help add the same for AMD case as well).
Without this we will end up with up 2 interfaces for 1dL Lut which is not nice where the one above
will be able to cover the current one. Let us know the problems with the proposed interface and we can
work to fix the same. But having a common and single interface is good and the current one will not fit
Intel's color pipeline distribution so the generic one anyways will be needed, and it will benefit userspace
to know the underlying LUT distribution to compute the LUT samples.

[1] https://patchwork.freedesktop.org/series/129812/

Regards,
Uma Shankar


^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 06/43] drm/colorop: Add 1D Curve subtype
  2025-04-08 16:40       ` Daniel Stone
  2025-04-08 17:30         ` Harry Wentland
  2025-04-10 10:05         ` [PATCH V8 06/43] drm/colorop: Add 1D Curve subtype Simon Ser
@ 2025-04-15 11:12         ` Borah, Chaitanya Kumar
  2025-04-17 15:13           ` Simon Ser
  2 siblings, 1 reply; 128+ messages in thread
From: Borah, Chaitanya Kumar @ 2025-04-15 11:12 UTC (permalink / raw)
  To: Daniel Stone, Simon Ser
  Cc: Alex Hung, dri-devel, amd-gfx, wayland-devel, harry.wentland,
	leo.liu, ville.syrjala, pekka.paalanen, mwen, jadahl,
	sebastian.wick, shashank.sharma, agoins, joshua, mdaenzer,
	aleixpol, xaver.hugl, victoria, daniel, uma.shankar, quic_naseer,
	quic_cbraga, quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	louis.chauvet


On 4/8/2025 10:10 PM, Daniel Stone wrote:
>
> As it stands, I've gone through the implementation pretty thoroughly,
> as well as our use of it in Weston. I'm happy with how it looks for
> pre-blend, and I'm even happier that the implementation is written to
> apply easily to apply to post-blend CRTC pipelines.

Since we are planning to use this frame work on post-blend pipelines 
eventually. Should we change the name space of the current pre-blend 
helpers to reflect that?

e.g.

s/drm_colorop_curve_1d_lut_init/drm_plane_colorop_curve_1d_lut_init/
s/drm_colorop_3dlut_init/drm_plane_colorop_3dlut_init/


Regards

Chaitanya


^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type
  2025-04-15  6:40       ` Shankar, Uma
@ 2025-04-15 15:05         ` Harry Wentland
  2025-04-15 16:25           ` Simon Ser
  0 siblings, 1 reply; 128+ messages in thread
From: Harry Wentland @ 2025-04-15 15:05 UTC (permalink / raw)
  To: Shankar, Uma, Simon Ser
  Cc: Alex Hung, dri-devel@lists.freedesktop.org,
	amd-gfx@lists.freedesktop.org, intel-gfx@lists.freedesktop.org,
	wayland-devel@lists.freedesktop.org, leo.liu@amd.com,
	ville.syrjala@linux.intel.com, pekka.paalanen@collabora.com,
	mwen@igalia.com, jadahl@redhat.com, sebastian.wick@redhat.com,
	shashank.sharma@amd.com, agoins@nvidia.com, joshua@froggi.es,
	mdaenzer@redhat.com, aleixpol@kde.org, xaver.hugl@gmail.com,
	victoria@system76.com, daniel@ffwll.ch, quic_naseer@quicinc.com,
	quic_cbraga@quicinc.com, quic_abhinavk@quicinc.com,
	marcan@marcan.st, Liviu.Dudau@arm.com, sashamcintosh@google.com,
	Borah, Chaitanya Kumar, louis.chauvet@bootlin.com



On 2025-04-15 02:40, Shankar, Uma wrote:
> 
> 
>> -----Original Message-----
>> From: Simon Ser <contact@emersion.fr>
>> Sent: Tuesday, April 15, 2025 11:47 AM
>> To: Shankar, Uma <uma.shankar@intel.com>
>> Cc: Alex Hung <alex.hung@amd.com>; dri-devel@lists.freedesktop.org; amd-
>> gfx@lists.freedesktop.org; intel-gfx@lists.freedesktop.org; wayland-
>> devel@lists.freedesktop.org; harry.wentland@amd.com; leo.liu@amd.com;
>> ville.syrjala@linux.intel.com; pekka.paalanen@collabora.com;
>> mwen@igalia.com; jadahl@redhat.com; sebastian.wick@redhat.com;
>> shashank.sharma@amd.com; agoins@nvidia.com; joshua@froggi.es;
>> mdaenzer@redhat.com; aleixpol@kde.org; xaver.hugl@gmail.com;
>> victoria@system76.com; daniel@ffwll.ch; quic_naseer@quicinc.com;
>> quic_cbraga@quicinc.com; quic_abhinavk@quicinc.com; marcan@marcan.st;
>> Liviu.Dudau@arm.com; sashamcintosh@google.com; Borah, Chaitanya Kumar
>> <chaitanya.kumar.borah@intel.com>; louis.chauvet@bootlin.com
>> Subject: RE: [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type
>>
>> On Tuesday, April 15th, 2025 at 08:09, Shankar, Uma <uma.shankar@intel.com>
>> wrote:
>>
>>> We want to have just one change in the way we expose the hardware
>>> capabilities else all looks good in general.
>>
>> I would really recommend leaving this as a follow-up extension. It's a complicated
>> addition that requires more discussion.
> 
> Hi Simon,
> We have tried to solve the complex part and made it simple to understand and implement
> along with a reference implementation [1] (can also help add the same for AMD case as well).
> Without this we will end up with up 2 interfaces for 1dL Lut which is not nice where the one above
> will be able to cover the current one. Let us know the problems with the proposed interface and we can
> work to fix the same. But having a common and single interface is good and the current one will not fit
> Intel's color pipeline distribution so the generic one anyways will be needed, and it will benefit userspace
> to know the underlying LUT distribution to compute the LUT samples.
> 
> [1] https://patchwork.freedesktop.org/series/129812/
> 

I think there is a lot of value in giving userspace a simple LUT
to work with. There are many compositors and many compositor
maintainers. When someone new jumps into color management usually
same thing happens. It starts with "it's not too complicated",
and then over a period of time progresses to "this is very much
non-trivial" as understanding one bit usually opens ten more
questions.

Forcing people to deal with another level of complexity will
discourage implementations and be counterproductive to furthering
adoption of color operations for HW acceleration, IMO.

I'm am not opposed to a complex LUT definition but I don't think
it should replace a simple and well-understood definition.

Harry

> Regards,
> Uma Shankar
> 


^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: Pipeline vs. no pipeline (Re: [PATCH V8 06/43] drm/colorop: Add 1D Curve subtype)
  2025-04-10  7:53           ` Pipeline vs. no pipeline (Re: [PATCH V8 06/43] drm/colorop: Add 1D Curve subtype) Pekka Paalanen
@ 2025-04-15 15:29             ` Harry Wentland
  2025-04-16 14:39               ` Xaver Hugl
  2025-04-17  8:28               ` Pekka Paalanen
  0 siblings, 2 replies; 128+ messages in thread
From: Harry Wentland @ 2025-04-15 15:29 UTC (permalink / raw)
  To: Pekka Paalanen
  Cc: Daniel Stone, Simon Ser, Alex Hung, dri-devel, amd-gfx,
	wayland-devel, leo.liu, ville.syrjala, mwen, jadahl,
	sebastian.wick, shashank.sharma, agoins, joshua, mdaenzer,
	aleixpol, xaver.hugl, victoria, daniel, uma.shankar, quic_naseer,
	quic_cbraga, quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet



On 2025-04-10 03:53, Pekka Paalanen wrote:
> On Tue, 8 Apr 2025 13:30:46 -0400
> Harry Wentland <harry.wentland@amd.com> wrote:
> 
>> On 2025-04-08 12:40, Daniel Stone wrote:
>>> Hi there,
>>>
>>> On Tue, 1 Apr 2025 at 20:53, Simon Ser <contact@emersion.fr> wrote:  
>>>> On Tuesday, April 1st, 2025 at 17:14, Daniel Stone <daniel@fooishbar.org> wrote:  
> 
> ...
> 
>>>>> 1. Is it guaranteed that, if any plane on a device supports the
>>>>> COLOR_PIPELINE property, all planes will support COLOR_PIPELINE?
>>>>> (Given the amdgpu cursor-plane discussion, it looks like no, which is
>>>>> unfortunate but oh well.)  
>>>>
>>>> I don't think so. (They could all expose a COLOR_PIPELINE with the only
>>>> choice as the zero bypass pipeline, but that sounds silly.)  
>>>
>>> Works for me: so any planes could not have colour pipelines, and the
>>> result would be undefined (well, less defined) colour.  
>>
>> Yes, basically it would be what we have now (without color pipelines).
> 
> Hi,
> 
> I see Alex wrote:
> 
>> In order to support YUV we'll need to add COLOR_ENCODING and COLOR_RANGE
>> support to the color pipeline. I have sketched these out already but
>> don't have it all hooked up yet. This should not hinder adoption of this
>> API for gaming use-cases.
> 
> Was it considered to be able to lift the full-range RGB restriction
> from the color pipelines, eventually leading to the possibility of
> scanning out limited-range YCbCr bit-identical, giving userspace access
> to the sub-black and super-white ranges for e.g. BT.814 purposes?
> 

For AMD HW design and validation assumes that the pipeline is
dealing with our internal floating point format and RGB values.
Anything beyond that is somewhat undefined. Things might work
as one expects but the product was definitely not designed and
validated for that usage.

I assume other HW design makes similar assumptions.

> These questions are pointing in the direction of a bypass
> COLOR_PIPELINE being different from no COLOR_PIPELINE. I assume a
> bypass pipeline needs to shovel values through unchanged, while
> "without color pipelines" would need the old COLOR_ENCODING and
> COLOR_RANGE properties.
> 

What I take it to mean is that this iteration of COLOR_PIPELINE
only allows for RGB pipelines as YCbCr ones are underspecified
without COLOR_RANGE and COLOR_ENCODING. For RGB a bypass pipeline
should be the same as no COLOR_PIPELINE.

> That reminds me of yet another question: if the framebuffer is limited
> range, and it's not converted to full-range at the start of a color
> pipeline, how will the sub-black and super-white ranges be represented?
> Will they be negative and greater than 1.0 values, respectively? This
> would be meaningful for the colorops being defined now, as I assume
> people might implicitly limit their thinking to the [0.0, 1.0] range,
> or at least exclude negative values.
> 

Without COLOR_RANGE there is no way to know whether the input is limited
or full.

Is your question about when we have COLOR_RANGE specified? If that is
set to LIMITED then I expect the values to get expanded at the beginning
of the pipeline. In that case it's probably a HW or driver implementation
detail whether the sub-blacks or super-whites will still be represented
(as negative or >1.0 values) or clipped.

> The 3x4 CTM colorop is not yet explicit on whether it clamps its inputs
> or outputs. Should all colorops be explicit about it?
> 

Do we expect all HW/drivers to be able to support the same behavior?
Is this critical to using the colorop?

Harry

> 
> Thanks,
> pq


^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type
  2025-04-15 15:05         ` Harry Wentland
@ 2025-04-15 16:25           ` Simon Ser
  2025-05-22 11:33             ` Shankar, Uma
  0 siblings, 1 reply; 128+ messages in thread
From: Simon Ser @ 2025-04-15 16:25 UTC (permalink / raw)
  To: Harry Wentland
  Cc: Shankar, Uma, Alex Hung, dri-devel@lists.freedesktop.org,
	amd-gfx@lists.freedesktop.org, intel-gfx@lists.freedesktop.org,
	wayland-devel@lists.freedesktop.org, leo.liu@amd.com,
	ville.syrjala@linux.intel.com, pekka.paalanen@collabora.com,
	mwen@igalia.com, jadahl@redhat.com, sebastian.wick@redhat.com,
	shashank.sharma@amd.com, agoins@nvidia.com, joshua@froggi.es,
	mdaenzer@redhat.com, aleixpol@kde.org, xaver.hugl@gmail.com,
	victoria@system76.com, daniel@ffwll.ch, quic_naseer@quicinc.com,
	quic_cbraga@quicinc.com, quic_abhinavk@quicinc.com,
	marcan@marcan.st, Liviu.Dudau@arm.com, sashamcintosh@google.com,
	Borah, Chaitanya Kumar, louis.chauvet@bootlin.com

On Tuesday, April 15th, 2025 at 17:05, Harry Wentland <harry.wentland@amd.com> wrote:

> > > > We want to have just one change in the way we expose the hardware
> > > > capabilities else all looks good in general.
> > > 
> > > I would really recommend leaving this as a follow-up extension. It's a complicated
> > > addition that requires more discussion.
> > 
> > Hi Simon,
> > We have tried to solve the complex part and made it simple to understand and implement
> > along with a reference implementation [1] (can also help add the same for AMD case as well).
> > Without this we will end up with up 2 interfaces for 1dL Lut which is not nice where the one above
> > will be able to cover the current one. Let us know the problems with the proposed interface and we can
> > work to fix the same. But having a common and single interface is good and the current one will not fit
> > Intel's color pipeline distribution so the generic one anyways will be needed, and it will benefit userspace
> > to know the underlying LUT distribution to compute the LUT samples.
> > 
> > [1] https://patchwork.freedesktop.org/series/129812/
> 
> I think there is a lot of value in giving userspace a simple LUT
> to work with. There are many compositors and many compositor
> maintainers. When someone new jumps into color management usually
> same thing happens. It starts with "it's not too complicated",
> and then over a period of time progresses to "this is very much
> non-trivial" as understanding one bit usually opens ten more
> questions.
> 
> Forcing people to deal with another level of complexity will
> discourage implementations and be counterproductive to furthering
> adoption of color operations for HW acceleration, IMO.
> 
> I'm am not opposed to a complex LUT definition but I don't think
> it should replace a simple and well-understood definition.

Agreed. To add on this, I think shipping many additional features from
day one significantly increases the work load (more code to write,
review, test at once) and we'd also need to go through supplementary
rounds to validate the API design and ensure it's not too
Intel-specific. Also adding this feature as a second step will prove
that the API is as extensible as we desire. 

I don't really understand why it's important to have this feature in
the first version. Intel has been converting simple LUTs into the
fancy distribution for the existing GAMMA_LUT and DEGAMMA_LUT for a
while, so can do it for colorop as well. The upsides of the fancy
distribution is more precise and smaller LUTs, but that doesn't seem
critical?

Simon

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: Pipeline vs. no pipeline (Re: [PATCH V8 06/43] drm/colorop: Add 1D Curve subtype)
  2025-04-15 15:29             ` Harry Wentland
@ 2025-04-16 14:39               ` Xaver Hugl
  2025-04-17  8:28               ` Pekka Paalanen
  1 sibling, 0 replies; 128+ messages in thread
From: Xaver Hugl @ 2025-04-16 14:39 UTC (permalink / raw)
  To: Harry Wentland
  Cc: Pekka Paalanen, Daniel Stone, Simon Ser, Alex Hung, dri-devel,
	amd-gfx, wayland-devel, leo.liu, ville.syrjala, mwen, jadahl,
	sebastian.wick, shashank.sharma, agoins, joshua, mdaenzer,
	aleixpol, victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

> > The 3x4 CTM colorop is not yet explicit on whether it clamps its inputs
> > or outputs. Should all colorops be explicit about it?
> >
>
> Do we expect all HW/drivers to be able to support the same behavior?
> Is this critical to using the colorop?
It doesn't need to be the same on all hardware, but it is critical for
userspace to know at runtime. If a color op clips to [0; 1], then
using it with scRGB would be a bad idea for example.

> Harry

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: Pipeline vs. no pipeline (Re: [PATCH V8 06/43] drm/colorop: Add 1D Curve subtype)
  2025-04-15 15:29             ` Harry Wentland
  2025-04-16 14:39               ` Xaver Hugl
@ 2025-04-17  8:28               ` Pekka Paalanen
  1 sibling, 0 replies; 128+ messages in thread
From: Pekka Paalanen @ 2025-04-17  8:28 UTC (permalink / raw)
  To: Harry Wentland
  Cc: Daniel Stone, Simon Ser, Alex Hung, dri-devel, amd-gfx,
	wayland-devel, leo.liu, ville.syrjala, mwen, jadahl,
	sebastian.wick, shashank.sharma, agoins, joshua, mdaenzer,
	aleixpol, xaver.hugl, victoria, daniel, uma.shankar, quic_naseer,
	quic_cbraga, quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

[-- Attachment #1: Type: text/plain, Size: 4951 bytes --]

On Tue, 15 Apr 2025 11:29:10 -0400
Harry Wentland <harry.wentland@amd.com> wrote:

> On 2025-04-10 03:53, Pekka Paalanen wrote:
> > On Tue, 8 Apr 2025 13:30:46 -0400
> > Harry Wentland <harry.wentland@amd.com> wrote:
> >   
> >> On 2025-04-08 12:40, Daniel Stone wrote:  
> >>> Hi there,
> >>>
> >>> On Tue, 1 Apr 2025 at 20:53, Simon Ser <contact@emersion.fr> wrote:    
> >>>> On Tuesday, April 1st, 2025 at 17:14, Daniel Stone <daniel@fooishbar.org> wrote:    
> > 
> > ...
> >   
> >>>>> 1. Is it guaranteed that, if any plane on a device supports the
> >>>>> COLOR_PIPELINE property, all planes will support COLOR_PIPELINE?
> >>>>> (Given the amdgpu cursor-plane discussion, it looks like no, which is
> >>>>> unfortunate but oh well.)    
> >>>>
> >>>> I don't think so. (They could all expose a COLOR_PIPELINE with the only
> >>>> choice as the zero bypass pipeline, but that sounds silly.)    
> >>>
> >>> Works for me: so any planes could not have colour pipelines, and the
> >>> result would be undefined (well, less defined) colour.    
> >>
> >> Yes, basically it would be what we have now (without color pipelines).  
> > 
> > Hi,
> > 
> > I see Alex wrote:
> >   
> >> In order to support YUV we'll need to add COLOR_ENCODING and COLOR_RANGE
> >> support to the color pipeline. I have sketched these out already but
> >> don't have it all hooked up yet. This should not hinder adoption of this
> >> API for gaming use-cases.  
> > 
> > Was it considered to be able to lift the full-range RGB restriction
> > from the color pipelines, eventually leading to the possibility of
> > scanning out limited-range YCbCr bit-identical, giving userspace access
> > to the sub-black and super-white ranges for e.g. BT.814 purposes?
> >   
> 
> For AMD HW design and validation assumes that the pipeline is
> dealing with our internal floating point format and RGB values.
> Anything beyond that is somewhat undefined. Things might work
> as one expects but the product was definitely not designed and
> validated for that usage.
> 
> I assume other HW design makes similar assumptions.

Hi Harry,

if that's just about minor rounding effects in conversion between
integer and internal formats, I wouldn't be too worried.

But if the internal format has severe limitations, like cannot
represent negative values, or smaller than -0.999 or bigger than 1.999
for example, then that is something userspace needs to know.

> > These questions are pointing in the direction of a bypass
> > COLOR_PIPELINE being different from no COLOR_PIPELINE. I assume a
> > bypass pipeline needs to shovel values through unchanged, while
> > "without color pipelines" would need the old COLOR_ENCODING and
> > COLOR_RANGE properties.
> >   
> 
> What I take it to mean is that this iteration of COLOR_PIPELINE
> only allows for RGB pipelines as YCbCr ones are underspecified
> without COLOR_RANGE and COLOR_ENCODING. For RGB a bypass pipeline
> should be the same as no COLOR_PIPELINE.

I'm thinking of the future extension of the color pipeline framework.
I'm concerned that not considering limited range YCbCr might make
adding support for it later much harder than it needs to be.

Xaver's point about scRGB is a really good one: we don't need YCbCr in
order to encounter nominal values outside of [0.0, 1.0]. We don't even
need scRGB, any conversion from a bigger to a small color space can
produce them and we should understand what to expect when that happens.

> > That reminds me of yet another question: if the framebuffer is limited
> > range, and it's not converted to full-range at the start of a color
> > pipeline, how will the sub-black and super-white ranges be represented?
> > Will they be negative and greater than 1.0 values, respectively? This
> > would be meaningful for the colorops being defined now, as I assume
> > people might implicitly limit their thinking to the [0.0, 1.0] range,
> > or at least exclude negative values.
> >   
> 
> Without COLOR_RANGE there is no way to know whether the input is limited
> or full.
> 
> Is your question about when we have COLOR_RANGE specified? If that is
> set to LIMITED then I expect the values to get expanded at the beginning
> of the pipeline. In that case it's probably a HW or driver implementation
> detail whether the sub-blacks or super-whites will still be represented
> (as negative or >1.0 values) or clipped.
> 
> > The 3x4 CTM colorop is not yet explicit on whether it clamps its inputs
> > or outputs. Should all colorops be explicit about it?
> >   
> 
> Do we expect all HW/drivers to be able to support the same behavior?
> Is this critical to using the colorop?

It is critical. It does not have to be the same for all hardware and
drivers, if there is a colorop property or type indicating it. But it
cannot be a hidden driver/hw implementation detail.


Thanks,
pq

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 06/43] drm/colorop: Add 1D Curve subtype
  2025-04-15 11:12         ` Borah, Chaitanya Kumar
@ 2025-04-17 15:13           ` Simon Ser
  0 siblings, 0 replies; 128+ messages in thread
From: Simon Ser @ 2025-04-17 15:13 UTC (permalink / raw)
  To: Borah, Chaitanya Kumar
  Cc: Daniel Stone, Alex Hung, dri-devel, amd-gfx, wayland-devel,
	harry.wentland, leo.liu, ville.syrjala, pekka.paalanen, mwen,
	jadahl, sebastian.wick, shashank.sharma, agoins, joshua, mdaenzer,
	aleixpol, xaver.hugl, victoria, daniel, uma.shankar, quic_naseer,
	quic_cbraga, quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	louis.chauvet

On Tuesday, April 15th, 2025 at 13:12, Borah, Chaitanya Kumar <chaitanya.kumar.borah@intel.com> wrote:

> On 4/8/2025 10:10 PM, Daniel Stone wrote:
> 
> > As it stands, I've gone through the implementation pretty thoroughly,
> > as well as our use of it in Weston. I'm happy with how it looks for
> > pre-blend, and I'm even happier that the implementation is written to
> > apply easily to apply to post-blend CRTC pipelines.
> 
> Since we are planning to use this frame work on post-blend pipelines
> eventually. Should we change the name space of the current pre-blend
> helpers to reflect that?
> 
> e.g.
> 
> s/drm_colorop_curve_1d_lut_init/drm_plane_colorop_curve_1d_lut_init/
> s/drm_colorop_3dlut_init/drm_plane_colorop_3dlut_init/

No objections against that, but I'd also be fine with keeping the
current names because it's not yet clear how these functions will be
adapted for post-blending. Maybe the functions will be re-used and the
plane argument dropped, in which case it'd make more sense to keep the
current name. We don't know yet.

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 40/43] drm/colorop: Add 3D LUT support to color pipeline
  2025-03-26 23:47 ` [PATCH V8 40/43] drm/colorop: Add 3D LUT support to color pipeline Alex Hung
  2025-03-29 14:57   ` Simon Ser
@ 2025-04-25 13:50   ` Leandro Ribeiro
  2025-05-13  3:39     ` Alex Hung
  2025-05-17  1:22   ` Xaver Hugl
  2 siblings, 1 reply; 128+ messages in thread
From: Leandro Ribeiro @ 2025-04-25 13:50 UTC (permalink / raw)
  To: Alex Hung, dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet



On 3/26/25 20:47, Alex Hung wrote:
> It is to be used to enable HDR by allowing userpace to create and pass
> 3D LUTs to kernel and hardware.
> 
> new drm_colorop_type: DRM_COLOROP_3D_LUT.
> 
> Signed-off-by: Alex Hung <alex.hung@amd.com>
> ---
> v8:
>  - Fix typo in subject (Simon Ser)
>  - Update documentation for DRM_COLOROP_3D_LUT (Simon Ser)
>  - Delete empty lines (Simon Ser)
> 
> v7:
>  - Simplify 3D LUT by removing lut_3d_modes and related functions (Simon Ser)
> 
>  drivers/gpu/drm/drm_atomic.c      |  6 +++
>  drivers/gpu/drm/drm_atomic_uapi.c |  6 +++
>  drivers/gpu/drm/drm_colorop.c     | 72 +++++++++++++++++++++++++++++++
>  include/drm/drm_colorop.h         | 21 +++++++++
>  include/uapi/drm/drm_mode.h       | 33 ++++++++++++++
>  5 files changed, 138 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> index 0efb0ead204a..ef47a06344f3 100644
> --- a/drivers/gpu/drm/drm_atomic.c
> +++ b/drivers/gpu/drm/drm_atomic.c
> @@ -806,6 +806,12 @@ static void drm_atomic_colorop_print_state(struct drm_printer *p,
>  	case DRM_COLOROP_MULTIPLIER:
>  		drm_printf(p, "\tmultiplier=%llu\n", state->multiplier);
>  		break;
> +	case DRM_COLOROP_3D_LUT:
> +		drm_printf(p, "\tsize=%d\n", colorop->lut_size);
> +		drm_printf(p, "\tinterpolation=%s\n",
> +			   drm_get_colorop_lut3d_interpolation_name(colorop->lut3d_interpolation));
> +		drm_printf(p, "\tdata blob id=%d\n", state->data ? state->data->base.id : 0);
> +		break;
>  	default:
>  		break;
>  	}
> diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
> index 947c18e8bf9b..d5d464b4d0f6 100644
> --- a/drivers/gpu/drm/drm_atomic_uapi.c
> +++ b/drivers/gpu/drm/drm_atomic_uapi.c
> @@ -719,6 +719,10 @@ static int drm_atomic_color_set_data_property(struct drm_colorop *colorop,
>  	case DRM_COLOROP_CTM_3X4:
>  		size = sizeof(struct drm_color_ctm_3x4);
>  		break;
> +	case DRM_COLOROP_3D_LUT:
> +		size = colorop->lut_size * colorop->lut_size * colorop->lut_size *
> +		       sizeof(struct drm_color_lut);
> +		break;
>  	default:
>  		/* should never get here */
>  		return -EINVAL;
> @@ -771,6 +775,8 @@ drm_atomic_colorop_get_property(struct drm_colorop *colorop,
>  		*val = state->multiplier;
>  	} else if (property == colorop->lut_size_property) {
>  		*val = colorop->lut_size;
> +	} else if (property == colorop->lut3d_interpolation_property) {
> +		*val = colorop->lut3d_interpolation;
>  	} else if (property == colorop->data_property) {
>  		*val = (state->data) ? state->data->base.id : 0;
>  	} else {
> diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
> index e03706e7179b..224c6be237d2 100644
> --- a/drivers/gpu/drm/drm_colorop.c
> +++ b/drivers/gpu/drm/drm_colorop.c
> @@ -67,6 +67,7 @@ static const struct drm_prop_enum_list drm_colorop_type_enum_list[] = {
>  	{ DRM_COLOROP_1D_LUT, "1D LUT" },
>  	{ DRM_COLOROP_CTM_3X4, "3x4 Matrix"},
>  	{ DRM_COLOROP_MULTIPLIER, "Multiplier"},
> +	{ DRM_COLOROP_3D_LUT, "3D LUT"},
>  };
>  
>  static const char * const colorop_curve_1d_type_names[] = {
> @@ -82,6 +83,11 @@ static const struct drm_prop_enum_list drm_colorop_lut1d_interpolation_list[] =
>  	{ DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR, "Linear" },
>  };
>  
> +
> +static const struct drm_prop_enum_list drm_colorop_lut3d_interpolation_list[] = {
> +	{ DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL, "Tetrahedral" },
> +};
> +
>  /* Init Helpers */
>  
>  static int drm_colorop_init(struct drm_device *dev, struct drm_colorop *colorop,
> @@ -349,6 +355,51 @@ int drm_colorop_mult_init(struct drm_device *dev, struct drm_colorop *colorop,
>  }
>  EXPORT_SYMBOL(drm_colorop_mult_init);
>  
> +int drm_colorop_3dlut_init(struct drm_device *dev, struct drm_colorop *colorop,
> +			   struct drm_plane *plane,
> +			   uint32_t lut_size,
> +			   enum drm_colorop_lut3d_interpolation_type interpolation,
> +			   bool allow_bypass)
> +{
> +	struct drm_property *prop;
> +	int ret;
> +
> +	ret = drm_colorop_init(dev, colorop, plane, DRM_COLOROP_3D_LUT, allow_bypass);
> +	if (ret)
> +		return ret;
> +
> +	/* LUT size */
> +	prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE  | DRM_MODE_PROP_ATOMIC,
> +					 "SIZE", 0, UINT_MAX);
> +	if (!prop)
> +		return -ENOMEM;
> +
> +	colorop->lut_size_property = prop;
> +	drm_object_attach_property(&colorop->base, colorop->lut_size_property, lut_size);
> +	colorop->lut_size = lut_size;
> +
> +	/* interpolation */
> +	prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, "LUT3D_INTERPOLATION",
> +					drm_colorop_lut3d_interpolation_list,
> +					ARRAY_SIZE(drm_colorop_lut3d_interpolation_list));
> +	if (!prop)
> +		return -ENOMEM;
> +
> +	colorop->lut3d_interpolation_property = prop;
> +	drm_object_attach_property(&colorop->base, prop, interpolation);
> +	colorop->lut3d_interpolation = interpolation;
> +
> +	/* data */
> +	ret = drm_colorop_create_data_prop(dev, colorop);
> +	if (ret)
> +		return ret;
> +
> +	drm_colorop_reset(colorop);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(drm_colorop_3dlut_init);
> +
>  static void __drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop,
>  							struct drm_colorop_state *state)
>  {
> @@ -441,7 +492,13 @@ static const char * const colorop_type_name[] = {
>  	[DRM_COLOROP_1D_LUT] = "1D LUT",
>  	[DRM_COLOROP_CTM_3X4] = "3x4 Matrix",
>  	[DRM_COLOROP_MULTIPLIER] = "Multiplier",
> +	[DRM_COLOROP_3D_LUT] = "3D LUT",
>  };
> +
> +static const char * const colorop_lu3d_interpolation_name[] = {
> +	[DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL] = "Tetrahedral",
> +};
> +
>  static const char * const colorop_lut1d_interpolation_name[] = {
>  	[DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR] = "Linear",
>  };
> @@ -477,6 +534,21 @@ const char *drm_get_colorop_lut1d_interpolation_name(enum drm_colorop_lut1d_inte
>  	return colorop_lut1d_interpolation_name[type];
>  }
>  
> +/**
> + * drm_get_colorop_lut3d_interpolation_name - return a string for interpolation type
> + * @type: interpolation type to compute name of
> + *
> + * In contrast to the other drm_get_*_name functions this one here returns a
> + * const pointer and hence is threadsafe.
> + */
> +const char *drm_get_colorop_lut3d_interpolation_name(enum drm_colorop_lut3d_interpolation_type type)
> +{
> +	if (WARN_ON(type >= ARRAY_SIZE(colorop_lu3d_interpolation_name)))
> +		return "unknown";
> +
> +	return colorop_lu3d_interpolation_name[type];
> +}
> +
>  /**
>   * drm_colorop_set_next_property - sets the next pointer
>   * @colorop: drm colorop
> diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
> index c89d5eb44856..e999d5ceb8a5 100644
> --- a/include/drm/drm_colorop.h
> +++ b/include/drm/drm_colorop.h
> @@ -281,6 +281,14 @@ struct drm_colorop {
>  	 */
>  	enum drm_colorop_lut1d_interpolation_type lut1d_interpolation;
>  
> +	/**
> +	 * @lut3d_interpolation:
> +	 *
> +	 * Read-only
> +	 * Interpolation for DRM_COLOROP_3D_LUT
> +	 */
> +	enum drm_colorop_lut3d_interpolation_type lut3d_interpolation;
> +
>  	/**
>  	 * @lut1d_interpolation_property:
>  	 *
> @@ -309,6 +317,13 @@ struct drm_colorop {
>  	 */
>  	struct drm_property *lut_size_property;
>  
> +	/**
> +	 * @lut3d_interpolation_property:
> +	 *
> +	 * Read-only property for DRM_COLOROP_3D_LUT interpolation
> +	 */
> +	struct drm_property *lut3d_interpolation_property;
> +
>  	/**
>  	 * @data_property:
>  	 *
> @@ -362,6 +377,11 @@ int drm_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop
>  			     struct drm_plane *plane, bool allow_bypass);
>  int drm_colorop_mult_init(struct drm_device *dev, struct drm_colorop *colorop,
>  			      struct drm_plane *plane, bool allow_bypass);
> +int drm_colorop_3dlut_init(struct drm_device *dev, struct drm_colorop *colorop,
> +			   struct drm_plane *plane,
> +			   uint32_t lut_size,
> +			   enum drm_colorop_lut3d_interpolation_type interpolation,
> +			   bool allow_bypass);
>  
>  struct drm_colorop_state *
>  drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop);
> @@ -412,6 +432,7 @@ const char *drm_get_colorop_type_name(enum drm_colorop_type type);
>   */
>  const char *drm_get_colorop_curve_1d_type_name(enum drm_colorop_curve_1d_type type);
>  const char *drm_get_colorop_lut1d_interpolation_name(enum drm_colorop_lut1d_interpolation_type type);
> +const char *drm_get_colorop_lut3d_interpolation_name(enum drm_colorop_lut3d_interpolation_type type);
>  
>  void drm_colorop_set_next_property(struct drm_colorop *colorop, struct drm_colorop *next);
>  
> diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
> index d76c8ffe5408..88fafbdeb2a2 100644
> --- a/include/uapi/drm/drm_mode.h
> +++ b/include/uapi/drm/drm_mode.h
> @@ -930,6 +930,39 @@ enum drm_colorop_type {
>  	 * property.
>  	 */
>  	DRM_COLOROP_MULTIPLIER,
> +
> +	/**
> +	 * @DRM_COLOROP_3D_LUT:
> +	 *
> +	 * enum string "3D LUT"
> +	 *
> +	 * A 3D LUT of &drm_color_lut entries,
> +	 * packed into a blob via the DATA property. The driver's expected
> +	 * LUT size is advertised via the SIZE property, i.e., a 3D LUT with
> +	 * 17x17x17 entries will have SIZE set to 17.
> +	 *
> +	 * The DATA blob is a 3D array of struct drm_color_lut with dimension
> +	 * length of "lut_size".
> +	 * The LUT elements are traversed like so:
> +	 *
> +	 *   for R in range 0..n
> +	 *     for G in range 0..n
> +	 *       for B in range 0..n
> +	 *         color = lut3d[R][G][B]
> +	 */
> +	DRM_COLOROP_3D_LUT,
> +};

Hi,

I'm experimenting with V7 of the this API on Weston, using the AMD driver,
and I'm seeing issues with the usage of 3D LUT's: channels R and B being
swapped.
On Weston, the 3D LUT is constructed as:

for B in range 0..n
    for G in range 0..n
       for R in range 0..n
           index = R + n * (G + n * B)
           lut[index].red   = foo
           lut[index].green = foo
           lut[index].blue  = foo

To map that to DRM_COLOROP_3D_LUT, we do:

for B in range 0..n
    for G in range 0..n
       for R in range 0..n
           index_weston = R + n * (G + n * B)
           index_kernel = B + n * (G + n * R)
           lut_kernel[index_kernel].red   = lut[index_weston].red
           lut_kernel[index_kernel].green = lut[index_weston].green
           lut_kernel[index_kernel].blue  = lut[index_weston].blue

If I ignore the documentation and use the same indices, everything works
fine regarding the color channels.

Maybe there's a bug in our Weston code, but writing this just to confirm
that the documentation and the AMD driver are matching.

Thanks,
Leandro

> +
> +/**
> + * enum drm_colorop_lut3d_interpolation_type - type of 3DLUT interpolation
> + */
> +enum drm_colorop_lut3d_interpolation_type {
> +	/**
> +	 * @DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL:
> +	 *
> +	 * Tetrahedral 3DLUT interpolation
> +	 */
> +	DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL,
>  };
>  
>  /**


^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 40/43] drm/colorop: Add 3D LUT support to color pipeline
  2025-04-25 13:50   ` Leandro Ribeiro
@ 2025-05-13  3:39     ` Alex Hung
  0 siblings, 0 replies; 128+ messages in thread
From: Alex Hung @ 2025-05-13  3:39 UTC (permalink / raw)
  To: Leandro Ribeiro, dri-devel, amd-gfx
  Cc: wayland-devel, harry.wentland, leo.liu, ville.syrjala,
	pekka.paalanen, contact, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, xaver.hugl,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet



On 4/25/25 07:50, Leandro Ribeiro wrote:
> 
> 
> On 3/26/25 20:47, Alex Hung wrote:
>> It is to be used to enable HDR by allowing userpace to create and pass
>> 3D LUTs to kernel and hardware.
>>
>> new drm_colorop_type: DRM_COLOROP_3D_LUT.
>>
>> Signed-off-by: Alex Hung <alex.hung@amd.com>
>> ---
>> v8:
>>   - Fix typo in subject (Simon Ser)
>>   - Update documentation for DRM_COLOROP_3D_LUT (Simon Ser)
>>   - Delete empty lines (Simon Ser)
>>
>> v7:
>>   - Simplify 3D LUT by removing lut_3d_modes and related functions (Simon Ser)
>>
>>   drivers/gpu/drm/drm_atomic.c      |  6 +++
>>   drivers/gpu/drm/drm_atomic_uapi.c |  6 +++
>>   drivers/gpu/drm/drm_colorop.c     | 72 +++++++++++++++++++++++++++++++
>>   include/drm/drm_colorop.h         | 21 +++++++++
>>   include/uapi/drm/drm_mode.h       | 33 ++++++++++++++
>>   5 files changed, 138 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
>> index 0efb0ead204a..ef47a06344f3 100644
>> --- a/drivers/gpu/drm/drm_atomic.c
>> +++ b/drivers/gpu/drm/drm_atomic.c
>> @@ -806,6 +806,12 @@ static void drm_atomic_colorop_print_state(struct drm_printer *p,
>>   	case DRM_COLOROP_MULTIPLIER:
>>   		drm_printf(p, "\tmultiplier=%llu\n", state->multiplier);
>>   		break;
>> +	case DRM_COLOROP_3D_LUT:
>> +		drm_printf(p, "\tsize=%d\n", colorop->lut_size);
>> +		drm_printf(p, "\tinterpolation=%s\n",
>> +			   drm_get_colorop_lut3d_interpolation_name(colorop->lut3d_interpolation));
>> +		drm_printf(p, "\tdata blob id=%d\n", state->data ? state->data->base.id : 0);
>> +		break;
>>   	default:
>>   		break;
>>   	}
>> diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
>> index 947c18e8bf9b..d5d464b4d0f6 100644
>> --- a/drivers/gpu/drm/drm_atomic_uapi.c
>> +++ b/drivers/gpu/drm/drm_atomic_uapi.c
>> @@ -719,6 +719,10 @@ static int drm_atomic_color_set_data_property(struct drm_colorop *colorop,
>>   	case DRM_COLOROP_CTM_3X4:
>>   		size = sizeof(struct drm_color_ctm_3x4);
>>   		break;
>> +	case DRM_COLOROP_3D_LUT:
>> +		size = colorop->lut_size * colorop->lut_size * colorop->lut_size *
>> +		       sizeof(struct drm_color_lut);
>> +		break;
>>   	default:
>>   		/* should never get here */
>>   		return -EINVAL;
>> @@ -771,6 +775,8 @@ drm_atomic_colorop_get_property(struct drm_colorop *colorop,
>>   		*val = state->multiplier;
>>   	} else if (property == colorop->lut_size_property) {
>>   		*val = colorop->lut_size;
>> +	} else if (property == colorop->lut3d_interpolation_property) {
>> +		*val = colorop->lut3d_interpolation;
>>   	} else if (property == colorop->data_property) {
>>   		*val = (state->data) ? state->data->base.id : 0;
>>   	} else {
>> diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
>> index e03706e7179b..224c6be237d2 100644
>> --- a/drivers/gpu/drm/drm_colorop.c
>> +++ b/drivers/gpu/drm/drm_colorop.c
>> @@ -67,6 +67,7 @@ static const struct drm_prop_enum_list drm_colorop_type_enum_list[] = {
>>   	{ DRM_COLOROP_1D_LUT, "1D LUT" },
>>   	{ DRM_COLOROP_CTM_3X4, "3x4 Matrix"},
>>   	{ DRM_COLOROP_MULTIPLIER, "Multiplier"},
>> +	{ DRM_COLOROP_3D_LUT, "3D LUT"},
>>   };
>>   
>>   static const char * const colorop_curve_1d_type_names[] = {
>> @@ -82,6 +83,11 @@ static const struct drm_prop_enum_list drm_colorop_lut1d_interpolation_list[] =
>>   	{ DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR, "Linear" },
>>   };
>>   
>> +
>> +static const struct drm_prop_enum_list drm_colorop_lut3d_interpolation_list[] = {
>> +	{ DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL, "Tetrahedral" },
>> +};
>> +
>>   /* Init Helpers */
>>   
>>   static int drm_colorop_init(struct drm_device *dev, struct drm_colorop *colorop,
>> @@ -349,6 +355,51 @@ int drm_colorop_mult_init(struct drm_device *dev, struct drm_colorop *colorop,
>>   }
>>   EXPORT_SYMBOL(drm_colorop_mult_init);
>>   
>> +int drm_colorop_3dlut_init(struct drm_device *dev, struct drm_colorop *colorop,
>> +			   struct drm_plane *plane,
>> +			   uint32_t lut_size,
>> +			   enum drm_colorop_lut3d_interpolation_type interpolation,
>> +			   bool allow_bypass)
>> +{
>> +	struct drm_property *prop;
>> +	int ret;
>> +
>> +	ret = drm_colorop_init(dev, colorop, plane, DRM_COLOROP_3D_LUT, allow_bypass);
>> +	if (ret)
>> +		return ret;
>> +
>> +	/* LUT size */
>> +	prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE  | DRM_MODE_PROP_ATOMIC,
>> +					 "SIZE", 0, UINT_MAX);
>> +	if (!prop)
>> +		return -ENOMEM;
>> +
>> +	colorop->lut_size_property = prop;
>> +	drm_object_attach_property(&colorop->base, colorop->lut_size_property, lut_size);
>> +	colorop->lut_size = lut_size;
>> +
>> +	/* interpolation */
>> +	prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, "LUT3D_INTERPOLATION",
>> +					drm_colorop_lut3d_interpolation_list,
>> +					ARRAY_SIZE(drm_colorop_lut3d_interpolation_list));
>> +	if (!prop)
>> +		return -ENOMEM;
>> +
>> +	colorop->lut3d_interpolation_property = prop;
>> +	drm_object_attach_property(&colorop->base, prop, interpolation);
>> +	colorop->lut3d_interpolation = interpolation;
>> +
>> +	/* data */
>> +	ret = drm_colorop_create_data_prop(dev, colorop);
>> +	if (ret)
>> +		return ret;
>> +
>> +	drm_colorop_reset(colorop);
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL(drm_colorop_3dlut_init);
>> +
>>   static void __drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop,
>>   							struct drm_colorop_state *state)
>>   {
>> @@ -441,7 +492,13 @@ static const char * const colorop_type_name[] = {
>>   	[DRM_COLOROP_1D_LUT] = "1D LUT",
>>   	[DRM_COLOROP_CTM_3X4] = "3x4 Matrix",
>>   	[DRM_COLOROP_MULTIPLIER] = "Multiplier",
>> +	[DRM_COLOROP_3D_LUT] = "3D LUT",
>>   };
>> +
>> +static const char * const colorop_lu3d_interpolation_name[] = {
>> +	[DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL] = "Tetrahedral",
>> +};
>> +
>>   static const char * const colorop_lut1d_interpolation_name[] = {
>>   	[DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR] = "Linear",
>>   };
>> @@ -477,6 +534,21 @@ const char *drm_get_colorop_lut1d_interpolation_name(enum drm_colorop_lut1d_inte
>>   	return colorop_lut1d_interpolation_name[type];
>>   }
>>   
>> +/**
>> + * drm_get_colorop_lut3d_interpolation_name - return a string for interpolation type
>> + * @type: interpolation type to compute name of
>> + *
>> + * In contrast to the other drm_get_*_name functions this one here returns a
>> + * const pointer and hence is threadsafe.
>> + */
>> +const char *drm_get_colorop_lut3d_interpolation_name(enum drm_colorop_lut3d_interpolation_type type)
>> +{
>> +	if (WARN_ON(type >= ARRAY_SIZE(colorop_lu3d_interpolation_name)))
>> +		return "unknown";
>> +
>> +	return colorop_lu3d_interpolation_name[type];
>> +}
>> +
>>   /**
>>    * drm_colorop_set_next_property - sets the next pointer
>>    * @colorop: drm colorop
>> diff --git a/include/drm/drm_colorop.h b/include/drm/drm_colorop.h
>> index c89d5eb44856..e999d5ceb8a5 100644
>> --- a/include/drm/drm_colorop.h
>> +++ b/include/drm/drm_colorop.h
>> @@ -281,6 +281,14 @@ struct drm_colorop {
>>   	 */
>>   	enum drm_colorop_lut1d_interpolation_type lut1d_interpolation;
>>   
>> +	/**
>> +	 * @lut3d_interpolation:
>> +	 *
>> +	 * Read-only
>> +	 * Interpolation for DRM_COLOROP_3D_LUT
>> +	 */
>> +	enum drm_colorop_lut3d_interpolation_type lut3d_interpolation;
>> +
>>   	/**
>>   	 * @lut1d_interpolation_property:
>>   	 *
>> @@ -309,6 +317,13 @@ struct drm_colorop {
>>   	 */
>>   	struct drm_property *lut_size_property;
>>   
>> +	/**
>> +	 * @lut3d_interpolation_property:
>> +	 *
>> +	 * Read-only property for DRM_COLOROP_3D_LUT interpolation
>> +	 */
>> +	struct drm_property *lut3d_interpolation_property;
>> +
>>   	/**
>>   	 * @data_property:
>>   	 *
>> @@ -362,6 +377,11 @@ int drm_colorop_ctm_3x4_init(struct drm_device *dev, struct drm_colorop *colorop
>>   			     struct drm_plane *plane, bool allow_bypass);
>>   int drm_colorop_mult_init(struct drm_device *dev, struct drm_colorop *colorop,
>>   			      struct drm_plane *plane, bool allow_bypass);
>> +int drm_colorop_3dlut_init(struct drm_device *dev, struct drm_colorop *colorop,
>> +			   struct drm_plane *plane,
>> +			   uint32_t lut_size,
>> +			   enum drm_colorop_lut3d_interpolation_type interpolation,
>> +			   bool allow_bypass);
>>   
>>   struct drm_colorop_state *
>>   drm_atomic_helper_colorop_duplicate_state(struct drm_colorop *colorop);
>> @@ -412,6 +432,7 @@ const char *drm_get_colorop_type_name(enum drm_colorop_type type);
>>    */
>>   const char *drm_get_colorop_curve_1d_type_name(enum drm_colorop_curve_1d_type type);
>>   const char *drm_get_colorop_lut1d_interpolation_name(enum drm_colorop_lut1d_interpolation_type type);
>> +const char *drm_get_colorop_lut3d_interpolation_name(enum drm_colorop_lut3d_interpolation_type type);
>>   
>>   void drm_colorop_set_next_property(struct drm_colorop *colorop, struct drm_colorop *next);
>>   
>> diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
>> index d76c8ffe5408..88fafbdeb2a2 100644
>> --- a/include/uapi/drm/drm_mode.h
>> +++ b/include/uapi/drm/drm_mode.h
>> @@ -930,6 +930,39 @@ enum drm_colorop_type {
>>   	 * property.
>>   	 */
>>   	DRM_COLOROP_MULTIPLIER,
>> +
>> +	/**
>> +	 * @DRM_COLOROP_3D_LUT:
>> +	 *
>> +	 * enum string "3D LUT"
>> +	 *
>> +	 * A 3D LUT of &drm_color_lut entries,
>> +	 * packed into a blob via the DATA property. The driver's expected
>> +	 * LUT size is advertised via the SIZE property, i.e., a 3D LUT with
>> +	 * 17x17x17 entries will have SIZE set to 17.
>> +	 *
>> +	 * The DATA blob is a 3D array of struct drm_color_lut with dimension
>> +	 * length of "lut_size".
>> +	 * The LUT elements are traversed like so:
>> +	 *
>> +	 *   for R in range 0..n
>> +	 *     for G in range 0..n
>> +	 *       for B in range 0..n
>> +	 *         color = lut3d[R][G][B]
>> +	 */
>> +	DRM_COLOROP_3D_LUT,
>> +};
> 
> Hi,
> 
> I'm experimenting with V7 of the this API on Weston, using the AMD driver,
> and I'm seeing issues with the usage of 3D LUT's: channels R and B being
> swapped.
> On Weston, the 3D LUT is constructed as:
> 
> for B in range 0..n
>      for G in range 0..n
>         for R in range 0..n
>             index = R + n * (G + n * B)
>             lut[index].red   = foo
>             lut[index].green = foo
>             lut[index].blue  = foo
> 
> To map that to DRM_COLOROP_3D_LUT, we do:
> 
> for B in range 0..n
>      for G in range 0..n
>         for R in range 0..n
>             index_weston = R + n * (G + n * B)
>             index_kernel = B + n * (G + n * R)
>             lut_kernel[index_kernel].red   = lut[index_weston].red
>             lut_kernel[index_kernel].green = lut[index_weston].green
>             lut_kernel[index_kernel].blue  = lut[index_weston].blue
> 
> If I ignore the documentation and use the same indices, everything works
> fine regarding the color channels.
> 

I think you are right here. The comment above should state index_kernel 
= R + n * (G + n * B). This also seems to be how corresponding IGT test is.

> Maybe there's a bug in our Weston code, but writing this just to confirm
> that the documentation and the AMD driver are matching.
> 
> Thanks,
> Leandro
> 
>> +
>> +/**
>> + * enum drm_colorop_lut3d_interpolation_type - type of 3DLUT interpolation
>> + */
>> +enum drm_colorop_lut3d_interpolation_type {
>> +	/**
>> +	 * @DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL:
>> +	 *
>> +	 * Tetrahedral 3DLUT interpolation
>> +	 */
>> +	DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL,
>>   };
>>   
>>   /**
> 


^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 40/43] drm/colorop: Add 3D LUT support to color pipeline
  2025-03-26 23:47 ` [PATCH V8 40/43] drm/colorop: Add 3D LUT support to color pipeline Alex Hung
  2025-03-29 14:57   ` Simon Ser
  2025-04-25 13:50   ` Leandro Ribeiro
@ 2025-05-17  1:22   ` Xaver Hugl
  2025-05-17 11:53     ` Simon Ser
  2025-05-17 17:36     ` Autumn Ashton
  2 siblings, 2 replies; 128+ messages in thread
From: Xaver Hugl @ 2025-05-17  1:22 UTC (permalink / raw)
  To: Alex Hung
  Cc: dri-devel, amd-gfx, wayland-devel, harry.wentland, leo.liu,
	ville.syrjala, pekka.paalanen, contact, mwen, jadahl,
	sebastian.wick, shashank.sharma, agoins, joshua, mdaenzer,
	aleixpol, victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

Am Do., 27. März 2025 um 00:58 Uhr schrieb Alex Hung <alex.hung@amd.com>:
>
> It is to be used to enable HDR by allowing userpace to create and pass
> 3D LUTs to kernel and hardware.
>
> new drm_colorop_type: DRM_COLOROP_3D_LUT.
>
> Signed-off-by: Alex Hung <alex.hung@amd.com>
> ---
> v8:
>  - Fix typo in subject (Simon Ser)
>  - Update documentation for DRM_COLOROP_3D_LUT (Simon Ser)
>  - Delete empty lines (Simon Ser)
>
> v7:
>  - Simplify 3D LUT by removing lut_3d_modes and related functions (Simon Ser)
>
>  drivers/gpu/drm/drm_atomic.c      |  6 +++
>  drivers/gpu/drm/drm_atomic_uapi.c |  6 +++
>  drivers/gpu/drm/drm_colorop.c     | 72 +++++++++++++++++++++++++++++++
>  include/drm/drm_colorop.h         | 21 +++++++++
>  include/uapi/drm/drm_mode.h       | 33 ++++++++++++++
>  5 files changed, 138 insertions(+)
>
> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> index 0efb0ead204a..ef47a06344f3 100644
> --- a/drivers/gpu/drm/drm_atomic.c
> +++ b/drivers/gpu/drm/drm_atomic.c
> @@ -806,6 +806,12 @@ static void drm_atomic_colorop_print_state(struct drm_printer *p,
>         case DRM_COLOROP_MULTIPLIER:
>                 drm_printf(p, "\tmultiplier=%llu\n", state->multiplier);
>                 break;
> +       case DRM_COLOROP_3D_LUT:
> +               drm_printf(p, "\tsize=%d\n", colorop->lut_size);
> +               drm_printf(p, "\tinterpolation=%s\n",
> +                          drm_get_colorop_lut3d_interpolation_name(colorop->lut3d_interpolation));
> +               drm_printf(p, "\tdata blob id=%d\n", state->data ? state->data->base.id : 0);
> +               break;
>         default:
>                 break;
>         }
> diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
> index 947c18e8bf9b..d5d464b4d0f6 100644
> --- a/drivers/gpu/drm/drm_atomic_uapi.c
> +++ b/drivers/gpu/drm/drm_atomic_uapi.c
> @@ -719,6 +719,10 @@ static int drm_atomic_color_set_data_property(struct drm_colorop *colorop,
>         case DRM_COLOROP_CTM_3X4:
>                 size = sizeof(struct drm_color_ctm_3x4);
>                 break;
> +       case DRM_COLOROP_3D_LUT:
> +               size = colorop->lut_size * colorop->lut_size * colorop->lut_size *
> +                      sizeof(struct drm_color_lut);
> +               break;
>         default:
>                 /* should never get here */
>                 return -EINVAL;
> @@ -771,6 +775,8 @@ drm_atomic_colorop_get_property(struct drm_colorop *colorop,
>                 *val = state->multiplier;
>         } else if (property == colorop->lut_size_property) {
>                 *val = colorop->lut_size;
> +       } else if (property == colorop->lut3d_interpolation_property) {
> +               *val = colorop->lut3d_interpolation;
>         } else if (property == colorop->data_property) {
>                 *val = (state->data) ? state->data->base.id : 0;
>         } else {
> diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
> index e03706e7179b..224c6be237d2 100644
> --- a/drivers/gpu/drm/drm_colorop.c
> +++ b/drivers/gpu/drm/drm_colorop.c
> @@ -67,6 +67,7 @@ static const struct drm_prop_enum_list drm_colorop_type_enum_list[] = {
>         { DRM_COLOROP_1D_LUT, "1D LUT" },
>         { DRM_COLOROP_CTM_3X4, "3x4 Matrix"},
>         { DRM_COLOROP_MULTIPLIER, "Multiplier"},
> +       { DRM_COLOROP_3D_LUT, "3D LUT"},
>  };
>
>  static const char * const colorop_curve_1d_type_names[] = {
> @@ -82,6 +83,11 @@ static const struct drm_prop_enum_list drm_colorop_lut1d_interpolation_list[] =
>         { DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR, "Linear" },
>  };
>
> +
> +static const struct drm_prop_enum_list drm_colorop_lut3d_interpolation_list[] = {
> +       { DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL, "Tetrahedral" },
> +};
> +
>  /* Init Helpers */
>
>  static int drm_colorop_init(struct drm_device *dev, struct drm_colorop *colorop,
> @@ -349,6 +355,51 @@ int drm_colorop_mult_init(struct drm_device *dev, struct drm_colorop *colorop,
>  }
>  EXPORT_SYMBOL(drm_colorop_mult_init);
>
> +int drm_colorop_3dlut_init(struct drm_device *dev, struct drm_colorop *colorop,
> +                          struct drm_plane *plane,
> +                          uint32_t lut_size,
> +                          enum drm_colorop_lut3d_interpolation_type interpolation,
> +                          bool allow_bypass)
> +{
> +       struct drm_property *prop;
> +       int ret;
> +
> +       ret = drm_colorop_init(dev, colorop, plane, DRM_COLOROP_3D_LUT, allow_bypass);
> +       if (ret)
> +               return ret;
> +
> +       /* LUT size */
> +       prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE  | DRM_MODE_PROP_ATOMIC,
> +                                        "SIZE", 0, UINT_MAX);
> +       if (!prop)
> +               return -ENOMEM;
> +
> +       colorop->lut_size_property = prop;
> +       drm_object_attach_property(&colorop->base, colorop->lut_size_property, lut_size);
> +       colorop->lut_size = lut_size;
> +
> +       /* interpolation */
> +       prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, "LUT3D_INTERPOLATION",

Do we ever expect this to be something with multiple options that
userspace could select? I think it would be good to keep our options
open and make this property not immutable (properties that are
sometimes but not always immutable are more annoying to deal with in
userspace).

Same applies to 1D LUTs as well.

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 40/43] drm/colorop: Add 3D LUT support to color pipeline
  2025-05-17  1:22   ` Xaver Hugl
@ 2025-05-17 11:53     ` Simon Ser
  2025-05-17 22:32       ` Xaver Hugl
  2025-05-17 17:36     ` Autumn Ashton
  1 sibling, 1 reply; 128+ messages in thread
From: Simon Ser @ 2025-05-17 11:53 UTC (permalink / raw)
  To: Xaver Hugl
  Cc: Alex Hung, dri-devel, amd-gfx, wayland-devel, harry.wentland,
	leo.liu, ville.syrjala, pekka.paalanen, mwen, jadahl,
	sebastian.wick, shashank.sharma, agoins, joshua, mdaenzer,
	aleixpol, victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

On Saturday, May 17th, 2025 at 03:23, Xaver Hugl <xaver.hugl@gmail.com> wrote:

> Do we ever expect this to be something with multiple options that
> userspace could select? I think it would be good to keep our options
> open and make this property not immutable (properties that are
> sometimes but not always immutable are more annoying to deal with in
> userspace).

We can always make the property mutable on drivers that support it in
the future, much like the zpos property. I think we should keep it
immutable for now.

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 40/43] drm/colorop: Add 3D LUT support to color pipeline
  2025-05-17  1:22   ` Xaver Hugl
  2025-05-17 11:53     ` Simon Ser
@ 2025-05-17 17:36     ` Autumn Ashton
  1 sibling, 0 replies; 128+ messages in thread
From: Autumn Ashton @ 2025-05-17 17:36 UTC (permalink / raw)
  To: Xaver Hugl, Alex Hung
  Cc: dri-devel, amd-gfx, wayland-devel, harry.wentland, leo.liu,
	ville.syrjala, pekka.paalanen, contact, mwen, jadahl,
	sebastian.wick, shashank.sharma, agoins, mdaenzer, aleixpol,
	victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet


On 5/17/25 2:22 AM, Xaver Hugl wrote:
> Am Do., 27. März 2025 um 00:58 Uhr schrieb Alex Hung <alex.hung@amd.com>:
>> It is to be used to enable HDR by allowing userpace to create and pass
>> 3D LUTs to kernel and hardware.
>>
>> new drm_colorop_type: DRM_COLOROP_3D_LUT.
>>
>> Signed-off-by: Alex Hung <alex.hung@amd.com>
>> ---
>> v8:
>>   - Fix typo in subject (Simon Ser)
>>   - Update documentation for DRM_COLOROP_3D_LUT (Simon Ser)
>>   - Delete empty lines (Simon Ser)
>>
>> v7:
>>   - Simplify 3D LUT by removing lut_3d_modes and related functions (Simon Ser)
>>
>>   drivers/gpu/drm/drm_atomic.c      |  6 +++
>>   drivers/gpu/drm/drm_atomic_uapi.c |  6 +++
>>   drivers/gpu/drm/drm_colorop.c     | 72 +++++++++++++++++++++++++++++++
>>   include/drm/drm_colorop.h         | 21 +++++++++
>>   include/uapi/drm/drm_mode.h       | 33 ++++++++++++++
>>   5 files changed, 138 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
>> index 0efb0ead204a..ef47a06344f3 100644
>> --- a/drivers/gpu/drm/drm_atomic.c
>> +++ b/drivers/gpu/drm/drm_atomic.c
>> @@ -806,6 +806,12 @@ static void drm_atomic_colorop_print_state(struct drm_printer *p,
>>          case DRM_COLOROP_MULTIPLIER:
>>                  drm_printf(p, "\tmultiplier=%llu\n", state->multiplier);
>>                  break;
>> +       case DRM_COLOROP_3D_LUT:
>> +               drm_printf(p, "\tsize=%d\n", colorop->lut_size);
>> +               drm_printf(p, "\tinterpolation=%s\n",
>> +                          drm_get_colorop_lut3d_interpolation_name(colorop->lut3d_interpolation));
>> +               drm_printf(p, "\tdata blob id=%d\n", state->data ? state->data->base.id : 0);
>> +               break;
>>          default:
>>                  break;
>>          }
>> diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
>> index 947c18e8bf9b..d5d464b4d0f6 100644
>> --- a/drivers/gpu/drm/drm_atomic_uapi.c
>> +++ b/drivers/gpu/drm/drm_atomic_uapi.c
>> @@ -719,6 +719,10 @@ static int drm_atomic_color_set_data_property(struct drm_colorop *colorop,
>>          case DRM_COLOROP_CTM_3X4:
>>                  size = sizeof(struct drm_color_ctm_3x4);
>>                  break;
>> +       case DRM_COLOROP_3D_LUT:
>> +               size = colorop->lut_size * colorop->lut_size * colorop->lut_size *
>> +                      sizeof(struct drm_color_lut);
>> +               break;
>>          default:
>>                  /* should never get here */
>>                  return -EINVAL;
>> @@ -771,6 +775,8 @@ drm_atomic_colorop_get_property(struct drm_colorop *colorop,
>>                  *val = state->multiplier;
>>          } else if (property == colorop->lut_size_property) {
>>                  *val = colorop->lut_size;
>> +       } else if (property == colorop->lut3d_interpolation_property) {
>> +               *val = colorop->lut3d_interpolation;
>>          } else if (property == colorop->data_property) {
>>                  *val = (state->data) ? state->data->base.id : 0;
>>          } else {
>> diff --git a/drivers/gpu/drm/drm_colorop.c b/drivers/gpu/drm/drm_colorop.c
>> index e03706e7179b..224c6be237d2 100644
>> --- a/drivers/gpu/drm/drm_colorop.c
>> +++ b/drivers/gpu/drm/drm_colorop.c
>> @@ -67,6 +67,7 @@ static const struct drm_prop_enum_list drm_colorop_type_enum_list[] = {
>>          { DRM_COLOROP_1D_LUT, "1D LUT" },
>>          { DRM_COLOROP_CTM_3X4, "3x4 Matrix"},
>>          { DRM_COLOROP_MULTIPLIER, "Multiplier"},
>> +       { DRM_COLOROP_3D_LUT, "3D LUT"},
>>   };
>>
>>   static const char * const colorop_curve_1d_type_names[] = {
>> @@ -82,6 +83,11 @@ static const struct drm_prop_enum_list drm_colorop_lut1d_interpolation_list[] =
>>          { DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR, "Linear" },
>>   };
>>
>> +
>> +static const struct drm_prop_enum_list drm_colorop_lut3d_interpolation_list[] = {
>> +       { DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL, "Tetrahedral" },
>> +};
>> +
>>   /* Init Helpers */
>>
>>   static int drm_colorop_init(struct drm_device *dev, struct drm_colorop *colorop,
>> @@ -349,6 +355,51 @@ int drm_colorop_mult_init(struct drm_device *dev, struct drm_colorop *colorop,
>>   }
>>   EXPORT_SYMBOL(drm_colorop_mult_init);
>>
>> +int drm_colorop_3dlut_init(struct drm_device *dev, struct drm_colorop *colorop,
>> +                          struct drm_plane *plane,
>> +                          uint32_t lut_size,
>> +                          enum drm_colorop_lut3d_interpolation_type interpolation,
>> +                          bool allow_bypass)
>> +{
>> +       struct drm_property *prop;
>> +       int ret;
>> +
>> +       ret = drm_colorop_init(dev, colorop, plane, DRM_COLOROP_3D_LUT, allow_bypass);
>> +       if (ret)
>> +               return ret;
>> +
>> +       /* LUT size */
>> +       prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE  | DRM_MODE_PROP_ATOMIC,
>> +                                        "SIZE", 0, UINT_MAX);
>> +       if (!prop)
>> +               return -ENOMEM;
>> +
>> +       colorop->lut_size_property = prop;
>> +       drm_object_attach_property(&colorop->base, colorop->lut_size_property, lut_size);
>> +       colorop->lut_size = lut_size;
>> +
>> +       /* interpolation */
>> +       prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, "LUT3D_INTERPOLATION",
> Do we ever expect this to be something with multiple options that
> userspace could select? I think it would be good to keep our options
> open and make this property not immutable (properties that are
> sometimes but not always immutable are more annoying to deal with in
> userspace).


I don't think so, AFAIK on AMD there is only tetrahedral.

Other vendors might have that as configurable, but I imagine that's why 
this is immutable in this instance.


Whether or not the interpolation mode is tetrahedral or linear would 
probably affect whether I would use the HW block.

Small (eg. 9x9x9 or 17x17x17) 3D LUTs interpolated as linear cannot 
apply identity 3D LUTs as identity.

This is why we do manual tetrahedral sampling in Gamescope in our shader 
path too...


- Autumn ✨


>
> Same applies to 1D LUTs as well.


^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 40/43] drm/colorop: Add 3D LUT support to color pipeline
  2025-05-17 11:53     ` Simon Ser
@ 2025-05-17 22:32       ` Xaver Hugl
  2025-05-19 23:43         ` Simon Ser
  0 siblings, 1 reply; 128+ messages in thread
From: Xaver Hugl @ 2025-05-17 22:32 UTC (permalink / raw)
  To: Simon Ser
  Cc: Alex Hung, dri-devel, amd-gfx, wayland-devel, harry.wentland,
	leo.liu, ville.syrjala, pekka.paalanen, mwen, jadahl,
	sebastian.wick, shashank.sharma, agoins, joshua, mdaenzer,
	aleixpol, victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

> We can always make the property mutable on drivers that support it in
> the future, much like the zpos property. I think we should keep it
> immutable for now.

Sure, but I don't see any reason for immutability with an enum
property - it can just limit the possible values to what it supports,
and that can be only one value. Either way, it's not a big issue.

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 40/43] drm/colorop: Add 3D LUT support to color pipeline
  2025-05-17 22:32       ` Xaver Hugl
@ 2025-05-19 23:43         ` Simon Ser
  2025-05-20 20:13           ` Harry Wentland
  0 siblings, 1 reply; 128+ messages in thread
From: Simon Ser @ 2025-05-19 23:43 UTC (permalink / raw)
  To: Xaver Hugl
  Cc: Alex Hung, dri-devel, amd-gfx, wayland-devel, harry.wentland,
	leo.liu, ville.syrjala, pekka.paalanen, mwen, jadahl,
	sebastian.wick, shashank.sharma, agoins, joshua, mdaenzer,
	aleixpol, victoria, daniel, uma.shankar, quic_naseer, quic_cbraga,
	quic_abhinavk, marcan, Liviu.Dudau, sashamcintosh,
	chaitanya.kumar.borah, louis.chauvet

On Sunday, May 18th, 2025 at 00:32, Xaver Hugl <xaver.hugl@gmail.com> wrote:

> > We can always make the property mutable on drivers that support it in
> 
> > the future, much like the zpos property. I think we should keep it
> > immutable for now.
> 
> Sure, but I don't see any reason for immutability with an enum
> property - it can just limit the possible values to what it supports,
> and that can be only one value. Either way, it's not a big issue.

Immutability is a clear indication that a property has a fixed read-only
value which can't be switched by user-space. That's also the pattern
used everywhere in the KMS uAPI, so I think it's better to remain
consistent here.

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 40/43] drm/colorop: Add 3D LUT support to color pipeline
  2025-05-19 23:43         ` Simon Ser
@ 2025-05-20 20:13           ` Harry Wentland
  2025-05-21 19:18             ` Harry Wentland
  0 siblings, 1 reply; 128+ messages in thread
From: Harry Wentland @ 2025-05-20 20:13 UTC (permalink / raw)
  To: Simon Ser, Xaver Hugl
  Cc: Alex Hung, dri-devel, amd-gfx, wayland-devel, leo.liu,
	ville.syrjala, pekka.paalanen, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, victoria,
	daniel, uma.shankar, quic_naseer, quic_cbraga, quic_abhinavk,
	marcan, Liviu.Dudau, sashamcintosh, chaitanya.kumar.borah,
	louis.chauvet



On 2025-05-19 19:43, Simon Ser wrote:
> On Sunday, May 18th, 2025 at 00:32, Xaver Hugl <xaver.hugl@gmail.com> wrote:
> 
>>> We can always make the property mutable on drivers that support it in
>>
>>> the future, much like the zpos property. I think we should keep it
>>> immutable for now.
>>
>> Sure, but I don't see any reason for immutability with an enum
>> property - it can just limit the possible values to what it supports,
>> and that can be only one value. Either way, it's not a big issue.
> 
> Immutability is a clear indication that a property has a fixed read-only
> value which can't be switched by user-space. That's also the pattern
> used everywhere in the KMS uAPI, so I think it's better to remain
> consistent here.

I was envisioning this to be a driver-caps thing, but I agree
if we make this mutable it can still serve that function but with
different/future HW possibly support other interpolation schemes.

Harry

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 40/43] drm/colorop: Add 3D LUT support to color pipeline
  2025-05-20 20:13           ` Harry Wentland
@ 2025-05-21 19:18             ` Harry Wentland
  2025-05-22 10:14               ` Simon Ser
  0 siblings, 1 reply; 128+ messages in thread
From: Harry Wentland @ 2025-05-21 19:18 UTC (permalink / raw)
  To: Simon Ser, Xaver Hugl
  Cc: Alex Hung, dri-devel, amd-gfx, wayland-devel, leo.liu,
	ville.syrjala, pekka.paalanen, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, victoria,
	daniel, uma.shankar, quic_naseer, quic_cbraga, quic_abhinavk,
	marcan, Liviu.Dudau, sashamcintosh, chaitanya.kumar.borah,
	louis.chauvet



On 2025-05-20 16:13, Harry Wentland wrote:
> 
> 
> On 2025-05-19 19:43, Simon Ser wrote:
>> On Sunday, May 18th, 2025 at 00:32, Xaver Hugl <xaver.hugl@gmail.com> wrote:
>>
>>>> We can always make the property mutable on drivers that support it in
>>>
>>>> the future, much like the zpos property. I think we should keep it
>>>> immutable for now.
>>>
>>> Sure, but I don't see any reason for immutability with an enum
>>> property - it can just limit the possible values to what it supports,
>>> and that can be only one value. Either way, it's not a big issue.
>>
>> Immutability is a clear indication that a property has a fixed read-only
>> value which can't be switched by user-space. That's also the pattern
>> used everywhere in the KMS uAPI, so I think it's better to remain
>> consistent here.
> 
> I was envisioning this to be a driver-caps thing, but I agree
> if we make this mutable it can still serve that function but with
> different/future HW possibly support other interpolation schemes.
> 

Would changing this enum property from IMMUTABLE to MUTABLE
in the future (for drivers that support multiple types) break
any userspace that assumes IMMUTABLE?

If not, maybe it's best to leave it IMMUTABLE now and change
it only in the future if needed.

Harry

> Harry


^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 40/43] drm/colorop: Add 3D LUT support to color pipeline
  2025-05-21 19:18             ` Harry Wentland
@ 2025-05-22 10:14               ` Simon Ser
  2025-05-22 11:46                 ` Shankar, Uma
  0 siblings, 1 reply; 128+ messages in thread
From: Simon Ser @ 2025-05-22 10:14 UTC (permalink / raw)
  To: Harry Wentland
  Cc: Xaver Hugl, Alex Hung, dri-devel, amd-gfx, wayland-devel, leo.liu,
	ville.syrjala, pekka.paalanen, mwen, jadahl, sebastian.wick,
	shashank.sharma, agoins, joshua, mdaenzer, aleixpol, victoria,
	daniel, uma.shankar, quic_naseer, quic_cbraga, quic_abhinavk,
	marcan, Liviu.Dudau, sashamcintosh, chaitanya.kumar.borah,
	louis.chauvet

On Wednesday, May 21st, 2025 at 21:18, Harry Wentland <harry.wentland@amd.com> wrote:

> On 2025-05-20 16:13, Harry Wentland wrote:
> 
> > On 2025-05-19 19:43, Simon Ser wrote:
> > 
> > > On Sunday, May 18th, 2025 at 00:32, Xaver Hugl xaver.hugl@gmail.com wrote:
> > > 
> > > > > We can always make the property mutable on drivers that support it in
> > > > 
> > > > > the future, much like the zpos property. I think we should keep it
> > > > > immutable for now.
> > > > 
> > > > Sure, but I don't see any reason for immutability with an enum
> > > > property - it can just limit the possible values to what it supports,
> > > > and that can be only one value. Either way, it's not a big issue.
> > > 
> > > Immutability is a clear indication that a property has a fixed read-only
> > > value which can't be switched by user-space. That's also the pattern
> > > used everywhere in the KMS uAPI, so I think it's better to remain
> > > consistent here.
> > 
> > I was envisioning this to be a driver-caps thing, but I agree
> > if we make this mutable it can still serve that function but with
> > different/future HW possibly support other interpolation schemes.
> 
> Would changing this enum property from IMMUTABLE to MUTABLE
> in the future (for drivers that support multiple types) break
> any userspace that assumes IMMUTABLE?

I don't think it would, see the zpos property.

^ permalink raw reply	[flat|nested] 128+ messages in thread

* RE: [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type
  2025-04-15 16:25           ` Simon Ser
@ 2025-05-22 11:33             ` Shankar, Uma
  2025-05-30 13:58               ` Pekka Paalanen
  0 siblings, 1 reply; 128+ messages in thread
From: Shankar, Uma @ 2025-05-22 11:33 UTC (permalink / raw)
  To: Simon Ser, Harry Wentland
  Cc: Alex Hung, dri-devel@lists.freedesktop.org,
	amd-gfx@lists.freedesktop.org, intel-gfx@lists.freedesktop.org,
	wayland-devel@lists.freedesktop.org, leo.liu@amd.com,
	ville.syrjala@linux.intel.com, pekka.paalanen@collabora.com,
	mwen@igalia.com, jadahl@redhat.com, sebastian.wick@redhat.com,
	shashank.sharma@amd.com, agoins@nvidia.com, joshua@froggi.es,
	mdaenzer@redhat.com, aleixpol@kde.org, xaver.hugl@gmail.com,
	victoria@system76.com, daniel@ffwll.ch, quic_naseer@quicinc.com,
	quic_cbraga@quicinc.com, quic_abhinavk@quicinc.com,
	marcan@marcan.st, Liviu.Dudau@arm.com, sashamcintosh@google.com,
	Borah, Chaitanya Kumar, louis.chauvet@bootlin.com



> -----Original Message-----
> From: wayland-devel <wayland-devel-bounces@lists.freedesktop.org> On Behalf
> Of Simon Ser
> Sent: Tuesday, April 15, 2025 9:55 PM
> To: Harry Wentland <harry.wentland@amd.com>
> Cc: Shankar, Uma <uma.shankar@intel.com>; Alex Hung <alex.hung@amd.com>;
> dri-devel@lists.freedesktop.org; amd-gfx@lists.freedesktop.org; intel-
> gfx@lists.freedesktop.org; wayland-devel@lists.freedesktop.org;
> leo.liu@amd.com; ville.syrjala@linux.intel.com; pekka.paalanen@collabora.com;
> mwen@igalia.com; jadahl@redhat.com; sebastian.wick@redhat.com;
> shashank.sharma@amd.com; agoins@nvidia.com; joshua@froggi.es;
> mdaenzer@redhat.com; aleixpol@kde.org; xaver.hugl@gmail.com;
> victoria@system76.com; daniel@ffwll.ch; quic_naseer@quicinc.com;
> quic_cbraga@quicinc.com; quic_abhinavk@quicinc.com; marcan@marcan.st;
> Liviu.Dudau@arm.com; sashamcintosh@google.com; Borah, Chaitanya Kumar
> <chaitanya.kumar.borah@intel.com>; louis.chauvet@bootlin.com
> Subject: Re: [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type
> 
> On Tuesday, April 15th, 2025 at 17:05, Harry Wentland
> <harry.wentland@amd.com> wrote:
> 
> > > > > We want to have just one change in the way we expose the
> > > > > hardware capabilities else all looks good in general.
> > > >
> > > > I would really recommend leaving this as a follow-up extension.
> > > > It's a complicated addition that requires more discussion.
> > >
> > > Hi Simon,
> > > We have tried to solve the complex part and made it simple to
> > > understand and implement along with a reference implementation [1] (can
> also help add the same for AMD case as well).
> > > Without this we will end up with up 2 interfaces for 1dL Lut which
> > > is not nice where the one above will be able to cover the current
> > > one. Let us know the problems with the proposed interface and we can
> > > work to fix the same. But having a common and single interface is
> > > good and the current one will not fit Intel's color pipeline distribution so the
> generic one anyways will be needed, and it will benefit userspace to know the
> underlying LUT distribution to compute the LUT samples.
> > >
> > > [1] https://patchwork.freedesktop.org/series/129812/
> >
> > I think there is a lot of value in giving userspace a simple LUT to
> > work with. There are many compositors and many compositor maintainers.
> > When someone new jumps into color management usually same thing
> > happens. It starts with "it's not too complicated", and then over a
> > period of time progresses to "this is very much non-trivial" as
> > understanding one bit usually opens ten more questions.
> >
> > Forcing people to deal with another level of complexity will
> > discourage implementations and be counterproductive to furthering
> > adoption of color operations for HW acceleration, IMO.
> >
> > I'm am not opposed to a complex LUT definition but I don't think it
> > should replace a simple and well-understood definition.
> 
> Agreed. To add on this, I think shipping many additional features from day one
> significantly increases the work load (more code to write, review, test at once)
> and we'd also need to go through supplementary rounds to validate the API
> design and ensure it's not too Intel-specific. Also adding this feature as a second
> step will prove that the API is as extensible as we desire.

Apologies for getting back late to the thread.  Sure, we can go with this and extend it later.

> I don't really understand why it's important to have this feature in the first
> version. Intel has been converting simple LUTs into the fancy distribution for the
> existing GAMMA_LUT and DEGAMMA_LUT for a while, so can do it for colorop as
> well. The upsides of the fancy distribution is more precise and smaller LUTs, but
> that doesn't seem critical?

Yes Simon, Intel has managed to somehow fit multiple segments with the existing design. It was
manageable where we had lut divided in 2-3 segments, but we have some cases where distribution
of luts is totally non-uniform (in logarithmic fashion as an example). But will add this as follow up once
the basic UAPI is merged.

One request though: Can we enhance the lut samples from existing 16bits to 32bits as lut precision is
going to be more than 16 in certain hardware. While adding the new UAPI, lets extend this to 32 to make it future proof.
Reference: https://patchwork.freedesktop.org/patch/642592/?series=129811&rev=4

+/**
+ * struct drm_color_lut_32 - Represents high precision lut values
+ *
+ * Creating 32 bit palette entries for better data
+ * precision. This will be required for HDR and
+ * similar color processing usecases.
+ */
+struct drm_color_lut_32 {
+	/*
+	 * Data for high precision LUTs
+	 */
+	__u32 red;
+	__u32 green;
+	__u32 blue;
+	__u32 reserved;
+};

Regards,
Uma Shankar

> Simon

^ permalink raw reply	[flat|nested] 128+ messages in thread

* RE: [PATCH V8 40/43] drm/colorop: Add 3D LUT support to color pipeline
  2025-05-22 10:14               ` Simon Ser
@ 2025-05-22 11:46                 ` Shankar, Uma
  0 siblings, 0 replies; 128+ messages in thread
From: Shankar, Uma @ 2025-05-22 11:46 UTC (permalink / raw)
  To: Simon Ser, Harry Wentland
  Cc: Xaver Hugl, Alex Hung, dri-devel@lists.freedesktop.org,
	amd-gfx@lists.freedesktop.org,
	wayland-devel@lists.freedesktop.org, leo.liu@amd.com,
	ville.syrjala@linux.intel.com, pekka.paalanen@collabora.com,
	mwen@igalia.com, jadahl@redhat.com, sebastian.wick@redhat.com,
	shashank.sharma@amd.com, agoins@nvidia.com, joshua@froggi.es,
	mdaenzer@redhat.com, aleixpol@kde.org, victoria@system76.com,
	daniel@ffwll.ch, quic_naseer@quicinc.com, quic_cbraga@quicinc.com,
	quic_abhinavk@quicinc.com, marcan@marcan.st, Liviu.Dudau@arm.com,
	sashamcintosh@google.com, Borah, Chaitanya Kumar,
	louis.chauvet@bootlin.com



> -----Original Message-----
> From: Simon Ser <contact@emersion.fr>
> Sent: Thursday, May 22, 2025 3:45 PM
> To: Harry Wentland <harry.wentland@amd.com>
> Cc: Xaver Hugl <xaver.hugl@gmail.com>; Alex Hung <alex.hung@amd.com>; dri-
> devel@lists.freedesktop.org; amd-gfx@lists.freedesktop.org; wayland-
> devel@lists.freedesktop.org; leo.liu@amd.com; ville.syrjala@linux.intel.com;
> pekka.paalanen@collabora.com; mwen@igalia.com; jadahl@redhat.com;
> sebastian.wick@redhat.com; shashank.sharma@amd.com; agoins@nvidia.com;
> joshua@froggi.es; mdaenzer@redhat.com; aleixpol@kde.org;
> victoria@system76.com; daniel@ffwll.ch; Shankar, Uma
> <uma.shankar@intel.com>; quic_naseer@quicinc.com;
> quic_cbraga@quicinc.com; quic_abhinavk@quicinc.com; marcan@marcan.st;
> Liviu.Dudau@arm.com; sashamcintosh@google.com; Borah, Chaitanya Kumar
> <chaitanya.kumar.borah@intel.com>; louis.chauvet@bootlin.com
> Subject: Re: [PATCH V8 40/43] drm/colorop: Add 3D LUT support to color pipeline
> 
> On Wednesday, May 21st, 2025 at 21:18, Harry Wentland
> <harry.wentland@amd.com> wrote:
> 
> > On 2025-05-20 16:13, Harry Wentland wrote:
> >
> > > On 2025-05-19 19:43, Simon Ser wrote:
> > >
> > > > On Sunday, May 18th, 2025 at 00:32, Xaver Hugl xaver.hugl@gmail.com
> wrote:
> > > >
> > > > > > We can always make the property mutable on drivers that
> > > > > > support it in
> > > > >
> > > > > > the future, much like the zpos property. I think we should
> > > > > > keep it immutable for now.
> > > > >
> > > > > Sure, but I don't see any reason for immutability with an enum
> > > > > property - it can just limit the possible values to what it
> > > > > supports, and that can be only one value. Either way, it's not a big issue.
> > > >
> > > > Immutability is a clear indication that a property has a fixed
> > > > read-only value which can't be switched by user-space. That's also
> > > > the pattern used everywhere in the KMS uAPI, so I think it's
> > > > better to remain consistent here.
> > >
> > > I was envisioning this to be a driver-caps thing, but I agree if we
> > > make this mutable it can still serve that function but with
> > > different/future HW possibly support other interpolation schemes.
> >
> > Would changing this enum property from IMMUTABLE to MUTABLE in the
> > future (for drivers that support multiple types) break any userspace
> > that assumes IMMUTABLE?
> 
> I don't think it would, see the zpos property.

I agree, should be ok as long as driver supports. Doesn't break any UAPI contract here.

Regards,
Uma Shankar

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type
  2025-05-22 11:33             ` Shankar, Uma
@ 2025-05-30 13:58               ` Pekka Paalanen
  2025-06-03  8:30                 ` Shankar, Uma
  0 siblings, 1 reply; 128+ messages in thread
From: Pekka Paalanen @ 2025-05-30 13:58 UTC (permalink / raw)
  To: Shankar, Uma
  Cc: Simon Ser, Harry Wentland, Alex Hung,
	dri-devel@lists.freedesktop.org, amd-gfx@lists.freedesktop.org,
	intel-gfx@lists.freedesktop.org,
	wayland-devel@lists.freedesktop.org, leo.liu@amd.com,
	ville.syrjala@linux.intel.com, pekka.paalanen@collabora.com,
	mwen@igalia.com, jadahl@redhat.com, sebastian.wick@redhat.com,
	shashank.sharma@amd.com, agoins@nvidia.com, joshua@froggi.es,
	mdaenzer@redhat.com, aleixpol@kde.org, xaver.hugl@gmail.com,
	victoria@system76.com, daniel@ffwll.ch, quic_naseer@quicinc.com,
	quic_cbraga@quicinc.com, quic_abhinavk@quicinc.com,
	marcan@marcan.st, Liviu.Dudau@arm.com, sashamcintosh@google.com,
	Borah, Chaitanya Kumar, louis.chauvet@bootlin.com

[-- Attachment #1: Type: text/plain, Size: 1522 bytes --]

On Thu, 22 May 2025 11:33:00 +0000
"Shankar, Uma" <uma.shankar@intel.com> wrote:

> One request though: Can we enhance the lut samples from existing 16bits to 32bits as lut precision is
> going to be more than 16 in certain hardware. While adding the new UAPI, lets extend this to 32 to make it future proof.
> Reference: https://patchwork.freedesktop.org/patch/642592/?series=129811&rev=4
> 
> +/**
> + * struct drm_color_lut_32 - Represents high precision lut values
> + *
> + * Creating 32 bit palette entries for better data
> + * precision. This will be required for HDR and
> + * similar color processing usecases.
> + */
> +struct drm_color_lut_32 {
> +	/*
> +	 * Data for high precision LUTs
> +	 */
> +	__u32 red;
> +	__u32 green;
> +	__u32 blue;
> +	__u32 reserved;
> +};

Hi,

I suppose you need this much precision for optical data? If so,
floating-point would be much more appropriate and we could probably
keep 16-bit storage.

What does the "more than 16-bit" hardware actually use? ISTR at least
AMD having some sort of float'ish point internal pipeline?

This sounds the same thing as non-uniformly distributed taps in a LUT.
That mimics floating-point input while this feels like floating-point
output of a LUT.

I've recently decided for myself (and Weston) that I will never store
optical data in an integer format, because it is far too wasteful. That's
why the electrical encodings like power-2.2 are so useful, not just for
emulating a CRT.


Thanks,
pq

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 128+ messages in thread

* RE: [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type
  2025-05-30 13:58               ` Pekka Paalanen
@ 2025-06-03  8:30                 ` Shankar, Uma
  2025-06-03 10:51                   ` Pekka Paalanen
  0 siblings, 1 reply; 128+ messages in thread
From: Shankar, Uma @ 2025-06-03  8:30 UTC (permalink / raw)
  To: Pekka Paalanen
  Cc: Simon Ser, Harry Wentland, Alex Hung,
	dri-devel@lists.freedesktop.org, amd-gfx@lists.freedesktop.org,
	intel-gfx@lists.freedesktop.org,
	wayland-devel@lists.freedesktop.org, leo.liu@amd.com,
	ville.syrjala@linux.intel.com, mwen@igalia.com, jadahl@redhat.com,
	sebastian.wick@redhat.com, shashank.sharma@amd.com,
	agoins@nvidia.com, joshua@froggi.es, mdaenzer@redhat.com,
	aleixpol@kde.org, xaver.hugl@gmail.com, victoria@system76.com,
	daniel@ffwll.ch, quic_naseer@quicinc.com, quic_cbraga@quicinc.com,
	quic_abhinavk@quicinc.com, marcan@marcan.st, Liviu.Dudau@arm.com,
	sashamcintosh@google.com, Borah, Chaitanya Kumar,
	louis.chauvet@bootlin.com



> -----Original Message-----
> From: Pekka Paalanen <pekka.paalanen@collabora.com>
> Sent: Friday, May 30, 2025 7:28 PM
> To: Shankar, Uma <uma.shankar@intel.com>
> Cc: Simon Ser <contact@emersion.fr>; Harry Wentland
> <harry.wentland@amd.com>; Alex Hung <alex.hung@amd.com>; dri-
> devel@lists.freedesktop.org; amd-gfx@lists.freedesktop.org; intel-
> gfx@lists.freedesktop.org; wayland-devel@lists.freedesktop.org;
> leo.liu@amd.com; ville.syrjala@linux.intel.com; pekka.paalanen@collabora.com;
> mwen@igalia.com; jadahl@redhat.com; sebastian.wick@redhat.com;
> shashank.sharma@amd.com; agoins@nvidia.com; joshua@froggi.es;
> mdaenzer@redhat.com; aleixpol@kde.org; xaver.hugl@gmail.com;
> victoria@system76.com; daniel@ffwll.ch; quic_naseer@quicinc.com;
> quic_cbraga@quicinc.com; quic_abhinavk@quicinc.com; marcan@marcan.st;
> Liviu.Dudau@arm.com; sashamcintosh@google.com; Borah, Chaitanya Kumar
> <chaitanya.kumar.borah@intel.com>; louis.chauvet@bootlin.com
> Subject: Re: [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type
> 
> On Thu, 22 May 2025 11:33:00 +0000
> "Shankar, Uma" <uma.shankar@intel.com> wrote:
> 
> > One request though: Can we enhance the lut samples from existing
> > 16bits to 32bits as lut precision is going to be more than 16 in certain hardware.
> While adding the new UAPI, lets extend this to 32 to make it future proof.
> > Reference:
> > https://patchwork.freedesktop.org/patch/642592/?series=129811&rev=4
> >
> > +/**
> > + * struct drm_color_lut_32 - Represents high precision lut values
> > + *
> > + * Creating 32 bit palette entries for better data
> > + * precision. This will be required for HDR and
> > + * similar color processing usecases.
> > + */
> > +struct drm_color_lut_32 {
> > +	/*
> > +	 * Data for high precision LUTs
> > +	 */
> > +	__u32 red;
> > +	__u32 green;
> > +	__u32 blue;
> > +	__u32 reserved;
> > +};
> 
> Hi,
> 
> I suppose you need this much precision for optical data? If so, floating-point would
> be much more appropriate and we could probably keep 16-bit storage.
> 
> What does the "more than 16-bit" hardware actually use? ISTR at least AMD
> having some sort of float'ish point internal pipeline?
> 
> This sounds the same thing as non-uniformly distributed taps in a LUT.
> That mimics floating-point input while this feels like floating-point output of a LUT.
> 
> I've recently decided for myself (and Weston) that I will never store optical data in
> an integer format, because it is far too wasteful. That's why the electrical
> encodings like power-2.2 are so useful, not just for emulating a CRT.

Hi Pekka,
Internal pipeline in hardware can operate at higher precision than the input framebuffer
to plane engines. So, in case we have optical data of 16bits or 10bits precision, hardware
can scale this up to higher precision in internal pipeline in hardware to take care of rounding
and overflow issues. Even FP16 optical data will be normalized and converted internally for
further processing.

Input to LUT hardware can be 16bits or even higher, so the look up table we program can
be of higher precision than 16 (certain cases 24 in Intel pipeline). This is later truncated to bpc supported
in output formats from sync (10, 12 or 16), mostly for electrical value to be sent to sink.

Hence requesting to increase the container from current u16 to u32, to get advantage of higher
precision luts.

Thanks & Regards,
Uma Shankar

> 
> Thanks,
> pq

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type
  2025-06-03  8:30                 ` Shankar, Uma
@ 2025-06-03 10:51                   ` Pekka Paalanen
  2025-06-03 20:26                     ` Harry Wentland
  0 siblings, 1 reply; 128+ messages in thread
From: Pekka Paalanen @ 2025-06-03 10:51 UTC (permalink / raw)
  To: Shankar, Uma
  Cc: Simon Ser, Harry Wentland, Alex Hung,
	dri-devel@lists.freedesktop.org, amd-gfx@lists.freedesktop.org,
	intel-gfx@lists.freedesktop.org,
	wayland-devel@lists.freedesktop.org, leo.liu@amd.com,
	ville.syrjala@linux.intel.com, mwen@igalia.com, jadahl@redhat.com,
	sebastian.wick@redhat.com, shashank.sharma@amd.com,
	agoins@nvidia.com, joshua@froggi.es, mdaenzer@redhat.com,
	aleixpol@kde.org, xaver.hugl@gmail.com, victoria@system76.com,
	daniel@ffwll.ch, quic_naseer@quicinc.com, quic_cbraga@quicinc.com,
	quic_abhinavk@quicinc.com, marcan@marcan.st, Liviu.Dudau@arm.com,
	sashamcintosh@google.com, Borah, Chaitanya Kumar,
	louis.chauvet@bootlin.com

[-- Attachment #1: Type: text/plain, Size: 4903 bytes --]

On Tue, 3 Jun 2025 08:30:23 +0000
"Shankar, Uma" <uma.shankar@intel.com> wrote:

> > -----Original Message-----
> > From: Pekka Paalanen <pekka.paalanen@collabora.com>
> > Sent: Friday, May 30, 2025 7:28 PM
> > To: Shankar, Uma <uma.shankar@intel.com>
> > Cc: Simon Ser <contact@emersion.fr>; Harry Wentland
> > <harry.wentland@amd.com>; Alex Hung <alex.hung@amd.com>; dri-
> > devel@lists.freedesktop.org; amd-gfx@lists.freedesktop.org; intel-
> > gfx@lists.freedesktop.org; wayland-devel@lists.freedesktop.org;
> > leo.liu@amd.com; ville.syrjala@linux.intel.com; pekka.paalanen@collabora.com;
> > mwen@igalia.com; jadahl@redhat.com; sebastian.wick@redhat.com;
> > shashank.sharma@amd.com; agoins@nvidia.com; joshua@froggi.es;
> > mdaenzer@redhat.com; aleixpol@kde.org; xaver.hugl@gmail.com;
> > victoria@system76.com; daniel@ffwll.ch; quic_naseer@quicinc.com;
> > quic_cbraga@quicinc.com; quic_abhinavk@quicinc.com; marcan@marcan.st;
> > Liviu.Dudau@arm.com; sashamcintosh@google.com; Borah, Chaitanya Kumar
> > <chaitanya.kumar.borah@intel.com>; louis.chauvet@bootlin.com
> > Subject: Re: [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type
> > 
> > On Thu, 22 May 2025 11:33:00 +0000
> > "Shankar, Uma" <uma.shankar@intel.com> wrote:
> >   
> > > One request though: Can we enhance the lut samples from existing
> > > 16bits to 32bits as lut precision is going to be more than 16 in certain hardware.  
> > While adding the new UAPI, lets extend this to 32 to make it future proof.  
> > > Reference:
> > > https://patchwork.freedesktop.org/patch/642592/?series=129811&rev=4
> > >
> > > +/**
> > > + * struct drm_color_lut_32 - Represents high precision lut values
> > > + *
> > > + * Creating 32 bit palette entries for better data
> > > + * precision. This will be required for HDR and
> > > + * similar color processing usecases.
> > > + */
> > > +struct drm_color_lut_32 {
> > > +	/*
> > > +	 * Data for high precision LUTs
> > > +	 */
> > > +	__u32 red;
> > > +	__u32 green;
> > > +	__u32 blue;
> > > +	__u32 reserved;
> > > +};  
> > 
> > Hi,
> > 
> > I suppose you need this much precision for optical data? If so, floating-point would
> > be much more appropriate and we could probably keep 16-bit storage.
> > 
> > What does the "more than 16-bit" hardware actually use? ISTR at least AMD
> > having some sort of float'ish point internal pipeline?
> > 
> > This sounds the same thing as non-uniformly distributed taps in a LUT.
> > That mimics floating-point input while this feels like floating-point output of a LUT.
> > 
> > I've recently decided for myself (and Weston) that I will never store optical data in
> > an integer format, because it is far too wasteful. That's why the electrical
> > encodings like power-2.2 are so useful, not just for emulating a CRT.  
> 
> Hi Pekka,
> Internal pipeline in hardware can operate at higher precision than the input framebuffer
> to plane engines. So, in case we have optical data of 16bits or 10bits precision, hardware
> can scale this up to higher precision in internal pipeline in hardware to take care of rounding
> and overflow issues. Even FP16 optical data will be normalized and converted internally for
> further processing.

Is it integer or floating-point?

If we take the full range of PQ as optical and put it into 16-bit
integer format, the luminance step from code 1 to code 2 is 0.15 cd/m².
That seems like a huge step in the dark end. Such a step would
probably need to be divided over several taps in a LUT, which wouldn't
be possible.

In that sense, if a LUT is used for the PQ EOTF, I totally agree that
16-bit integer won't be even nearly enough precision.

This actually points out the caveat that increasing the number of taps
in a LUT can cause the LUT to become non-monotonic when the sample
precision runs out. That is, consecutive taps don't always increase in
value.

> Input to LUT hardware can be 16bits or even higher, so the look up table we program can
> be of higher precision than 16 (certain cases 24 in Intel pipeline). This is later truncated to bpc supported
> in output formats from sync (10, 12 or 16), mostly for electrical value to be sent to sink.
> 
> Hence requesting to increase the container from current u16 to u32, to get advantage of higher
> precision luts.

My argument though is to use a floating-point format for the LUT samples
instead of adding more and more integer bits. That naturally puts more
precision where it is needed: near zero.

A driver can easily convert that to any format the hardware needs.

However, it might make best sense for a driver to expose a LUT with a
format that best matches the hardware precision, especially
floating-point vs. integer.

I guess we may eventually need both 32 bpc integer and 16 (or 32) bpc
floating-point.


Thanks,
pq

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type
  2025-06-03 10:51                   ` Pekka Paalanen
@ 2025-06-03 20:26                     ` Harry Wentland
  2025-06-04 18:59                       ` Shankar, Uma
  0 siblings, 1 reply; 128+ messages in thread
From: Harry Wentland @ 2025-06-03 20:26 UTC (permalink / raw)
  To: Pekka Paalanen, Shankar, Uma
  Cc: Simon Ser, Alex Hung, dri-devel@lists.freedesktop.org,
	amd-gfx@lists.freedesktop.org, intel-gfx@lists.freedesktop.org,
	wayland-devel@lists.freedesktop.org, leo.liu@amd.com,
	ville.syrjala@linux.intel.com, mwen@igalia.com, jadahl@redhat.com,
	sebastian.wick@redhat.com, shashank.sharma@amd.com,
	agoins@nvidia.com, joshua@froggi.es, mdaenzer@redhat.com,
	aleixpol@kde.org, xaver.hugl@gmail.com, victoria@system76.com,
	daniel@ffwll.ch, quic_naseer@quicinc.com, quic_cbraga@quicinc.com,
	quic_abhinavk@quicinc.com, marcan@marcan.st, Liviu.Dudau@arm.com,
	sashamcintosh@google.com, Borah, Chaitanya Kumar,
	louis.chauvet@bootlin.com



On 2025-06-03 06:51, Pekka Paalanen wrote:
> On Tue, 3 Jun 2025 08:30:23 +0000
> "Shankar, Uma" <uma.shankar@intel.com> wrote:
> 
>>> -----Original Message-----
>>> From: Pekka Paalanen <pekka.paalanen@collabora.com>
>>> Sent: Friday, May 30, 2025 7:28 PM
>>> To: Shankar, Uma <uma.shankar@intel.com>
>>> Cc: Simon Ser <contact@emersion.fr>; Harry Wentland
>>> <harry.wentland@amd.com>; Alex Hung <alex.hung@amd.com>; dri-
>>> devel@lists.freedesktop.org; amd-gfx@lists.freedesktop.org; intel-
>>> gfx@lists.freedesktop.org; wayland-devel@lists.freedesktop.org;
>>> leo.liu@amd.com; ville.syrjala@linux.intel.com; pekka.paalanen@collabora.com;
>>> mwen@igalia.com; jadahl@redhat.com; sebastian.wick@redhat.com;
>>> shashank.sharma@amd.com; agoins@nvidia.com; joshua@froggi.es;
>>> mdaenzer@redhat.com; aleixpol@kde.org; xaver.hugl@gmail.com;
>>> victoria@system76.com; daniel@ffwll.ch; quic_naseer@quicinc.com;
>>> quic_cbraga@quicinc.com; quic_abhinavk@quicinc.com; marcan@marcan.st;
>>> Liviu.Dudau@arm.com; sashamcintosh@google.com; Borah, Chaitanya Kumar
>>> <chaitanya.kumar.borah@intel.com>; louis.chauvet@bootlin.com
>>> Subject: Re: [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type
>>>
>>> On Thu, 22 May 2025 11:33:00 +0000
>>> "Shankar, Uma" <uma.shankar@intel.com> wrote:
>>>   
>>>> One request though: Can we enhance the lut samples from existing
>>>> 16bits to 32bits as lut precision is going to be more than 16 in certain hardware.  
>>> While adding the new UAPI, lets extend this to 32 to make it future proof.  
>>>> Reference:
>>>> https://patchwork.freedesktop.org/patch/642592/?series=129811&rev=4
>>>>
>>>> +/**
>>>> + * struct drm_color_lut_32 - Represents high precision lut values
>>>> + *
>>>> + * Creating 32 bit palette entries for better data
>>>> + * precision. This will be required for HDR and
>>>> + * similar color processing usecases.
>>>> + */
>>>> +struct drm_color_lut_32 {
>>>> +	/*
>>>> +	 * Data for high precision LUTs
>>>> +	 */
>>>> +	__u32 red;
>>>> +	__u32 green;
>>>> +	__u32 blue;
>>>> +	__u32 reserved;
>>>> +};  
>>>
>>> Hi,
>>>
>>> I suppose you need this much precision for optical data? If so, floating-point would
>>> be much more appropriate and we could probably keep 16-bit storage.
>>>
>>> What does the "more than 16-bit" hardware actually use? ISTR at least AMD
>>> having some sort of float'ish point internal pipeline?
>>>
>>> This sounds the same thing as non-uniformly distributed taps in a LUT.
>>> That mimics floating-point input while this feels like floating-point output of a LUT.
>>>
>>> I've recently decided for myself (and Weston) that I will never store optical data in
>>> an integer format, because it is far too wasteful. That's why the electrical
>>> encodings like power-2.2 are so useful, not just for emulating a CRT.  
>>
>> Hi Pekka,
>> Internal pipeline in hardware can operate at higher precision than the input framebuffer
>> to plane engines. So, in case we have optical data of 16bits or 10bits precision, hardware
>> can scale this up to higher precision in internal pipeline in hardware to take care of rounding
>> and overflow issues. Even FP16 optical data will be normalized and converted internally for
>> further processing.
> 
> Is it integer or floating-point?
> 

For AMD the internal format is floating point with slightly
higher precision than FP16.

> If we take the full range of PQ as optical and put it into 16-bit
> integer format, the luminance step from code 1 to code 2 is 0.15 cd/m².
> That seems like a huge step in the dark end. Such a step would
> probably need to be divided over several taps in a LUT, which wouldn't
> be possible.
> 

Right, and with 32-bpc we'll get a luminance step size of
~0.0000023 cd/m^2, which seems plenty fine-grained.

> In that sense, if a LUT is used for the PQ EOTF, I totally agree that
> 16-bit integer won't be even nearly enough precision.
> 
> This actually points out the caveat that increasing the number of taps
> in a LUT can cause the LUT to become non-monotonic when the sample
> precision runs out. That is, consecutive taps don't always increase in
> value.
> 
>> Input to LUT hardware can be 16bits or even higher, so the look up table we program can
>> be of higher precision than 16 (certain cases 24 in Intel pipeline). This is later truncated to bpc supported
>> in output formats from sync (10, 12 or 16), mostly for electrical value to be sent to sink.
>>
>> Hence requesting to increase the container from current u16 to u32, to get advantage of higher
>> precision luts.
> 
> My argument though is to use a floating-point format for the LUT samples
> instead of adding more and more integer bits. That naturally puts more
> precision where it is needed: near zero.
> 
> A driver can easily convert that to any format the hardware needs.
> 
> However, it might make best sense for a driver to expose a LUT with a
> format that best matches the hardware precision, especially
> floating-point vs. integer.
> 
> I guess we may eventually need both 32 bpc integer and 16 (or 32) bpc
> floating-point.
> 

While I like floating point better for representing these things
I don't think it's a great idea to pass floating point values
via IOCTLs but 32 bpc integer values make sense here.

Thanks, Uma, for pushing on this.

Harry

> 
> Thanks,
> pq


^ permalink raw reply	[flat|nested] 128+ messages in thread

* RE: [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type
  2025-06-03 20:26                     ` Harry Wentland
@ 2025-06-04 18:59                       ` Shankar, Uma
  2025-06-05  7:30                         ` Pekka Paalanen
  0 siblings, 1 reply; 128+ messages in thread
From: Shankar, Uma @ 2025-06-04 18:59 UTC (permalink / raw)
  To: Harry Wentland, Pekka Paalanen
  Cc: Simon Ser, Alex Hung, dri-devel@lists.freedesktop.org,
	amd-gfx@lists.freedesktop.org, intel-gfx@lists.freedesktop.org,
	wayland-devel@lists.freedesktop.org, leo.liu@amd.com,
	ville.syrjala@linux.intel.com, mwen@igalia.com, jadahl@redhat.com,
	sebastian.wick@redhat.com, shashank.sharma@amd.com,
	agoins@nvidia.com, joshua@froggi.es, mdaenzer@redhat.com,
	aleixpol@kde.org, xaver.hugl@gmail.com, victoria@system76.com,
	daniel@ffwll.ch, quic_naseer@quicinc.com, quic_cbraga@quicinc.com,
	quic_abhinavk@quicinc.com, marcan@marcan.st, Liviu.Dudau@arm.com,
	sashamcintosh@google.com, Borah, Chaitanya Kumar,
	louis.chauvet@bootlin.com



> -----Original Message-----
> From: Harry Wentland <harry.wentland@amd.com>
> Sent: Wednesday, June 4, 2025 1:57 AM
> To: Pekka Paalanen <pekka.paalanen@collabora.com>; Shankar, Uma
> <uma.shankar@intel.com>
> Cc: Simon Ser <contact@emersion.fr>; Alex Hung <alex.hung@amd.com>; dri-
> devel@lists.freedesktop.org; amd-gfx@lists.freedesktop.org; intel-
> gfx@lists.freedesktop.org; wayland-devel@lists.freedesktop.org;
> leo.liu@amd.com; ville.syrjala@linux.intel.com; mwen@igalia.com;
> jadahl@redhat.com; sebastian.wick@redhat.com; shashank.sharma@amd.com;
> agoins@nvidia.com; joshua@froggi.es; mdaenzer@redhat.com;
> aleixpol@kde.org; xaver.hugl@gmail.com; victoria@system76.com;
> daniel@ffwll.ch; quic_naseer@quicinc.com; quic_cbraga@quicinc.com;
> quic_abhinavk@quicinc.com; marcan@marcan.st; Liviu.Dudau@arm.com;
> sashamcintosh@google.com; Borah, Chaitanya Kumar
> <chaitanya.kumar.borah@intel.com>; louis.chauvet@bootlin.com
> Subject: Re: [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type
> 
> 
> 
> On 2025-06-03 06:51, Pekka Paalanen wrote:
> > On Tue, 3 Jun 2025 08:30:23 +0000
> > "Shankar, Uma" <uma.shankar@intel.com> wrote:
> >
> >>> -----Original Message-----
> >>> From: Pekka Paalanen <pekka.paalanen@collabora.com>
> >>> Sent: Friday, May 30, 2025 7:28 PM
> >>> To: Shankar, Uma <uma.shankar@intel.com>
> >>> Cc: Simon Ser <contact@emersion.fr>; Harry Wentland
> >>> <harry.wentland@amd.com>; Alex Hung <alex.hung@amd.com>; dri-
> >>> devel@lists.freedesktop.org; amd-gfx@lists.freedesktop.org; intel-
> >>> gfx@lists.freedesktop.org; wayland-devel@lists.freedesktop.org;
> >>> leo.liu@amd.com; ville.syrjala@linux.intel.com;
> >>> pekka.paalanen@collabora.com; mwen@igalia.com; jadahl@redhat.com;
> >>> sebastian.wick@redhat.com; shashank.sharma@amd.com;
> >>> agoins@nvidia.com; joshua@froggi.es; mdaenzer@redhat.com;
> >>> aleixpol@kde.org; xaver.hugl@gmail.com; victoria@system76.com;
> >>> daniel@ffwll.ch; quic_naseer@quicinc.com; quic_cbraga@quicinc.com;
> >>> quic_abhinavk@quicinc.com; marcan@marcan.st; Liviu.Dudau@arm.com;
> >>> sashamcintosh@google.com; Borah, Chaitanya Kumar
> >>> <chaitanya.kumar.borah@intel.com>; louis.chauvet@bootlin.com
> >>> Subject: Re: [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT
> >>> type
> >>>
> >>> On Thu, 22 May 2025 11:33:00 +0000
> >>> "Shankar, Uma" <uma.shankar@intel.com> wrote:
> >>>
> >>>> One request though: Can we enhance the lut samples from existing
> >>>> 16bits to 32bits as lut precision is going to be more than 16 in certain
> hardware.
> >>> While adding the new UAPI, lets extend this to 32 to make it future proof.
> >>>> Reference:
> >>>> https://patchwork.freedesktop.org/patch/642592/?series=129811&rev=4
> >>>>
> >>>> +/**
> >>>> + * struct drm_color_lut_32 - Represents high precision lut values
> >>>> + *
> >>>> + * Creating 32 bit palette entries for better data
> >>>> + * precision. This will be required for HDR and
> >>>> + * similar color processing usecases.
> >>>> + */
> >>>> +struct drm_color_lut_32 {
> >>>> +	/*
> >>>> +	 * Data for high precision LUTs
> >>>> +	 */
> >>>> +	__u32 red;
> >>>> +	__u32 green;
> >>>> +	__u32 blue;
> >>>> +	__u32 reserved;
> >>>> +};
> >>>
> >>> Hi,
> >>>
> >>> I suppose you need this much precision for optical data? If so,
> >>> floating-point would be much more appropriate and we could probably keep
> 16-bit storage.
> >>>
> >>> What does the "more than 16-bit" hardware actually use? ISTR at
> >>> least AMD having some sort of float'ish point internal pipeline?
> >>>
> >>> This sounds the same thing as non-uniformly distributed taps in a LUT.
> >>> That mimics floating-point input while this feels like floating-point output of a
> LUT.
> >>>
> >>> I've recently decided for myself (and Weston) that I will never
> >>> store optical data in an integer format, because it is far too
> >>> wasteful. That's why the electrical encodings like power-2.2 are so useful, not
> just for emulating a CRT.
> >>
> >> Hi Pekka,
> >> Internal pipeline in hardware can operate at higher precision than
> >> the input framebuffer to plane engines. So, in case we have optical
> >> data of 16bits or 10bits precision, hardware can scale this up to
> >> higher precision in internal pipeline in hardware to take care of
> >> rounding and overflow issues. Even FP16 optical data will be normalized and
> converted internally for further processing.
> >
> > Is it integer or floating-point?
> >
> 
> For AMD the internal format is floating point with slightly higher precision than
> FP16.
> 
> > If we take the full range of PQ as optical and put it into 16-bit
> > integer format, the luminance step from code 1 to code 2 is 0.15 cd/m².
> > That seems like a huge step in the dark end. Such a step would
> > probably need to be divided over several taps in a LUT, which wouldn't
> > be possible.
> >
> 
> Right, and with 32-bpc we'll get a luminance step size of
> ~0.0000023 cd/m^2, which seems plenty fine-grained.
> 
> > In that sense, if a LUT is used for the PQ EOTF, I totally agree that
> > 16-bit integer won't be even nearly enough precision.
> >
> > This actually points out the caveat that increasing the number of taps
> > in a LUT can cause the LUT to become non-monotonic when the sample
> > precision runs out. That is, consecutive taps don't always increase in
> > value.
> >
> >> Input to LUT hardware can be 16bits or even higher, so the look up
> >> table we program can be of higher precision than 16 (certain cases 24
> >> in Intel pipeline). This is later truncated to bpc supported in output formats from
> sync (10, 12 or 16), mostly for electrical value to be sent to sink.
> >>
> >> Hence requesting to increase the container from current u16 to u32,
> >> to get advantage of higher precision luts.
> >
> > My argument though is to use a floating-point format for the LUT
> > samples instead of adding more and more integer bits. That naturally
> > puts more precision where it is needed: near zero.
> >
> > A driver can easily convert that to any format the hardware needs.
> >
> > However, it might make best sense for a driver to expose a LUT with a
> > format that best matches the hardware precision, especially
> > floating-point vs. integer.
> >
> > I guess we may eventually need both 32 bpc integer and 16 (or 32) bpc
> > floating-point.
> >
> 
> While I like floating point better for representing these things I don't think it's a
> great idea to pass floating point values via IOCTLs but 32 bpc integer values make
> sense here.
> 

Nice, we all are on same page here.

> Thanks, Uma, for pushing on this.

Thanks Harry and Pekka for valuable inputs.

Regards,
Uma Shankar

> Harry
> 
> >
> > Thanks,
> > pq


^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type
  2025-06-04 18:59                       ` Shankar, Uma
@ 2025-06-05  7:30                         ` Pekka Paalanen
  0 siblings, 0 replies; 128+ messages in thread
From: Pekka Paalanen @ 2025-06-05  7:30 UTC (permalink / raw)
  To: Shankar, Uma
  Cc: Harry Wentland, Simon Ser, Alex Hung,
	dri-devel@lists.freedesktop.org, amd-gfx@lists.freedesktop.org,
	intel-gfx@lists.freedesktop.org,
	wayland-devel@lists.freedesktop.org, leo.liu@amd.com,
	ville.syrjala@linux.intel.com, mwen@igalia.com, jadahl@redhat.com,
	sebastian.wick@redhat.com, shashank.sharma@amd.com,
	agoins@nvidia.com, joshua@froggi.es, mdaenzer@redhat.com,
	aleixpol@kde.org, xaver.hugl@gmail.com, victoria@system76.com,
	daniel@ffwll.ch, quic_naseer@quicinc.com, quic_cbraga@quicinc.com,
	quic_abhinavk@quicinc.com, marcan@marcan.st, Liviu.Dudau@arm.com,
	sashamcintosh@google.com, Borah, Chaitanya Kumar,
	louis.chauvet@bootlin.com

[-- Attachment #1: Type: text/plain, Size: 7169 bytes --]

On Wed, 4 Jun 2025 18:59:22 +0000
"Shankar, Uma" <uma.shankar@intel.com> wrote:

> > -----Original Message-----
> > From: Harry Wentland <harry.wentland@amd.com>
> > Sent: Wednesday, June 4, 2025 1:57 AM
> > To: Pekka Paalanen <pekka.paalanen@collabora.com>; Shankar, Uma
> > <uma.shankar@intel.com>
> > Cc: Simon Ser <contact@emersion.fr>; Alex Hung <alex.hung@amd.com>; dri-
> > devel@lists.freedesktop.org; amd-gfx@lists.freedesktop.org; intel-
> > gfx@lists.freedesktop.org; wayland-devel@lists.freedesktop.org;
> > leo.liu@amd.com; ville.syrjala@linux.intel.com; mwen@igalia.com;
> > jadahl@redhat.com; sebastian.wick@redhat.com; shashank.sharma@amd.com;
> > agoins@nvidia.com; joshua@froggi.es; mdaenzer@redhat.com;
> > aleixpol@kde.org; xaver.hugl@gmail.com; victoria@system76.com;
> > daniel@ffwll.ch; quic_naseer@quicinc.com; quic_cbraga@quicinc.com;
> > quic_abhinavk@quicinc.com; marcan@marcan.st; Liviu.Dudau@arm.com;
> > sashamcintosh@google.com; Borah, Chaitanya Kumar
> > <chaitanya.kumar.borah@intel.com>; louis.chauvet@bootlin.com
> > Subject: Re: [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type
> > 
> > 
> > 
> > On 2025-06-03 06:51, Pekka Paalanen wrote:  
> > > On Tue, 3 Jun 2025 08:30:23 +0000
> > > "Shankar, Uma" <uma.shankar@intel.com> wrote:
> > >  
> > >>> -----Original Message-----
> > >>> From: Pekka Paalanen <pekka.paalanen@collabora.com>
> > >>> Sent: Friday, May 30, 2025 7:28 PM
> > >>> To: Shankar, Uma <uma.shankar@intel.com>
> > >>> Cc: Simon Ser <contact@emersion.fr>; Harry Wentland
> > >>> <harry.wentland@amd.com>; Alex Hung <alex.hung@amd.com>; dri-
> > >>> devel@lists.freedesktop.org; amd-gfx@lists.freedesktop.org; intel-
> > >>> gfx@lists.freedesktop.org; wayland-devel@lists.freedesktop.org;
> > >>> leo.liu@amd.com; ville.syrjala@linux.intel.com;
> > >>> pekka.paalanen@collabora.com; mwen@igalia.com; jadahl@redhat.com;
> > >>> sebastian.wick@redhat.com; shashank.sharma@amd.com;
> > >>> agoins@nvidia.com; joshua@froggi.es; mdaenzer@redhat.com;
> > >>> aleixpol@kde.org; xaver.hugl@gmail.com; victoria@system76.com;
> > >>> daniel@ffwll.ch; quic_naseer@quicinc.com; quic_cbraga@quicinc.com;
> > >>> quic_abhinavk@quicinc.com; marcan@marcan.st; Liviu.Dudau@arm.com;
> > >>> sashamcintosh@google.com; Borah, Chaitanya Kumar
> > >>> <chaitanya.kumar.borah@intel.com>; louis.chauvet@bootlin.com
> > >>> Subject: Re: [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT
> > >>> type
> > >>>
> > >>> On Thu, 22 May 2025 11:33:00 +0000
> > >>> "Shankar, Uma" <uma.shankar@intel.com> wrote:
> > >>>  
> > >>>> One request though: Can we enhance the lut samples from existing
> > >>>> 16bits to 32bits as lut precision is going to be more than 16 in certain  
> > hardware.  
> > >>> While adding the new UAPI, lets extend this to 32 to make it future proof.  
> > >>>> Reference:
> > >>>> https://patchwork.freedesktop.org/patch/642592/?series=129811&rev=4
> > >>>>
> > >>>> +/**
> > >>>> + * struct drm_color_lut_32 - Represents high precision lut values
> > >>>> + *
> > >>>> + * Creating 32 bit palette entries for better data
> > >>>> + * precision. This will be required for HDR and
> > >>>> + * similar color processing usecases.
> > >>>> + */
> > >>>> +struct drm_color_lut_32 {
> > >>>> +	/*
> > >>>> +	 * Data for high precision LUTs
> > >>>> +	 */
> > >>>> +	__u32 red;
> > >>>> +	__u32 green;
> > >>>> +	__u32 blue;
> > >>>> +	__u32 reserved;
> > >>>> +};  
> > >>>
> > >>> Hi,
> > >>>
> > >>> I suppose you need this much precision for optical data? If so,
> > >>> floating-point would be much more appropriate and we could probably keep  
> > 16-bit storage.  
> > >>>
> > >>> What does the "more than 16-bit" hardware actually use? ISTR at
> > >>> least AMD having some sort of float'ish point internal pipeline?
> > >>>
> > >>> This sounds the same thing as non-uniformly distributed taps in a LUT.
> > >>> That mimics floating-point input while this feels like floating-point output of a  
> > LUT.  
> > >>>
> > >>> I've recently decided for myself (and Weston) that I will never
> > >>> store optical data in an integer format, because it is far too
> > >>> wasteful. That's why the electrical encodings like power-2.2 are so useful, not  
> > just for emulating a CRT.  
> > >>
> > >> Hi Pekka,
> > >> Internal pipeline in hardware can operate at higher precision than
> > >> the input framebuffer to plane engines. So, in case we have optical
> > >> data of 16bits or 10bits precision, hardware can scale this up to
> > >> higher precision in internal pipeline in hardware to take care of
> > >> rounding and overflow issues. Even FP16 optical data will be normalized and  
> > converted internally for further processing.  
> > >
> > > Is it integer or floating-point?
> > >  
> > 
> > For AMD the internal format is floating point with slightly higher precision than
> > FP16.
> >   
> > > If we take the full range of PQ as optical and put it into 16-bit
> > > integer format, the luminance step from code 1 to code 2 is 0.15 cd/m².
> > > That seems like a huge step in the dark end. Such a step would
> > > probably need to be divided over several taps in a LUT, which wouldn't
> > > be possible.
> > >  
> > 
> > Right, and with 32-bpc we'll get a luminance step size of
> > ~0.0000023 cd/m^2, which seems plenty fine-grained.
> >   
> > > In that sense, if a LUT is used for the PQ EOTF, I totally agree that
> > > 16-bit integer won't be even nearly enough precision.
> > >
> > > This actually points out the caveat that increasing the number of taps
> > > in a LUT can cause the LUT to become non-monotonic when the sample
> > > precision runs out. That is, consecutive taps don't always increase in
> > > value.
> > >  
> > >> Input to LUT hardware can be 16bits or even higher, so the look up
> > >> table we program can be of higher precision than 16 (certain cases 24
> > >> in Intel pipeline). This is later truncated to bpc supported in output formats from  
> > sync (10, 12 or 16), mostly for electrical value to be sent to sink.  
> > >>
> > >> Hence requesting to increase the container from current u16 to u32,
> > >> to get advantage of higher precision luts.  
> > >
> > > My argument though is to use a floating-point format for the LUT
> > > samples instead of adding more and more integer bits. That naturally
> > > puts more precision where it is needed: near zero.
> > >
> > > A driver can easily convert that to any format the hardware needs.
> > >
> > > However, it might make best sense for a driver to expose a LUT with a
> > > format that best matches the hardware precision, especially
> > > floating-point vs. integer.
> > >
> > > I guess we may eventually need both 32 bpc integer and 16 (or 32) bpc
> > > floating-point.
> > >  
> > 
> > While I like floating point better for representing these things I don't think it's a
> > great idea to pass floating point values via IOCTLs but 32 bpc integer values make
> > sense here.
> >   
> 
> Nice, we all are on same page here.

Fine by me!

Thanks,
pq

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 128+ messages in thread

end of thread, other threads:[~2025-06-05  7:31 UTC | newest]

Thread overview: 128+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-26 23:46 [PATCH V8 00/43] Color Pipeline API w/ VKMS Alex Hung
2025-03-26 23:46 ` [PATCH V8 01/43] drm: Add helper for conversion from signed-magnitude Alex Hung
2025-03-26 23:46 ` [PATCH V8 02/43] drm/vkms: Add kunit tests for VKMS LUT handling Alex Hung
2025-03-26 23:46 ` [PATCH V8 03/43] drm/doc/rfc: Describe why prescriptive color pipeline is needed Alex Hung
2025-03-29 15:26   ` Simon Ser
2025-04-01  0:10     ` Alex Hung
2025-04-01  7:26       ` Simon Ser
2025-03-31 16:24   ` Shengyu Qu
2025-03-31 16:41     ` Alex Hung
2025-03-31 16:54       ` Shengyu Qu
2025-03-26 23:46 ` [PATCH V8 04/43] drm/colorop: Introduce new drm_colorop mode object Alex Hung
2025-03-26 23:46 ` [PATCH V8 05/43] drm/colorop: Add TYPE property Alex Hung
2025-03-26 23:46 ` [PATCH V8 06/43] drm/colorop: Add 1D Curve subtype Alex Hung
2025-04-01 15:14   ` Daniel Stone
2025-04-01 19:53     ` Simon Ser
2025-04-01 21:02       ` Harry Wentland
2025-04-08 16:40       ` Daniel Stone
2025-04-08 17:30         ` Harry Wentland
2025-04-08 18:28           ` Daniel Stone
2025-04-10  7:53           ` Pipeline vs. no pipeline (Re: [PATCH V8 06/43] drm/colorop: Add 1D Curve subtype) Pekka Paalanen
2025-04-15 15:29             ` Harry Wentland
2025-04-16 14:39               ` Xaver Hugl
2025-04-17  8:28               ` Pekka Paalanen
2025-04-10 10:05         ` [PATCH V8 06/43] drm/colorop: Add 1D Curve subtype Simon Ser
2025-04-15 11:12         ` Borah, Chaitanya Kumar
2025-04-17 15:13           ` Simon Ser
2025-03-26 23:46 ` [PATCH V8 07/43] drm/colorop: Add BYPASS property Alex Hung
2025-03-26 23:46 ` [PATCH V8 08/43] drm/colorop: Add NEXT property Alex Hung
2025-03-27 23:26   ` Simon Ser
2025-03-26 23:46 ` [PATCH V8 09/43] drm/colorop: Add atomic state print for drm_colorop Alex Hung
2025-03-27 23:29   ` Simon Ser
2025-03-26 23:46 ` [PATCH V8 10/43] drm/plane: Add COLOR PIPELINE property Alex Hung
2025-03-29 14:33   ` Simon Ser
2025-03-26 23:46 ` [PATCH V8 11/43] drm/colorop: Introduce DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE Alex Hung
2025-03-29 14:37   ` Simon Ser
2025-04-01  1:42   ` Shengyu Qu
2025-03-26 23:46 ` [PATCH V8 12/43] Documentation/gpu: document drm_colorop Alex Hung
2025-03-29 14:40   ` Simon Ser
2025-03-26 23:46 ` [PATCH V8 13/43] drm/vkms: Add enumerated 1D curve colorop Alex Hung
2025-03-26 23:46 ` [PATCH V8 14/43] drm/vkms: Add kunit tests for linear and sRGB LUTs Alex Hung
2025-03-26 23:46 ` [PATCH V8 15/43] drm/colorop: Add 3x4 CTM type Alex Hung
2025-03-26 23:46 ` [PATCH V8 16/43] drm/vkms: Use s32 for internal color pipeline precision Alex Hung
2025-03-26 23:46 ` [PATCH V8 17/43] drm/vkms: add 3x4 matrix in color pipeline Alex Hung
2025-03-26 23:46 ` [PATCH V8 18/43] drm/tests: Add a few tests around drm_fixed.h Alex Hung
2025-03-26 23:47 ` [PATCH V8 19/43] drm/vkms: Add tests for CTM handling Alex Hung
2025-03-26 23:47 ` [PATCH V8 20/43] drm/colorop: pass plane_color_pipeline client cap to atomic check Alex Hung
2025-03-29 15:32   ` Simon Ser
2025-03-26 23:47 ` [PATCH V8 21/43] drm/colorop: define a new macro for_each_new_colorop_in_state Alex Hung
2025-03-26 23:47 ` [PATCH V8 22/43] drm/amd/display: Ignore deprecated props when plane_color_pipeline set Alex Hung
2025-03-26 23:47 ` [PATCH V8 23/43] drm/amd/display: Add bypass COLOR PIPELINE Alex Hung
2025-03-26 23:47 ` [PATCH V8 24/43] drm/amd/display: Skip color pipeline initialization for cursor plane Alex Hung
2025-03-30  9:48   ` Shengyu Qu
2025-03-30 12:59   ` Shengyu Qu
2025-03-31 14:28     ` Alex Hung
2025-03-31 15:43       ` Shengyu Qu
2025-03-31 16:06         ` Alex Hung
2025-03-31 16:12           ` Shengyu Qu
2025-03-31 16:26             ` Alex Hung
2025-03-31 16:31               ` Shengyu Qu
2025-03-31 16:34                 ` Alex Hung
2025-03-31 16:50                   ` Shengyu Qu
2025-03-31 17:04                     ` Shengyu Qu
2025-03-31 17:42                       ` Alex Hung
2025-03-31 18:53                         ` Xaver Hugl
2025-04-01  0:28                           ` Alex Hung
2025-04-01 15:04                             ` Xaver Hugl
2025-04-01 15:45                           ` Melissa Wen
2025-04-01 19:39                             ` Harry Wentland
2025-04-01  1:04                         ` Shengyu Qu
2025-04-01  1:24                           ` Alex Hung
2025-04-01  9:56                         ` Michel Dänzer
2025-04-01 12:32                           ` Shengyu Qu
2025-04-01 14:11                             ` Michel Dänzer
2025-04-01 15:45                               ` Shengyu Qu
2025-04-01 19:45                                 ` Harry Wentland
2025-04-02  3:47                                   ` Qu Shengyu
2025-04-01 16:24                               ` Shengyu Qu
2025-03-26 23:47 ` [PATCH V8 25/43] drm/amd/display: Add support for sRGB EOTF in DEGAM block Alex Hung
2025-03-26 23:47 ` [PATCH V8 26/43] drm/amd/display: Add support for sRGB Inverse EOTF in SHAPER block Alex Hung
2025-03-26 23:47 ` [PATCH V8 27/43] drm/amd/display: Add support for sRGB EOTF in BLND block Alex Hung
2025-03-26 23:47 ` [PATCH V8 28/43] drm/colorop: Add PQ 125 EOTF and its inverse Alex Hung
2025-03-29 14:48   ` Simon Ser
2025-03-26 23:47 ` [PATCH V8 29/43] drm/amd/display: Enable support for PQ 125 EOTF and Inverse Alex Hung
2025-03-26 23:47 ` [PATCH V8 30/43] drm/colorop: add BT2020/BT709 OETF and Inverse OETF Alex Hung
2025-03-29 14:53   ` Simon Ser
2025-03-26 23:47 ` [PATCH V8 31/43] drm/amd/display: Add support for BT.709 and BT.2020 TFs Alex Hung
2025-03-26 23:47 ` [PATCH V8 32/43] drm/colorop: Add 1D Curve Custom LUT type Alex Hung
2025-03-29 14:55   ` Simon Ser
2025-04-15  6:09   ` Shankar, Uma
2025-04-15  6:16     ` Simon Ser
2025-04-15  6:40       ` Shankar, Uma
2025-04-15 15:05         ` Harry Wentland
2025-04-15 16:25           ` Simon Ser
2025-05-22 11:33             ` Shankar, Uma
2025-05-30 13:58               ` Pekka Paalanen
2025-06-03  8:30                 ` Shankar, Uma
2025-06-03 10:51                   ` Pekka Paalanen
2025-06-03 20:26                     ` Harry Wentland
2025-06-04 18:59                       ` Shankar, Uma
2025-06-05  7:30                         ` Pekka Paalanen
2025-03-26 23:47 ` [PATCH V8 33/43] drm/amd/display: add shaper and blend colorops for 1D Curve Custom LUT Alex Hung
2025-03-26 23:47 ` [PATCH V8 34/43] drm/amd/display: add 3x4 matrix colorop Alex Hung
2025-03-26 23:47 ` [PATCH V8 35/43] drm/colorop: Add mutliplier type Alex Hung
2025-03-26 23:47 ` [PATCH V8 36/43] drm/amd/display: add multiplier colorop Alex Hung
2025-03-26 23:47 ` [PATCH V8 37/43] drm/amd/display: Swap matrix and multiplier Alex Hung
2025-03-26 23:47 ` [PATCH V8 38/43] drm/colorop: Define LUT_1D interpolation Alex Hung
2025-03-26 23:47 ` [PATCH V8 39/43] drm/colorop: allow non-bypass colorops Alex Hung
2025-03-29 15:41   ` Simon Ser
2025-03-26 23:47 ` [PATCH V8 40/43] drm/colorop: Add 3D LUT support to color pipeline Alex Hung
2025-03-29 14:57   ` Simon Ser
2025-04-25 13:50   ` Leandro Ribeiro
2025-05-13  3:39     ` Alex Hung
2025-05-17  1:22   ` Xaver Hugl
2025-05-17 11:53     ` Simon Ser
2025-05-17 22:32       ` Xaver Hugl
2025-05-19 23:43         ` Simon Ser
2025-05-20 20:13           ` Harry Wentland
2025-05-21 19:18             ` Harry Wentland
2025-05-22 10:14               ` Simon Ser
2025-05-22 11:46                 ` Shankar, Uma
2025-05-17 17:36     ` Autumn Ashton
2025-03-26 23:47 ` [PATCH V8 41/43] drm/amd/display: add 3D LUT colorop Alex Hung
2025-03-26 23:47 ` [PATCH V8 42/43] drm/amd/display: Add AMD color pipeline doc Alex Hung
2025-03-26 23:47 ` [PATCH V8 43/43] drm/colorop: Add destroy functions for color pipeline Alex Hung
2025-03-29 15:48   ` Simon Ser
2025-04-01  2:42     ` Alex Hung
2025-04-10 16:18       ` Simon Ser
2025-03-29 15:51 ` [PATCH V8 00/43] Color Pipeline API w/ VKMS Simon Ser

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).