dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 0/5] Proposal for Pre-blending 3D LUT interfaces
@ 2022-10-04 21:14 Alex Hung
  2022-10-04 21:14 ` [RFC PATCH 1/5] drm: Add 3D LUT mode and its attributes Alex Hung
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Alex Hung @ 2022-10-04 21:14 UTC (permalink / raw)
  To: dri-devel, amd-gfx; +Cc: mwen, bhawanpreet.lakha, Alex Hung

This is an proposal and a draft implementation to enable 3D LUT on
drm_plane. This proposal defines a new interface for userspace
applications to query hardware capabilities and to pass/enable 3D LUT
functions via this DRM/KMS APIs.

Overviews:

┌─────────┐    ┌─────────┐    ┌───┐    ┌──────────┐   ┌────────┐
│Userspace│◄──►│3DLUT API│◄──►│DRM│◄──►│GPU driver├──►│hardware│
└─────────┘    └─────────┘    └───┘    └──────────┘   └────────┘

1. Userspace queries the 3DLUT mode (defined by drm_mode_3dlut_mode)
   from the GPU drivers (ex. amdgpu).

2. The GPU Driver replies sizes and the color depth of the
   3DLUT modes, such as defined by struct lut_3d_mode_17_12bit.

3. If applicable, userspace selects and sets one of preferred 3DLUT
   modes by "lut_3d_mode" to driver.

4. Userspace passes 3D LUT via drm_property_blob "lut_3d". In the case
   of the mode "lut_3d_mode_17_12bit", the 3D LUT should have a cube
   size = 17x17x17 (lut_size), color depth = 12 bits (bit_depth), and
   X/Y/Z axis = R/G/B (color_format).

5. The GPU driver parses 3D LUT and passes it to hardware pipeline, and
   enables 3D LUT accordingly.

Notes:

1. The patchset is based on the previous work on
   https://gitlab.freedesktop.org/hwentland/linux/-/tree/color-and-hdr

2. This interface can be part of the newly proposed DRM/KMS color pipeline
   API (https://gitlab.freedesktop.org/pq/color-and-hdr/-/issues/11). A
   future integration to the new API may be required or preferred, such
   as the followings:

  struct drm_color_pipeline_element {
    drm_color_pipeline_element_type;
    drm_color_pipeline_element_lut3d
  };

  struct drm_mode_3dlut_mode -> struct drm_color_pipeline_lut3d_config

  struct drm_color_pipeline_lut3d {
    lut_3d_mode_17_12bit;
  };

  struct drm_color_pipeline_lut3d_data {
    *lut_3d;
  };

  and etc.

3. A patchset "IGT tests for pre-blending 3D LUT interfaces" for this
   proposal is sent to IGT mailing list.

Related Work:
 - Enable 3D LUT to AMD display drivers (https://www.spinics.net/lists/amd-gfx/msg83032.html)

Alex Hung (5):
  drm: Add 3D LUT mode and its attributes
  drm: Add Plane 3DLUT and 3DLUT mode properties
  drm/amd/display: Define 3D LUT struct for HDR planes
  drm/amd/display: Enable plane 3DLUT mode
  drm/amd/display: Fill 3D LUT from userspace

 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  20 ++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |   1 +
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 181 ++++++++++++++++++
 .../amd/display/modules/color/color_gamma.h   |  12 ++
 drivers/gpu/drm/drm_atomic_state_helper.c     |   3 +
 drivers/gpu/drm/drm_atomic_uapi.c             |  11 ++
 drivers/gpu/drm/drm_color_mgmt.c              |  68 +++++++
 include/drm/drm_mode_object.h                 |   2 +-
 include/drm/drm_plane.h                       |  33 ++++
 include/uapi/drm/drm_mode.h                   |  17 ++
 10 files changed, 347 insertions(+), 1 deletion(-)

-- 
2.37.3


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

* [RFC PATCH 1/5] drm: Add 3D LUT mode and its attributes
  2022-10-04 21:14 [RFC PATCH 0/5] Proposal for Pre-blending 3D LUT interfaces Alex Hung
@ 2022-10-04 21:14 ` Alex Hung
  2022-10-04 21:14 ` [RFC PATCH 2/5] drm: Add Plane 3DLUT and 3DLUT mode properties Alex Hung
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Alex Hung @ 2022-10-04 21:14 UTC (permalink / raw)
  To: dri-devel, amd-gfx; +Cc: mwen, bhawanpreet.lakha, Alex Hung

A struct is defined for 3D LUT modes to be supported by hardware.
The elements includes lut_isze, lut_stride, bit_depth, color_format
and flags.

Note: A patchset "IGT tests for pre-blending 3D LUT interfaces" for this
proposal is sent to IGT mailing list.

Signed-off-by: Alex Hung <alex.hung@amd.com>
---
 include/uapi/drm/drm_mode.h | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index d0ce48d2e732..334e8a9b49cc 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -877,6 +877,23 @@ struct drm_color_lut_ext {
 	__u64 reserved;
 };
 
+/*
+ * struct drm_mode_3dlut_mode - 3D LUT mode information.
+ * @lut_size: number of valid points on every dimension of 3D LUT.
+ * @lut_stride: number of points on every dimension of 3D LUT.
+ * @bit_depth: number of bits of RGB. If color_mode defines entries with higher
+ *             bit_depth the least significant bits will be truncated.
+ * @color_format: fourcc values, ex. DRM_FORMAT_XRGB16161616 or DRM_FORMAT_XBGR16161616.
+ * @flags: flags for hardware-sepcific features
+ */
+struct drm_mode_3dlut_mode {
+	__u16 lut_size;
+	__u16 lut_stride[3];
+	__u16 bit_depth;
+	__u32 color_format;
+	__u32 flags;
+};
+
 #define DRM_MODE_PAGE_FLIP_EVENT 0x01
 #define DRM_MODE_PAGE_FLIP_ASYNC 0x02
 #define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4
-- 
2.37.3


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

* [RFC PATCH 2/5] drm: Add Plane 3DLUT and 3DLUT mode properties
  2022-10-04 21:14 [RFC PATCH 0/5] Proposal for Pre-blending 3D LUT interfaces Alex Hung
  2022-10-04 21:14 ` [RFC PATCH 1/5] drm: Add 3D LUT mode and its attributes Alex Hung
