[PATCH v3] tests/kms_cursor_crc.: Test async cursor crc

Kamil Konieczny kamil.konieczny at linux.intel.com
Tue Mar 25 12:00:31 UTC 2025


Hi Shekhar,
On 2025-03-25 at 08:25:21 +0530, Shekhar Chauhan wrote:

please improve subject, first remove dot from 'crc.:' and
also change description, as you already have 'cursor' and 'crc'
in test name, so instead of:

[PATCH v3] tests/kms_cursor_crc.: Test async cursor crc

better:

[PATCH v3] tests/kms_cursor_crc: Test async changes midframe

or:
[PATCH v3] tests/kms_cursor_crc: Midframe async changes with 2 cursors

> Check if cursor IOCTLs are behaving in timely manner via CRC.
> Test CRC of the display with 2 cursors, separated by a vblank and a
> sleep so that the drawing of the cursors only happens when the screen is
> active and then compare the CRC of the two cases. This helps validates
> that there is no tearing when doing cursor changes midframe. Test
> consists of two subtests, one for checking the timely change and the
> second test also adds changing position into the first test.
> 
> v2: Trim down the description.
> v3: Require Intel device/driver.
> 
> Signed-off-by: Shekhar Chauhan <shekhar.chauhan at intel.com>
> ---
>  tests/kms_cursor_crc.c | 139 +++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 139 insertions(+)
> 
> diff --git a/tests/kms_cursor_crc.c b/tests/kms_cursor_crc.c
> index 7c6f61f55..d3a2eb689 100644
> --- a/tests/kms_cursor_crc.c
> +++ b/tests/kms_cursor_crc.c
> @@ -100,6 +100,16 @@
>   * @max-size:              Max supported size
>   */
>  
> +/**
> + * SUBTEST: async-cursor-crc-framebuffer-change
> + * Description: Validate cursor IOCTLs tearing via framebuffer changes and CRC.
> + */
> +
> +/**
> + * SUBTEST: async-cursor-crc-position-change
> + * Description: Similar to async-cursor-change, but this test changes position.

Do not rely on previous one, write it down here in full form.

Regards,
Kamil

> + */
> +
>  IGT_TEST_DESCRIPTION(
>     "Use the display CRC support to validate cursor plane functionality. "
>     "The test will position the cursor plane either fully onscreen, "
> @@ -123,6 +133,11 @@ enum cursor_buffers {
>  	MAXCURSORBUFFER
>  };
>  
> +enum cursor_change {
> +	FIRSTIMAGE,
> +	SECONDIMAGE
> +};
> +
>  typedef struct {
>  	int x;
>  	int y;
> @@ -151,6 +166,7 @@ typedef struct {
>  	double alpha;
>  	int vblank_wait_count; /* because of msm */
>  	cursorarea oldcursorarea[MAXCURSORBUFFER];
> +	struct igt_fb timed_fb[2];
>  } data_t;
>  
>  static bool extended;
> @@ -674,6 +690,78 @@ static void test_cursor_transparent(data_t *data)
>  	data->alpha = 1.0;
>  }
>  
> +static void do_timed_cursor_fb_change(data_t *data, enum cursor_change change)
> +{
> +	if (change == FIRSTIMAGE) {
> +		igt_plane_set_fb(data->cursor, &data->timed_fb[0]);
> +		igt_plane_set_position(data->cursor,
> +				       data->left + data->cursor_max_w - 10,
> +				       data->bottom - data->cursor_max_h - 10);
> +	} else {
> +		igt_plane_set_fb(data->cursor, &data->timed_fb[1]);
> +	}
> +}
> +
> +static void do_timed_cursor_fb_pos_change(data_t *data, enum cursor_change change)
> +{
> +	if (change == FIRSTIMAGE) {
> +		igt_plane_set_fb(data->cursor, &data->timed_fb[0]);
> +		igt_plane_set_position(data->cursor,
> +				       data->left + data->cursor_max_w - 10,
> +				       data->bottom - data->cursor_max_h - 10);
> +	} else {
> +		igt_plane_set_position(data->cursor,
> +				       data->left + data->cursor_max_w + 20,
> +				       data->bottom - data->cursor_max_h + 20);
> +	}
> +}
> +
> +static void timed_cursor_changes(data_t *data, void (changefunc)(data_t *, enum cursor_change))
> +{
> +	/* Legacy cursor API does not guarantee that the cursor update happens at vBlank.
> +	 * So, not assuming that this happens across all platforms, the test requires
> +	 * Intel plaforms.
> +	 */
> +	igt_require_intel(data->drm_fd);
> +
> +	igt_crc_t crc1, crc2;
> +
> +	data->cursor = igt_output_get_plane_type(data->output, DRM_PLANE_TYPE_CURSOR);
> +	changefunc(data, FIRSTIMAGE);
> +
> +	igt_display_commit(&data->display);
> +
> +	/* Extra vblank wait is because nonblocking cursor ioctl */
> +	igt_wait_for_vblank_count(data->drm_fd,
> +				  data->display.pipes[data->pipe].crtc_offset,
> +				  data->vblank_wait_count);
> +
> +	igt_pipe_crc_get_current(data->drm_fd, data->pipe_crc, &crc1);
> +
> +	/* get the screen refresh rate, then wait for vblank, and
> +	 * wait for 1/5 of time of screen refresh and change image.
> +	 * change it mid screen to validate that the change happens
> +	 * at the end of the current frame.
> +	 */
> +	usleep(1.0f / data->refresh / 5.0f * 1e6);
> +
> +	changefunc(data, SECONDIMAGE);
> +	igt_display_commit(&data->display);
> +	igt_pipe_crc_get_current(data->drm_fd, data->pipe_crc, &crc2);
> +
> +	igt_assert_crc_equal(&crc1, &crc2);
> +}
> +
> +static void test_crc_cursors(data_t *data)
> +{
> +	timed_cursor_changes(data, do_timed_cursor_fb_change);
> +}
> +
> +static void test_crc_pos_cursors(data_t *data)
> +{
> +	timed_cursor_changes(data, do_timed_cursor_fb_pos_change);
> +}
> +
>  static void test_cursor_opaque(data_t *data)
>  {
>  	data->alpha = 1.0;
> @@ -1013,6 +1101,57 @@ static void run_tests_on_pipe(data_t *data)
>  	}
>  
>  	igt_fixture {
> +		igt_create_color_fb(data->drm_fd, data->cursor_max_w, data->cursor_max_h,
> +				DRM_FORMAT_ARGB8888, DRM_FORMAT_MOD_LINEAR,
> +				1.f, 1.f, 1.f, &data->timed_fb[0]);
> +
> +		igt_create_color_fb(data->drm_fd, data->cursor_max_w, data->cursor_max_h,
> +				DRM_FORMAT_ARGB8888, DRM_FORMAT_MOD_LINEAR,
> +				1.f, 0.f, 0.f, &data->timed_fb[1]);
> +	}
> +
> +	igt_describe("Validate CRC with two cursors");
> +	igt_subtest_with_dynamic("async-cursor-crc-framebuffer-change") {
> +		for_each_pipe_with_single_output(&data->display, pipe, data->output) {
> +			if (execution_constraint(pipe))
> +				continue;
> +
> +			data->pipe = pipe;
> +
> +			if (!valid_pipe_output_combo(data))
> +				continue;
> +
> +			igt_dynamic_f("pipe-%s-%s",
> +					  kmstest_pipe_name(pipe),
> +					  data->output->name)
> +				run_test(data, test_crc_cursors,
> +					  data->cursor_max_w, data->cursor_max_h);
> +		}
> +	}
> +
> +	igt_describe("Validate CRC with two cursors and cursor position change");
> +	igt_subtest_with_dynamic("async-cursor-crc-position-change") {
> +		for_each_pipe_with_single_output(&data->display, pipe, data->output) {
> +			if (execution_constraint(pipe))
> +				continue;
> +
> +			data->pipe = pipe;
> +
> +			if (!valid_pipe_output_combo(data))
> +				continue;
> +
> +			igt_dynamic_f("pipe-%s-%s",
> +					  kmstest_pipe_name(pipe),
> +					  data->output->name)
> +				run_test(data, test_crc_pos_cursors,
> +					  data->cursor_max_w, data->cursor_max_h);
> +		}
> +	}
> +
> +	igt_fixture {
> +		igt_remove_fb(data->drm_fd, &data->timed_fb[0]);
> +		igt_remove_fb(data->drm_fd, &data->timed_fb[1]);
> +
>  		create_cursor_fb(data, data->cursor_max_w, data->cursor_max_h);
>  	}
>  
> -- 
> 2.34.1
> 


More information about the igt-dev mailing list