public inbox for igt-dev@lists.freedesktop.org
 help / color / mirror / Atom feed
From: Swati Sharma <swati2.sharma@intel.com>
To: igt-dev@lists.freedesktop.org
Cc: chaitanya.kumar.borah@intel.com, Swati Sharma <swati2.sharma@intel.com>
Subject: [PATCH i-g-t, v8 4/5] tests/kms_color_pipeline: Add Intel plane pipeline tests with LUT1D and CTM
Date: Tue, 30 Dec 2025 12:15:51 +0530	[thread overview]
Message-ID: <20251230064552.22909-5-swati2.sharma@intel.com> (raw)
In-Reply-To: <20251230064552.22909-1-swati2.sharma@intel.com>

For now, Intel plane color pipeline contains 3 colorops:
Pre-csc gamma (1D LUT) --> CTM 3x4 --> Post-csc gamma (1D LUT)

These tests follow a common flow:
-Configure the primary plane with a deterministic test pattern.
-Enable one or more colorops on the plane color pipeline in a defined
order.
-Program the corresponding color properties with known transformation
values.
-Validate the output by comparing the resulting frame against the
expected transformed output using CRC-based verification.

Separate subtests exercise different valid combinations of the
available colorops to ensure correct programming, ordering, and
interaction of plane color pipeline elements:
  igt@kms_color@plane-lut1d
  igt@kms_color@plane-lut1d-pre-ctm3x4
  igt@kms_color@plane-lut1d-post-ctm3x4
  igt@kms_color@plane-lut1d-ctm3x4
  igt@kms_color@plane-ctm3x4-lut1d
  igt@kms_color@plane-lut1d-lut1d
  igt@kms_color@plane-lut1d-ctm3x4-lut1d

v2: -add new tests pre/post ctm (Chaitanya)
    -remove redundant code (Chaitanya)
    -create plane tests subtest_group (Chaitanya)
    -add/use transfer linear/max func (Chaitanya)
    -improve commit message (Chaitanya)
v3: -create new IGT test (Chaitanya)

Signed-off-by: Swati Sharma <swati2.sharma@intel.com>
---
 lib/igt_color.c            |  19 +++
 lib/igt_color.h            |   6 +
 tests/kms_color_helper.h   |   1 +
 tests/kms_color_pipeline.c | 310 +++++++++++++++++++++++++++++++++++++
 tests/meson.build          |   2 +
 5 files changed, 338 insertions(+)
 create mode 100644 tests/kms_color_pipeline.c

diff --git a/lib/igt_color.c b/lib/igt_color.c
index a34872763..4d94421ba 100644
--- a/lib/igt_color.c
+++ b/lib/igt_color.c
@@ -19,6 +19,9 @@
 const struct igt_color_tf srgb_eotf = {2.4f, (float)(1/1.055), (float)(0.055/1.055), (float)(1/12.92), 0.04045f, 0, 0};
 const struct igt_color_tf bt2020_inv_oetf = {(float)(1/0.45f), (float)(1/1.0993f), (float)(0.0993f/1.0993f), (float)(1/4.5f), (float)(0.081), 0, 0};
 