@ 2022-10-04 21:14 ` Alex Hung
  2022-10-04 21:14 ` [RFC PATCH 3/5] drm/amd/display: Define 3D LUT struct for HDR planes Alex Hung
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Alex Hung @ 2022-10-04 21:14 UTC (permalink / raw)
  To: dri-devel, amd-gfx; +Cc: mwen, bhawanpreet.lakha, Alex Hung

Add plane lut_3d mode and lut_3d as blob properties.

lut_3d mode is an enum property with values as blob_ids.
Userspace can get supported modes and also set one of the modes.

Note: A patchset "IGT tests for pre-blending 3D LUT interfaces" for this
proposal is sent to IGT mailing list.

Signed-off-by: Alex Hung <alex.hung@amd.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  4 ++
 drivers/gpu/drm/drm_atomic_state_helper.c     |  3 ++
 drivers/gpu/drm/drm_atomic_uapi.c             | 11 ++++++
 drivers/gpu/drm/drm_color_mgmt.c              | 37 +++++++++++++++++++
 include/drm/drm_mode_object.h                 |  2 +-
 include/drm/drm_plane.h                       | 31 ++++++++++++++++
 6 files changed, 87 insertions(+), 1 deletion(-)

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 f546c1326db3..ee277f357140 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -8006,6 +8006,10 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
 	drm_plane_attach_gamma_properties(plane);
 	drm_plane_attach_ctm_property(plane);
 
+	/* TODO need to check ASICs */
+	drm_plane_create_3d_lut_properties(plane->dev, plane, 1);
+	drm_plane_attach_3dlut_properties(plane);
+
 	/* Create (reset) the plane state */
 	if (plane->funcs->reset)
 		plane->funcs->reset(plane);
diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c
index 7ddf6e4b956b..85900cd1bffe 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -318,6 +318,8 @@ void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
 		drm_property_blob_get(state->ctm);
 	if (state->gamma_lut)
 		drm_property_blob_get(state->gamma_lut);
+	if (state->lut_3d)
+		drm_property_blob_get(state->lut_3d);
 
 	state->color_mgmt_changed = false;
 }
@@ -369,6 +371,7 @@ void __drm_atomic_helper_plane_destroy_state(struct drm_plane_state *state)
 	drm_property_blob_put(state->degamma_lut);
 	drm_property_blob_put(state->ctm);
 	drm_property_blob_put(state->gamma_lut);
+	drm_property_blob_put(state->lut_3d);
 }
 EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state);
 
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index ba3e64cb184a..66e59e7c194d 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -622,6 +622,13 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane,
 					&replaced);
 		state->color_mgmt_changed |= replaced;
 		return ret;
+	} else if (property == plane->lut_3d_property) {
+		ret = drm_atomic_replace_property_blob_from_id(dev,
+					&state->lut_3d, val, -1, 8, &replaced);
+		state->color_mgmt_changed |= replaced;
+		return 0;
+	} else if (property == plane->lut_3d_mode_property) {
+		state->lut_3d_mode = val;
 	} else if (property == config->prop_fb_damage_clips) {
 		ret = drm_atomic_replace_property_blob_from_id(dev,
 					&state->fb_damage_clips,
@@ -700,6 +707,10 @@ drm_atomic_plane_get_property(struct drm_plane *plane,
 	} else if (property == plane->gamma_lut_property) {
 		*val = (state->gamma_lut) ?
 			state->gamma_lut->base.id : 0;
+	} else if (property == plane->lut_3d_property) {
+		*val = (state->lut_3d) ? state->lut_3d->base.id : 0;
+	} else if (property == plane->lut_3d_mode_property) {
+		*val = state->lut_3d_mode;
 	} 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_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c
index b5b3ff7f654d..4bfe5b5c9670 100644
--- a/drivers/gpu/drm/drm_color_mgmt.c
+++ b/drivers/gpu/drm/drm_color_mgmt.c
@@ -706,6 +706,43 @@ void drm_plane_attach_gamma_properties(struct drm_plane *plane)
 }
 EXPORT_SYMBOL(drm_plane_attach_gamma_properties);
 
+int drm_plane_create_3d_lut_properties(struct drm_device *dev,
+					   struct drm_plane *plane,
+					   int num_values)
+{
+	struct drm_property *mode;
+	struct drm_property *blob;
+
+	mode = drm_property_create(dev, DRM_MODE_PROP_ENUM, "PLANE_3D_LUT_MODE", num_values);
+	if (!mode)
+		return -ENOMEM;
+
+	plane->lut_3d_mode_property = mode;
+
+	blob = drm_property_create(dev, DRM_MODE_PROP_BLOB, "PLANE_3D_LUT", 0);
+	if (!blob)
+		return -ENOMEM;
+
+	plane->lut_3d_property = blob;
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_plane_create_3d_lut_properties);
+
+void drm_plane_attach_3dlut_properties(struct drm_plane *plane)
+{
+	if (!plane->lut_3d_property)
+		return;
+
+	drm_object_attach_property(&plane->base, plane->lut_3d_property, 0);
+
+	if (!plane->lut_3d_mode_property)
+		return;
+
+	drm_object_attach_property(&plane->base, plane->lut_3d_mode_property, 0);
+}
+EXPORT_SYMBOL(drm_plane_attach_3dlut_properties);
+
 int drm_plane_color_add_gamma_degamma_mode_range(struct drm_plane *plane,
 						 const char *name,
 						 const struct drm_color_lut_range *ranges,
diff --git a/include/drm/drm_mode_object.h b/include/drm/drm_mode_object.h
index d4128c7daa08..c2b31dbf7325 100644
--- a/include/drm/drm_mode_object.h
+++ b/include/drm/drm_mode_object.h
@@ -60,7 +60,7 @@ struct drm_mode_object {
 	void (*free_cb)(struct kref *kref);
 };
 
-#define DRM_OBJECT_MAX_PROPERTY 26
+#define DRM_OBJECT_MAX_PROPERTY 28
 /**
  * struct drm_object_properties - property tracking for &drm_mode_object
  */
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index 8989bb1aa46c..4e272144170f 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -275,6 +275,21 @@ struct drm_plane_state {
 	 */
 	struct drm_property_blob *gamma_lut;
 
+	/**
+	 * @lut_3d_mode:
+	 * This is a blob_id and exposes the platform capabilities wrt
+	 * various 3dlut. This also helps user select a 3dlut mode amongst
+	 * the supported ones.
+	 */
+	u32 lut_3d_mode;
+
+	/**
+	 * @lut_3d:
+	 * 3D lookup table blob. The blob data is laid out as defined by the
+	 * FOURCC value in color_format in the drm_mode_3dlut_mode struct.
+	 */
+	struct drm_property_blob *lut_3d;
+
 	u8 color_mgmt_changed : 1;
 };
 
@@ -818,6 +833,18 @@ struct drm_plane {
 	 * used to convert the framebuffer's colors to non-linear gamma.
 	 */
 	struct drm_property *gamma_lut_property;
+
+	/**
+	 * @lut_3d_mode_property: Optional Plane property to set the 3DLUT mode
+	 * used to convert the framebuffer's colors to non-linear gamma.
+	 */
+	struct drm_property *lut_3d_mode_property;
+
+	/**
+	 * @lut_3d_property: Optional Plane property to set the 3DLUT
+	 * used to convert the framebuffer's colors to non-linear gamma.
+	 */
+	struct drm_property *lut_3d_property;
 };
 
 #define obj_to_plane(x) container_of(x, struct drm_plane, base)
@@ -915,6 +942,10 @@ int drm_plane_create_color_mgmt_properties(struct drm_device *dev,
 void drm_plane_attach_degamma_properties(struct drm_plane *plane);
 void drm_plane_attach_ctm_property(struct drm_plane *plane);
 void drm_plane_attach_gamma_properties(struct drm_plane *plane);
+int drm_plane_create_3d_lut_properties(struct drm_device *dev,
+					   struct drm_plane *plane,
+					   int num_values);
+void drm_plane_attach_3dlut_properties(struct drm_plane *plane);
 int drm_plane_color_add_gamma_degamma_mode_range(struct drm_plane *plane,
 						 const char *name,
 						 const struct drm_color_lut_range *ranges,
-- 
2.37.3


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

* [RFC PATCH 3/5] drm/amd/display: Define 3D LUT struct for HDR planes
  2022-10-04 21:14 [RFC PATCH 0/5] Proposal for Pre-blending 3D LUT interfaces Alex Hung
  2022-10-04 21:14 ` [RFC PATCH 1/5] drm: Add 3D LUT mode and its attributes Alex Hung
  2022-10-04 21:14 ` [RFC PATCH 2/5] drm: Add Plane 3DLUT and 3DLUT mode properties Alex Hung
@ 2022-10-04 21:14 ` Alex Hung
  2022-10-04 21:14 ` [RFC PATCH 4/5] drm/amd/display: Enable plane 3DLUT mode Alex Hung
  2022-10-04 21:14 ` [RFC PATCH 5/5] drm/amd/display: Fill 3D LUT from userspace Alex Hung
  4 siblings, 0 replies; 6+ messages in thread
From: Alex Hung @ 2022-10-04 21:14 UTC (permalink / raw)
  To: dri-devel, amd-gfx; +Cc: mwen, bhawanpreet.lakha, Alex Hung

Add a 3D LUT mode supported by amdgpu driver.

Note: A patchset "IGT tests for pre-blending 3D LUT interfaces" for this
proposal is sent to IGT mailing list.

Signed-off-by: Alex Hung <alex.hung@amd.com>
---
 .../gpu/drm/amd/display/modules/color/color_gamma.h  | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/modules/color/color_gamma.h b/drivers/gpu/drm/amd/display/modules/color/color_gamma.h
index e06e0a8effc8..aceb23b03a4b 100644
--- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.h
+++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.h
@@ -27,6 +27,7 @@
 #define COLOR_MOD_COLOR_GAMMA_H_
 
 #include "color_table.h"
+#include <drm/drm_fourcc.h>
 
 struct dc_transfer_func;
 struct dc_gamma;
@@ -35,6 +36,17 @@ struct dc_rgb_fixed;
 struct dc_color_caps;
 enum dc_transfer_func_predefined;
 
+/*
+ * 3D LUT mode for 17x17x17 LUT and 12 bits of color depth
+ */
+static const struct drm_mode_3dlut_mode lut_3d_mode_17_12bit = {
+	.lut_size = 17,
+	.lut_stride = {17, 17, 18},
+	.bit_depth = 12,
+	.color_format = DRM_FORMAT_XRGB16161616,
+	.flags = 0,
+};
+
 static const struct drm_color_lut_range nonlinear_pwl[] = {
        { 
                .flags = (DRM_MODE_LUT_GAMMA | DRM_MODE_LUT_REFLECT_NEGATIVE | DRM_MODE_LUT_INTERPOLATE | DRM_MODE_LUT_REUSE_LAST | DRM_MODE_LUT_NON_DECREASING),
-- 
2.37.3


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

* [RFC PATCH 4/5] drm/amd/display: Enable plane 3DLUT mode
  2022-10-04 21:14 [RFC PATCH 0/5] Proposal for Pre-blending 3D LUT interfaces Alex Hung
                   ` (2 preceding siblings ...)
  2022-10-04 21:14 ` [RFC PATCH 3/5] drm/amd/display: Define 3D LUT struct for HDR planes Alex Hung
@ 2022-10-04 21:14 ` Alex Hung
  2022-10-04 21:14 ` [RFC PATCH 5/5] drm/amd/display: Fill 3D LUT from userspace Alex Hung
  4 siblings, 0 replies; 6+ messages in thread
From: Alex Hung @ 2022-10-04 21:14 UTC (permalink / raw)
  To: dri-devel, amd-gfx; +Cc: mwen, bhawanpreet.lakha, Alex Hung

Enable the 3D LUT mode supported by amdgpu.

Note: A patchset "IGT tests for pre-blending 3D LUT interfaces" for this
proposal is sent to IGT mailing list.

Signed-off-by: Alex Hung <alex.hung@amd.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  3 ++
 drivers/gpu/drm/drm_color_mgmt.c              | 31 +++++++++++++++++++
 include/drm/drm_plane.h                       |  2 ++
 3 files changed, 36 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 ee277f357140..7094578a683f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -8008,6 +8008,9 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
 
 	/* TODO need to check ASICs */
 	drm_plane_create_3d_lut_properties(plane->dev, plane, 1);
+	res = drm_plane_color_add_3dlut_mode(plane, "3dlut_17_12bit", &lut_3d_mode_17_12bit, sizeof(lut_3d_mode_17_12bit));
+	if (res)
+		return res;
 	drm_plane_attach_3dlut_properties(plane);
 
 	/* Create (reset) the plane state */
diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c
index 4bfe5b5c9670..5418ca24db73 100644
--- a/drivers/gpu/drm/drm_color_mgmt.c
+++ b/drivers/gpu/drm/drm_color_mgmt.c
@@ -743,6 +743,37 @@ void drm_plane_attach_3dlut_properties(struct drm_plane *plane)
 }
 EXPORT_SYMBOL(drm_plane_attach_3dlut_properties);
 
+int drm_plane_color_add_3dlut_mode(struct drm_plane *plane,
+						 const char *name,
+						 const struct drm_mode_3dlut_mode *mode_3dlut,
+						 size_t length)
+{
+	struct drm_property_blob *blob;
+	struct drm_property *prop = NULL;
+	int ret;
+
+	prop = plane->lut_3d_mode_property;
+
+	if (!prop)
+		return -EINVAL;
+
+	if (length == 0 && name)
+		return drm_property_add_enum(prop, 0, name);
+
+	blob = drm_property_create_blob(plane->dev, length, mode_3dlut);
+	if (IS_ERR(blob))
+		return PTR_ERR(blob);
+
+	ret = drm_property_add_enum(prop, blob->base.id, name);
+	if (ret) {
+		drm_property_blob_put(blob);
+		return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_plane_color_add_3dlut_mode);
+
 int drm_plane_color_add_gamma_degamma_mode_range(struct drm_plane *plane,
 						 const char *name,
 						 const struct drm_color_lut_range *ranges,
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index 4e272144170f..f94f91466675 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -946,6 +946,8 @@ int drm_plane_create_3d_lut_properties(struct drm_device *dev,
 					   struct drm_plane *plane,
 					   int num_values);
 void drm_plane_attach_3dlut_properties(struct drm_plane *plane);
+int drm_plane_color_add_3dlut_mode(struct drm_plane *plane, const char *name,
+						 const struct drm_mode_3dlut_mode *mode_3dlut, size_t length);
 int drm_plane_color_add_gamma_degamma_mode_range(struct drm_plane *plane,
 						 const char *name,
 						 const struct drm_color_lut_range *ranges,
-- 
2.37.3


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

* [RFC PATCH 5/5] drm/amd/display: Fill 3D LUT from userspace
  2022-10-04 21:14 [RFC PATCH 0/5] Proposal for Pre-blending 3D LUT interfaces Alex Hung
                   ` (3 preceding siblings ...)
  2022-10-04 21:14 ` [RFC PATCH 4/5] drm/amd/display: Enable plane 3DLUT mode Alex Hung
@ 2022-10-04 21:14 ` Alex Hung
  4 siblings, 0 replies; 6+ messages in thread
From: Alex Hung @ 2022-10-04 21:14 UTC (permalink / raw)
  To: dri-devel, amd-gfx; +Cc: mwen, bhawanpreet.lakha, Alex Hung

Implement the 3D LUT interface, convert and pass the data for amdgpu
driver.

Note: A patchset "IGT tests for pre-blending 3D LUT interfaces" for this
proposal is sent to IGT mailing list.

Signed-off-by: Alex Hung <alex.hung@amd.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  13 ++
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |   1 +
 .../amd/display/amdgpu_dm/amdgpu_dm_color.c   | 181 ++++++++++++++++++
 3 files changed, 195 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 7094578a683f..10e6dc5c8552 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -5656,6 +5656,19 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
 		dc_plane_state->in_transfer_func->type = TF_TYPE_HWPWL;
 	}
 
+	/* 3D LUT from userspace */
+	if (plane_state->color_mgmt_changed) {
+		if (plane_state->lut_3d && dc_plane_state->lut3d_func) {
+			ret = amdgpu_dm_fill_3dlut_data(plane_state, &dc_plane_state->lut3d_func->lut_3d);
+			if (!ret)
+				dc_plane_state->lut3d_func->state.bits.initialized = 1;
+			else
+				return ret;
+		} else {
+			/* TODO disable 3D LUT */
+		}
+	}
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index 667957087ccf..644c5ff6ee9a 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -726,6 +726,7 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
 				      struct dc_plane_state *dc_plane_state);
 
 void amdgpu_dm_fill_pwl_data(struct drm_property_blob *lut_blob, struct pwl_params *lut_params, struct drm_color_lut_range *pwl_definition, int pwl_size);
+int amdgpu_dm_fill_3dlut_data(const struct drm_plane_state *plane_state, struct tetrahedral_params *param);
 void amdgpu_dm_update_connector_after_detect(
 		struct amdgpu_dm_connector *aconnector);
 
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 ae633fe52525..705852bf63e7 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
@@ -22,6 +22,7 @@
  * Authors: AMD
  *
  */
+ #include <linux/videodev2.h>
 #include "amdgpu.h"
 #include "amdgpu_mode.h"
 #include "amdgpu_dm.h"
@@ -469,6 +470,186 @@ int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state)
 	return 0;
 }
 
