Re: [igt-dev] [i-g-t 03/14] kms_color_helper: Add helper functions for plane color mgmt
From: Pekka Paalanen <ppaalanen@gmail.com>
Date: 2021-11-18 08:41:42
Also in:
dri-devel
On Mon, 15 Nov 2021 15:17:48 +0530 Bhanuprakash Modem [off-list ref] wrote:
quoted hunk ↗ jump to hunk
Add helper functions to support Plane color management properties. Cc: Harry Wentland <harry.wentland@amd.com> Cc: Ville Syrjälä <redacted> Cc: Juha-Pekka Heikkila <redacted> Cc: Uma Shankar <redacted> Signed-off-by: Bhanuprakash Modem <redacted> --- tests/kms_color_helper.c | 173 +++++++++++++++++++++++++++++++++++++++ tests/kms_color_helper.h | 29 +++++++ 2 files changed, 202 insertions(+)diff --git a/tests/kms_color_helper.c b/tests/kms_color_helper.c index d71e7bb2e6..c65b7a0f50 100644 --- a/tests/kms_color_helper.c +++ b/tests/kms_color_helper.c@@ -241,6 +241,150 @@ void disable_prop(igt_pipe_t *pipe, enum igt_atomic_crtc_properties prop) igt_pipe_obj_replace_prop_blob(pipe, prop, NULL, 0); } +drmModePropertyPtr get_plane_gamma_degamma_mode(igt_plane_t *plane, + enum igt_atomic_plane_properties prop) +{ + igt_display_t *display = plane->pipe->display; + uint32_t prop_id = plane->props[prop]; + drmModePropertyPtr drmProp; + + igt_assert(prop_id); + + drmProp = drmModeGetProperty(display->drm_fd, prop_id); + + igt_assert(drmProp); + igt_assert(drmProp->count_enums); + + return drmProp; +} + +struct drm_color_lut_ext *create_linear_lut(segment_data_t *info)
Hi, this actually creates an identity transformation as a LUT, does it not? If so, it should be named that way. A linear transformation represented by a LUT may not be identity transformation. Identity is quite a bad case to test with, because it is a no-op, and simply accidentally disabling the whole LUT will pass a writeback test.
+{
+ uint32_t val, segment, entry, index = 0;
+ uint32_t max_val = 0xffffffff;
+ struct drm_color_lut_ext *lut = malloc(sizeof(struct drm_color_lut_ext) * info->entries_count);
+ igt_assert(lut);
+
+ for (segment = 0; segment < info->segment_count; segment++) {
+ uint32_t entry_count = info->segment_data[segment].count;
+ uint32_t start = info->segment_data[segment].start;
+ uint32_t end = info->segment_data[segment].end;
+
+ for (entry = 1; entry <= entry_count; entry++) {
+ val = (index == 0) ? /* First entry is Zero. */
+ 0 : start + entry * ((end - start) * 1.0 / entry_count);Having to explicitly special-case index zero feels odd to me. Why does it need explicit special-casing? To me it's a hint that the definitions of .start and .end are somehow inconsistent.
+ + lut[index].red = lut[index].green = lut[index].blue = MIN(val, max_val);
There are tests that use different curves for each of red, green and blue and check that they also work, right?
+ + index++; + } + } + + return lut; +} + +struct drm_color_lut_ext *create_max_lut(segment_data_t *info)
What is the point of testing this pathological case?
+{
+ int i;
+ struct drm_color_lut_ext *lut;
+ uint32_t max_val = 0xffffffff;
+
+ lut = malloc(sizeof(struct drm_color_lut_ext) * info->entries_count);
+ igt_assert(lut);
+
+ lut[0].red = lut[0].green = lut[0].blue = 0; /* First entry is Zero. */It's not a max LUT, if the first entry is zero.
+
+ for (i = 1; i < info->entries_count; i++)
+ lut[i].red = lut[i].green = lut[i].blue = max_val;
+
+ return lut;
+}
+
+void clear_segment_data(segment_data_t *info)
+{
+ if (!info)
+ return;
+
+ free(info->segment_data);
+ free(info);
+}
+
+segment_data_t *get_segment_data(data_t *data,
+ uint64_t blob_id, char *mode)
+{
+ drmModePropertyBlobPtr blob;
+ struct drm_color_lut_range *lut_range = NULL;
+ segment_data_t *info = NULL;
+ uint32_t i;
+
+ blob = drmModeGetPropertyBlob(data->drm_fd, blob_id);
+ igt_assert(blob);
+ igt_assert(blob->length);
+
+ info = malloc(sizeof(segment_data_t));
+ igt_assert(info);
+
+ lut_range = (struct drm_color_lut_range *) blob->data;
+ info->segment_count = blob->length / sizeof(lut_range[0]);
+ igt_assert(info->segment_count);
+
+ info->segment_data = malloc(sizeof(struct drm_color_lut_range) * info->segment_count);
+ igt_assert(info->segment_data);
+
+ for (i = 0; i < info->segment_count; i++) {
+ info->entries_count += lut_range[i].count;
+ info->segment_data[i] = lut_range[i];
+ }
+
+ drmModeFreePropertyBlob(blob);
+
+ return info;
+}
+
+void set_plane_gamma(igt_plane_t *plane,
+ char *mode,
+ struct drm_color_lut_ext *lut,
+ uint32_t size)
+{
+ igt_plane_set_prop_enum(plane, IGT_PLANE_GAMMA_MODE, mode);
+ igt_plane_replace_prop_blob(plane, IGT_PLANE_GAMMA_LUT, lut, size);
+}
+
+void set_plane_degamma(igt_plane_t *plane,
+ char *mode,
+ struct drm_color_lut_ext *lut,
+ uint32_t size)
+{
+ igt_plane_set_prop_enum(plane, IGT_PLANE_DEGAMMA_MODE, mode);
+ igt_plane_replace_prop_blob(plane, IGT_PLANE_DEGAMMA_LUT, lut, size);
+}
+
+void set_plane_ctm(igt_plane_t *plane, const double *coefficients)
+{
+ struct drm_color_ctm ctm;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ctm.matrix); i++) {
+ if (coefficients[i] < 0) {
+ ctm.matrix[i] =
+ (int64_t) (-coefficients[i] *
+ ((int64_t) 1L << 32));
+ ctm.matrix[i] |= 1ULL << 63;
+ } else
+ ctm.matrix[i] =
+ (int64_t) (coefficients[i] *
+ ((int64_t) 1L << 32));
+ }Is this literally the only function that converts double to the KMS matrix element type? If not, I think the value conversion should be a separate function that just converts a single value, and be called from all sites that need the same conversion.
quoted hunk ↗ jump to hunk
+ + igt_plane_replace_prop_blob(plane, IGT_PLANE_CTM, &ctm, sizeof(ctm)); +} + +void disable_plane_prop(igt_plane_t *plane, enum igt_atomic_plane_properties prop) +{ + if (igt_plane_has_prop(plane, prop)) + igt_plane_replace_prop_blob(plane, prop, NULL, 0); +} + drmModePropertyBlobPtr get_blob(data_t *data, igt_pipe_t *pipe, enum igt_atomic_crtc_properties prop) {@@ -274,6 +418,19 @@ pipe_set_property_blob_id(igt_pipe_t *pipe, return ret; } +static int +plane_set_property_blob(igt_display_t *display, + igt_plane_t *plane, + enum igt_atomic_plane_properties prop, + void *ptr, size_t length) +{ + igt_plane_replace_prop_blob(plane, prop, ptr, length); + + return igt_display_try_commit2(display, + display->is_atomic ? + COMMIT_ATOMIC : COMMIT_LEGACY); +} + int pipe_set_property_blob(igt_pipe_t *pipe, enum igt_atomic_crtc_properties prop,@@ -319,6 +476,22 @@ invalid_lut_sizes(data_t *data, enum pipe p, free(lut); } +void +invalid_plane_lut_sizes(igt_display_t *display, + igt_plane_t *plane, + enum igt_atomic_plane_properties prop, + size_t lut_size) +{ + void *lut = malloc(lut_size * 2);
Feeding garbage data does not seem like a good idea. Maybe it can lead to EINVAL even when the driver misses the size check because the values are illegal? I think this needs to craft a real and good lut data blob, with the only problem that it is of the wrong size.
+ igt_assert(lut); + + igt_assert_eq(plane_set_property_blob(display, plane, prop, lut, 1), -EINVAL); + igt_assert_eq(plane_set_property_blob(display, plane, prop, lut, lut_size + 1), -EINVAL); + igt_assert_eq(plane_set_property_blob(display, plane, prop, lut, lut_size - 1), -EINVAL); + + free(lut); +}
Thanks, pq
quoted hunk ↗ jump to hunk
+ void invalid_gamma_lut_sizes(data_t *data, enum pipe p) {diff --git a/tests/kms_color_helper.h b/tests/kms_color_helper.h index bb6f0054f3..5a35dcaac1 100644 --- a/tests/kms_color_helper.h +++ b/tests/kms_color_helper.h@@ -64,6 +64,14 @@ typedef struct { color_t coeffs[]; } gamma_lut_t; +typedef struct { + uint32_t segment_count; + struct drm_color_lut_range *segment_data; + uint32_t entries_count; +} segment_data_t; + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + void paint_gradient_rectangles(data_t *data, drmModeModeInfo *mode, color_t *colors,@@ -90,10 +98,31 @@ void set_gamma(data_t *data, void set_ctm(igt_pipe_t *pipe, const double *coefficients); void disable_prop(igt_pipe_t *pipe, enum igt_atomic_crtc_properties prop); +drmModePropertyPtr get_plane_gamma_degamma_mode(igt_plane_t *plane, + enum igt_atomic_plane_properties prop); +void clear_segment_data(segment_data_t *info); +struct drm_color_lut_ext *create_linear_lut(segment_data_t *info); +struct drm_color_lut_ext *create_max_lut(segment_data_t *info); +segment_data_t *get_segment_data(data_t *data, uint64_t blob_id, char *mode); +void set_plane_gamma(igt_plane_t *plane, + char *mode, struct drm_color_lut_ext *lut, uint32_t size); +void set_plane_degamma(igt_plane_t *plane, + char *mode, struct drm_color_lut_ext *lut, uint32_t size); +void set_plane_ctm(igt_plane_t *plane, const double *coefficients); +void disable_plane_prop(igt_plane_t *plane, enum igt_atomic_plane_properties prop); +void invalid_plane_lut_sizes(igt_display_t *display, + igt_plane_t *plane, + enum igt_atomic_plane_properties prop, + size_t lut_size); + #define disable_degamma(pipe) disable_prop(pipe, IGT_CRTC_DEGAMMA_LUT) #define disable_gamma(pipe) disable_prop(pipe, IGT_CRTC_GAMMA_LUT) #define disable_ctm(pipe) disable_prop(pipe, IGT_CRTC_CTM) +#define disable_plane_degamma(plane) disable_plane_prop(plane, IGT_PLANE_DEGAMMA_LUT) +#define disable_plane_gamma(plane) disable_plane_prop(plane, IGT_PLANE_GAMMA_LUT) +#define disable_plane_ctm(plane) disable_plane_prop(plane, IGT_PLANE_CTM) + drmModePropertyBlobPtr get_blob(data_t *data, igt_pipe_t *pipe, enum igt_atomic_crtc_properties prop); bool crc_equal(igt_crc_t *a, igt_crc_t *b);
Attachments
- (unnamed) [application/pgp-signature] 833 bytes