]> Git Repo - linux.git/blob - drivers/gpu/drm/tests/drm_plane_helper_test.c
Linux 6.14-rc3
[linux.git] / drivers / gpu / drm / tests / drm_plane_helper_test.c
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 <[email protected]>
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 static int drm_plane_helper_init(struct kunit *test)
48 {
49         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         plane = kunit_kzalloc(test, sizeof(*plane), GFP_KERNEL);
55         KUNIT_ASSERT_NOT_NULL(test, plane);
56
57         fb = kunit_kzalloc(test, sizeof(*fb), GFP_KERNEL);
58         KUNIT_ASSERT_NOT_NULL(test, fb);
59         fb->width = 2048;
60         fb->height = 2048;
61
62         mock = kunit_kzalloc(test, sizeof(*mock), GFP_KERNEL);
63         KUNIT_ASSERT_NOT_NULL(test, mock);
64         mock->plane = plane;
65         mock->crtc = ZERO_SIZE_PTR;
66         mock->fb = fb;
67         mock->rotation = params->rotation;
68         mock->src_x = params->src.x;
69         mock->src_y = params->src.y;
70         mock->src_w = params->src.w;
71         mock->src_h = params->src.h;
72         mock->crtc_x = params->crtc.x;
73         mock->crtc_y = params->crtc.y;
74         mock->crtc_w = params->crtc.w;
75         mock->crtc_h = params->crtc.h;
76
77         test->priv = mock;
78
79         return 0;
80 }
81
82 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         struct drm_rect expected = DRM_RECT_INIT(src_x, src_y, src_w, src_h);
87
88         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         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         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 }
100
101 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         struct drm_rect expected = DRM_RECT_INIT(crtc_x, crtc_y, crtc_w, crtc_h);
106
107         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 }
111
112 static void drm_test_check_plane_state(struct kunit *test)
113 {
114         const struct drm_check_plane_state_test *params = test->param_value;
115         struct drm_plane_state *plane_state = test->priv;
116
117         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         KUNIT_EXPECT_TRUE(test, plane_state->visible);
124         check_src_eq(test, plane_state, params->src_expected.x, params->src_expected.y,
125                      params->src_expected.w, params->src_expected.h);
126         check_crtc_eq(test, plane_state, params->crtc_expected.x, params->crtc_expected.y,
127                       params->crtc_expected.w, params->crtc_expected.h);
128 }
129
130 static void drm_check_plane_state_desc(const struct drm_check_plane_state_test *t,
131                                        char *desc)
132 {
133         sprintf(desc, "%s", t->name);
134 }
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 KUNIT_ARRAY_PARAM(drm_check_plane_state, drm_check_plane_state_tests, drm_check_plane_state_desc);
253
254 static void drm_test_check_invalid_plane_state(struct kunit *test)
255 {
256         const struct drm_check_plane_state_test *params = test->param_value;
257         struct drm_plane_state *plane_state = test->priv;
258
259         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 }
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 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_DESCRIPTION("Test cases for the drm_plane_helper functions");
319 MODULE_LICENSE("GPL");
This page took 0.049122 seconds and 4 git commands to generate.