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
next prev 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