[igt-dev] [PATCH 1/2] tests/kms_hdr: Add test for output Colorspace

Harry Wentland harry.wentland at amd.com
Mon Dec 12 19:24:24 UTC 2022


The drm_connector Colorspace property needs a test.
This adds a Colorspace switch test, similar to the
bpc switch.

Currently this will only work on amdgpu. Other drivers
will need to provide a debugfs to readback the currently
set Colorspace in order to pass the test.

Signed-off-by: Harry Wentland <harry.wentland at amd.com>
Cc: Pekka Paalanen <ppaalanen at gmail.com>
Cc: Sebastian Wick <sebastian.wick at redhat.com>
Cc: Vitaly.Prosyak at amd.com
Cc: Uma Shankar <uma.shankar at intel.com>
Cc: Ville Syrjälä <ville.syrjala at linux.intel.com>
Cc: Joshua Ashton <joshua at froggi.es>
Cc: Bhanuprakash Modem <bhanuprakash.modem at intel.com>
Cc: Rodrigo Siqueira <Rodrigo.Siqueira at amd.com>
Cc: Alex Hung <Alex.Hung at amd.com>
---
 lib/igt_kms.c   |  51 +++++++++++++++++
 lib/igt_kms.h   |   6 ++
 tests/kms_hdr.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 200 insertions(+)

