On 2025-07-23 13:27, ivan.lip...@amd.com wrote:
> From: Ivan Lipski <ivan.lip...@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.lip...@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',

Reply via email to