[igt-dev] [PATCH i-g-t 7/9] tests/kms_color: Add CTM tests
Chaitanya Kumar Borah
chaitanya.kumar.borah at intel.com
Tue Aug 29 14:38:19 UTC 2023
Add test cases to validate color conversion using CTM matrix.
We use a frame with RGB color bars and convert one color to
another using the plane CSC block.
Also added tests to program CTM with varying co-effs based on
usecases.
ToDo: This patch needs to broken down to smaller logical patches.
Co-developed-by: Uma Shankar <uma.shankar at intel.com>
Signed-off-by: Uma Shankar <uma.shankar at intel.com>
Signed-off-by: Chaitanya Kumar Borah <chaitanya.kumar.borah at intel.com>
---
tests/kms_color.c | 219 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 215 insertions(+), 4 deletions(-)
diff --git a/tests/kms_color.c b/tests/kms_color.c
index d00ba13a1..2f874a59a 100644
--- a/tests/kms_color.c
+++ b/tests/kms_color.c
@@ -1631,10 +1631,6 @@ static bool plane_cp_test_2(data_t *data, igt_plane_t *plane)
return true;
}
-#undef HAS_PRE_CSC
-#undef HAS_CSC
-#undef HAS_POST_CSC
-#undef HAS_COLOR_CONVERSION_CAP
static void
run_colorpipeline_tests_for_plane(data_t *data, enum pipe p,
@@ -1651,6 +1647,205 @@ run_colorpipeline_tests_for_plane(data_t *data, enum pipe p,
test_cleanup(data);
}
+static bool test_plane_ctm(data_t *data,
+ igt_plane_t *plane,
+ const color_t *before,
+ const color_t *after,
+ const double *ctm_matrix)
+{
+ const double ctm_identity[] = {
+ 1.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0
+ };
+ struct drm_color_ctm *ctm1, *ctm2;
+ igt_output_t *output = data->output;
+ igt_display_t *display = &data->display;
+ drmModeModeInfo *mode = data->mode;
+ struct igt_fb fb;
+ igt_crc_t crc_software, crc_hardware;
+ igt_pipe_crc_t *pipe_crc = data->pipe_crc;
+ bool ret = true;
+ uint32_t color_pipeline, blob_id = 0;
+ struct drm_color_pipeline cp;
+ struct drm_color_op_data *color_op_data;
+ uint32_t old_blob_id;
+
+ igt_info("Plane CTM test is running on pipe-%s plane-%d(%s)\n",
+ kmstest_pipe_name(plane->pipe->pipe), plane->index,
+ kmstest_plane_type_name(plane->type));
+
+ igt_require(igt_plane_has_prop(plane, IGT_PLANE_GET_COLOR_PIPELINE));
+ igt_require(igt_plane_has_prop(plane, IGT_PLANE_SET_COLOR_PIPELINE));
+
+ igt_output_set_pipe(output, plane->pipe->pipe);
+
+ /* Create a framebuffer at the size of the output. */
+ igt_assert(igt_create_fb(data->drm_fd,
+ mode->hdisplay,
+ mode->vdisplay,
+ data->drm_format,
+ DRM_FORMAT_MOD_LINEAR,
+ &fb));
+
+ igt_plane_set_fb(plane, &fb);
+
+ disable_degamma(plane->pipe);
+ disable_gamma(plane->pipe);
+ disable_ctm(plane->pipe);
+
+ /* Reset all color hardware blocks in pipeline by setting blob as NULL */
+ igt_plane_replace_prop_blob(plane, IGT_PLANE_SET_COLOR_PIPELINE, NULL, 0);
+ igt_display_commit2(display, COMMIT_ATOMIC);
+
+ color_pipeline = get_color_pipeline(data, plane, HAS_CSC);
+ igt_info("ctm color pipeline %d\n", color_pipeline);
+
+ color_op_data = calloc(1, sizeof(struct drm_color_op_data));
+ cp.num = color_pipeline;
+ cp.size = sizeof(struct drm_color_op_data);
+ cp.data = color_op_data;
+
+ /* Without CTM transformation. */
+ paint_rectangles(data, mode, after, &fb);
+ igt_plane_set_fb(plane, &fb);
+
+ color_op_data[0].name = DRM_CB_CSC;
+ ctm1 = create_ctm(ctm_identity);
+ igt_assert(drmModeCreatePropertyBlob(display->drm_fd,
+ ctm1, sizeof(struct drm_color_ctm), &blob_id) == 0);
+ color_op_data[0].blob_id = blob_id;
+
+ /* Enable CTM hardware with unity matrix */
+ igt_plane_replace_prop_blob(plane, IGT_PLANE_SET_COLOR_PIPELINE, &cp,
+ sizeof(struct drm_color_pipeline));
+ igt_display_commit2(display, COMMIT_ATOMIC);
+
+ igt_wait_for_vblank(data->drm_fd,
+ display->pipes[plane->pipe->pipe].crtc_offset);
+ igt_pipe_crc_collect_crc(pipe_crc, &crc_software);
+
+ /* With CTM transformation. */
+ paint_rectangles(data, mode, before, &fb);
+ igt_plane_set_fb(plane, &fb);
+
+ ctm2 = create_ctm(ctm_matrix);
+ old_blob_id = color_op_data[0].blob_id;
+ igt_assert(drmModeCreatePropertyBlob(display->drm_fd,
+ ctm2, sizeof(struct drm_color_ctm), &blob_id) == 0);
+ color_op_data[0].blob_id = blob_id;
+
+ /* Now change the matrix co-effs based on desired color conversion */
+ igt_plane_replace_prop_blob(plane, IGT_PLANE_SET_COLOR_PIPELINE, &cp,
+ sizeof(struct drm_color_pipeline));
+ igt_display_commit2(display, COMMIT_ATOMIC);
+
+ igt_wait_for_vblank(data->drm_fd,
+ display->pipes[plane->pipe->pipe].crtc_offset);
+ igt_pipe_crc_collect_crc(pipe_crc, &crc_hardware);
+
+ /* Clean up old blob */
+ drmModeDestroyPropertyBlob(display->drm_fd,
+ old_blob_id);
+ free(ctm1);
+ /* Verify that the CRC of the software computed ouutput
+ * is equal to the CRC of the CTM matrix transformation
+ * output.
+ */
+ ret &= igt_skip_crc_compare || igt_check_crc_equal(&crc_software, &crc_hardware);
+
+ /****** Reset Pipe Line *******/
+ igt_plane_replace_prop_blob(plane, IGT_PLANE_SET_COLOR_PIPELINE, NULL, 0);
+ igt_display_commit2(display, COMMIT_ATOMIC);
+
+ drmModeDestroyPropertyBlob(display->drm_fd,
+ color_op_data[0].blob_id);
+ free(ctm2);
+
+ igt_plane_set_fb(plane, NULL);
+ igt_output_set_pipe(output, PIPE_NONE);
+ igt_display_commit2(display, COMMIT_ATOMIC);
+
+ return ret;
+}
+
+#undef HAS_PRE_CSC
+#undef HAS_CSC
+#undef HAS_POST_CSC
+#undef HAS_COLOR_CONVERSION_CAP
+
+static void run_ctm_tests_for_plane(data_t *data,
+ enum pipe pipe,
+ const color_t *fb_colors,
+ const double *ctm,
+ int iter)
+{
+ igt_plane_t *plane;
+ double delta;
+
+ color_t red_green_blue[] = {
+ { 1.0, 0.0, 0.0 },
+ { 0.0, 1.0, 0.0 },
+ { 0.0, 0.0, 1.0 }
+ };
+
+ test_setup(data, pipe);
+
+ data->color_depth = 8;
+ delta = 1.0 / (1 << data->color_depth);
+ data->drm_format = DRM_FORMAT_XRGB8888;
+ data->mode = igt_output_get_mode(data->output);
+
+ igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe), data->output->name) {
+ bool result = false;
+ int i, count = 0;
+ /* Run only for two planes */
+ int first_plane = 0;
+ int last_plane = 1;
+
+ for_each_plane_on_pipe(&data->display, pipe, plane) {
+ if (j__ != first_plane && j__ != last_plane)
+ continue;
+
+ if (!iter) {
+ color_t expected_colors[3];
+
+ memcpy(&expected_colors, fb_colors, sizeof(expected_colors));
+ result |= test_plane_ctm(data, plane,
+ red_green_blue,
+ expected_colors, ctm);
+ }
+
+ for (i = 0; i < iter; i++) {
+ color_t expected_colors[3] = {
+ fb_colors[0],
+ fb_colors[1],
+ fb_colors[2],
+ };
+
+ transform_color(&expected_colors[0], ctm, delta * (i - (iter / 2)));
+ transform_color(&expected_colors[1], ctm, delta * (i - (iter / 2)));
+ transform_color(&expected_colors[2], ctm, delta * (i - (iter / 2)));
+
+ result |= test_plane_ctm(data, plane,
+ fb_colors,
+ expected_colors, ctm);
+
+ if (result)
+ break;
+ }
+
+ igt_assert(result);
+ count++;
+ }
+
+ if (!count)
+ igt_skip("No valid planes found.\n");
+ }
+
+ test_cleanup(data);
+}
+
static void
run_tests_for_pipe(data_t *data)
{
@@ -1837,6 +2032,22 @@ run_tests_for_pipe(data_t *data)
}
}
+ for (i = 0; i < ARRAY_SIZE(ctm_tests); i++) {
+ igt_describe_f("%s", ctm_tests[i].desc);
+ igt_subtest_with_dynamic_f("plane-%s", ctm_tests[i].name) {
+ for_each_pipe(&data->display, pipe) {
+ if (pipe != active_pipes[0] &&
+ pipe != active_pipes[last_pipe])
+ continue;
+
+ run_ctm_tests_for_plane(data, pipe,
+ ctm_tests[i].fb_colors,
+ ctm_tests[i].ctm,
+ ctm_tests[i].iter);
+ }
+ }
+ }
+
igt_fixture
igt_require(data->display.is_atomic);
--
2.25.1
More information about the igt-dev
mailing list