Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0
2 : /*
3 : * Test cases for the drm_rect functions
4 : *
5 : * Copyright (c) 2022 MaĆra Canal <mairacanal@riseup.net>
6 : */
7 :
8 : #include <kunit/test.h>
9 :
10 : #include <drm/drm_rect.h>
11 : #include <drm/drm_mode.h>
12 :
13 : #include <linux/string_helpers.h>
14 : #include <linux/errno.h>
15 :
16 25 : static void drm_rect_compare(struct kunit *test, const struct drm_rect *r,
17 : const struct drm_rect *expected)
18 : {
19 25 : KUNIT_EXPECT_EQ(test, r->x1, expected->x1);
20 25 : KUNIT_EXPECT_EQ(test, r->y1, expected->y1);
21 75 : KUNIT_EXPECT_EQ(test, drm_rect_width(r), drm_rect_width(expected));
22 75 : KUNIT_EXPECT_EQ(test, drm_rect_height(r), drm_rect_height(expected));
23 25 : }
24 :
25 1 : static void drm_test_rect_clip_scaled_div_by_zero(struct kunit *test)
26 : {
27 : struct drm_rect src, dst, clip;
28 : bool visible;
29 :
30 : /*
31 : * Make sure we don't divide by zero when dst
32 : * width/height is zero and dst and clip do not intersect.
33 : */
34 1 : drm_rect_init(&src, 0, 0, 0, 0);
35 1 : drm_rect_init(&dst, 0, 0, 0, 0);
36 1 : drm_rect_init(&clip, 1, 1, 1, 1);
37 1 : visible = drm_rect_clip_scaled(&src, &dst, &clip);
38 :
39 1 : KUNIT_EXPECT_FALSE_MSG(test, visible, "Destination not be visible\n");
40 1 : KUNIT_EXPECT_FALSE_MSG(test, drm_rect_visible(&src), "Source should not be visible\n");
41 :
42 1 : drm_rect_init(&src, 0, 0, 0, 0);
43 1 : drm_rect_init(&dst, 3, 3, 0, 0);
44 1 : drm_rect_init(&clip, 1, 1, 1, 1);
45 1 : visible = drm_rect_clip_scaled(&src, &dst, &clip);
46 :
47 1 : KUNIT_EXPECT_FALSE_MSG(test, visible, "Destination not be visible\n");
48 1 : KUNIT_EXPECT_FALSE_MSG(test, drm_rect_visible(&src), "Source should not be visible\n");
49 1 : }
50 :
51 1 : static void drm_test_rect_clip_scaled_not_clipped(struct kunit *test)
52 : {
53 : struct drm_rect src, dst, clip;
54 : bool visible;
55 :
56 : /* 1:1 scaling */
57 1 : drm_rect_init(&src, 0, 0, 1 << 16, 1 << 16);
58 1 : drm_rect_init(&dst, 0, 0, 1, 1);
59 1 : drm_rect_init(&clip, 0, 0, 1, 1);
60 :
61 1 : visible = drm_rect_clip_scaled(&src, &dst, &clip);
62 :
63 1 : KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 1 << 16 ||
64 : src.y1 != 0 || src.y2 != 1 << 16, "Source badly clipped\n");
65 1 : KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 ||
66 : dst.y1 != 0 || dst.y2 != 1, "Destination badly clipped\n");
67 1 : KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
68 1 : KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
69 :
70 : /* 2:1 scaling */
71 1 : drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
72 1 : drm_rect_init(&dst, 0, 0, 1, 1);
73 1 : drm_rect_init(&clip, 0, 0, 1, 1);
74 :
75 1 : visible = drm_rect_clip_scaled(&src, &dst, &clip);
76 :
77 1 : KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 2 << 16 ||
78 : src.y1 != 0 || src.y2 != 2 << 16, "Source badly clipped\n");
79 1 : KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 ||
80 : dst.y1 != 0 || dst.y2 != 1, "Destination badly clipped\n");
81 1 : KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
82 1 : KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
83 :
84 : /* 1:2 scaling */
85 1 : drm_rect_init(&src, 0, 0, 1 << 16, 1 << 16);
86 1 : drm_rect_init(&dst, 0, 0, 2, 2);
87 1 : drm_rect_init(&clip, 0, 0, 2, 2);
88 :
89 1 : visible = drm_rect_clip_scaled(&src, &dst, &clip);
90 :
91 1 : KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 1 << 16 ||
92 : src.y1 != 0 || src.y2 != 1 << 16, "Source badly clipped\n");
93 1 : KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 2 ||
94 : dst.y1 != 0 || dst.y2 != 2, "Destination badly clipped\n");
95 1 : KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
96 1 : KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
97 1 : }
98 :
99 1 : static void drm_test_rect_clip_scaled_clipped(struct kunit *test)
100 : {
101 : struct drm_rect src, dst, clip;
102 : bool visible;
103 :
104 : /* 1:1 scaling top/left clip */
105 1 : drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
106 1 : drm_rect_init(&dst, 0, 0, 2, 2);
107 : drm_rect_init(&clip, 0, 0, 1, 1);
108 :
109 1 : visible = drm_rect_clip_scaled(&src, &dst, &clip);
110 :
111 1 : KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 1 << 16 ||
112 : src.y1 != 0 || src.y2 != 1 << 16, "Source badly clipped\n");
113 1 : KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 ||
114 : dst.y1 != 0 || dst.y2 != 1, "Destination badly clipped\n");
115 1 : KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
116 1 : KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
117 :
118 : /* 1:1 scaling bottom/right clip */
119 1 : drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
120 1 : drm_rect_init(&dst, 0, 0, 2, 2);
121 1 : drm_rect_init(&clip, 1, 1, 1, 1);
122 :
123 1 : visible = drm_rect_clip_scaled(&src, &dst, &clip);
124 :
125 1 : KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 1 << 16 || src.x2 != 2 << 16 ||
126 : src.y1 != 1 << 16 || src.y2 != 2 << 16, "Source badly clipped\n");
127 1 : KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 1 || dst.x2 != 2 || dst.y1 != 1 ||
128 : dst.y2 != 2, "Destination badly clipped\n");
129 1 : KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
130 1 : KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
131 :
132 : /* 2:1 scaling top/left clip */
133 1 : drm_rect_init(&src, 0, 0, 4 << 16, 4 << 16);
134 1 : drm_rect_init(&dst, 0, 0, 2, 2);
135 1 : drm_rect_init(&clip, 0, 0, 1, 1);
136 :
137 1 : visible = drm_rect_clip_scaled(&src, &dst, &clip);
138 :
139 1 : KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 2 << 16 ||
140 : src.y1 != 0 || src.y2 != 2 << 16, "Source badly clipped\n");
141 1 : KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 || dst.y1 != 0 ||
142 : dst.y2 != 1, "Destination badly clipped\n");
143 1 : KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
144 1 : KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
145 :
146 : /* 2:1 scaling bottom/right clip */
147 1 : drm_rect_init(&src, 0, 0, 4 << 16, 4 << 16);
148 1 : drm_rect_init(&dst, 0, 0, 2, 2);
149 1 : drm_rect_init(&clip, 1, 1, 1, 1);
150 :
151 1 : visible = drm_rect_clip_scaled(&src, &dst, &clip);
152 :
153 1 : KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 2 << 16 || src.x2 != 4 << 16 ||
154 : src.y1 != 2 << 16 || src.y2 != 4 << 16, "Source badly clipped\n");
155 1 : KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 1 || dst.x2 != 2 || dst.y1 != 1 ||
156 : dst.y2 != 2, "Destination badly clipped\n");
157 1 : KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
158 1 : KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
159 :
160 : /* 1:2 scaling top/left clip */
161 1 : drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
162 1 : drm_rect_init(&dst, 0, 0, 4, 4);
163 1 : drm_rect_init(&clip, 0, 0, 2, 2);
164 :
165 1 : visible = drm_rect_clip_scaled(&src, &dst, &clip);
166 :
167 1 : KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 1 << 16 ||
168 : src.y1 != 0 || src.y2 != 1 << 16, "Source badly clipped\n");
169 1 : KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 2 || dst.y1 != 0 ||
170 : dst.y2 != 2, "Destination badly clipped\n");
171 1 : KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
172 1 : KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
173 :
174 : /* 1:2 scaling bottom/right clip */
175 1 : drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
176 1 : drm_rect_init(&dst, 0, 0, 4, 4);
177 1 : drm_rect_init(&clip, 2, 2, 2, 2);
178 :
179 1 : visible = drm_rect_clip_scaled(&src, &dst, &clip);
180 :
181 1 : KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 1 << 16 || src.x2 != 2 << 16 ||
182 : src.y1 != 1 << 16 || src.y2 != 2 << 16, "Source badly clipped\n");
183 1 : KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 2 || dst.x2 != 4 || dst.y1 != 2 ||
184 : dst.y2 != 4, "Destination badly clipped\n");
185 1 : KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
186 1 : KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
187 1 : }
188 :
189 1 : static void drm_test_rect_clip_scaled_signed_vs_unsigned(struct kunit *test)
190 : {
191 : struct drm_rect src, dst, clip;
192 : bool visible;
193 :
194 : /*
195 : * 'clip.x2 - dst.x1 >= dst width' could result a negative
196 : * src rectangle width which is no longer expected by the
197 : * code as it's using unsigned types. This could lead to
198 : * the clipped source rectangle appering visible when it
199 : * should have been fully clipped. Make sure both rectangles
200 : * end up invisible.
201 : */
202 1 : drm_rect_init(&src, 0, 0, INT_MAX, INT_MAX);
203 1 : drm_rect_init(&dst, 0, 0, 2, 2);
204 1 : drm_rect_init(&clip, 3, 3, 1, 1);
205 :
206 1 : visible = drm_rect_clip_scaled(&src, &dst, &clip);
207 :
208 1 : KUNIT_EXPECT_FALSE_MSG(test, visible, "Destination should not be visible\n");
209 1 : KUNIT_EXPECT_FALSE_MSG(test, drm_rect_visible(&src), "Source should not be visible\n");
210 1 : }
211 :
212 : struct drm_rect_intersect_case {
213 : const char *description;
214 : struct drm_rect r1, r2;
215 : bool should_be_visible;
216 : struct drm_rect expected_intersection;
217 : };
218 :
219 : static const struct drm_rect_intersect_case drm_rect_intersect_cases[] = {
220 : {
221 : .description = "top-left X bottom-right",
222 : .r1 = DRM_RECT_INIT(1, 1, 2, 2),
223 : .r2 = DRM_RECT_INIT(0, 0, 2, 2),
224 : .should_be_visible = true,
225 : .expected_intersection = DRM_RECT_INIT(1, 1, 1, 1),
226 : },
227 : {
228 : .description = "top-right X bottom-left",
229 : .r1 = DRM_RECT_INIT(0, 0, 2, 2),
230 : .r2 = DRM_RECT_INIT(1, -1, 2, 2),
231 : .should_be_visible = true,
232 : .expected_intersection = DRM_RECT_INIT(1, 0, 1, 1),
233 : },
234 : {
235 : .description = "bottom-left X top-right",
236 : .r1 = DRM_RECT_INIT(1, -1, 2, 2),
237 : .r2 = DRM_RECT_INIT(0, 0, 2, 2),
238 : .should_be_visible = true,
239 : .expected_intersection = DRM_RECT_INIT(1, 0, 1, 1),
240 : },
241 : {
242 : .description = "bottom-right X top-left",
243 : .r1 = DRM_RECT_INIT(0, 0, 2, 2),
244 : .r2 = DRM_RECT_INIT(1, 1, 2, 2),
245 : .should_be_visible = true,
246 : .expected_intersection = DRM_RECT_INIT(1, 1, 1, 1),
247 : },
248 : {
249 : .description = "right X left",
250 : .r1 = DRM_RECT_INIT(0, 0, 2, 1),
251 : .r2 = DRM_RECT_INIT(1, 0, 3, 1),
252 : .should_be_visible = true,
253 : .expected_intersection = DRM_RECT_INIT(1, 0, 1, 1),
254 : },
255 : {
256 : .description = "left X right",
257 : .r1 = DRM_RECT_INIT(1, 0, 3, 1),
258 : .r2 = DRM_RECT_INIT(0, 0, 2, 1),
259 : .should_be_visible = true,
260 : .expected_intersection = DRM_RECT_INIT(1, 0, 1, 1),
261 : },
262 : {
263 : .description = "up X bottom",
264 : .r1 = DRM_RECT_INIT(0, 0, 1, 2),
265 : .r2 = DRM_RECT_INIT(0, -1, 1, 3),
266 : .should_be_visible = true,
267 : .expected_intersection = DRM_RECT_INIT(0, 0, 1, 2),
268 : },
269 : {
270 : .description = "bottom X up",
271 : .r1 = DRM_RECT_INIT(0, -1, 1, 3),
272 : .r2 = DRM_RECT_INIT(0, 0, 1, 2),
273 : .should_be_visible = true,
274 : .expected_intersection = DRM_RECT_INIT(0, 0, 1, 2),
275 : },
276 : {
277 : .description = "touching corner",
278 : .r1 = DRM_RECT_INIT(0, 0, 1, 1),
279 : .r2 = DRM_RECT_INIT(1, 1, 2, 2),
280 : .should_be_visible = false,
281 : .expected_intersection = DRM_RECT_INIT(1, 1, 0, 0),
282 : },
283 : {
284 : .description = "touching side",
285 : .r1 = DRM_RECT_INIT(0, 0, 1, 1),
286 : .r2 = DRM_RECT_INIT(1, 0, 1, 1),
287 : .should_be_visible = false,
288 : .expected_intersection = DRM_RECT_INIT(1, 0, 0, 1),
289 : },
290 : {
291 : .description = "equal rects",
292 : .r1 = DRM_RECT_INIT(0, 0, 2, 2),
293 : .r2 = DRM_RECT_INIT(0, 0, 2, 2),
294 : .should_be_visible = true,
295 : .expected_intersection = DRM_RECT_INIT(0, 0, 2, 2),
296 : },
297 : {
298 : .description = "inside another",
299 : .r1 = DRM_RECT_INIT(0, 0, 2, 2),
300 : .r2 = DRM_RECT_INIT(1, 1, 1, 1),
301 : .should_be_visible = true,
302 : .expected_intersection = DRM_RECT_INIT(1, 1, 1, 1),
303 : },
304 : {
305 : .description = "far away",
306 : .r1 = DRM_RECT_INIT(0, 0, 1, 1),
307 : .r2 = DRM_RECT_INIT(3, 6, 1, 1),
308 : .should_be_visible = false,
309 : .expected_intersection = DRM_RECT_INIT(3, 6, -2, -5),
310 : },
311 : };
312 :
313 13 : static void drm_rect_intersect_case_desc(const struct drm_rect_intersect_case *t, char *desc)
314 : {
315 13 : if (!t->description)
316 0 : snprintf(desc, KUNIT_PARAM_DESC_SIZE,
317 : DRM_RECT_FMT " X " DRM_RECT_FMT,
318 : DRM_RECT_ARG(&t->r1), DRM_RECT_ARG(&t->r2));
319 : else
320 65 : snprintf(desc, KUNIT_PARAM_DESC_SIZE,
321 : "%s: " DRM_RECT_FMT " X " DRM_RECT_FMT,
322 : t->description, DRM_RECT_ARG(&t->r1), DRM_RECT_ARG(&t->r2));
323 13 : }
324 :
325 14 : KUNIT_ARRAY_PARAM(drm_rect_intersect, drm_rect_intersect_cases, drm_rect_intersect_case_desc);
326 :
327 13 : static void drm_test_rect_intersect(struct kunit *test)
328 : {
329 13 : const struct drm_rect_intersect_case *params = test->param_value;
330 13 : struct drm_rect r1_aux = params->r1;
331 : bool visible;
332 :
333 13 : visible = drm_rect_intersect(&r1_aux, ¶ms->r2);
334 :
335 13 : KUNIT_EXPECT_EQ(test, visible, params->should_be_visible);
336 13 : drm_rect_compare(test, &r1_aux, ¶ms->expected_intersection);
337 13 : }
338 :
339 1 : static void drm_test_rect_calc_hscale(struct kunit *test)
340 : {
341 : struct drm_rect src, dst;
342 : int scaling_factor;
343 :
344 1 : drm_rect_init(&src, 0, 0, 2 << 16, 0);
345 1 : drm_rect_init(&dst, 0, 0, 1 << 16, 0);
346 :
347 1 : scaling_factor = drm_rect_calc_hscale(&src, &dst, 0, INT_MAX);
348 :
349 1 : KUNIT_EXPECT_EQ(test, scaling_factor, 2);
350 1 : }
351 :
352 1 : static void drm_test_rect_calc_hscale_out_of_range(struct kunit *test)
353 : {
354 : struct drm_rect src, dst;
355 : int scaling_factor;
356 :
357 1 : drm_rect_init(&src, 0, 0, 10 << 16, 0);
358 1 : drm_rect_init(&dst, 0, 0, 1 << 16, 0);
359 :
360 1 : scaling_factor = drm_rect_calc_hscale(&src, &dst, 3, 5);
361 :
362 1 : KUNIT_EXPECT_EQ(test, scaling_factor, -ERANGE);
363 :
364 1 : drm_rect_init(&src, 0, 0, 2 << 16, 0);
365 1 : drm_rect_init(&dst, 0, 0, 1 << 16, 0);
366 :
367 1 : scaling_factor = drm_rect_calc_hscale(&src, &dst, 3, 5);
368 :
369 1 : KUNIT_EXPECT_EQ(test, scaling_factor, -ERANGE);
370 1 : }
371 :
372 1 : static void drm_test_rect_calc_hscale_negative_args(struct kunit *test)
373 : {
374 : struct drm_rect src, dst;
375 : int scaling_factor;
376 :
377 1 : drm_rect_init(&src, 0, 0, -1 << 16, 0);
378 1 : drm_rect_init(&dst, 0, 0, 1 << 16, 0);
379 :
380 1 : scaling_factor = drm_rect_calc_hscale(&src, &dst, 0, INT_MAX);
381 :
382 1 : KUNIT_EXPECT_EQ(test, scaling_factor, -EINVAL);
383 :
384 1 : drm_rect_init(&src, 0, 0, 1 << 16, 0);
385 1 : drm_rect_init(&dst, 0, 0, -1 << 16, 0);
386 :
387 1 : scaling_factor = drm_rect_calc_hscale(&src, &dst, 0, INT_MAX);
388 :
389 1 : KUNIT_EXPECT_EQ(test, scaling_factor, -EINVAL);
390 1 : }
391 :
392 1 : static void drm_test_rect_calc_vscale(struct kunit *test)
393 : {
394 : struct drm_rect src, dst;
395 : int scaling_factor;
396 :
397 1 : drm_rect_init(&src, 0, 0, 0, 2 << 16);
398 1 : drm_rect_init(&dst, 0, 0, 0, 1 << 16);
399 :
400 1 : scaling_factor = drm_rect_calc_vscale(&src, &dst, 0, INT_MAX);
401 :
402 1 : KUNIT_EXPECT_EQ(test, scaling_factor, 2);
403 1 : }
404 :
405 1 : static void drm_test_rect_calc_vscale_out_of_range(struct kunit *test)
406 : {
407 : struct drm_rect src, dst;
408 : int scaling_factor;
409 :
410 1 : drm_rect_init(&src, 0, 0, 0, 10 << 16);
411 1 : drm_rect_init(&dst, 0, 0, 0, 1 << 16);
412 :
413 1 : scaling_factor = drm_rect_calc_vscale(&src, &dst, 3, 5);
414 :
415 1 : KUNIT_EXPECT_EQ(test, scaling_factor, -ERANGE);
416 :
417 1 : drm_rect_init(&src, 0, 0, 0, 2 << 16);
418 1 : drm_rect_init(&dst, 0, 0, 0, 1 << 16);
419 :
420 1 : scaling_factor = drm_rect_calc_vscale(&src, &dst, 3, 5);
421 :
422 1 : KUNIT_EXPECT_EQ(test, scaling_factor, -ERANGE);
423 1 : }
424 :
425 1 : static void drm_test_rect_calc_vscale_negative_args(struct kunit *test)
426 : {
427 : struct drm_rect src, dst;
428 : int scaling_factor;
429 :
430 1 : drm_rect_init(&src, 0, 0, 0, -1 << 16);
431 1 : drm_rect_init(&dst, 0, 0, 0, 1 << 16);
432 :
433 1 : scaling_factor = drm_rect_calc_vscale(&src, &dst, 0, INT_MAX);
434 :
435 1 : KUNIT_EXPECT_EQ(test, scaling_factor, -EINVAL);
436 :
437 1 : drm_rect_init(&src, 0, 0, 0, 1 << 16);
438 1 : drm_rect_init(&dst, 0, 0, 0, -1 << 16);
439 :
440 1 : scaling_factor = drm_rect_calc_vscale(&src, &dst, 0, INT_MAX);
441 :
442 1 : KUNIT_EXPECT_EQ(test, scaling_factor, -EINVAL);
443 1 : }
444 :
445 : struct drm_rect_rotate_case {
446 : const char *name;
447 : unsigned int rotation;
448 : struct drm_rect rect;
449 : int width, height;
450 : struct drm_rect expected;
451 : };
452 :
453 : static const struct drm_rect_rotate_case drm_rect_rotate_cases[] = {
454 : {
455 : .name = "reflect x",
456 : .rotation = DRM_MODE_REFLECT_X,
457 : .rect = DRM_RECT_INIT(0, 0, 5, 5),
458 : .width = 5, .height = 10,
459 : .expected = DRM_RECT_INIT(0, 0, 5, 5),
460 : },
461 : {
462 : .name = "reflect y",
463 : .rotation = DRM_MODE_REFLECT_Y,
464 : .rect = DRM_RECT_INIT(0, 0, 5, 5),
465 : .width = 5, .height = 10,
466 : .expected = DRM_RECT_INIT(0, 5, 5, 5),
467 : },
468 : {
469 : .name = "rotate 0",
470 : .rotation = DRM_MODE_ROTATE_0,
471 : .rect = DRM_RECT_INIT(0, 0, 5, 5),
472 : .width = 5, .height = 10,
473 : .expected = DRM_RECT_INIT(0, 0, 5, 5),
474 : },
475 : {
476 : .name = "rotate 90",
477 : .rotation = DRM_MODE_ROTATE_90,
478 : .rect = DRM_RECT_INIT(0, 0, 5, 10),
479 : .width = 5, .height = 10,
480 : .expected = DRM_RECT_INIT(0, 0, 10, 5),
481 : },
482 : {
483 : .name = "rotate 180",
484 : .rotation = DRM_MODE_ROTATE_180,
485 : .rect = DRM_RECT_INIT(0, 0, 5, 10),
486 : .width = 5, .height = 10,
487 : .expected = DRM_RECT_INIT(0, 0, 5, 10),
488 : },
489 : {
490 : .name = "rotate 270",
491 : .rotation = DRM_MODE_ROTATE_270,
492 : .rect = DRM_RECT_INIT(0, 0, 5, 10),
493 : .width = 5, .height = 10,
494 : .expected = DRM_RECT_INIT(0, 0, 10, 5),
495 : },
496 : };
497 :
498 12 : static void drm_rect_case_desc(const struct drm_rect_rotate_case *t, char *desc)
499 : {
500 12 : strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
501 12 : }
502 :
503 14 : KUNIT_ARRAY_PARAM(drm_rect_rotate, drm_rect_rotate_cases, drm_rect_case_desc);
504 :
505 6 : static void drm_test_rect_rotate(struct kunit *test)
506 : {
507 6 : const struct drm_rect_rotate_case *params = test->param_value;
508 6 : struct drm_rect r = params->rect;
509 :
510 6 : drm_rect_rotate(&r, params->width, params->height, params->rotation);
511 :
512 6 : drm_rect_compare(test, &r, ¶ms->expected);
513 6 : }
514 :
515 6 : static void drm_test_rect_rotate_inv(struct kunit *test)
516 : {
517 6 : const struct drm_rect_rotate_case *params = test->param_value;
518 6 : struct drm_rect r = params->expected;
519 :
520 6 : drm_rect_rotate_inv(&r, params->width, params->height, params->rotation);
521 :
522 6 : drm_rect_compare(test, &r, ¶ms->rect);
523 6 : }
524 :
525 : static struct kunit_case drm_rect_tests[] = {
526 : KUNIT_CASE(drm_test_rect_clip_scaled_div_by_zero),
527 : KUNIT_CASE(drm_test_rect_clip_scaled_not_clipped),
528 : KUNIT_CASE(drm_test_rect_clip_scaled_clipped),
529 : KUNIT_CASE(drm_test_rect_clip_scaled_signed_vs_unsigned),
530 : KUNIT_CASE_PARAM(drm_test_rect_intersect, drm_rect_intersect_gen_params),
531 : KUNIT_CASE(drm_test_rect_calc_hscale),
532 : KUNIT_CASE(drm_test_rect_calc_hscale_out_of_range),
533 : KUNIT_CASE(drm_test_rect_calc_hscale_negative_args),
534 : KUNIT_CASE(drm_test_rect_calc_vscale),
535 : KUNIT_CASE(drm_test_rect_calc_vscale_out_of_range),
536 : KUNIT_CASE(drm_test_rect_calc_vscale_negative_args),
537 : KUNIT_CASE_PARAM(drm_test_rect_rotate, drm_rect_rotate_gen_params),
538 : KUNIT_CASE_PARAM(drm_test_rect_rotate_inv, drm_rect_rotate_gen_params),
539 : { }
540 : };
541 :
542 : static struct kunit_suite drm_rect_test_suite = {
543 : .name = "drm_rect",
544 : .test_cases = drm_rect_tests,
545 : };
546 :
547 : kunit_test_suite(drm_rect_test_suite);
548 :
549 : MODULE_LICENSE("GPL");
|