[PATCH V10 03/30] drm-uapi: Add COLOROP object
Alex Hung
alex.hung at amd.com
Fri Aug 15 04:06:32 UTC 2025
From: Harry Wentland <harry.wentland at amd.com>
DRM is introducing a new DRM core obejct, a drm_colorop. This
object will represent one color operation in a color pipeline.
Introduce the object type in the drm-uapi, including the
following types:
- DRM_COLOROP_1D_CURVE,
- DRM_COLOROP_1D_LUT,
- DRM_COLOROP_CTM_3X4,
Signed-off-by: Alex Hung <alex.hung at amd.com>
Signed-off-by: Harry Wentland <harry.wentland at amd.com>
---
include/drm-uapi/amdgpu_drm.h | 9 --
include/drm-uapi/drm_mode.h | 23 +++
lib/igt_kms.c | 272 +++++++++++++++++++++++++++++++++-
lib/igt_kms.h | 89 +++++++++++
tests/kms_properties.c | 3 +
5 files changed, 381 insertions(+), 15 deletions(-)
diff --git a/include/drm-uapi/amdgpu_drm.h b/include/drm-uapi/amdgpu_drm.h
index b38f27d69..ca24519c7 100644
--- a/include/drm-uapi/amdgpu_drm.h
+++ b/include/drm-uapi/amdgpu_drm.h
@@ -1590,15 +1590,6 @@ struct drm_amdgpu_info_uq_metadata {
#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/drm-uapi/drm_mode.h b/include/drm-uapi/drm_mode.h
index c082810c0..fce45b5cf 100644
--- a/include/drm-uapi/drm_mode.h
+++ b/include/drm-uapi/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 {
@@ -846,6 +847,22 @@ 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.
+ *
+ * TODO what's the format?
+ *
+ * out matrix in
+ * |R| |0 1 2 3 | | R |
+ * |G| = |4 5 6 7 | x | G |
+ * |B| |8 9 10 12| | 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
@@ -857,6 +874,12 @@ struct drm_color_lut {
__u16 reserved;
};
+enum drm_colorop_type {
+ DRM_COLOROP_1D_CURVE,
+ DRM_COLOROP_1D_LUT,
+ DRM_COLOROP_CTM_3X4,
+};
+
/**
* struct drm_plane_size_hint - Plane size hints
* @width: The width of the plane in pixel
diff --git a/lib/igt_kms.c b/lib/igt_kms.c
index a9641eba4..69beb523f 100644
--- a/lib/igt_kms.c
+++ b/lib/igt_kms.c
@@ -92,6 +92,7 @@
#define MAX_CONNECTORS 32
#define MAX_EDID 2
#define DISPLAY_TILE_BLOCK 0x12
+#define MAX_NUM_COLOROPS 128
typedef bool (*igt_connector_attr_set)(int dir, const char *attr, const char *value);
@@ -702,6 +703,14 @@ const char * const igt_plane_prop_names[IGT_NUM_PLANE_PROPS] = {
[IGT_PLANE_SCALING_FILTER] = "SCALING_FILTER",
[IGT_PLANE_SIZE_HINTS] = "SIZE_HINTS",
[IGT_PLANE_IN_FORMATS_ASYNC] = "IN_FORMATS_ASYNC",
+ [IGT_PLANE_COLOR_PIPELINE] = "COLOR_PIPELINE",
+};
+
+const char * const igt_colorop_prop_names[IGT_NUM_COLOROP_PROPS] = {
+ [IGT_COLOROP_TYPE] = "TYPE",
+ [IGT_COLOROP_BYPASS] = "BYPASS",
+ [IGT_COLOROP_CURVE_1D_TYPE] = "CURVE_1D_TYPE",
+ [IGT_COLOROP_NEXT] = "NEXT",
};
const char * const igt_crtc_prop_names[IGT_NUM_CRTC_PROPS] = {
@@ -769,6 +778,108 @@ igt_plane_rotations(igt_display_t *display, igt_plane_t *plane,
return rotations;
}
+/**
+ * igt_find_colorop:
+ * @display: display on which to look for colorop.
+ * @id: DRM object id of the colorop.
+ *
+ * Returns: An igt_colorop_t if found, or NULL otherwise.
+ */
+igt_colorop_t *igt_find_colorop(igt_display_t *display, uint32_t id)
+{
+ int i;
+
+ /* find corresponding igt_colorop */
+ for (i = 0; i < display->n_colorops; ++i) {
+ igt_colorop_t *colorop = &display->colorops[i];
+
+ if (colorop->id == id)
+ return colorop;
+ }
+
+ return NULL;
+}
+
+/*
+ * Retrieve all the properies specified in props_name and store them into
+ * colorop->props.
+ */
+static void
+igt_fill_colorop_props(igt_display_t *display, igt_colorop_t *colorop,
+ int num_props, const char * const prop_names[])
+{
+ drmModeObjectPropertiesPtr props;
+ int i, j, fd;
+
+ fd = display->drm_fd;
+
+ props = drmModeObjectGetProperties(fd, colorop->id, DRM_MODE_OBJECT_COLOROP);
+ igt_assert(props);
+
+ for (i = 0; i < props->count_props; i++) {
+ drmModePropertyPtr prop =
+ drmModeGetProperty(fd, props->props[i]);
+
+ for (j = 0; j < num_props; j++) {
+ if (strcmp(prop->name, prop_names[j]) != 0)
+ continue;
+
+ colorop->props[j] = props->props[i];
+ break;
+ }
+
+ drmModeFreeProperty(prop);
+ }
+ drmModeFreeObjectProperties(props);
+}
+
+static void igt_fill_colorop(igt_display_t *display, igt_plane_t *plane,
+ igt_colorop_t *colorop, uint32_t id,
+ char *name)
+{
+ colorop->id = id;
+ colorop->plane = plane;
+
+ if (name)
+ memcpy(colorop->name, name, sizeof(colorop->name));
+
+ igt_fill_colorop_props(display, colorop, IGT_NUM_COLOROP_PROPS, igt_colorop_prop_names);
+}
+
+static void
+igt_fill_plane_color_pipelines(igt_display_t *display, igt_plane_t *plane,
+ drmModePropertyPtr prop)
+{
+ int i;
+ uint32_t colorop_id;
+
+ plane->num_color_pipelines = 0;
+
+ for (i = 0; i < prop->count_enums; i++) {
+ if (prop->enums[i].value) {
+ igt_colorop_t *colorop = &display->colorops[display->n_colorops++];
+
+ igt_assert(display->n_colorops < MAX_NUM_COLOROPS);
+
+ igt_fill_colorop(display, plane, colorop, prop->enums[i].value, prop->enums[i].name);
+ plane->color_pipelines[plane->num_color_pipelines++] = colorop;
+
+ /* get all NEXT colorops */
+ colorop_id = igt_colorop_get_prop(display, colorop,
+ IGT_COLOROP_NEXT);
+ while (colorop_id) {
+ colorop = &display->colorops[display->n_colorops++];
+ igt_fill_colorop(display, plane, colorop, colorop_id, NULL);
+ colorop_id = igt_colorop_get_prop(display, colorop,
+ IGT_COLOROP_NEXT);
+ }
+ }
+ }
+
+ igt_assert(plane->num_color_pipelines < IGT_NUM_PLANE_COLOR_PIPELINES);
+
+}
+
/*
* Retrieve all the properties specified in props_name and store them into
* plane->props.
@@ -800,6 +911,9 @@ igt_fill_plane_props(igt_display_t *display, igt_plane_t *plane,
if (strcmp(prop->name, "rotation") == 0)
plane->rotations = igt_plane_rotations(display, plane, prop);
+ if (strcmp(prop->name, "COLOR_PIPELINE") == 0)
+ igt_fill_plane_color_pipelines(display, plane, prop);
+
drmModeFreeProperty(prop);
}
@@ -3004,16 +3118,14 @@ void igt_display_require(igt_display_t *display, int drm_fd)
igt_assert(plane->drm_plane);
plane->type = get_drm_plane_type(display->drm_fd, id);
-
- /*
- * TODO: Fill in the rest of the plane properties here and
- * move away from the plane per pipe model to align closer
- * to the DRM KMS model.
- */
}
drmModeFreePlaneResources(plane_resources);
+ /* init colorops */
+ display->colorops = calloc(MAX_NUM_COLOROPS, sizeof(igt_colorop_t));
+ display->n_colorops = 0;
+
for_each_pipe(display, i) {
igt_pipe_t *pipe = &display->pipes[i];
igt_plane_t *plane;
@@ -3631,6 +3743,8 @@ igt_atomic_ignore_plane_prop(igt_pipe_t *pipe, uint32_t prop)
}
} else {
switch (prop) {
+ case IGT_PLANE_COLOR_PIPELINE:
+ return true;
default:
return false;
}
@@ -3680,6 +3794,45 @@ igt_atomic_prepare_plane_commit(igt_plane_t *plane, igt_pipe_t *pipe,
}
}
+/*
+ * Add colorop properties
+ */
+static void
+igt_atomic_prepare_colorop_commit(igt_colorop_t *colorop, igt_pipe_t *pipe,
+ drmModeAtomicReq *req)
+{
+ igt_display_t *display = pipe->display;
+ int i, next_val;
+
+ while (colorop) {
+ LOG(display,
+ "populating colorop data: %s.%d\n",
+ kmstest_pipe_name(pipe->pipe),
+ colorop->id);
+
+ for (i = 0; i < IGT_NUM_COLOROP_PROPS; i++) {
+ if (!igt_colorop_is_prop_changed(colorop, i))
+ continue;
+
+ /* it's an error to try an unsupported feature */
+ igt_assert(colorop->props[i]);
+
+ igt_debug("colorop %s.%d: Setting property \"%s\" to 0x%"PRIx64"/%"PRIi64"\n",
+ kmstest_pipe_name(pipe->pipe), colorop->id, igt_colorop_prop_names[i],
+ colorop->values[i], colorop->values[i]);
+
+ igt_assert_lt(0, drmModeAtomicAddProperty(req, colorop->id,
+ colorop->props[i],
+ colorop->values[i]));
+ }
+
+ /* get next colorop */
+ next_val = igt_colorop_get_prop(display, colorop,
+ IGT_COLOROP_NEXT);
+ colorop = igt_find_colorop(display, next_val);
+ }
+}
+
/*
* Properties that can be changed through legacy SetProperty:
* - Obviously not the XYWH SRC/CRTC coordinates.
@@ -4127,6 +4280,25 @@ uint64_t igt_plane_get_prop(igt_plane_t *plane, enum igt_atomic_plane_properties
plane->drm_plane->plane_id, plane->props[prop]);
}
+/**
+ * igt_colorop_get_prop:
+ * @colorop: Target colorop.
+ * @prop: Property to check.
+ *
+ * Return current value on a colorop for a given property.
+ *
+ * Returns: The value the property is set to, if this
+ * is a blob, the blob id is returned. This can be passed
+ * to drmModeGetPropertyBlob() to get the contents of the blob.
+ */
+uint64_t igt_colorop_get_prop(igt_display_t *display, igt_colorop_t *colorop, enum igt_atomic_colorop_properties prop)
+{
+ igt_assert(igt_colorop_has_prop(colorop, prop));
+
+ return igt_mode_object_get_prop(display, DRM_MODE_OBJECT_COLOROP,
+ colorop->id, colorop->props[prop]);
+}
+
static bool igt_mode_object_get_prop_enum_value(int drm_fd, uint32_t id, const char *str, uint64_t *val)
{
drmModePropertyPtr prop = drmModeGetProperty(drm_fd, id);
@@ -4215,6 +4387,44 @@ bool igt_plane_check_prop_is_mutable(igt_plane_t *plane,
return !(prop->flags & DRM_MODE_PROP_IMMUTABLE);
}
+/**
+ * igt_plane_is_valid_colorop:
+ * @plane: Target plane.
+ * @colorop: Colorop to check.
+ *
+ * Returns: True if the given @colorop is a valid color pipeline on
+ * the given @plane
+ */
+bool igt_plane_is_valid_colorop(igt_plane_t *plane, igt_colorop_t *colorop)
+{
+ int i;
+ bool found = false;
+
+ for (i = 0; i < plane->num_color_pipelines; i++) {
+ if (plane->color_pipelines[i] == colorop) {
+ found = true;
+ break;
+ }
+ }
+
+ return found;
+}
+/**
+ * igt_plane_set_color_pipeline:
+ * @plane: Target plane.
+ * @colorop: Colorop to set as color pipeline.
+ *
+ * This function sets the given @colorop as color pipeline on @plane, or fails
+ * the test if it's an invalid color pipeline for the plane.
+ */
+void igt_plane_set_color_pipeline(igt_plane_t *plane, igt_colorop_t *colorop)
+{
+ igt_assert(igt_plane_is_valid_colorop(plane, colorop));
+
+ plane->assigned_color_pipeline = colorop;
+ igt_plane_set_prop_enum(plane, IGT_PLANE_COLOR_PIPELINE, colorop->name);
+}
+
/**
* igt_plane_replace_prop_blob:
* @plane: plane to set property on.
@@ -4247,6 +4457,51 @@ igt_plane_replace_prop_blob(igt_plane_t *plane, enum igt_atomic_plane_properties
igt_plane_set_prop_changed(plane, prop);
}
+/**
+ * igt_colorop_try_prop_enum:
+ * @colorop: Target colorop.
+ * @prop: Property to check.
+ * @val: Value to set.
+ *
+ * Returns: False if the given @colorop doesn't have the enum @prop or
+ * failed to set the enum property @val else True.
+ */
+bool igt_colorop_try_prop_enum(igt_colorop_t *colorop,
+ enum igt_atomic_colorop_properties prop,
+ const char *val)
+{
+ igt_display_t *display = colorop->plane->pipe->display;
+ uint64_t uval;
+
+ igt_assert(colorop->props[prop]);
+
+ if (!igt_mode_object_get_prop_enum_value(display->drm_fd,
+ colorop->props[prop], val, &uval))
+ return false;
+
+ igt_colorop_set_prop_value(colorop, prop, uval);
+ return true;
+}
+
+/**
+ * igt_colorop_set_prop_enum:
+ * @plane: Target plane.
+ * @prop: Property to check.
+ * @val: Value to set.
+ *
+ * This function tries to set given enum property @prop value @val to
+ * the given @colorop, and terminate the execution if its failed.
+ */
+void igt_colorop_set_prop_enum(igt_colorop_t *colorop,
+ enum igt_atomic_colorop_properties prop,
+ const char *val)
+{
+ bool result = false;
+
+ result = igt_colorop_try_prop_enum(colorop, prop, val);
+ igt_assert(result);
+}
+
/**
* igt_output_get_prop:
* @output: Target output.
@@ -4519,6 +4774,11 @@ static int igt_atomic_commit(igt_display_t *display, uint32_t flags, void *user_
if (plane->changed)
igt_atomic_prepare_plane_commit(plane, pipe_obj, req);
+
+ /* TODO iterate over assigned color pipeline and prepare colorop commit */
+ if (plane->assigned_color_pipeline)
+ igt_atomic_prepare_colorop_commit(plane->assigned_color_pipeline,
+ pipe_obj, req);
}
}
diff --git a/lib/igt_kms.h b/lib/igt_kms.h
index 8ec39fa85..dc2a2d9e0 100644
--- a/lib/igt_kms.h
+++ b/lib/igt_kms.h
@@ -366,9 +366,18 @@ enum igt_atomic_plane_properties {
IGT_PLANE_HOTSPOT_Y,
IGT_PLANE_SIZE_HINTS,
IGT_PLANE_IN_FORMATS_ASYNC,
+ IGT_PLANE_COLOR_PIPELINE,
IGT_NUM_PLANE_PROPS,
};
+enum igt_atomic_colorop_properties {
+ IGT_COLOROP_TYPE,
+ IGT_COLOROP_BYPASS,
+ IGT_COLOROP_CURVE_1D_TYPE,
+ IGT_COLOROP_NEXT,
+ IGT_NUM_COLOROP_PROPS
+};
+
/**
* igt_plane_prop_names
*
@@ -377,10 +386,20 @@ enum igt_atomic_plane_properties {
*/
extern const char * const igt_plane_prop_names[];
+/**
+ * igt_colorop_prop_names
+ *
+ * igt_colorop_prop_names contains a list of colorop property names,
+ * as indexed by the igt_atomic_colorop_properties enum.
+ */
+extern const char * const igt_colorop_prop_names[];
+
typedef struct igt_display igt_display_t;
typedef struct igt_pipe igt_pipe_t;
typedef uint32_t igt_fixed_t; /* 16.16 fixed point */
+#define IGT_NUM_PLANE_COLOR_PIPELINES 4
+
typedef enum {
/* this maps to the kernel API */
IGT_ROTATION_0 = 1 << 0,
@@ -406,6 +425,20 @@ static inline bool igt_rotation_90_or_270(igt_rotation_t rotation)
return rotation & (IGT_ROTATION_90 | IGT_ROTATION_270);
}
+typedef struct igt_plane igt_plane_t;
+
+typedef struct igt_colorop {
+ uint32_t id;
+ igt_plane_t *plane;
+
+ char name[DRM_PROP_NAME_LEN];
+
+ uint64_t changed;
+ uint32_t props[IGT_NUM_COLOROP_PROPS];
+ uint64_t values[IGT_NUM_COLOROP_PROPS];
+
+} igt_colorop_t;
+
typedef struct igt_plane {
/*< private >*/
igt_pipe_t *pipe;
@@ -443,6 +476,11 @@ typedef struct igt_plane {
uint64_t *async_modifiers;
uint32_t *async_formats;
int async_format_mod_count;
+
+ igt_colorop_t *color_pipelines[IGT_NUM_PLANE_COLOR_PIPELINES];
+ int num_color_pipelines;
+
+ igt_colorop_t *assigned_color_pipeline;
} igt_plane_t;
/*
@@ -501,9 +539,11 @@ struct igt_display {
int log_shift;
int n_pipes;
int n_planes;
+ int n_colorops;
int n_outputs;
igt_output_t *outputs;
igt_plane_t *planes;
+ igt_colorop_t *colorops;
igt_pipe_t *pipes;
bool has_cursor_plane;
bool is_atomic;
@@ -846,6 +886,53 @@ extern void igt_plane_set_prop_enum(igt_plane_t *plane,
enum igt_atomic_plane_properties prop,
const char *val);
+
+
+extern bool igt_plane_is_valid_colorop(igt_plane_t *plane, igt_colorop_t *colorop);
+
+extern void igt_plane_set_color_pipeline(igt_plane_t *plane, igt_colorop_t *colorop);
+
+/**
+ * igt_colorop_has_prop:
+ * @colorop: colorop to check.
+ * @prop: Property to check.
+ *
+ * Check whether colorop supports a given property.
+ *
+ * Returns: True if the property is supported, otherwise false.
+ */
+static inline bool
+igt_colorop_has_prop(igt_colorop_t *colorop, enum igt_atomic_colorop_properties prop)
+{
+ return colorop->props[prop];
+}
+
+uint64_t igt_colorop_get_prop(igt_display_t *display, igt_colorop_t *colorop, enum igt_atomic_colorop_properties prop);
+
+#define igt_colorop_is_prop_changed(colorop, prop) \
+ (!!((colorop)->changed & (1 << (prop))))
+
+#define igt_colorop_set_prop_changed(colorop, prop) \
+ ((colorop)->changed |= 1 << (prop))
+
+#define igt_colorop_clear_prop_changed(colorop, prop) \
+ ((colorop)->changed &= ~(1 << (prop)))
+
+#define igt_colorop_set_prop_value(colorop, prop, value) \
+ do { \
+ colorop->values[prop] = value; \
+ igt_colorop_set_prop_changed(colorop, prop); \
+ } while (0)
+
+
+extern bool igt_colorop_try_prop_enum(igt_colorop_t *colorop,
+ enum igt_atomic_colorop_properties prop,
+ const char *val);
+
+extern void igt_colorop_set_prop_enum(igt_colorop_t *colorop,
+ enum igt_atomic_colorop_properties prop,
+ const char *val);
+
extern void igt_plane_replace_prop_blob(igt_plane_t *plane,
enum igt_atomic_plane_properties prop,
const void *ptr, size_t length);
@@ -1289,4 +1376,6 @@ int igt_backlight_write(int value, const char *fname, igt_backlight_context_t *c
drmModePropertyBlobRes *igt_get_writeback_formats_blob(igt_output_t *output);
+igt_colorop_t *igt_find_colorop(igt_display_t *display, uint32_t id);
+
#endif /* __IGT_KMS_H__ */
diff --git a/tests/kms_properties.c b/tests/kms_properties.c
index e646b8184..3bdf23aad 100644
--- a/tests/kms_properties.c
+++ b/tests/kms_properties.c
@@ -112,6 +112,9 @@ static bool ignore_property(uint32_t obj_type, uint32_t prop_flags,
return true;
break;
case DRM_MODE_OBJECT_PLANE:
+ if (!has_color_pipeline && !strcmp(name, "COLOR_PIPELINE"))
+ return true;
+
if (has_color_pipeline && !strcmp(name, "COLOR_RANGE"))
return true;
--
2.43.0
More information about the igt-dev
mailing list