[PATCH i-g-t v3] tests/amdgpu: Add test for native cursor fallback to overlay

Leo Li sunpeng.li at amd.com
Thu Aug 21 18:28:19 UTC 2025



On 2025-07-23 13:27, IVAN.LIPSKI at amd.com wrote:
> From: Ivan Lipski <ivan.lipski at amd.com>
> 
> [Why & How]
> The AMD display hardware does not use dedicated cursor planes.
> Instead, the cursor is rendered either using the primary plane
> or an available overlay plane. This test verifies that the
> cursor correctly falls back from native to overlay mode
> when the underneath primary plane is incompatible. It also tests

The last sentence seems like a typo?

> 
> It has 5 subtests:
> 
> rgb-to-yuv
> Switches the primary plane to a NV12 format FB and verifies that
> the cursor falls back from native to overlay.
> 
> non-full
> Switches the primary planeto a FB that does not fill the entire CRTC
> (currently sized at a quarter of the CRTC).
> 
> scaling-[50,75,125,150,175,200]
> Switches the primary plane to a FB with a chosen scaling (50%-200%), which
> is then filled in the CRTC.
> 
> max-planes
> Enables 2 overlay planes, a primary plane and a cursor. Then
> switches the primary plane to YUV to cause the cursor to fall back to
> overlay. Verifies that the cursor can still fallback to overlay when 4
> planes are enabled.
> 
> no-available-planes
> Enables 3 available overlay planes, a primary plane and a cursor. Then
> switches the primary plane to YUV to cause the cursor to fall back to
> overlay. Verifies that the atomic commit fails due to no available overlay
> planes.
> 
> Signed-off-by: Ivan Lipski <ivan.lipski at amd.com>
> ---
>  tests/amdgpu/amd_cursor_overlay.c | 484 ++++++++++++++++++++++++++++++
>  tests/amdgpu/meson.build          |   1 +
>  2 files changed, 485 insertions(+)
>  create mode 100644 tests/amdgpu/amd_cursor_overlay.c
> 
> diff --git a/tests/amdgpu/amd_cursor_overlay.c b/tests/amdgpu/amd_cursor_overlay.c
> new file mode 100644
> index 000000000..cf5ea83a0
> --- /dev/null
> +++ b/tests/amdgpu/amd_cursor_overlay.c
> @@ -0,0 +1,484 @@
> +// SPDX-License-Identifier: MIT
> +// Copyright 2025 Advanced Micro Devices, Inc.
> +
> +#include "igt.h"
> +#include "igt_kms.h"
> +
> +/**
> + * TEST: amd_cursor_overlay
> + * Category: Display
> + * Description: Tests cursor fall back from native to overlay
> + * Driver requirement: amdgpu
> + */
> +
> +/**
> + * SUBTEST: rgb-to-yuv
> + * Description: Tests native cursor fall back to overlay cursor when a top plane
> + *				switches from RGB to YUV.
> + * SUBTEST: non-full
> + * Description: Tests native cursor fall back to overlay cursor when a top plane
> + *				does not fill the crtc.
> + * SUBTEST: scaling-%d
> + * Description: Tests native cursor fall back to overlay cursor when a top plane
> + *				is scaled.
> + *
> + * arg[1].values: 50, 75, 125, 150, 175, 200
> + *
> + * SUBTEST: max-planes
> + * Description: Tests native cursor fall back to overlay cursor when a top plane
> + *				is YUV and there are two overlay planes used.
> + *
> + * SUBTEST: no-available-planes
> + * Description: Tests native cursor attempt to fall back to overlay cursor required,
> + *				but fails atomic commit due to no available overlay planes.
> + */
> +
> +enum {
> +	TEST_YUV = 1,
> +	TEST_QUARTER_FB = 1 << 1,
> +	TEST_SCALING = 1 << 2,
> +	TEST_MAX_PLANES = 1 << 3,
> +	TEST_NO_PLANES = 1 << 4,

nit: to avoid confusion, s/NO_PLANES/NO_AVAILABLE_PLANES

> +};
> +
> +typedef struct {
> +	int x;
> +	int y;
> +} pos_t;
> +
> +/* Common test data. */
> +typedef struct data {
> +	igt_display_t display;
> +	igt_plane_t *primary;
> +	igt_plane_t *cursor;
> +	igt_plane_t *overlay1;
> +	igt_plane_t *overlay2;
> +	igt_plane_t *overlay3;
> +	igt_output_t *output;
> +	igt_pipe_t *pipe;
> +	igt_pipe_crc_t *pipe_crc;
> +	drmModeModeInfo *mode;
> +	igt_fb_t rgb_fb;
> +	igt_fb_t yuv_fb;
> +	igt_fb_t rgb_fb_o1;
> +	igt_fb_t rgb_fb_o2;
> +	igt_fb_t rgb_fb_o3;
> +	igt_fb_t quarter_fb;
> +	igt_fb_t scale_fb;
> +	igt_fb_t cfb;
> +	enum pipe pipe_id;
> +	int drm_fd;
> +	uint64_t max_curw;
> +	uint64_t max_curh;
> +} data_t;
> +
> +/* Retuns the number of available overlay planes */
> +static int get_overlay_planes_count(igt_display_t *display, enum pipe pipe)
> +{
> +	int count = 0;
> +	igt_plane_t *plane;
> +
> +	for_each_plane_on_pipe(display, pipe, plane)
> +		if (plane->type == DRM_PLANE_TYPE_OVERLAY)
> +			count++;
> +
> +	return count;
> +}
> +
> +/* Common test setup. */
> +static void test_init(data_t *data, enum pipe pipe_id, igt_output_t *output,
> +		      unsigned int flags)
> +{
> +	data->pipe_id = pipe_id;
> +	data->pipe = &data->display.pipes[data->pipe_id];
> +	data->output = output;
> +	data->mode = igt_output_get_mode(data->output);
> +	data->primary = igt_pipe_get_plane_type(data->pipe, DRM_PLANE_TYPE_PRIMARY);
> +	data->cursor = igt_pipe_get_plane_type(data->pipe, DRM_PLANE_TYPE_CURSOR);
> +
> +	if (flags & TEST_NO_PLANES || flags & TEST_MAX_PLANES) {
> +		data->overlay1 = igt_pipe_get_plane_type_index(data->pipe, DRM_PLANE_TYPE_OVERLAY, 0);
> +		data->overlay2 = igt_pipe_get_plane_type_index(data->pipe, DRM_PLANE_TYPE_OVERLAY, 1);
> +	}
> +	if (flags & TEST_NO_PLANES)
> +		data->overlay3 = igt_pipe_get_plane_type_index(data->pipe, DRM_PLANE_TYPE_OVERLAY, 2);
> +
> +	igt_info("Using (pipe %s + %s) to run the subtest.\n",
> +		 kmstest_pipe_name(data->pipe_id), igt_output_name(data->output));
> +
> +	igt_require_pipe_crc(data->drm_fd);
> +	data->pipe_crc = igt_pipe_crc_new(data->drm_fd, data->pipe_id,
> +					  IGT_PIPE_CRC_SOURCE_AUTO);
> +}
> +
> +/* Common test finish. */
> +static void test_fini(data_t *data)
> +{
> +	igt_pipe_crc_free(data->pipe_crc);
> +	igt_display_reset(&data->display);
> +	igt_plane_set_fb(data->primary, NULL);
> +	igt_plane_set_fb(data->cursor, NULL);
> +	if (data->overlay1)
> +		igt_plane_set_fb(data->overlay1, NULL);
> +	if (data->overlay2)
> +		igt_plane_set_fb(data->overlay2, NULL);
> +	if (data->overlay3)
> +                igt_plane_set_fb(data->overlay3, NULL);
> +	igt_display_commit2(&data->display, COMMIT_ATOMIC);
> +}
> +
> +/* Common test cleanup. */
> +static void test_cleanup(data_t *data)
> +{
> +	igt_remove_fb(data->drm_fd, &data->cfb);
> +	igt_remove_fb(data->drm_fd, &data->rgb_fb);
> +	igt_remove_fb(data->drm_fd, &data->yuv_fb);
> +	if (data->overlay1)
> +		igt_remove_fb(data->drm_fd, &data->rgb_fb_o1);
> +	if (data->overlay2)
> +		igt_remove_fb(data->drm_fd, &data->rgb_fb_o2);
> +	if (data->overlay3)
> +		igt_remove_fb(data->drm_fd, &data->rgb_fb_o3);
> +	igt_remove_fb(data->drm_fd, &data->quarter_fb);
> +	igt_remove_fb(data->drm_fd, &data->scale_fb);
> +}
> +
> +
> +static void test_cursor_pos(data_t *data, int x, int y, unsigned int flags, unsigned int scaling_factor)
> +{
> +	igt_crc_t ref_crc, test_crc;
> +	cairo_t *cr;
> +	igt_fb_t *rgb_fb = &data->rgb_fb;
> +	igt_fb_t *yuv_fb = &data->yuv_fb;
> +	igt_fb_t *quarter_fb = &data->quarter_fb;
> +	igt_fb_t *rgb_fb_o1 = &data->rgb_fb_o1;
> +	igt_fb_t *rgb_fb_o2 = &data->rgb_fb_o2;
> +	igt_fb_t *rgb_fb_o3 = &data->rgb_fb_o3;
> +	igt_fb_t *cfb = &data->cfb;
> +	int cw = cfb->width;
> +	int ch = cfb->height;
> +	int ret;
> +
> +
> +	cr = igt_get_cairo_ctx(rgb_fb->fd, rgb_fb);
> +
> +	igt_plane_set_fb(data->primary, rgb_fb);
> +	igt_display_commit2(&data->display, COMMIT_ATOMIC);
> +
> +	igt_paint_color(cr, 0, 0, rgb_fb->width, rgb_fb->height, 0.0, 0.0, 0.0);
> +
> +	/* Draw a magenta square where the cursor should be. */
> +	igt_paint_color(cr, x, y, cw, ch, 1.0, 0.0, 1.0);
> +	igt_put_cairo_ctx(cr);
> +
> +	if (flags & TEST_MAX_PLANES) {
> +		/* Display the overlay planes. */
> +		igt_plane_set_fb(data->overlay1, rgb_fb_o1);
> +		igt_plane_set_position(data->overlay1, 0, 0);
> +		igt_plane_set_fb(data->overlay2, rgb_fb_o2);
> +		igt_plane_set_position(data->overlay2, data->rgb_fb_o1.width, data->rgb_fb_o1.height);
> +		igt_display_commit_atomic(&data->display, 0, NULL);
> +
> +		/* Display the cursor. */
> +		igt_plane_set_fb(data->cursor, cfb);
> +		igt_plane_set_position(data->cursor, x, y);
> +		igt_display_commit_atomic(&data->display, 0, NULL);
> +
> +		/* Trigger cursor fall back due to a YUV plane;
> +		 * expect the atomic commit to fail due to no
> +		 * available overlay planes.
> +		 */
> +		igt_plane_set_fb(data->primary, &data->yuv_fb);
> +		ret = igt_display_try_commit_atomic(&data->display, DRM_MODE_ATOMIC_ALLOW_MODESET, 0);
> +
> +		/* Remove the overlay planes. */
> +		igt_plane_set_fb(data->overlay1, NULL);
> +		igt_plane_set_fb(data->overlay2, NULL);
> +		igt_plane_set_fb(data->cursor, NULL);
> +		igt_display_commit_atomic(&data->display, 0, NULL);
> +
> +		/* Expected atomic commit to fail due to no available overlay planes. */
> +		igt_assert_f(ret == 0, "Expected atomic commit to succeed.\n");
> +		return;
> +	}
> +	if (flags & TEST_NO_PLANES) {
> +
> +		/* Display the overlay planes. */
> +		igt_plane_set_fb(data->overlay1, rgb_fb_o1);
> +		igt_plane_set_position(data->overlay1, 0, 0);
> +		igt_plane_set_fb(data->overlay2, rgb_fb_o2);
> +		igt_plane_set_position(data->overlay2, data->rgb_fb_o1.width, data->rgb_fb_o1.height);
> +		igt_plane_set_fb(data->overlay3, rgb_fb_o3);
> +                igt_plane_set_position(data->overlay3, data->rgb_fb_o1.width, 0);
> +		igt_display_commit_atomic(&data->display, 0, NULL);
> +
> +		/* Display the cursor. */
> +		igt_plane_set_fb(data->cursor, cfb);
> +		igt_plane_set_position(data->cursor, x, y);
> +		igt_display_commit_atomic(&data->display, 0, NULL);
> +
> +		/* Trigger cursor fall back due to a YUV plane;
> +		 * expect the atomic commit to fail due to no
> +		 * available overlay planes.
> +		 */
> +		igt_plane_set_fb(data->primary, &data->yuv_fb);
> +		ret = igt_display_try_commit_atomic(&data->display, DRM_MODE_ATOMIC_ALLOW_MODESET, 0);
> +
> +		/* Remove the overlay planes. */
> +		igt_plane_set_fb(data->overlay1, NULL);
> +		igt_plane_set_fb(data->overlay2, NULL);
> +		igt_plane_set_fb(data->overlay3, NULL);
> +		igt_plane_set_fb(data->cursor, NULL);
> +		igt_display_commit_atomic(&data->display, 0, NULL);
> +
> +		/* Expected atomic commit to fail due to no available overlay planes. */
> +		igt_assert_f(ret == -EINVAL, "Expected atomic commit to fail due to no available overlay planes.\n");
> +		return;
> +	}

Is the TEST_MAX_PLANES testing the 
1 PRIMARY + 2 OVERLAY + 1 Overlay CURSOR = 4 planes scenario? 
If so, atomic commit is expected to succeed, not fail.

TEST_NO_PLANES here looks correct in that regard, since amdgpu_dm would 
reject 1 PRIMARY + 3 OVERLAYS + 1 Overlay CURSOR = 5 planes.

These tests would only be valid for APUs that have 4 hw planes though.
Some DGPUs have more than 4, for which these tests wouldn't make sense.

Perhaps we can programatically determine the number of OVERLAYs via
get_overlay_planes_count(), and enable the right amount (count-1 for
MAX_PLANES and count for NO_PLANES)? We should be able to use the same
fb for all of them, instead of creating a new fb for each.

> +
> +	/* Display the cursor. */
> +	igt_plane_set_fb(data->cursor, cfb);
> +	igt_plane_set_position(data->cursor, x, y);
> +	igt_display_commit_atomic(&data->display, 0, NULL);
> +
> +	/** Record a reference CRC */
> +	igt_pipe_crc_start(data->pipe_crc);
> +	igt_pipe_crc_get_current(data->drm_fd, data->pipe_crc, &ref_crc);
> +
> +	/* Switch primary plane to use YUV Fb. */
> +	if (flags & TEST_YUV) {
> +		igt_plane_set_fb(data->primary, yuv_fb);
> +		igt_plane_set_position(data->primary, 0, 0);
> +		igt_plane_set_size(data->primary, yuv_fb->width, yuv_fb->height);
> +		igt_display_commit_atomic(&data->display, DRM_MODE_ATOMIC_ALLOW_MODESET, 0);
> +
> +	/* Switch primary plane to use a quarter-sized FB. */
> +	} else if (flags & TEST_QUARTER_FB) {
> +		igt_plane_set_fb(data->primary, quarter_fb);
> +		igt_plane_set_position(data->primary, 0, 0);
> +		igt_display_commit_atomic(&data->display, 0, NULL);
> +
> +	/* Switch primary plane to use a scaled FB. */
> +	} else if (flags & TEST_SCALING) {
> +		igt_create_fb(data->drm_fd,
> +			data->rgb_fb.width * scaling_factor / 100,
> +			data->rgb_fb.height * scaling_factor / 100,
> +			DRM_FORMAT_XRGB8888,
> +			DRM_FORMAT_MOD_LINEAR, &data->scale_fb);
> +
> +		igt_plane_set_fb(data->primary, &data->scale_fb);
> +		igt_plane_set_position(data->primary, 0, 0);
> +		igt_plane_set_size(data->primary, data->mode->hdisplay, data->mode->vdisplay);
> +
> +		igt_display_commit_atomic(&data->display, 0, NULL);
> +	}
> +
> +	/* Wait for one more vblank since cursor updates are not
> +	 * synchronized to the same frame on AMD hw.
> +	 */
> +	if (is_amdgpu_device(data->drm_fd))
> +		igt_wait_for_vblank_count(data->drm_fd, data->display.pipes[data->pipe_id].crtc_offset, 1);
> +
> +	/* Record the new CRC. */
> +	igt_pipe_crc_get_current(data->drm_fd, data->pipe_crc, &test_crc);
> +	igt_pipe_crc_stop(data->pipe_crc);
> +
> +	/** CRC Check is sufficient for this test */
> +	igt_assert_crc_equal(&ref_crc, &test_crc);
> +}
> +
> +/*
> + * Tests the cursor on a variety of positions on the screen.
> + * Specific edge cases that should be captured here are the negative edges
> + * of each plane and the centers.
> + */
> +static void test_cursor_spots(data_t *data, int size, unsigned int flags, unsigned int scaling_factor)
> +{
> +	int sw = data->mode->hdisplay;
> +	int sh = data->mode->vdisplay;
> +	int i;
> +		const pos_t pos[] = {
> +		/* Test diagonally from top left to bottom right. */
> +		{ -size / 3, -size / 3 },
> +		{ 0, 0 },
> +		{ sw / 4 - size, sh / 4 - size },
> +		{ sw / 4 - size / 3, sh / 4 - size / 3 },
> +		{ sw / 4, sh / 4 },
> +		{ sw / 4 + size, sh / 4 + size },
> +		{ sw / 2, sh / 2 },
> +		{ sw / 4 + sw / 2 - size, sh / 4 + sh / 2 - size },
> +		{ sw / 4 + sw / 2 - size / 3, sh / 4 + sh / 2 - size / 3 },
> +		{ sw / 4 + sw / 2 + size, sh / 4 + sh / 2 + size },
> +		{ sw - size, sh - size },
> +		{ sw - size / 3, sh - size / 3 },
> +		/* Test remaining corners. */
> +		{ sw - size, 0 },
> +		{ 0, sh - size },
> +		{ sw / 4 + sw / 2 - size, sh / 4 },
> +		{ sw / 4, sh / 4 + sh / 2 - size }
> +	};
> +
> +	for (i = 0; i < ARRAY_SIZE(pos); ++i)
> +		test_cursor_pos(data, pos[i].x, pos[i].y, flags, scaling_factor);
> +}
> +
> +static void test_cursor(data_t *data, int size, unsigned int flags, unsigned int scaling_factor)
> +{
> +	int sw, sh;
> +
> +	igt_skip_on(size > data->max_curw || size > data->max_curh);
> +
> +	sw = data->mode->hdisplay;
> +	sh = data->mode->vdisplay;
> +
> +	test_cleanup(data);
> +
> +	/* Create RGB FB for reference. */
> +	igt_create_color_fb(data->drm_fd, sw, sh, DRM_FORMAT_XRGB8888,
> +			    DRM_FORMAT_MOD_LINEAR, 0.0, 0.0, 0.0, &data->rgb_fb);
> +
> +	/* Create YUV FB for RGB-to-YUV, MAX_PLANES and NO_PLANES subtests */
> +	if (flags & TEST_YUV || flags & TEST_MAX_PLANES ||flags & TEST_NO_PLANES)
> +		igt_create_fb(data->drm_fd, sw, sh, DRM_FORMAT_NV12,
> +					DRM_FORMAT_MOD_NONE, &data->yuv_fb);
> +
> +	/* Create a quarter-sized empty FB. */
> +	if (flags & TEST_QUARTER_FB)
> +		igt_create_color_fb(data->drm_fd, sw / 2, sh / 2, DRM_FORMAT_XRGB8888,
> +					DRM_FORMAT_MOD_LINEAR, 0.0, 0.0, 0.0, &data->quarter_fb);
> +
> +	/* Create two RGB FBs for the overlay planes. */
> +	if (flags & TEST_MAX_PLANES || flags & TEST_NO_PLANES) {
> +		igt_create_color_fb(data->drm_fd, sw / 2, sh / 2, DRM_FORMAT_XRGB8888,
> +			DRM_FORMAT_MOD_NONE, 0.5, 0.0, 0.0, &data->rgb_fb_o1);
> +		igt_create_color_fb(data->drm_fd, sw / 2, sh / 2, DRM_FORMAT_XRGB8888,
> +			DRM_FORMAT_MOD_NONE, 0.0, 0.5, 0.0, &data->rgb_fb_o2);
> +	}
> +
> +	/* Create a third overlay plane for TEST_NO_PLANES test */
> +	if (flags & TEST_NO_PLANES) {
> +		igt_create_color_fb(data->drm_fd, sw / 2, sh / 2, DRM_FORMAT_XRGB8888,
> +			DRM_FORMAT_MOD_NONE, 0.0, 0.0, 0.5, &data->rgb_fb_o3);
> +	}
> +
> +	/* Create a FB for scaling. */
> +	if (flags & TEST_SCALING)
> +		igt_create_color_fb(data->drm_fd, sw, sh, DRM_FORMAT_XRGB8888,
> +					DRM_FORMAT_MOD_LINEAR, 0.0, 0.0, 0.0, &data->scale_fb);
> +
> +	/* Create a cursor FB. */
> +	igt_create_color_fb(data->drm_fd, size, size, DRM_FORMAT_ARGB8888,
> +				DRM_FORMAT_MOD_LINEAR, 1.0, 0.0, 1.0, &data->cfb);
> +
> +	igt_output_set_pipe(data->output, data->pipe_id);
> +
> +	/* Run the test for different cursor spots. */
> +	test_cursor_spots(data, size, flags, scaling_factor);
> +
> +}
> +
> +igt_main
> +{
> +	static const int cursor_sizes[] = { 64, 128, 256 };
> +	data_t data = { .max_curw = 64, .max_curh = 64 };
> +	enum pipe pipe;
> +	igt_output_t *output;
> +	igt_display_t *display;
> +	int i, j;
> +	struct {
> +		const char *name;
> +		unsigned int flags;
> +		unsigned int scale_factor;
> +		const char *desc;
> +	} tests[] = {
> +		{ "rgb-to-yuv", TEST_YUV, 100,
> +		"Tests native cursor fall back to overlay cursor when a top plane switches from RGB to YUV" },
> +		{"non-full", TEST_QUARTER_FB, 100,
> +		"Tests native cursor fall back to overlay cursor when a top plane does not fill the crtc"},
> +		{"max-planes", TEST_MAX_PLANES, 100,
> +		"Tests native cursor fall back to overlay cursor when a top plane is YUV and there are two overlay planes used."},
> +		{"no-available-planes", TEST_NO_PLANES, 100,
> +		"Tests native cursor attempt to fall back to overlay cursor required, but fails atomic commit due to no available overlay planes."},
> +		{"scaling-50", TEST_SCALING, 50,
> +		"Tests native cursor fall back to overlay cursor when a top plane is scaled"},
> +		{"scaling-75", TEST_SCALING, 75,
> +		"Tests native cursor fall back to overlay cursor when a top plane is scaled"},
> +		{"scaling-125", TEST_SCALING, 125,
> +		"Tests native cursor fall back to overlay cursor when a top plane is scaled"},
> +		{"scaling-150", TEST_SCALING, 150,
> +		"Tests native cursor fall back to overlay cursor when a top plane is scaled"},
> +		{"scaling-175", TEST_SCALING, 175,
> +		"Tests native cursor fall back to overlay cursor when a top plane is scaled"},
> +		{"scaling-200", TEST_SCALING, 200,
> +		"Tests native cursor fall back to overlay cursor when a top plane is scaled"},
> +	};
> +
> +	igt_fixture {
> +		int ret;
> +
> +		data.drm_fd = drm_open_driver_master(DRIVER_AMDGPU);
> +
> +		igt_display_require(&data.display, data.drm_fd);
> +		igt_require(data.display.is_atomic);
> +		igt_display_require_output(&data.display);
> +		display = &data.display;
> +
> +		ret = drmGetCap(data.drm_fd, DRM_CAP_CURSOR_WIDTH, &data.max_curw);
> +		igt_assert(ret == 0 || errno == EINVAL);
> +		ret = drmGetCap(data.drm_fd, DRM_CAP_CURSOR_HEIGHT, &data.max_curh);
> +		igt_assert(ret == 0 || errno == EINVAL);
> +
> +		kmstest_set_vt_graphics_mode();
> +	}
> +
> +
> +	for (i = 0; i < ARRAY_SIZE(tests); i++) {
> +		igt_describe_f("%s", tests[i].desc);
> +		igt_subtest_with_dynamic_f("%s", tests[i].name) {
> +
> +			/* Skip YUV and NO_PLANES subtests if YUV is not supported*/
> +			if (tests[i].flags & TEST_YUV || tests[i].flags & TEST_NO_PLANES)
> +				igt_require(igt_display_has_format_mod(display,
> +							DRM_FORMAT_NV12,
> +							DRM_FORMAT_MOD_LINEAR));
> +
> +			for_each_pipe_with_single_output(&data.display, pipe, output) {
> +
> +				igt_display_reset(display);
> +
> +				igt_output_set_pipe(output, pipe);
> +				if (!intel_pipe_output_combo_valid(display))
> +					continue;
> +
> +				/* Skip TEST_NO_PLANES if the ASIC has less than 3 overlay planes*/
> +				if (tests[i].flags & TEST_NO_PLANES)
> +					igt_require(get_overlay_planes_count(&data.display, pipe) >= 3);
> +
> +				/* Skip TEST_MAX_PLANES if the ASIC has less than 2 overlay planes*/
> +				if (tests[i].flags & TEST_MAX_PLANES)
> +					igt_require(get_overlay_planes_count(&data.display, pipe) >= 2);

The skip checks here don't quite make sense, see comment above.

Thanks,
Leo

> +
> +				test_init(&data, pipe, output, tests[i].flags);
> +
> +				for (j = 0; j < ARRAY_SIZE(cursor_sizes); j++) {
> +					int size = cursor_sizes[j];
> +
> +					igt_dynamic_f("pipe-%s-%s-size-%d",
> +						      kmstest_pipe_name(pipe),
> +						      igt_output_name(output),
> +						      size)
> +						test_cursor(&data, size, tests[i].flags, tests[i].scale_factor);
> +
> +					test_cleanup(&data);
> +				}
> +
> +				test_fini(&data);
> +			}
> +		}
> +	}
> +
> +	igt_fixture {
> +		igt_display_fini(&data.display);
> +		drm_close_driver(data.drm_fd);
> +	}
> +}
> diff --git a/tests/amdgpu/meson.build b/tests/amdgpu/meson.build
> index 421e686d3..b9f1842e2 100644
> --- a/tests/amdgpu/meson.build
> +++ b/tests/amdgpu/meson.build
> @@ -10,6 +10,7 @@ if libdrm_amdgpu.found()
>  			  'amd_color',
>  			  'amd_cp_dma_misc',
>  			  'amd_cs_nop',
> +			  'amd_cursor_overlay',
>  			  'amd_deadlock',
>  			  'amd_dp_dsc',
>  			  'amd_freesync_video_mode',



More information about the amd-gfx mailing list