+#define R_3DLUT	0
+#define G_3DLUT	1
+#define B_3DLUT	2
+
+static __u16 extract_rgb_value(void *lut_3d, __u32 color_format, __u8 color)
+{
+	__u64 val = *(__u64 *) lut_3d;
+
+	switch (color_format) {
+	case DRM_FORMAT_XRGB16161616:
+		if (color == R_3DLUT)
+			return val & 0xFFFF;
+		else if (color == G_3DLUT)
+			return (val >> 16) & 0xFFFF;
+		else if (color == B_3DLUT)
+			return (val >> 32) & 0xFFFF;
+		break;
+	case DRM_FORMAT_XBGR16161616:
+		if (color == B_3DLUT)
+			return val & 0xFFFF;
+		else if (color == G_3DLUT)
+			return (val >> 16) & 0xFFFF;
+		else if (color == R_3DLUT)
+			return (val >> 32) & 0xFFFF;
+		break;
+	case DRM_FORMAT_XRGB8888:
+		if (color == R_3DLUT)
+			return val & 0xFF;
+		else if (color == G_3DLUT)
+			return (val >> 8) & 0xFF;
+		else if (color == B_3DLUT)
+			return (val >> 16) & 0xFF;
+		break;
+	case DRM_FORMAT_XBGR8888:
+		if (color == B_3DLUT)
+			return val & 0xFF;
+		else if (color == G_3DLUT)
+			return (val >> 8) & 0xFF;
+		else if (color == R_3DLUT)
+			return (val >> 16) & 0xFF;
+			break;
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static bool extract_rgb_data(const struct drm_plane_state *plane_state, struct drm_mode_3dlut_mode *mode, __u16 *lut_data)
+{
+	__u16 i, lut_volume;
+	void *lut_3d = plane_state->lut_3d->data;
+	__u32 cfmt = mode->color_format;
+
+	/* copy RGB accordingly */
+	lut_volume = mode->lut_size * mode->lut_size * mode->lut_size;
+	for (i = 0; i < lut_volume; i += 3) {
+		lut_data[i] = extract_rgb_value(lut_3d, cfmt, R_3DLUT);
+		lut_data[i+1] = extract_rgb_value(lut_3d, cfmt, G_3DLUT);
+		lut_data[i+2] = extract_rgb_value(lut_3d, cfmt, B_3DLUT);
+
+		if (cfmt == DRM_FORMAT_XRGB16161616 || cfmt == DRM_FORMAT_XBGR16161616)
+			lut_3d += sizeof(__u64);
+		else if (cfmt == DRM_FORMAT_XRGB8888 || cfmt == DRM_FORMAT_XBGR8888)
+			lut_3d += sizeof(__u32);
+		else
+			return false;
+	}
+	return true;
+}
+
+static void convert_3dlut_to_tetrahedral_params(struct dc_rgb *rgb,
+	bool is_17x17x17, bool is_12_bits, struct tetrahedral_params *params)
+{
+	struct dc_rgb *lut0;
+	struct dc_rgb *lut1;
+	struct dc_rgb *lut2;
+	struct dc_rgb *lut3;
+	int i, lut_i;
+
+	int num_values;
+
+	if (is_17x17x17 == false) {
+		lut0 = params->tetrahedral_9.lut0;
+		lut1 = params->tetrahedral_9.lut1;
+		lut2 = params->tetrahedral_9.lut2;
+		lut3 = params->tetrahedral_9.lut3;
+		num_values = 729;
+	} else {
+		lut0 = params->tetrahedral_17.lut0;
+		lut1 = params->tetrahedral_17.lut1;
+		lut2 = params->tetrahedral_17.lut2;
+		lut3 = params->tetrahedral_17.lut3;
+		num_values = 4913;
+	}
+
+	params->use_12bits = is_12_bits;
+	params->use_tetrahedral_9 = !is_17x17x17;
+
+	for (lut_i = 0, i = 0; i < num_values - 4; lut_i++, i += 4) {
+		lut0[lut_i].red   = rgb[i].red;
+		lut0[lut_i].green = rgb[i].green;
+		lut0[lut_i].blue  = rgb[i].blue;
+
+		lut1[lut_i].red   = rgb[i + 1].red;
+		lut1[lut_i].green = rgb[i + 1].green;
+		lut1[lut_i].blue  = rgb[i + 1].blue;
+
+		lut2[lut_i].red   = rgb[i + 2].red;
+		lut2[lut_i].green = rgb[i + 2].green;
+		lut2[lut_i].blue  = rgb[i + 2].blue;
+
+		lut3[lut_i].red   = rgb[i + 3].red;
+		lut3[lut_i].green = rgb[i + 3].green;
+		lut3[lut_i].blue  = rgb[i + 3].blue;
+	}
+
+	lut0[lut_i].red      = rgb[i].red;
+	lut0[lut_i].green    = rgb[i].green;
+	lut0[lut_i].blue     = rgb[i].blue;
+}
+
+/* only use for 17x17x17 */
+bool convert_to_tetrahedral(unsigned short rgb_lib[17*17*17*3], struct tetrahedral_params *params)
+{
+	bool ret = false;
+	struct dc_rgb *rgb_area = NULL;
+	int ind = 0;
+	int ind_lut = 0;
+	int nir, nig, nib;
+
+	rgb_area = kvcalloc(17 * 17 * 17, sizeof(struct dc_rgb), GFP_KERNEL);
+	if (rgb_area == NULL)
+		goto release;
+
+	memset(rgb_area, 0, sizeof(17 * 17 * 17 * sizeof(struct dc_rgb)));
+
+	for (nib = 0; nib < 17; nib++) {
+		for (nig = 0; nig < 17; nig++) {
+			for (nir = 0; nir < 17; nir++) {
+				ind_lut = 3 * (nib + 17*nig + 289*nir);
+
+				rgb_area[ind].red = rgb_lib[ind_lut + 0];
+				rgb_area[ind].green = rgb_lib[ind_lut + 1];
+				rgb_area[ind].blue = rgb_lib[ind_lut + 2];
+				ind++;
+			}
+		}
+	}
+	convert_3dlut_to_tetrahedral_params(rgb_area, true, true, params);
+	kvfree(rgb_area);
+	ret = true;
+
+release:
+	return ret;
+}
+
+int amdgpu_dm_fill_3dlut_data(const struct drm_plane_state *plane_state, struct tetrahedral_params *param)
+{
+	const struct drm_mode_3dlut_mode *mode = &lut_3d_mode_17_12bit;
+	unsigned short *lut_data;
+
+	lut_data = kmalloc(mode->lut_size * mode->lut_size * mode->lut_size * sizeof(__u16) * 3, GFP_KERNEL);
+	if (!extract_rgb_data(plane_state, mode, lut_data))
+		return -EINVAL;
+
+	if (!convert_to_tetrahedral(lut_data, param))
+		return -EINVAL;
+
+	kfree(lut_data);
+
+	if (mode->lut_size == 17)
+		param->use_tetrahedral_9 = false;
+
+	if (mode->bit_depth == 12)
+		param->use_12bits = true;
+
+	return 0;
+}
+
 /**
  * amdgpu_dm_update_crtc_color_mgmt: Maps DRM color management to DC stream.
  * @crtc: amdgpu_dm crtc state
-- 
2.37.3


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

end of thread, other threads:[~2022-10-04 21:16 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-04 21:14 [RFC PATCH 0/5] Proposal for Pre-blending 3D LUT interfaces Alex Hung
2022-10-04 21:14 ` [RFC PATCH 1/5] drm: Add 3D LUT mode and its attributes Alex Hung
2022-10-04 21:14 ` [RFC PATCH 2/5] drm: Add Plane 3DLUT and 3DLUT mode properties Alex Hung
2022-10-04 21:14 ` [RFC PATCH 3/5] drm/amd/display: Define 3D LUT struct for HDR planes Alex Hung
2022-10-04 21:14 ` [RFC PATCH 4/5] drm/amd/display: Enable plane 3DLUT mode Alex Hung
2022-10-04 21:14 ` [RFC PATCH 5/5] drm/amd/display: Fill 3D LUT from userspace Alex Hung

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