diff --git a/lib/igt_kms.c b/lib/igt_kms.c
index b4a98ae176e1..15fe49b3f55c 100644
--- a/lib/igt_kms.c
+++ b/lib/igt_kms.c
@@ -640,6 +640,7 @@ const char * const igt_connector_prop_names[IGT_NUM_CONNECTOR_PROPS] = {
 	[IGT_CONNECTOR_LINK_STATUS] = "link-status",
 	[IGT_CONNECTOR_MAX_BPC] = "max bpc",
 	[IGT_CONNECTOR_HDR_OUTPUT_METADATA] = "HDR_OUTPUT_METADATA",
+	[IGT_CONNECTOR_COLORSPACE] = "Colorspace",
 	[IGT_CONNECTOR_WRITEBACK_PIXEL_FORMATS] = "WRITEBACK_PIXEL_FORMATS",
 	[IGT_CONNECTOR_WRITEBACK_FB_ID] = "WRITEBACK_FB_ID",
 	[IGT_CONNECTOR_WRITEBACK_OUT_FENCE_PTR] = "WRITEBACK_OUT_FENCE_PTR",
@@ -2272,6 +2273,10 @@ static void igt_output_reset(igt_output_t *output)
 		igt_output_set_prop_value(output,
 					  IGT_CONNECTOR_HDR_OUTPUT_METADATA, 0);
 
+	if (igt_output_has_prop(output, IGT_CONNECTOR_COLORSPACE))
+		igt_output_set_prop_enum(output,
+					  IGT_CONNECTOR_COLORSPACE, "Default");
+
 	if (igt_output_has_prop(output, IGT_CONNECTOR_WRITEBACK_FB_ID))
 		igt_output_set_prop_value(output, IGT_CONNECTOR_WRITEBACK_FB_ID, 0);
 	if (igt_output_has_prop(output, IGT_CONNECTOR_WRITEBACK_OUT_FENCE_PTR)) {
@@ -2296,6 +2301,7 @@ static void igt_output_reset(igt_output_t *output)
  * - %IGT_CONNECTOR_BROADCAST_RGB (if applicable)
  *   %IGT_CONNECTOR_CONTENT_PROTECTION (if applicable)
  *   %IGT_CONNECTOR_HDR_OUTPUT_METADATA (if applicable)
+ *   %IGT_CONNECTOR_COLORSPACE (if applicable)
  * - %IGT_CONNECTOR_DITHERING_MODE (if applicable)
  * - igt_output_override_mode() to default.
  *
@@ -5801,6 +5807,51 @@ bool igt_check_output_bpc_equal(int drmfd, enum pipe pipe,
 	return (current == bpc);
 }
 
+
+/*
+ * igt_get_pipe_current_colorspace:
+ * @drmfd: A drm file descriptor
+ * @pipe: Display pipe
+ *
+ * Returns: The current colorspace from the crtc debugfs.
+ */
+void igt_get_pipe_current_colorspace(int drmfd, enum pipe pipe,
+				     char *colorspace, int size)
+{
+	char debugfs_name[30];
+	int fd, res;
+
+	fd = igt_debugfs_pipe_dir(drmfd, pipe, O_RDONLY);
+	igt_assert(fd >= 0);
+
+	/* TODO add support for other drivers */
+	if (is_amdgpu_device(drmfd))
+		strcpy(debugfs_name, "amdgpu_current_colorspace");
+
+	res = igt_debugfs_simple_read(fd, debugfs_name, colorspace, size);
+	igt_require(res > 0);
+
+	close(fd);
+}
+
+/*
+ * igt_assert_output_bpc_equal:
+ * @drmfd: A drm file descriptor
+ * @pipe: Display pipe
+ * @output_name: Name of the libdrm connector we're going to use
+ * @bpc: BPC to compare with max & current bpc
+ *
+ * Assert if crtc's current bpc is not matched with the requested one.
+ */
+void igt_assert_output_colorspace_equal(int drmfd, enum pipe pipe,
+					const char *colorspace)
+{
+	char buf[35];
+
+	igt_get_pipe_current_colorspace(drmfd, pipe, buf, sizeof(buf));
+	igt_assert(strcmp(colorspace, buf) == 0);
+}
+
 /*
  * igt_max_bpc_constraint
  * @display: a pointer to an #igt_display_t structure
diff --git a/lib/igt_kms.h b/lib/igt_kms.h
index 7a00d204545e..136292929fab 100644
--- a/lib/igt_kms.h
+++ b/lib/igt_kms.h
@@ -152,6 +152,7 @@ enum igt_atomic_connector_properties {
        IGT_CONNECTOR_LINK_STATUS,
        IGT_CONNECTOR_MAX_BPC,
        IGT_CONNECTOR_HDR_OUTPUT_METADATA,
+       IGT_CONNECTOR_COLORSPACE,
        IGT_CONNECTOR_WRITEBACK_PIXEL_FORMATS,
        IGT_CONNECTOR_WRITEBACK_FB_ID,
        IGT_CONNECTOR_WRITEBACK_OUT_FENCE_PTR,
@@ -991,6 +992,11 @@ void igt_assert_output_bpc_equal(int drmfd, enum pipe pipe,
 bool igt_check_output_bpc_equal(int drmfd, enum pipe pipe,
 				char *output_name, unsigned int bpc);
 
+void igt_get_pipe_current_colorspace(int drmfd, enum pipe pipe,
+				     char *colorspace, int size);
+void igt_assert_output_colorspace_equal(int drmfd, enum pipe pipe,
+					const char *colorspace);
+
 int sort_drm_modes_by_clk_dsc(const void *a, const void *b);
 int sort_drm_modes_by_clk_asc(const void *a, const void *b);
 int sort_drm_modes_by_res_dsc(const void *a, const void *b);
diff --git a/tests/kms_hdr.c b/tests/kms_hdr.c
index 655c3e14f7ef..b656dc7a7ed5 100644
--- a/tests/kms_hdr.c
+++ b/tests/kms_hdr.c
@@ -244,6 +244,145 @@ static void test_bpc_switch(data_t *data, uint32_t flags)
 	}
 }
 
+/*
+ * List of all DP and HDMI colorspaces from drm_connector.c
+ *
+ * We purposely omit "Default" since driver behavior varies
+ * and there is no good way to test for it.
+ */
+static const char *colorspaces[] = {
+	/* Standard Definition Colorimetry based on CEA 861 */
+	"SMPTE_170M_YCC",
+	"BT709_YCC",
+	/* Standard Definition Colorimetry based on IEC 61966-2-4 */
+	"XVYCC_601",
+	/* High Definition Colorimetry based on IEC 61966-2-4 */
+	"XVYCC_709",
+	/* Colorimetry based on IEC 61966-2-1/Amendment 1 */
+	"SYCC_601",
+	/* Colorimetry based on IEC 61966-2-5 [33] */
+	"opYCC_601",
+	/* Colorimetry based on IEC 61966-2-5 */
+	"opRGB",
+	/* Colorimetry based on ITU-R BT.2020 */
+	"BT2020_CYCC",
+	/* Colorimetry based on ITU-R BT.2020 */
+	"BT2020_RGB",
+	/* Colorimetry based on ITU-R BT.2020 */
+	"BT2020_YCC",
+	/* Added as part of Additional Colorimetry Extension in 861.G */
+	"DCI-P3_RGB_D65",
+	"DCI-P3_RGB_Theater",
+	/* For Default case, driver will set the colorspace */
+	"RGB_Wide_Gamut_Fixed_Point",
+	/* Colorimetry based on scRGB (IEC 61966-2-2) */
+	"RGB_Wide_Gamut_Floating_Point",
+	"BT601_YCC",
+	NULL
+};
+
+/* Prints the colorspace name on the framebuffer */
+static void draw_colorspace(igt_fb_t *fb, const char* colorspace)
+{
+	cairo_t *cr = igt_get_cairo_ctx(fb->fd, fb);
+
+	igt_paint_color(cr, 0, 0, fb->width, 50, 1.0, 1.0, 1.0);
+	cairo_move_to(cr, fb->width / 2, 20);
+	cairo_set_font_size(cr, 12);
+	igt_cairo_printf_line(cr, align_hcenter, 0, "%s", colorspace);
+
+	igt_put_cairo_ctx(cr);
+}
+
+
+static void test_colorspace_switch_on_output(data_t *data, enum pipe pipe,
+				      igt_output_t *output,
+				      uint32_t flags)
+{
+	igt_display_t *display = &data->display;
+	// igt_crc_t ref_crc, new_crc;
+	igt_fb_t afb;
+	int afb_id, ret;
+
+	/* 10-bit formats are slow, so limit the size. */
+	afb_id = igt_create_fb(data->fd, 512, 512, DRM_FORMAT_XRGB2101010, 0, &afb);
+	igt_assert(afb_id);
+
+	draw_hdr_pattern(&afb);
+
+	/* Plane may be required to fit fullscreen. Check it here and allow
+	 * smaller plane size in following tests.
+	 */
+	igt_plane_set_fb(data->primary, &afb);
+	igt_plane_set_size(data->primary, data->w, data->h);
+	ret = igt_display_try_commit_atomic(display, DRM_MODE_ATOMIC_TEST_ONLY, NULL);
+	if (!ret) {
+		data->w = afb.width;
+		data->h = afb.height;
+	}
+
+	/* require Colorspace prop */
+	igt_require(igt_output_has_prop(output, IGT_CONNECTOR_COLORSPACE));
+
+	/* Get enum values for colorspace */
+	/* for each value set colorspace */
+	for (int i = 0; colorspaces[i]; i++) {
+		if (igt_output_try_prop_enum(output, IGT_CONNECTOR_COLORSPACE, colorspaces[i])) {
+			igt_info("Testing colorspace %s on %s\n",
+				 colorspaces[i],
+				 igt_output_name(output));
+			draw_colorspace(&afb, colorspaces[i]);
+			igt_output_set_prop_enum(output, IGT_CONNECTOR_COLORSPACE, colorspaces[i]);
+			igt_display_commit_atomic(display, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
+			/* get and check current colorspace */
+			igt_assert_output_colorspace_equal(data->fd, pipe, colorspaces[i]);
+		}
+	}
+
+	igt_info("Testing bad colorspace on %s\n",
+			igt_output_name(output));
+	draw_colorspace(&afb, "bad");
+	igt_require(!igt_output_try_prop_enum(output, IGT_CONNECTOR_COLORSPACE, "bad"));
+
+	/* revert back to "Default" */
+	igt_info("Testing colorspace %s on %s\n",
+			"Default",
+			igt_output_name(output));
+	draw_colorspace(&afb, "Default");
+	igt_output_set_prop_enum(output, IGT_CONNECTOR_COLORSPACE, "Default");
+	igt_display_commit_atomic(display, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
+
+	test_fini(data);
+	igt_remove_fb(data->fd, &afb);
+}
+
+static void test_colorspace_switch(data_t *data, uint32_t flags)
+{
+	igt_display_t *display = &data->display;
+	igt_output_t *output;
+
+	for_each_connected_output(display, output) {
+		enum pipe pipe;
+
+		for_each_pipe(display, pipe) {
+			if (igt_pipe_connector_valid(pipe, output)) {
+				prepare_test(data, output, pipe);
+
+				data->mode = igt_output_get_mode(output);
+				data->w = data->mode->hdisplay;
+				data->h = data->mode->vdisplay;
+
+				igt_dynamic_f("pipe-%s-%s",
+					      kmstest_pipe_name(pipe), output->name)
+					test_colorspace_switch_on_output(data, pipe, output, flags);
+
+				/* One pipe is enough */
+				break;
+			}
+		}
+	}
+}
+
 static bool cta_block(const char *edid_ext)
 {
 	/*
@@ -599,6 +738,10 @@ igt_main
 	igt_subtest_with_dynamic("bpc-switch-suspend")
 		test_bpc_switch(&data, TEST_SUSPEND);
 
+	igt_describe("Tests switching Colorspace property, .i.e., the display colorimetry");
+	igt_subtest_with_dynamic("colorspace-switch")
+		test_colorspace_switch(&data, TEST_NONE);
+
 	igt_describe("Tests entering and exiting HDR mode");
 	igt_subtest_with_dynamic("static-toggle")
 		test_hdr(&data, TEST_NONE);
-- 
2.38.1



More information about the igt-dev mailing list