+const struct igt_color_tf linear_tf = {1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f};
+const struct igt_color_tf max_tf = {1.0f, 0.0f, 1.0f, 0.0f, 1.0e-6f, 0.0f, 0.0f};
+
 const struct igt_color_tf_pq pq_eotf = {-107/128.0f, 1.0f, 32/2523.0f, 2413/128.0f, -2392/128.0f, 8192/1305.0f };
 
 igt_1dlut_t igt_1dlut_srgb_inv_eotf = { {
@@ -27,6 +30,12 @@ igt_1dlut_t igt_1dlut_srgb_inv_eotf = { {
 igt_1dlut_t igt_1dlut_srgb_eotf = { {
 } };
 
+igt_1dlut_t igt_1dlut_linear = { {
+} };
+
+igt_1dlut_t igt_1dlut_max = { {
+} };
+
 static float clamp(float val, float min, float max)
 {
 	return ((val < min) ? min : ((val > max) ? max : val));
@@ -130,6 +139,16 @@ void igt_color_srgb_inv_eotf(igt_pixel_t *pixel)
 	igt_color_inv_tf(pixel, &srgb_eotf);
 }
 
+void igt_color_linear(igt_pixel_t *pixel)
+{
+	igt_color_tf(pixel, &linear_tf);
+}
+
+void igt_color_max(igt_pixel_t *pixel)
+{
+	igt_color_tf(pixel, &max_tf);
+}
+
 void igt_color_bt2020_inv_oetf(igt_pixel_t *pixel)
 {
 	igt_color_tf(pixel, &bt2020_inv_oetf);
diff --git a/lib/igt_color.h b/lib/igt_color.h
index 45cf8f3c7..919330c8b 100644
--- a/lib/igt_color.h
+++ b/lib/igt_color.h
@@ -45,6 +45,9 @@ typedef struct igt_1dlut {
 extern igt_1dlut_t igt_1dlut_srgb_inv_eotf;
 extern igt_1dlut_t igt_1dlut_srgb_eotf;
 
+extern igt_1dlut_t igt_1dlut_linear;
+extern igt_1dlut_t igt_1dlut_max;
+
 typedef struct igt_matrix_3x4 {
 	/*
 	 * out   matrix          in
@@ -93,6 +96,9 @@ void igt_colorop_set_3dlut(igt_display_t *display,
 void igt_color_srgb_inv_eotf(igt_pixel_t *pixel);
 void igt_color_srgb_eotf(igt_pixel_t *pixel);
 
+void igt_color_max(igt_pixel_t *pixel);
+void igt_color_linear(igt_pixel_t *pixel);
+
 void igt_color_pq_inv_eotf(igt_pixel_t *pixel);
 void igt_color_pq_eotf(igt_pixel_t *pixel);
 
diff --git a/tests/kms_color_helper.h b/tests/kms_color_helper.h
index fb9c3b3aa..0be312342 100644
--- a/tests/kms_color_helper.h
+++ b/tests/kms_color_helper.h
@@ -38,6 +38,7 @@
 #include "igt.h"
 #include "igt_edid.h"
 
+#include "kms_colorop_helper.h"
 
 /* Internal */
 typedef struct {
diff --git a/tests/kms_color_pipeline.c b/tests/kms_color_pipeline.c
new file mode 100644
index 000000000..a085ff823
--- /dev/null
+++ b/tests/kms_color_pipeline.c
@@ -0,0 +1,310 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2025 Intel Corporation
+ */
+
+/**
+ * TEST: kms color pipeline
+ * Category: Display
+ * Description: Test to validate DRM colorops at plane level
+ * Driver requirement: i915, xe
+ * Mega feature: Color Management
+ */
+
+#include "kms_color_helper.h"
+
+#define MAX_COLOROPS	5
+
+/**
+ * SUBTEST: plane-%s
+ * Description: Test plane color pipeline with colorops: %arg[1].
+ *
+ * arg[1]:
+ *
+ * @lut1d:			1D LUT
+ * @lut1d-pre-ctm3x4:		1D LUT PRE CTM 3x4
+ * @lut1d-post-ctm3x4:		1D LUT POST CTM 3x4
+ * @ctm3x4:			3X4 CTM
+ * @lut1d-ctm3x4:		1D LUT --> 3X4 CTM
+ * @ctm3x4-lut1d:		3X4 CTM --> 1D LUT
+ * @lut1d-lut1d:		1D LUT --> 1D LUT
+ * @lut1d-ctm3x4-lut1d:		1D LUT --> 3X4 CTM --> 1D LUT
+ */
+
+IGT_TEST_DESCRIPTION("Test DRM colorops at plane level");
+
+static void test_cleanup(data_t *data)
+{
+	if (data->pipe_crc) {
+		igt_pipe_crc_free(data->pipe_crc);
+		data->pipe_crc = NULL;
+	}
+
+	igt_output_set_crtc(data->output, NULL);
+	igt_display_commit2(&data->display, COMMIT_ATOMIC);
+}
+
+static void test_setup(data_t *data, enum pipe p)
+{
+	igt_crtc_t *pipe;
+
+	igt_require_pipe_crc(data->drm_fd);
+
+	pipe = igt_crtc_for_pipe(&data->display, p);
+	igt_require(pipe);
+	igt_require(pipe->n_planes > 0);
+
+	igt_output_set_crtc(data->output, pipe);
+
+	data->primary = igt_pipe_get_plane_type(pipe, DRM_PLANE_TYPE_PRIMARY);
+	data->mode = igt_output_get_mode(data->output);
+	igt_require(data->mode);
+
+	data->pipe_crc = igt_pipe_crc_new(data->drm_fd,
+					  data->primary->pipe->pipe,
+					  IGT_PIPE_CRC_SOURCE_AUTO);
+
+	igt_display_commit2(&data->display, COMMIT_ATOMIC);
+}
+
+static bool ctm_colorop_only(kms_colorop_t *colorops[])
+{
+	int i;
+
+	if (!colorops[0])
+		return false;
+
+	for (i = 0; colorops[i]; i++) {
+		if (colorops[i]->type != KMS_COLOROP_CTM_3X4)
+			return false;
+	}
+
+	return true;
+}
+
+static bool test_plane_colorops(data_t *data,
+				const color_t *fb_colors,
+				const color_t *exp_colors,
+				kms_colorop_t *colorops[])
+{
+	igt_plane_t *plane = data->primary;
+	igt_display_t *display = &data->display;
+	drmModeModeInfo *mode = data->mode;
+	igt_colorop_t *color_pipeline;
+	igt_crc_t crc_ref, crc_pipe;
+	struct igt_fb fb;
+	bool ret;
+
+	color_pipeline = get_color_pipeline(display, plane, colorops);
+	igt_skip_on(!color_pipeline);
+
+	/* Create a framebuffer at the size of the output. */
+	igt_assert(igt_create_fb(data->drm_fd,
+				 mode->hdisplay,
+				 mode->vdisplay,
+				 DRM_FORMAT_XRGB8888,
+				 DRM_FORMAT_MOD_LINEAR,
+				 &fb));
+	igt_plane_set_fb(plane, &fb);
+
+	/* Disable Pipe color props. */
+	disable_ctm(plane->pipe);
+	disable_degamma(plane->pipe);
+	disable_gamma(plane->pipe);
+	igt_display_commit2(display, COMMIT_ATOMIC);
+
+	/* Reference (software-equivalent) CRC */
+	set_color_pipeline_bypass(plane);
+	paint_rectangles(data, mode, exp_colors, &fb);
+
+	igt_plane_set_fb(plane, &fb);
+	igt_display_commit2(display, COMMIT_ATOMIC);
+	igt_wait_for_vblank(plane->pipe);
+	igt_pipe_crc_collect_crc(data->pipe_crc, &crc_ref);
+
+	/* Hardware pipeline CRC */
+	set_color_pipeline(display, plane, colorops, color_pipeline);
+	/*
+	 * Use flat colors only when the pipeline
+	 * contains CTM colorops exclusively.
+	 */
+	if (ctm_colorop_only(colorops))
+		paint_rectangles(data, mode, fb_colors, &fb);
+	else
+		paint_gradient_rectangles(data, mode, fb_colors, &fb);
+
+	igt_plane_set_fb(plane, &fb);
+	igt_display_commit2(display, COMMIT_ATOMIC);
+	igt_wait_for_vblank(plane->pipe);
+	igt_pipe_crc_collect_crc(data->pipe_crc, &crc_pipe);
+
+	ret = igt_check_crc_equal(&crc_ref, &crc_pipe);
+
+	/* Cleanup per-test state */
+	reset_colorops(colorops);
+	igt_plane_set_fb(plane, NULL);
+	igt_display_commit2(display, COMMIT_ATOMIC);
+
+	igt_remove_fb(data->drm_fd, &fb);
+
+	return ret;
+}
+
+static void
+run_tests_for_plane(data_t *data)
+{
+	enum pipe pipe;
+	igt_output_t *output = NULL;
+	static const color_t colors_rgb[] = {
+	        { 1.0, 0.0, 0.0 },
+	        { 0.0, 1.0, 0.0 },
+	        { 0.0, 0.0, 1.0 },
+	};
+	static const color_t colors_red_to_blue[] = {
+		{ 0.0, 0.0, 1.0 },
+		{ 0.0, 1.0, 0.0 },
+		{ 0.0, 0.0, 1.0 },
+	};
+	const igt_matrix_3x4_t ctm_red_to_blue = { {
+		0.0, 0.0, 0.0, 0.0,
+		0.0, 1.0, 0.0, 0.0,
+		1.0, 0.0, 1.0, 0.0,
+	} };
+	const igt_matrix_3x4_t ctm_linear = { {
+		1.0, 0.0, 0.0, 0.0,
+		0.0, 1.0, 0.0, 0.0,
+		0.0, 0.0, 1.0, 0.0,
+	} };
+	kms_colorop_t lut1d_linear = {
+		.type = KMS_COLOROP_CUSTOM_LUT1D,
+		.name = "Pre/Post CSC GAMMA (linear LUT)",
+		.lut1d = &igt_1dlut_linear,
+		.transform = &igt_color_linear,
+	};
+	kms_colorop_t lut1d_max = {
+		.type = KMS_COLOROP_CUSTOM_LUT1D,
+		.lut1d = &igt_1dlut_max,
+		.name = "Pre/Post CSC GAMMA (max LUT)",
+		.transform = &igt_color_max,
+	};
+	kms_colorop_t ctm_3x4 = {
+		.type = KMS_COLOROP_CTM_3X4,
+		.name = "CTM 3X4 (red to blue)",
+		.matrix_3x4 = &ctm_red_to_blue,
+	};
+	kms_colorop_t ctm_3x4_linear = {
+		.type = KMS_COLOROP_CTM_3X4,
+		.name = "CTM 3X4 (linear)",
+		.matrix_3x4 = &ctm_linear,
+	};
+
+	struct {
+		const char *name;
+		const color_t *fb_colors;
+		const color_t *exp_colors;
+		kms_colorop_t *colorops[MAX_COLOROPS];
+	} plane_colorops_tests[] = {
+		{ .name = "lut1d",
+		  .fb_colors = colors_rgb,
+		  .exp_colors = colors_rgb,
+		  .colorops = { &lut1d_max, NULL },
+		},
+		{ .name = "lut1d-pre-ctm3x4",
+		  .fb_colors = colors_rgb,
+		  .exp_colors = colors_rgb,
+		  .colorops = { &lut1d_max, &ctm_3x4_linear, NULL },
+		},
+		{ .name = "lut1d-post-ctm3x4",
+		  .fb_colors = colors_rgb,
+		  .exp_colors = colors_rgb,
+		  .colorops = { &ctm_3x4_linear, &lut1d_max, NULL },
+		},
+		{ .name = "ctm3x4",
+		  .fb_colors = colors_rgb,
+		  .exp_colors = colors_red_to_blue,
+		  .colorops = { &ctm_3x4, NULL },
+		},
+		{ .name = "lut1d-ctm3x4",
+		  .fb_colors = colors_rgb,
+		  .exp_colors = colors_red_to_blue,
+		  .colorops = { &lut1d_max, &ctm_3x4, NULL },
+		},
+		{ .name = "ctm3x4-lut1d",
+		  .fb_colors = colors_rgb,
+		  .exp_colors = colors_red_to_blue,
+		  .colorops = { &ctm_3x4, &lut1d_max, NULL },
+		},
+		{ .name = "lut1d-lut1d",
+		  .fb_colors = colors_rgb,
+		  .exp_colors = colors_rgb,
+		  .colorops = { &lut1d_linear, &lut1d_max, NULL },
+		},
+		{ .name = "lut1d-ctm3x4-lut1d",
+		  .fb_colors = colors_rgb,
+		  .exp_colors = colors_red_to_blue,
+		  .colorops = { &lut1d_linear, &ctm_3x4, &lut1d_max, NULL },
+		},
+	};
+
+	for (int i = 0; i < ARRAY_SIZE(plane_colorops_tests); i++) {
+		igt_describe_f("Test plane color pipeline with colorops: %s", plane_colorops_tests[i].name);
+		igt_subtest_with_dynamic_f("plane-%s", plane_colorops_tests[i].name) {
+			for_each_pipe_with_single_output(&data->display, pipe, output) {
+				data->output = output;
+
+				if (!pipe_output_combo_valid(data, pipe))
+					continue;
+
+				test_setup(data, pipe);
+
+				if (!igt_plane_has_prop(data->primary, IGT_PLANE_COLOR_PIPELINE)) {
+					test_cleanup(data);
+					continue;
+				}
+
+				igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(pipe),
+					       igt_output_name(data->output)) {
+					data->color_depth = 8;
+					data->drm_format = DRM_FORMAT_XRGB8888;
+
+					igt_assert(test_plane_colorops(data,
+								       plane_colorops_tests[i].fb_colors,
+								       plane_colorops_tests[i].exp_colors,
+								       plane_colorops_tests[i].colorops));
+				}
+
+				test_cleanup(data);
+			}
+		}
+	}
+}
+
+int igt_main()
+{
+	int has_plane_color_pipeline = 0;
+	data_t data = {};
+
+	igt_fixture() {
+		data.drm_fd = drm_open_driver_master(DRIVER_ANY);
+
+		if (drmSetClientCap(data.drm_fd, DRM_CLIENT_CAP_ATOMIC, 1) == 0)
+			data.display.is_atomic = 1;
+
+		if (drmSetClientCap(data.drm_fd, DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE, 1) == 0)
+			has_plane_color_pipeline = 1;
+
+		kmstest_set_vt_graphics_mode();
+
+		igt_display_require(&data.display, data.drm_fd);
+		data.display.has_plane_color_pipeline = has_plane_color_pipeline;
+		igt_require(data.display.is_atomic);
+	}
+
+	igt_subtest_group()
+		run_tests_for_plane(&data);
+
+	igt_fixture() {
+		igt_display_fini(&data.display);
+		drm_close_driver(data.drm_fd);
+	}
+}
diff --git a/tests/meson.build b/tests/meson.build
index ae48dfe04..912d8cd38 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -25,6 +25,7 @@ test_progs = [
 	'kms_atomic_transition',
 	'kms_bw',
 	'kms_color',
+	'kms_color_pipeline',
 	'kms_concurrent',
 	'kms_colorop',
 	'kms_content_protection',
@@ -379,6 +380,7 @@ extra_sources = {
 	'dumb_buffer': ['dumb_buffer.c' ],
 	'testdisplay': [ 'testdisplay_hotplug.c' ],
 	'kms_color':  [ 'kms_color_helper.c' ],
+	'kms_color_pipeline':  [ 'kms_color_helper.c', 'kms_colorop_helper.c' ],
 	'kms_colorop':  [ 'kms_colorop_helper.c' ],
 	'kms_chamelium_audio': [ join_paths ('chamelium', 'kms_chamelium_helper.c') ],
 	'kms_chamelium_color':  [ 'kms_color_helper.c', join_paths ('chamelium', 'kms_chamelium_helper.c') ],
-- 
2.25.1


  parent reply	other threads:[~2025-12-30  6:37 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-12-30  6:45 [PATCH i-g-t, v8 0/5] Add plane color pipeline tests for Intel hardware Swati Sharma
2025-12-30  6:45 ` [PATCH i-g-t, v8 2/5] tests/kms_colorop_helper: Add helpers to clear colorops data Swati Sharma
2025-12-30  6:45 ` [PATCH i-g-t, v8 3/5] tests/kms_colorop_helper: Cast pixel values to double Swati Sharma
2025-12-30  6:45 ` Swati Sharma [this message]
2026-01-05  7:47   ` [PATCH i-g-t,v8 4/5] tests/kms_color_pipeline: Add Intel plane pipeline tests with LUT1D and CTM Borah, Chaitanya Kumar
2025-12-30  6:45 ` [PATCH i-g-t, v8 5/5] tests/kms_color_pipeline: Add 3D LUT subtest for green-only output with RGB traversal Swati Sharma
2025-12-30  7:16 ` ✓ Xe.CI.BAT: success for Add plane color pipeline tests for Intel hardware (rev9) Patchwork
2025-12-30  7:46 ` ✓ i915.CI.BAT: " Patchwork
2025-12-30  8:51 ` ✓ Xe.CI.Full: " Patchwork
2025-12-30  9:26 ` ✗ i915.CI.Full: failure " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251230064552.22909-5-swati2.sharma@intel.com \
    --to=swati2.sharma@intel.com \
    --cc=chaitanya.kumar.borah@intel.com \
    --cc=igt-dev@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox