LCOV - code coverage report
Current view: top level - drivers/gpu/drm/tests - drm_plane_helper_test.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 52 52 100.0 %
Date: 2023-07-19 18:55:55 Functions: 8 8 100.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Test cases for the drm_plane_helper functions
       4             :  *
       5             :  * Copyright (c) 2022 MaĆ­ra Canal <mairacanal@riseup.net>
       6             :  */
       7             : 
       8             : #include <kunit/test.h>
       9             : 
      10             : #include <drm/drm_atomic_helper.h>
      11             : #include <drm/drm_framebuffer.h>
      12             : #include <drm/drm_modes.h>
      13             : #include <drm/drm_rect.h>
      14             : 
      15             : static const struct drm_crtc_state crtc_state = {
      16             :         .crtc = ZERO_SIZE_PTR,
      17             :         .enable = true,
      18             :         .active = true,
      19             :         .mode = {
      20             :                 DRM_MODE("1024x768", 0, 65000, 1024, 1048,
      21             :                          1184, 1344, 0, 768, 771, 777, 806, 0,
      22             :                          DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC)
      23             :         },
      24             : };
      25             : 
      26             : struct drm_check_plane_state_test {
      27             :         const char *name;
      28             :         const char *msg;
      29             :         struct {
      30             :                 unsigned int x;
      31             :                 unsigned int y;
      32             :                 unsigned int w;
      33             :                 unsigned int h;
      34             :         } src, src_expected;
      35             :         struct {
      36             :                 int x;
      37             :                 int y;
      38             :                 unsigned int w;
      39             :                 unsigned int h;
      40             :         } crtc, crtc_expected;
      41             :         unsigned int rotation;
      42             :         int min_scale;
      43             :         int max_scale;
      44             :         bool can_position;
      45             : };
      46             : 
      47          12 : static int drm_plane_helper_init(struct kunit *test)
      48             : {
      49          12 :         const struct drm_check_plane_state_test *params = test->param_value;
      50             :         struct drm_plane *plane;
      51             :         struct drm_framebuffer *fb;
      52             :         struct drm_plane_state *mock;
      53             : 
      54          12 :         plane = kunit_kzalloc(test, sizeof(*plane), GFP_KERNEL);
      55          12 :         KUNIT_ASSERT_NOT_NULL(test, plane);
      56             : 
      57          12 :         fb = kunit_kzalloc(test, sizeof(*fb), GFP_KERNEL);
      58          12 :         KUNIT_ASSERT_NOT_NULL(test, fb);
      59          12 :         fb->width = 2048;
      60          12 :         fb->height = 2048;
      61             : 
      62          12 :         mock = kunit_kzalloc(test, sizeof(*mock), GFP_KERNEL);
      63          12 :         KUNIT_ASSERT_NOT_NULL(test, mock);
      64          12 :         mock->plane = plane;
      65          12 :         mock->crtc = ZERO_SIZE_PTR;
      66          12 :         mock->fb = fb;
      67          12 :         mock->rotation = params->rotation;
      68          12 :         mock->src_x = params->src.x;
      69          12 :         mock->src_y = params->src.y;
      70          12 :         mock->src_w = params->src.w;
      71          12 :         mock->src_h = params->src.h;
      72          12 :         mock->crtc_x = params->crtc.x;
      73          12 :         mock->crtc_y = params->crtc.y;
      74          12 :         mock->crtc_w = params->crtc.w;
      75          12 :         mock->crtc_h = params->crtc.h;
      76             : 
      77          12 :         test->priv = mock;
      78             : 
      79          12 :         return 0;
      80             : }
      81             : 
      82           9 : static void check_src_eq(struct kunit *test, struct drm_plane_state *plane_state,
      83             :                          unsigned int src_x, unsigned int src_y,
      84             :                          unsigned int src_w, unsigned int src_h)
      85             : {
      86           9 :         struct drm_rect expected = DRM_RECT_INIT(src_x, src_y, src_w, src_h);
      87             : 
      88           9 :         KUNIT_ASSERT_GE_MSG(test, plane_state->src.x1, 0,
      89             :                             "src x coordinate %x should never be below 0, src: " DRM_RECT_FP_FMT,
      90             :                             plane_state->src.x1, DRM_RECT_FP_ARG(&plane_state->src));
      91             : 
      92           9 :         KUNIT_ASSERT_GE_MSG(test, plane_state->src.y1, 0,
      93             :                             "src y coordinate %x should never be below 0, src: " DRM_RECT_FP_FMT,
      94             :                             plane_state->src.y1, DRM_RECT_FP_ARG(&plane_state->src));
      95             : 
      96          18 :         KUNIT_EXPECT_TRUE_MSG(test, drm_rect_equals(&plane_state->src, &expected),
      97             :                               "dst: " DRM_RECT_FP_FMT ", expected: " DRM_RECT_FP_FMT,
      98             :                               DRM_RECT_FP_ARG(&plane_state->src), DRM_RECT_FP_ARG(&expected));
      99           9 : }
     100             : 
     101           9 : static void check_crtc_eq(struct kunit *test, struct drm_plane_state *plane_state,
     102             :                           int crtc_x, int crtc_y,
     103             :                           unsigned int crtc_w, unsigned int crtc_h)
     104             : {
     105           9 :         struct drm_rect expected = DRM_RECT_INIT(crtc_x, crtc_y, crtc_w, crtc_h);
     106             : 
     107          18 :         KUNIT_EXPECT_TRUE_MSG(test, drm_rect_equals(&plane_state->dst, &expected),
     108             :                               "dst: " DRM_RECT_FMT ", expected: " DRM_RECT_FMT,
     109             :                               DRM_RECT_ARG(&plane_state->dst), DRM_RECT_ARG(&expected));
     110           9 : }
     111             : 
     112           9 : static void drm_test_check_plane_state(struct kunit *test)
     113             : {
     114           9 :         const struct drm_check_plane_state_test *params = test->param_value;
     115           9 :         struct drm_plane_state *plane_state = test->priv;
     116             : 
     117           9 :         KUNIT_ASSERT_EQ_MSG(test,
     118             :                             drm_atomic_helper_check_plane_state(plane_state, &crtc_state,
     119             :                                                                 params->min_scale,
     120             :                                                                 params->max_scale,
     121             :                                                                 params->can_position, false),
     122             :                             0, params->msg);
     123           9 :         KUNIT_EXPECT_TRUE(test, plane_state->visible);
     124           9 :         check_src_eq(test, plane_state, params->src_expected.x, params->src_expected.y,
     125             :                      params->src_expected.w, params->src_expected.h);
     126           9 :         check_crtc_eq(test, plane_state, params->crtc_expected.x, params->crtc_expected.y,
     127             :                       params->crtc_expected.w, params->crtc_expected.h);
     128           9 : }
     129             : 
     130          12 : static void drm_check_plane_state_desc(const struct drm_check_plane_state_test *t,
     131             :                                        char *desc)
     132             : {
     133          12 :         sprintf(desc, "%s", t->name);
     134          12 : }
     135             : 
     136             : static const struct drm_check_plane_state_test drm_check_plane_state_tests[] = {
     137             :         {
     138             :                 .name = "clipping_simple",
     139             :                 .msg = "Simple clipping check should pass",
     140             :                 .src = { 0, 0,
     141             :                          2048 << 16,
     142             :                          2048 << 16 },
     143             :                 .crtc = { 0, 0, 2048, 2048 },
     144             :                 .rotation = DRM_MODE_ROTATE_0,
     145             :                 .min_scale = DRM_PLANE_NO_SCALING,
     146             :                 .max_scale = DRM_PLANE_NO_SCALING,
     147             :                 .can_position = false,
     148             :                 .src_expected = { 0, 0, 1024 << 16, 768 << 16 },
     149             :                 .crtc_expected = { 0, 0, 1024, 768 },
     150             :         },
     151             :         {
     152             :                 .name = "clipping_rotate_reflect",
     153             :                 .msg = "Rotated clipping check should pass",
     154             :                 .src = { 0, 0,
     155             :                          2048 << 16,
     156             :                          2048 << 16 },
     157             :                 .crtc = { 0, 0, 2048, 2048 },
     158             :                 .rotation = DRM_MODE_ROTATE_90 | DRM_MODE_REFLECT_X,
     159             :                 .min_scale = DRM_PLANE_NO_SCALING,
     160             :                 .max_scale = DRM_PLANE_NO_SCALING,
     161             :                 .can_position = false,
     162             :                 .src_expected = { 0, 0, 768 << 16, 1024 << 16 },
     163             :                 .crtc_expected = { 0, 0, 1024, 768 },
     164             :         },
     165             :         {
     166             :                 .name = "positioning_simple",
     167             :                 .msg = "Simple positioning should work",
     168             :                 .src = { 0, 0, 1023 << 16, 767 << 16 },
     169             :                 .crtc = { 0, 0, 1023, 767 },
     170             :                 .rotation = DRM_MODE_ROTATE_0,
     171             :                 .min_scale = DRM_PLANE_NO_SCALING,
     172             :                 .max_scale = DRM_PLANE_NO_SCALING,
     173             :                 .can_position = true,
     174             :                 .src_expected = { 0, 0, 1023 << 16, 767 << 16 },
     175             :                 .crtc_expected = { 0, 0, 1023, 767 },
     176             :         },
     177             :         {
     178             :                 .name = "upscaling",
     179             :                 .msg = "Upscaling exactly 2x should work",
     180             :                 .src = { 0, 0, 512 << 16, 384 << 16 },
     181             :                 .crtc = { 0, 0, 1024, 768 },
     182             :                 .rotation = DRM_MODE_ROTATE_0,
     183             :                 .min_scale = 0x8000,
     184             :                 .max_scale = DRM_PLANE_NO_SCALING,
     185             :                 .can_position = false,
     186             :                 .src_expected = { 0, 0, 512 << 16, 384 << 16 },
     187             :                 .crtc_expected = { 0, 0, 1024, 768 },
     188             :         },
     189             :         {
     190             :                 .name = "downscaling",
     191             :                 .msg = "Should succeed with exact scaling limit",
     192             :                 .src = { 0, 0, 2048 << 16, 1536 << 16 },
     193             :                 .crtc = { 0, 0, 1024, 768 },
     194             :                 .rotation = DRM_MODE_ROTATE_0,
     195             :                 .min_scale = DRM_PLANE_NO_SCALING,
     196             :                 .max_scale = 0x20000,
     197             :                 .can_position = false,
     198             :                 .src_expected = { 0, 0, 2048 << 16, 1536 << 16 },
     199             :                 .crtc_expected = { 0, 0, 1024, 768 },
     200             :         },
     201             :         {
     202             :                 .name = "rounding1",
     203             :                 .msg = "Should succeed by clipping to exact multiple",
     204             :                 .src = { 0, 0, 0x40001, 0x40001 },
     205             :                 .crtc = { 1022, 766, 4, 4 },
     206             :                 .rotation = DRM_MODE_ROTATE_0,
     207             :                 .min_scale = DRM_PLANE_NO_SCALING,
     208             :                 .max_scale = 0x10001,
     209             :                 .can_position = true,
     210             :                 .src_expected = { 0, 0, 2 << 16, 2 << 16 },
     211             :                 .crtc_expected = { 1022, 766, 2, 2 },
     212             :         },
     213             :         {
     214             :                 .name = "rounding2",
     215             :                 .msg = "Should succeed by clipping to exact multiple",
     216             :                 .src = { 0x20001, 0x20001, 0x4040001, 0x3040001 },
     217             :                 .crtc = { -2, -2, 1028, 772 },
     218             :                 .rotation = DRM_MODE_ROTATE_0,
     219             :                 .min_scale = DRM_PLANE_NO_SCALING,
     220             :                 .max_scale = 0x10001,
     221             :                 .can_position = false,
     222             :                 .src_expected = { 0x40002, 0x40002, 1024 << 16, 768 << 16 },
     223             :                 .crtc_expected = { 0, 0, 1024, 768 },
     224             :         },
     225             :         {
     226             :                 .name = "rounding3",
     227             :                 .msg = "Should succeed by clipping to exact multiple",
     228             :                 .src = { 0, 0, 0x3ffff, 0x3ffff },
     229             :                 .crtc = { 1022, 766, 4, 4 },
     230             :                 .rotation = DRM_MODE_ROTATE_0,
     231             :                 .min_scale = 0xffff,
     232             :                 .max_scale = DRM_PLANE_NO_SCALING,
     233             :                 .can_position = true,
     234             :                 /* Should not be rounded to 0x20001, which would be upscaling. */
     235             :                 .src_expected = { 0, 0, 2 << 16, 2 << 16 },
     236             :                 .crtc_expected = { 1022, 766, 2, 2 },
     237             :         },
     238             :         {
     239             :                 .name = "rounding4",
     240             :                 .msg = "Should succeed by clipping to exact multiple",
     241             :                 .src = { 0x1ffff, 0x1ffff, 0x403ffff, 0x303ffff },
     242             :                 .crtc = { -2, -2, 1028, 772 },
     243             :                 .rotation = DRM_MODE_ROTATE_0,
     244             :                 .min_scale = 0xffff,
     245             :                 .max_scale = DRM_PLANE_NO_SCALING,
     246             :                 .can_position = false,
     247             :                 .src_expected = { 0x3fffe, 0x3fffe, 1024 << 16, 768 << 16 },
     248             :                 .crtc_expected = { 0, 0, 1024, 768 },
     249             :         },
     250             : };
     251             : 
     252          10 : KUNIT_ARRAY_PARAM(drm_check_plane_state, drm_check_plane_state_tests, drm_check_plane_state_desc);
     253             : 
     254           3 : static void drm_test_check_invalid_plane_state(struct kunit *test)
     255             : {
     256           3 :         const struct drm_check_plane_state_test *params = test->param_value;
     257           3 :         struct drm_plane_state *plane_state = test->priv;
     258             : 
     259           3 :         KUNIT_ASSERT_LT_MSG(test,
     260             :                             drm_atomic_helper_check_plane_state(plane_state, &crtc_state,
     261             :                                                                 params->min_scale,
     262             :                                                                 params->max_scale,
     263             :                                                                 params->can_position, false),
     264             :                             0, params->msg);
     265           3 : }
     266             : 
     267             : static const struct drm_check_plane_state_test drm_check_invalid_plane_state_tests[] = {
     268             :         {
     269             :                 .name = "positioning_invalid",
     270             :                 .msg = "Should not be able to position on the crtc with can_position=false",
     271             :                 .src = { 0, 0, 1023 << 16, 767 << 16 },
     272             :                 .crtc = { 0, 0, 1023, 767 },
     273             :                 .rotation = DRM_MODE_ROTATE_0,
     274             :                 .min_scale = DRM_PLANE_NO_SCALING,
     275             :                 .max_scale = DRM_PLANE_NO_SCALING,
     276             :                 .can_position = false,
     277             :         },
     278             :         {
     279             :                 .name = "upscaling_invalid",
     280             :                 .msg = "Upscaling out of range should fail",
     281             :                 .src = { 0, 0, 512 << 16, 384 << 16 },
     282             :                 .crtc = { 0, 0, 1024, 768 },
     283             :                 .rotation = DRM_MODE_ROTATE_0,
     284             :                 .min_scale = 0x8001,
     285             :                 .max_scale = DRM_PLANE_NO_SCALING,
     286             :                 .can_position = false,
     287             :         },
     288             :         {
     289             :                 .name = "downscaling_invalid",
     290             :                 .msg = "Downscaling out of range should fail",
     291             :                 .src = { 0, 0, 2048 << 16, 1536 << 16 },
     292             :                 .crtc = { 0, 0, 1024, 768 },
     293             :                 .rotation = DRM_MODE_ROTATE_0,
     294             :                 .min_scale = DRM_PLANE_NO_SCALING,
     295             :                 .max_scale = 0x1ffff,
     296             :                 .can_position = false,
     297             :         },
     298             : };
     299             : 
     300           4 : KUNIT_ARRAY_PARAM(drm_check_invalid_plane_state, drm_check_invalid_plane_state_tests,
     301             :                   drm_check_plane_state_desc);
     302             : 
     303             : static struct kunit_case drm_plane_helper_test[] = {
     304             :         KUNIT_CASE_PARAM(drm_test_check_plane_state, drm_check_plane_state_gen_params),
     305             :         KUNIT_CASE_PARAM(drm_test_check_invalid_plane_state,
     306             :                          drm_check_invalid_plane_state_gen_params),
     307             :         {}
     308             : };
     309             : 
     310             : static struct kunit_suite drm_plane_helper_test_suite = {
     311             :         .name = "drm_plane_helper",
     312             :         .init = drm_plane_helper_init,
     313             :         .test_cases = drm_plane_helper_test,
     314             : };
     315             : 
     316             : kunit_test_suite(drm_plane_helper_test_suite);
     317             : 
     318             : MODULE_LICENSE("GPL");

Generated by: LCOV version 1.14