linux/drivers/gpu/drm/selftests/test-drm_plane_helper.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Test cases for the drm_plane_helper functions
   4 */
   5
   6#define pr_fmt(fmt) "drm_plane_helper: " fmt
   7
   8#include <drm/drm_atomic_helper.h>
   9#include <drm/drm_plane_helper.h>
  10#include <drm/drm_modes.h>
  11
  12#include "test-drm_modeset_common.h"
  13
  14static void set_src(struct drm_plane_state *plane_state,
  15                    unsigned src_x, unsigned src_y,
  16                    unsigned src_w, unsigned src_h)
  17{
  18        plane_state->src_x = src_x;
  19        plane_state->src_y = src_y;
  20        plane_state->src_w = src_w;
  21        plane_state->src_h = src_h;
  22}
  23
  24static bool check_src_eq(struct drm_plane_state *plane_state,
  25                         unsigned src_x, unsigned src_y,
  26                         unsigned src_w, unsigned src_h)
  27{
  28        if (plane_state->src.x1 < 0) {
  29                pr_err("src x coordinate %x should never be below 0.\n", plane_state->src.x1);
  30                drm_rect_debug_print("src: ", &plane_state->src, true);
  31                return false;
  32        }
  33        if (plane_state->src.y1 < 0) {
  34                pr_err("src y coordinate %x should never be below 0.\n", plane_state->src.y1);
  35                drm_rect_debug_print("src: ", &plane_state->src, true);
  36                return false;
  37        }
  38
  39        if (plane_state->src.x1 != src_x ||
  40            plane_state->src.y1 != src_y ||
  41            drm_rect_width(&plane_state->src) != src_w ||
  42            drm_rect_height(&plane_state->src) != src_h) {
  43                drm_rect_debug_print("src: ", &plane_state->src, true);
  44                return false;
  45        }
  46
  47        return true;
  48}
  49
  50static void set_crtc(struct drm_plane_state *plane_state,
  51                     int crtc_x, int crtc_y,
  52                     unsigned crtc_w, unsigned crtc_h)
  53{
  54        plane_state->crtc_x = crtc_x;
  55        plane_state->crtc_y = crtc_y;
  56        plane_state->crtc_w = crtc_w;
  57        plane_state->crtc_h = crtc_h;
  58}
  59
  60static bool check_crtc_eq(struct drm_plane_state *plane_state,
  61                          int crtc_x, int crtc_y,
  62                          unsigned crtc_w, unsigned crtc_h)
  63{
  64        if (plane_state->dst.x1 != crtc_x ||
  65            plane_state->dst.y1 != crtc_y ||
  66            drm_rect_width(&plane_state->dst) != crtc_w ||
  67            drm_rect_height(&plane_state->dst) != crtc_h) {
  68                drm_rect_debug_print("dst: ", &plane_state->dst, false);
  69
  70                return false;
  71        }
  72
  73        return true;
  74}
  75
  76int igt_check_plane_state(void *ignored)
  77{
  78        int ret;
  79
  80        const struct drm_crtc_state crtc_state = {
  81                .crtc = ZERO_SIZE_PTR,
  82                .enable = true,
  83                .active = true,
  84                .mode = {
  85                        DRM_MODE("1024x768", 0, 65000, 1024, 1048,
  86                                1184, 1344, 0, 768, 771, 777, 806, 0,
  87                                DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC)
  88                },
  89        };
  90        struct drm_framebuffer fb = {
  91                .width = 2048,
  92                .height = 2048
  93        };
  94        struct drm_plane_state plane_state = {
  95                .crtc = ZERO_SIZE_PTR,
  96                .fb = &fb,
  97                .rotation = DRM_MODE_ROTATE_0
  98        };
  99
 100        /* Simple clipping, no scaling. */
 101        set_src(&plane_state, 0, 0, fb.width << 16, fb.height << 16);
 102        set_crtc(&plane_state, 0, 0, fb.width, fb.height);
 103        ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
 104                                                  DRM_PLANE_HELPER_NO_SCALING,
 105                                                  DRM_PLANE_HELPER_NO_SCALING,
 106                                                  false, false);
 107        FAIL(ret < 0, "Simple clipping check should pass\n");
 108        FAIL_ON(!plane_state.visible);
 109        FAIL_ON(!check_src_eq(&plane_state, 0, 0, 1024 << 16, 768 << 16));
 110        FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
 111
 112        /* Rotated clipping + reflection, no scaling. */
 113        plane_state.rotation = DRM_MODE_ROTATE_90 | DRM_MODE_REFLECT_X;
 114        ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
 115                                                  DRM_PLANE_HELPER_NO_SCALING,
 116                                                  DRM_PLANE_HELPER_NO_SCALING,
 117                                                  false, false);
 118        FAIL(ret < 0, "Rotated clipping check should pass\n");
 119        FAIL_ON(!plane_state.visible);
 120        FAIL_ON(!check_src_eq(&plane_state, 0, 0, 768 << 16, 1024 << 16));
 121        FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
 122        plane_state.rotation = DRM_MODE_ROTATE_0;
 123
 124        /* Check whether positioning works correctly. */
 125        set_src(&plane_state, 0, 0, 1023 << 16, 767 << 16);
 126        set_crtc(&plane_state, 0, 0, 1023, 767);
 127        ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
 128                                                  DRM_PLANE_HELPER_NO_SCALING,
 129                                                  DRM_PLANE_HELPER_NO_SCALING,
 130                                                  false, false);
 131        FAIL(!ret, "Should not be able to position on the crtc with can_position=false\n");
 132
 133        ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
 134                                                  DRM_PLANE_HELPER_NO_SCALING,
 135                                                  DRM_PLANE_HELPER_NO_SCALING,
 136                                                  true, false);
 137        FAIL(ret < 0, "Simple positioning should work\n");
 138        FAIL_ON(!plane_state.visible);
 139        FAIL_ON(!check_src_eq(&plane_state, 0, 0, 1023 << 16, 767 << 16));
 140        FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1023, 767));
 141
 142        /* Simple scaling tests. */
 143        set_src(&plane_state, 0, 0, 512 << 16, 384 << 16);
 144        set_crtc(&plane_state, 0, 0, 1024, 768);
 145        ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
 146                                                  0x8001,
 147                                                  DRM_PLANE_HELPER_NO_SCALING,
 148                                                  false, false);
 149        FAIL(!ret, "Upscaling out of range should fail.\n");
 150        ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
 151                                                  0x8000,
 152                                                  DRM_PLANE_HELPER_NO_SCALING,
 153                                                  false, false);
 154        FAIL(ret < 0, "Upscaling exactly 2x should work\n");
 155        FAIL_ON(!plane_state.visible);
 156        FAIL_ON(!check_src_eq(&plane_state, 0, 0, 512 << 16, 384 << 16));
 157        FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
 158
 159        set_src(&plane_state, 0, 0, 2048 << 16, 1536 << 16);
 160        ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
 161                                                  DRM_PLANE_HELPER_NO_SCALING,
 162                                                  0x1ffff, false, false);
 163        FAIL(!ret, "Downscaling out of range should fail.\n");
 164        ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
 165                                                  DRM_PLANE_HELPER_NO_SCALING,
 166                                                  0x20000, false, false);
 167        FAIL(ret < 0, "Should succeed with exact scaling limit\n");
 168        FAIL_ON(!plane_state.visible);
 169        FAIL_ON(!check_src_eq(&plane_state, 0, 0, 2048 << 16, 1536 << 16));
 170        FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
 171
 172        /* Testing rounding errors. */
 173        set_src(&plane_state, 0, 0, 0x40001, 0x40001);
 174        set_crtc(&plane_state, 1022, 766, 4, 4);
 175        ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
 176                                                  DRM_PLANE_HELPER_NO_SCALING,
 177                                                  0x10001,
 178                                                  true, false);
 179        FAIL(ret < 0, "Should succeed by clipping to exact multiple");
 180        FAIL_ON(!plane_state.visible);
 181        FAIL_ON(!check_src_eq(&plane_state, 0, 0, 2 << 16, 2 << 16));
 182        FAIL_ON(!check_crtc_eq(&plane_state, 1022, 766, 2, 2));
 183
 184        set_src(&plane_state, 0x20001, 0x20001, 0x4040001, 0x3040001);
 185        set_crtc(&plane_state, -2, -2, 1028, 772);
 186        ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
 187                                                  DRM_PLANE_HELPER_NO_SCALING,
 188                                                  0x10001,
 189                                                  false, false);
 190        FAIL(ret < 0, "Should succeed by clipping to exact multiple");
 191        FAIL_ON(!plane_state.visible);
 192        FAIL_ON(!check_src_eq(&plane_state, 0x40002, 0x40002, 1024 << 16, 768 << 16));
 193        FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
 194
 195        set_src(&plane_state, 0, 0, 0x3ffff, 0x3ffff);
 196        set_crtc(&plane_state, 1022, 766, 4, 4);
 197        ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
 198                                                  0xffff,
 199                                                  DRM_PLANE_HELPER_NO_SCALING,
 200                                                  true, false);
 201        FAIL(ret < 0, "Should succeed by clipping to exact multiple");
 202        FAIL_ON(!plane_state.visible);
 203        /* Should not be rounded to 0x20001, which would be upscaling. */
 204        FAIL_ON(!check_src_eq(&plane_state, 0, 0, 2 << 16, 2 << 16));
 205        FAIL_ON(!check_crtc_eq(&plane_state, 1022, 766, 2, 2));
 206
 207        set_src(&plane_state, 0x1ffff, 0x1ffff, 0x403ffff, 0x303ffff);
 208        set_crtc(&plane_state, -2, -2, 1028, 772);
 209        ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
 210                                                  0xffff,
 211                                                  DRM_PLANE_HELPER_NO_SCALING,
 212                                                  false, false);
 213        FAIL(ret < 0, "Should succeed by clipping to exact multiple");
 214        FAIL_ON(!plane_state.visible);
 215        FAIL_ON(!check_src_eq(&plane_state, 0x3fffe, 0x3fffe, 1024 << 16, 768 << 16));
 216        FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
 217
 218        return 0;
 219}
 220