[PATCH i-g-t,v5 10/10] tests/chamelium/kms_chamelium_sharpness_filter: Add basic test
Nautiyal, Ankit K
ankit.k.nautiyal at intel.com
Wed Apr 23 03:51:07 UTC 2025
On 4/14/2025 4:46 PM, Swati Sharma wrote:
> This test validates the content adaptive sharpness filter functionality
> by toggling the sharpness property on the CRTC and capturing frames
> using Chamelium. It ensures that the filter visually alters the output as
> expected.
>
> Test steps:
> 1. Display a test image with no sharpness filter.
> 2. Capture output (Frame 0).
> 3. Enable sharpness filter at mid strength.
> 4. Capture output (Frame 1).
> 5. Disable the filter again.
> 6. Capture output (Frame 2).
> 7. Re-enable filter with same strength.
> 8. Capture output (Frame 3).
> 9. Compare frame pairs:
> - Frame 0 vs Frame 1 → should differ
> - Frame 1 vs Frame 2 → should differ
> - Frame 0 vs Frame 2 → should match
> - Frame 1 vs Frame 3 → should match
>
> v2: -removed MIN/MAX_FILTER_STRENGTH (Ankit)
> -fixed alignment (Ankit)
> -removed commit with fb_ref (Ankit)
> -set data->pipe_id (Ankit)
> -removed disable_filter_strength_on_pipe()
> -fixed CRASH
> -fixed assert condition
> v3: -minor fixes
> v4: -modified test (Ankit)
> -change in seq (Ankit)
> v5: -changed igt_assert() and return type of test_t()
>
> Signed-off-by: Swati Sharma <swati2.sharma at intel.com>
> ---
> .../kms_chamelium_sharpness_filter.c | 282 ++++++++++++++++++
> tests/meson.build | 2 +
> 2 files changed, 284 insertions(+)
> create mode 100644 tests/chamelium/kms_chamelium_sharpness_filter.c
>
> diff --git a/tests/chamelium/kms_chamelium_sharpness_filter.c b/tests/chamelium/kms_chamelium_sharpness_filter.c
> new file mode 100644
> index 000000000..2ac05717a
> --- /dev/null
> +++ b/tests/chamelium/kms_chamelium_sharpness_filter.c
> @@ -0,0 +1,282 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2025 Intel Corporation
> + */
> +
> +/**
> + * TEST: kms chamelium sharpness filter
> + * Category: Display
> + * Description: Test to validate content adaptive sharpness filter using Chamelium
> + * Driver requirement: xe
> + * Mega feature: General Display Features
> + */
> +
> +#include "igt.h"
> +#include "igt_kms.h"
> +
> +/**
> + * SUBTEST: filter-basic
> + * Description: Verify basic content adaptive sharpness filter.
> + */
> +
> +IGT_TEST_DESCRIPTION("Test to validate content adaptive sharpness filter using Chamelium");
> +
> +#define MID_FILTER_STRENGTH 128
> +#define MAX_FRAMES 4
> +
> +typedef struct {
> + int drm_fd;
> + enum pipe pipe_id;
> + struct igt_fb fb;
> + igt_display_t display;
> + igt_output_t *output;
> + igt_plane_t *primary;
> + drmModeModeInfo *mode;
> + int filter_strength;
> + struct chamelium *chamelium;
> + struct chamelium_port **ports;
> + int port_count;
> +} data_t;
> +
> +static bool pipe_output_combo_valid(data_t *data, enum pipe pipe)
> +{
> + bool ret = true;
> +
> + igt_output_set_pipe(data->output, pipe);
> + if (!intel_pipe_output_combo_valid(&data->display))
> + ret = false;
> + igt_output_set_pipe(data->output, PIPE_NONE);
> +
> + return ret;
> +}
> +
> +static void set_filter_strength_on_pipe(data_t *data)
> +{
> + igt_pipe_set_prop_value(&data->display, data->pipe_id,
> + IGT_CRTC_SHARPNESS_STRENGTH,
> + data->filter_strength);
> +}
> +
> +static void reset_filter_strength_on_pipe(data_t *data)
> +{
> + igt_pipe_set_prop_value(&data->display, data->pipe_id,
> + IGT_CRTC_SHARPNESS_STRENGTH, 0);
> +}
> +
> +static void paint_image(igt_fb_t *fb)
> +{
> + cairo_t *cr = igt_get_cairo_ctx(fb->fd, fb);
> + int img_x, img_y, img_w, img_h;
> + const char *file = "1080p-left.png";
> +
> + img_x = img_y = 0;
> + img_w = fb->width;
> + img_h = fb->height;
> +
> + igt_paint_image(cr, file, img_x, img_y, img_w, img_h);
> +
> + igt_put_cairo_ctx(cr);
> +}
> +
> +static void setup_fb(int fd, int width, int height, uint32_t format,
> + uint64_t modifier, struct igt_fb *fb)
> +{
> + int fb_id;
> +
> + fb_id = igt_create_fb(fd, width, height, format, modifier, fb);
> + igt_assert(fb_id);
> +
> + paint_image(fb);
> +}
> +
> +static void destroy_frame_dumps(struct chamelium_frame_dump *frames[], int count)
> +{
> + for (int i = 0; i < count; i++) {
> + if (frames[i]) {
> + chamelium_destroy_frame_dump(frames[i]);
> + frames[i] = NULL;
> + }
> + }
> +}
> +
> +static void cleanup(data_t *data)
> +{
> + igt_remove_fb(data->drm_fd, &data->fb);
> + igt_output_set_pipe(data->output, PIPE_NONE);
> + igt_output_override_mode(data->output, NULL);
> + igt_display_commit2(&data->display, COMMIT_ATOMIC);
> +}
> +
> +static void test_t(data_t *data, igt_plane_t *primary,
> + struct chamelium_port *port)
> +{
> + struct chamelium_frame_dump *frame[4];
> + drmModeModeInfo *mode;
> + int height, width;
> + bool ret[4], ret_ok = false;
Can we have `eq` or `match` instead of ret?
> +
> + igt_output_set_pipe(data->output, data->pipe_id);
> +
> + mode = igt_output_get_mode(data->output);
> + height = mode->hdisplay;
> + width = mode->vdisplay;
> +
> + setup_fb(data->drm_fd, height, width, DRM_FORMAT_XRGB8888, DRM_FORMAT_MOD_LINEAR, &data->fb);
> +
> + igt_plane_set_fb(data->primary, &data->fb);
> + igt_display_commit2(&data->display, COMMIT_ATOMIC);
> +
> + chamelium_capture(data->chamelium, port, 0, 0, 0, 0, 1);
> + frame[0] =
> + chamelium_read_captured_frame(data->chamelium, 0);
> +
> + set_filter_strength_on_pipe(data);
> + igt_display_commit_atomic(&data->display, 0, NULL);
> +
> + chamelium_capture(data->chamelium, port, 0, 0, 0, 0, 1);
> + frame[1] =
> + chamelium_read_captured_frame(data->chamelium, 0);
> +
> + reset_filter_strength_on_pipe(data);
> + igt_display_commit_atomic(&data->display, 0, NULL);
> +
> + chamelium_capture(data->chamelium, port, 0, 0, 0, 0, 1);
> + frame[2] =
> + chamelium_read_captured_frame(data->chamelium, 0);
> +
> + set_filter_strength_on_pipe(data);
> + igt_display_commit_atomic(&data->display, 0, NULL);
> +
> + chamelium_capture(data->chamelium, port, 0, 0, 0, 0, 1);
> + frame[3] =
> + chamelium_read_captured_frame(data->chamelium, 0);
> +
> + ret[0] = chamelium_frame_eq_or_dump_frame_pair(data->chamelium,
> + frame[0], frame[1]);
> +
> + ret[1] = chamelium_frame_eq_or_dump_frame_pair(data->chamelium,
> + frame[1], frame[2]);
> +
> + ret[2] = chamelium_frame_eq_or_dump_frame_pair(data->chamelium,
> + frame[0], frame[2]);
> +
> + ret[3] = chamelium_frame_eq_or_dump_frame_pair(data->chamelium,
> + frame[1], frame[3]);
> +
> + ret_ok = (ret[0] == 0) && (ret[1] == 0) && (ret[2] == 1) && (ret[3] == 1);
IMO, compare with true and false will be more intuitive.
match_ok = (match[0] == false) && (match[1] == false) and so on..
In any case, patch looks good to me.
Reviewed-by: Ankit Nautiyal <ankit.k.nautiyal at intel.com>
> +
> + destroy_frame_dumps(frame, MAX_FRAMES);
> + cleanup(data);
> +
> + igt_assert_f(ret_ok, "Sharpness filter test failed:\n"
> + "Expected: Frame[0]==Frame[1]: 0, Frame[1]==Frame[2]: 0, Frame[0]==Frame[2]: 1, Frame[1]==Frame[3]: 1\n"
> + "Observed: Frame[0]==Frame[1]: %d, Frame[1]==Frame[2]: %d, Frame[0]==Frame[2]: %d, Frame[1]==Frame[3]: %d\n", ret[0], ret[1], ret[2], ret[3]);
> +}
> +
> +static int test_setup(data_t *data, enum pipe p)
> +{
> + igt_pipe_t *pipe;
> + int i = 0;
> +
> + igt_display_reset(&data->display);
> +
> + pipe = &data->display.pipes[p];
> + igt_require(pipe->n_planes >= 0);
> +
> + data->primary = igt_pipe_get_plane_type(pipe, DRM_PLANE_TYPE_PRIMARY);
> + igt_assert(data->primary);
> +
> + /*
> + * Prefer to run this test on HDMI connector if its connected, since on DP we
> + * sometimes face DP FSM issue
> + */
> + for_each_valid_output_on_pipe(&data->display, p, data->output) {
> + data->pipe_id = p;
> + for (i = 0; i < data->port_count; i++) {
> + if ((data->output->config.connector->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
> + data->output->config.connector->connector_type == DRM_MODE_CONNECTOR_HDMIB) &&
> + strcmp(data->output->name, chamelium_port_get_name(data->ports[i])) == 0)
> + return i;
> + }
> + }
> +
> + for_each_valid_output_on_pipe(&data->display, p, data->output) {
> + data->pipe_id = p;
> + for (i = 0; i < data->port_count; i++) {
> + if (strcmp(data->output->name,
> + chamelium_port_get_name(data->ports[i])) == 0)
> + return i;
> + }
> + }
> +
> + return -1;
> +}
> +
> +static void test_sharpness_filter(data_t *data, enum pipe p)
> +{
> + int port_idx = test_setup(data, p);
> +
> + igt_require(port_idx >= 0);
> + igt_require(igt_pipe_obj_has_prop(&data->display.pipes[p], IGT_CRTC_SHARPNESS_STRENGTH));
> +
> + if (!pipe_output_combo_valid(data, p))
> + return;
> +
> + igt_dynamic_f("pipe-%s-%s", kmstest_pipe_name(p), data->output->name)
> + (test_t(data, data->primary, data->ports[port_idx]));
> +}
> +
> +static void
> +run_sharpness_filter_test(data_t *data)
> +{
> + igt_display_t *display = &data->display;
> + enum pipe pipe;
> +
> + igt_describe("Verify basic content adaptive sharpness filter.");
> + igt_subtest_with_dynamic("filter-basic") {
> + for_each_pipe(display, pipe) {
> + data->filter_strength = MID_FILTER_STRENGTH;
> + test_sharpness_filter(data, pipe);
> + }
> + }
> +}
> +
> +igt_main
> +{
> + data_t data = {};
> +
> + igt_fixture {
> + data.drm_fd = drm_open_driver_master(DRIVER_XE);
> +
> + igt_display_require(&data.display, data.drm_fd);
> + igt_require(data.display.is_atomic);
> +
> + igt_chamelium_allow_fsm_handling = false;
> +
> + /* we need to initalize chamelium after igt_display_require */
> + data.chamelium = chamelium_init(data.drm_fd, &data.display);
> + igt_require(data.chamelium);
> +
> + data.ports = chamelium_get_ports(data.chamelium,
> + &data.port_count);
> +
> + if (!data.port_count)
> + igt_skip("No ports connected\n");
> + /*
> + * We don't cause any harm by plugging
> + * discovered ports, just incase they are not plugged
> + * we currently skip in test_setup
> + */
> + for(int i = 0; i < data.port_count; i++)
> + chamelium_plug(data.chamelium, data.ports[i]);
> +
> + kmstest_set_vt_graphics_mode();
> + }
> +
> + run_sharpness_filter_test(&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 bef4d302c..24a9a1f28 100644
> --- a/tests/meson.build
> +++ b/tests/meson.build
> @@ -348,6 +348,7 @@ chamelium_progs = [
> 'kms_chamelium_edid',
> 'kms_chamelium_frames',
> 'kms_chamelium_hpd',
> + 'kms_chamelium_sharpness_filter',
> ]
>
> test_deps = [ igt_deps ]
> @@ -373,6 +374,7 @@ extra_sources = {
> 'kms_chamelium_edid': [ join_paths ('chamelium', 'kms_chamelium_helper.c') ],
> 'kms_chamelium_frames': [ join_paths ('chamelium', 'kms_chamelium_helper.c') ],
> 'kms_chamelium_hpd': [ join_paths ('chamelium', 'kms_chamelium_helper.c') ],
> + 'kms_chamelium_sharpness_filter': [ join_paths ('chamelium', 'kms_chamelium_helper.c') ],
> 'kms_dp_linktrain_fallback': [
> join_paths ('intel', 'kms_mst_helper.c'),
> join_paths ('intel', 'kms_dsc_helper.c') ],
More information about the igt-dev
mailing list