public inbox for igt-dev@lists.freedesktop.org
 help / color / mirror / Atom feed
From: Leo Li <sunpeng.li@amd.com>
To: <IVAN.LIPSKI@amd.com>, <igt-dev@lists.freedesktop.org>
Cc: <harry.wentland@amd.com>, <amd-gfx@lists.freedesktop.org>
Subject: Re: [PATCH i-g-t] tests/amdgpu: Add test for native cursor fallback to overlay
Date: Mon, 12 Jan 2026 09:35:26 -0500	[thread overview]
Message-ID: <066cd83a-752b-4e2c-b5ef-34c5d8555305@amd.com> (raw)
In-Reply-To: <20260108030750.1012908-1-IVAN.LIPSKI@amd.com>



On 2026-01-07 22:07, IVAN.LIPSKI@amd.com wrote:
> From: Ivan Lipski <ivan.lipski@amd.com>
> 
> [Why & How]
> The AMD display hardware does not use dedicated cursor planes.
> Instead, the cursor is rendered either using the primary plane (native)
> or an available overlay plane (overlay). This test verifies that the
> cursor correctly falls back from native to overlay mode
> when the underneath primary plane is incompatible.
> It has 5 subtests:
> 
> rgb-to-yuv
> Switches the primary plane to a YUV format FB and verifies that
> the cursor falls back from primary to overlay plane. Uses CRC to verify
> that the cursor fall back to overlay plane is successful.
> 
> non-full
> Switches the primary plane to a FB that does not fill the entire CRTC, not
> underneath the cursor to trigger the fall back from native to overlay
> plane. Uses CRC to verify that the cursor fall back to overlay plane is
> successful.
> 
> 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. Uses CRC to verify that the cursor fall back
> to overlay plane is successful.
> 
> max-planes
> Enables all but one overlay planes, a primary plane and a cursor above
> the primary plane. Then switches the primary plane to YUV to cause the
> cursor to fall back to use an overlay plane. Uses CRC to verify that the
> cursor fall back to overlay plane is successful.
> 
> no-available-planes
> Enables all available overlay planes, a primary plane and a cursor above
> the primary plane. 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.
> NOTE: This subtest is currently only available for DCN 2.1 & DCN 3.5 AMD
> APU's.
> 
> Signed-off-by: Ivan Lipski <ivan.lipski@amd.com>

Thanks for the test!
Reviewed-by: Leo Li <sunpeng.li@amd.com>

- Leo

