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