On 2026-01-07 22:07, [email protected] wrote:
> From: Ivan Lipski <[email protected]>
> 
> [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 <[email protected]>

Thanks for the test!
Reviewed-by: Leo Li <[email protected]>

- 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',

Reply via email to