> ---
>  tests/amdgpu/amd_cursor_overlay.c | 529 ++++++++++++++++++++++++++++++
>  tests/amdgpu/meson.build          |   1 +
>  2 files changed, 530 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..481219f9f
> --- /dev/null
> +++ b/tests/amdgpu/amd_cursor_overlay.c
> @@ -0,0 +1,529 @@
> +// SPDX-License-Identifier: MIT
> +// Copyright 2025 Advanced Micro Devices, Inc.
> +
> +#include "igt.h"
> +#include "igt_kms.h"
> +#include "amdgpu_drm.h"
> +#include "amdgpu.h"
> +
> +/*
> + * Only two ASICs of FAMILY_RV are DCN 2.1.
> + * They can be determined by their external chip revision.
> + *
> + * This is necessary to determine if the NO_AVAILABLE_PLANES subtest is
> + * applicable to the ASIC under test.
> + *
> + * NOTE: Copied from dal_asic_id.h in AMD's display driver on Linux.
> + */
> +#define ASICREV_IS_RENOIR(eChipRev) ((eChipRev >= 0x91) && (eChipRev < 0xF0))
> +#define ASICREV_IS_GREEN_SARDINE(eChipRev) ((eChipRev >= 0xA1) && (eChipRev < 0xFF))
> +
> +
> +/**
> + * 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 all but one overlay planes are used.
> + *
> + * SUBTEST: no-available-planes
> + * Description: Tests native cursor attempt to fall back to overlay cursor,
> + *				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_AVAILABLE_PLANES = 1 << 4,
> +};
> +
> +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 *overlays[6];
> +	igt_output_t *output;
> +	igt_crtc_t *pipe;
> +	igt_pipe_crc_t *pipe_crc;
> +	drmModeModeInfo *mode;
> +	igt_fb_t rgb_fb;
> +	igt_fb_t rgb_fb_o;
> +	igt_fb_t yuv_fb;
> +	igt_fb_t quarter_fb;
> +	igt_fb_t scale_fb;
> +	igt_fb_t cfb;
> +	enum pipe pipe_id;
> +	int drm_fd;
> +	int available_overlay_planes;
> +	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;
> +}
> +
> +/* Sets all overlay planes to the given fb and position, then commits. */
> +static void set_overlay_planes(data_t *data, int count, igt_fb_t *fb, int x, int y)
> +{
> +	for (int i = 0; i < count; i++) {
> +		igt_plane_set_fb(data->overlays[i], fb);
> +		igt_plane_set_position(data->overlays[i], x, y);
> +	}
> +	igt_display_commit_atomic(&data->display, 0, NULL);
> +}
> +
> +/*
> + * Checks the ASIC has enough overlay planes and from a supported family.
> + *
> + * Currently TEST_NO_AVAILABLE_PLANES subtest is only
> + * applicable to DCN 2.1 & DCN 3.5+ APUs.
> + */
> +static bool can_support_all_overlay_planes(int available_overlay_planes, int family_id, int chip_rev_id)
> +{
> +	/* For now we only support ASICs with 3 overlay planes. */
> +	if (available_overlay_planes != 3)
> +		return false;
> +
> +	switch (family_id) {
> +	case AMDGPU_FAMILY_RV:
> +		return (ASICREV_IS_RENOIR(chip_rev_id) ||
> +			ASICREV_IS_GREEN_SARDINE(chip_rev_id));
> +	case AMDGPU_FAMILY_GC_11_5_0:
> +		return true;
> +	default:
> +		return false;
> +	}
> +}
> +
> +/* Common test setup. */
> +static void test_init(data_t *data, enum pipe pipe_id, igt_output_t *output,
> +		      unsigned int flags, int available_overlay_planes)
> +{
> +	int i;
> +
> +	data->pipe_id = pipe_id;
> +	data->available_overlay_planes = available_overlay_planes;
> +	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_MAX_PLANES)
> +		for (i = 0; i < available_overlay_planes - 1; i++)
> +			data->overlays[i] = igt_pipe_get_plane_type_index(data->pipe,
> +						DRM_PLANE_TYPE_OVERLAY, i);
> +	if (flags & TEST_NO_AVAILABLE_PLANES)
> +		for (i = 0; i < available_overlay_planes; i++)
> +			data->overlays[i] = igt_pipe_get_plane_type_index(data->pipe,
> +						DRM_PLANE_TYPE_OVERLAY, i);
> +
> +	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)
> +{
> +	/* Free CRC collector first */
> +	igt_pipe_crc_free(data->pipe_crc);
> +
> +	/* Clear all planes */
> +	igt_plane_set_fb(data->primary, NULL);
> +	igt_plane_set_fb(data->cursor, NULL);
> +
> +	for (int i = 0; i < data->available_overlay_planes; i++)
> +		if (data->overlays[i])
> +			igt_plane_set_fb(data->overlays[i], NULL);
> +
> +	/* Commit the cleared plane state before resetting the graph */
> +	igt_display_commit2(&data->display, COMMIT_ATOMIC);
> +
> +	/* Reset the display graph after committing the null state */
> +	igt_display_reset(&data->display);
> +}
> +
> +/* 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->rgb_fb_o);
> +	igt_remove_fb(data->drm_fd, &data->yuv_fb);
> +	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)
> +{
> +	igt_crc_t ref_crc, test_crc;
> +	cairo_t *cr;
> +	igt_fb_t *rgb_fb = &data->rgb_fb;
> +	igt_fb_t *rgb_fb_o = &data->rgb_fb_o;
> +	igt_fb_t *yuv_fb = &data->yuv_fb;
> +	igt_fb_t *quarter_fb = &data->quarter_fb;
> +	igt_fb_t *cfb = &data->cfb;
> +	igt_fb_t *scale_fb = &data->scale_fb;
> +	int cw = cfb->width;
> +	int ch = cfb->height;
> +	int available_overlay_planes = data->available_overlay_planes;
> +	int opp_x, opp_y, 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);
> +
> +	/* 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);
> +
> +	/* Place the overlay plane on the opposite quarter of the screen from the cursor. */
> +	if (flags & TEST_MAX_PLANES ||
> +	    flags & TEST_NO_AVAILABLE_PLANES ||
> +	    flags & TEST_QUARTER_FB) {
> +		opp_x = x < (data->mode->hdisplay / 2) ? (data->mode->hdisplay / 2) : 0;
> +		opp_y = y < (data->mode->vdisplay / 2) ? (data->mode->vdisplay / 2) : 0;
> +	}
> +
> +	if (flags & TEST_NO_AVAILABLE_PLANES) {
> +
> +		/* Display the overlay planes. */
> +		set_overlay_planes(data, available_overlay_planes, rgb_fb_o, opp_x, opp_y);
> +
> +		/*
> +		 * 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);
> +
> +		/* Expected atomic commit to fail due to no available overlay planes. */
> +		igt_assert_f(ret == -EINVAL,
> +			"Expected commit fail due to no available overlay planes.\n");
> +
> +		/* Exit early. */
> +		return;
> +	}
> +
> +	/* Display the overlay planes as a reference for TEST_MAX_PLANES. */
> +	if (flags & TEST_MAX_PLANES) {
> +		/* Display the overlay planes. */
> +		set_overlay_planes(data, available_overlay_planes - 1, rgb_fb_o, opp_x, opp_y);
> +	}
> +
> +	/** 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 YUV FB for TEST_YUV and TEST_MAX_PLANES. */
> +	if (flags & TEST_YUV || flags & TEST_MAX_PLANES) {
> +		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, opposite from cursor. */
> +	} else if (flags & TEST_QUARTER_FB) {
> +		igt_plane_set_fb(data->primary, quarter_fb);
> +		igt_plane_set_position(data->primary, opp_x, opp_y);
> +		igt_display_commit_atomic(&data->display, 0, NULL);
> +
> +	/* Switch primary plane to use a scaled FB. */
> +	} else if (flags & TEST_SCALING) {
> +		igt_plane_set_fb(data->primary, 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(igt_crtc_for_pipe(&data->display, data->pipe_id), 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)
> +{
> +	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);
> +}
> +
> +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 primary FB. */
> +	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 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);
> +
> +	/* Create YUV FB for RGB-to-YUV, MAX_PLANES and NO_AVAILABLE_PLANES subtests */
> +	if (flags & TEST_YUV ||
> +	    flags & TEST_MAX_PLANES ||
> +	    flags & TEST_NO_AVAILABLE_PLANES)
> +		igt_create_fb(data->drm_fd, sw, sh, DRM_FORMAT_NV12,
> +					DRM_FORMAT_MOD_NONE, &data->yuv_fb);
> +
> +	/* Create a quarter-sized 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 a FB for scaling. */
> +	if (flags & TEST_SCALING)
> +		igt_create_color_fb(data->drm_fd, (sw * scaling_factor) / 100, (sh * scaling_factor) / 100, DRM_FORMAT_XRGB8888,
> +					DRM_FORMAT_MOD_LINEAR, 0.0, 0.0, 0.0, &data->scale_fb);
> +
> +	/*
> +	 * Create RGB FB for overlay planes for MAX_PLANES and
> +	 * NO_AVAILABLE_PLANES subtests.
> +	 *
> +	 * The overlay FB size is quarter the screen size to ensure that
> +	 * the cursor can be placed on the primary plane to trigger fall back.
> +	 */
> +	if (flags & TEST_MAX_PLANES || flags & TEST_NO_AVAILABLE_PLANES) {
> +		/* Create RGB FB for overlay planes. */
> +		igt_create_color_fb(data->drm_fd, sw / 2, sh / 2, DRM_FORMAT_XRGB8888,
> +					DRM_FORMAT_MOD_LINEAR, 0.0, 1.0, 0.0, &data->rgb_fb_o);
> +	}
> +
> +	igt_output_set_crtc(data->output,
> +		igt_crtc_for_pipe(data->output->display, data->pipe_id));
> +
> +	/* Run the test for different cursor spots. */
> +	test_cursor_spots(data, size, flags);
> +}
> +
> +int 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, available_overlay_planes;
> +	int ret, err, family_id, chip_rev_id;
> +	uint32_t major, minor;
> +	amdgpu_device_handle device;
> +	struct amdgpu_gpu_info gpu_info = {0};
> +	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 all but one overlay planes used."},
> +		{"no-available-planes", TEST_NO_AVAILABLE_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() {
> +
> +		/* Initialize the driver and retrieve GPU info. */
> +		data.drm_fd = drm_open_driver_master(DRIVER_AMDGPU);
> +		err = amdgpu_device_initialize(data.drm_fd, &major, &minor, &device);
> +		igt_require(err == 0);
> +
> +		err = amdgpu_query_gpu_info(device, &gpu_info);
> +		igt_require(err == 0);
> +
> +		family_id = gpu_info.family_id;
> +		chip_rev_id = gpu_info.chip_external_rev;
> +
> +		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, MAX_PLANES and NO_AVAILABLE_PLANES subtests
> +			 * if YUV is not supported.
> +			 */
> +			if (tests[i].flags & TEST_YUV ||
> +			    tests[i].flags & TEST_MAX_PLANES ||
> +			    tests[i].flags & TEST_NO_AVAILABLE_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_crtc(output,
> +					igt_crtc_for_pipe(output->display, pipe));
> +
> +				available_overlay_planes = get_overlay_planes_count(display, pipe);
> +
> +				/* Require at least one overlay plane. */
> +				if (!available_overlay_planes)
> +					igt_skip("%s subtest requires at least 1 overlay plane.\n",
> +						 tests[i].name);
> +
> +				/*
> +				 * For now, NO_AVAILABLE_PLANES substest is only appropriate for
> +				 * AMD ASICs with 3 overlay planes and with DCN 2.1 & 3.5+ APU's.
> +				 */
> +				if (tests[i].flags & TEST_NO_AVAILABLE_PLANES &&
> +				    !can_support_all_overlay_planes(available_overlay_planes, family_id, chip_rev_id))
> +					igt_skip("%s subtest requires 3 overlay planes with a supported DCN.\n",
> +						 tests[i].name);
> +
> +				test_init(&data, pipe, output, tests[i].flags, available_overlay_planes);
> +
> +				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);
> +
> +				/* Detach output and commit a clean state before moving to the next subtest */
> +				igt_output_set_crtc(output, NULL);
> +				igt_display_commit2(&data.display, COMMIT_ATOMIC);
> +			}
> +		}
> +	}
> +
> +	igt_fixture() {
> +
> +		igt_display_reset(&data.display);
> +		igt_display_commit2(&data.display, COMMIT_ATOMIC);
> +		igt_display_fini(&data.display);
> +		drm_close_driver(data.drm_fd);
> +	}
> +}
> diff --git a/tests/amdgpu/meson.build b/tests/amdgpu/meson.build
> index b718699f1..01c8b4fec 100644
> --- a/tests/amdgpu/meson.build
> +++ b/tests/amdgpu/meson.build
> @@ -12,6 +12,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',


  parent reply	other threads:[~2026-01-12 14:35 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-08  3:07 [PATCH i-g-t] tests/amdgpu: Add test for native cursor fallback to overlay IVAN.LIPSKI
2026-01-08  4:10 ` ✓ Xe.CI.BAT: success for tests/amdgpu: Add test for native cursor fallback to overlay (rev5) Patchwork
2026-01-08  4:30 ` ✗ i915.CI.BAT: failure " Patchwork
2026-01-08  5:27 ` ✓ Xe.CI.Full: success " Patchwork
2026-01-12 14:35 ` Leo Li [this message]
  -- strict thread matches above, loose matches on Subject: below --
2025-07-17 20:41 [PATCH i-g-t] tests/amdgpu: Add test for native cursor fallback to overlay IVAN.LIPSKI
2025-07-18 15:37 ` Kamil Konieczny

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=066cd83a-752b-4e2c-b5ef-34c5d8555305@amd.com \
    --to=sunpeng.li@amd.com \
    --cc=IVAN.LIPSKI@amd.com \
    --cc=amd-gfx@lists.freedesktop.org \
    --cc=harry.wentland@amd.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