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 27 : static void drm_rect_compare(struct kunit *test, const struct drm_rect *r,
17 : const struct drm_rect *expected)
18 : {
19 27 : KUNIT_EXPECT_EQ(test, r->x1, expected->x1);
20 27 : KUNIT_EXPECT_EQ(test, r->y1, expected->y1);
21 81 : KUNIT_EXPECT_EQ(test, drm_rect_width(r), drm_rect_width(expected));
22 81 : KUNIT_EXPECT_EQ(test, drm_rect_height(r), drm_rect_height(expected));
23 27 : }
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 : .description = "points intersecting",
313 : .r1 = DRM_RECT_INIT(5, 10, 0, 0),
314 : .r2 = DRM_RECT_INIT(5, 10, 0, 0),
315 : .should_be_visible = false,
316 : .expected_intersection = DRM_RECT_INIT(5, 10, 0, 0),
317 : },
318 : {
319 : .description = "points not intersecting",
320 : .r1 = DRM_RECT_INIT(0, 0, 0, 0),
321 : .r2 = DRM_RECT_INIT(5, 10, 0, 0),
322 : .should_be_visible = false,
323 : .expected_intersection = DRM_RECT_INIT(5, 10, -5, -10),
324 : },
325 : };
326 :
327 15 : static void drm_rect_intersect_case_desc(const struct drm_rect_intersect_case *t, char *desc)
328 : {
329 75 : snprintf(desc, KUNIT_PARAM_DESC_SIZE,
330 : "%s: " DRM_RECT_FMT " x " DRM_RECT_FMT,
331 : t->description, DRM_RECT_ARG(&t->r1), DRM_RECT_ARG(&t->r2));
332 15 : }
333 :
334 16 : KUNIT_ARRAY_PARAM(drm_rect_intersect, drm_rect_intersect_cases, drm_rect_intersect_case_desc);
335 :
336 15 : static void drm_test_rect_intersect(struct kunit *test)
337 : {
338 15 : const struct drm_rect_intersect_case *params = test->param_value;
339 15 : struct drm_rect r1_aux = params->r1;
340 : bool visible;
341 :
342 15 : visible = drm_rect_intersect(&r1_aux, ¶ms->r2);
343 :
344 15 : KUNIT_EXPECT_EQ(test, visible, params->should_be_visible);
345 15 : drm_rect_compare(test, &r1_aux, ¶ms->expected_intersection);
346 15 : }
347 :
348 : struct drm_rect_scale_case {
349 : const char *name;
350 : struct drm_rect src, dst;
351 : int min_range, max_range;
352 : int expected_scaling_factor;
353 : };
354 :
355 : static const struct drm_rect_scale_case drm_rect_hscale_cases[] = {
356 : {
357 : .name = "normal use",
358 : .src = DRM_RECT_INIT(0, 0, 2 << 16, 0),
359 : .dst = DRM_RECT_INIT(0, 0, 1 << 16, 0),
360 : .min_range = 0, .max_range = INT_MAX,
361 : .expected_scaling_factor = 2,
362 : },
363 : {
364 : .name = "out of max range",
365 : .src = DRM_RECT_INIT(0, 0, 10 << 16, 0),
366 : .dst = DRM_RECT_INIT(0, 0, 1 << 16, 0),
367 : .min_range = 3, .max_range = 5,
368 : .expected_scaling_factor = -ERANGE,
369 : },
370 : {
371 : .name = "out of min range",
372 : .src = DRM_RECT_INIT(0, 0, 2 << 16, 0),
373 : .dst = DRM_RECT_INIT(0, 0, 1 << 16, 0),
374 : .min_range = 3, .max_range = 5,
375 : .expected_scaling_factor = -ERANGE,
376 : },
377 : {
378 : .name = "zero dst width",
379 : .src = DRM_RECT_INIT(0, 0, 2 << 16, 0),
380 : .dst = DRM_RECT_INIT(0, 0, 0 << 16, 0),
381 : .min_range = 0, .max_range = INT_MAX,
382 : .expected_scaling_factor = 0,
383 : },
384 : {
385 : .name = "negative src width",
386 : .src = DRM_RECT_INIT(0, 0, -(1 << 16), 0),
387 : .dst = DRM_RECT_INIT(0, 0, 1 << 16, 0),
388 : .min_range = 0, .max_range = INT_MAX,
389 : .expected_scaling_factor = -EINVAL,
390 : },
391 : {
392 : .name = "negative dst width",
393 : .src = DRM_RECT_INIT(0, 0, 1 << 16, 0),
394 : .dst = DRM_RECT_INIT(0, 0, -(1 << 16), 0),
395 : .min_range = 0, .max_range = INT_MAX,
396 : .expected_scaling_factor = -EINVAL,
397 : },
398 : };
399 :
400 12 : static void drm_rect_scale_case_desc(const struct drm_rect_scale_case *t, char *desc)
401 : {
402 12 : strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
403 12 : }
404 :
405 7 : KUNIT_ARRAY_PARAM(drm_rect_hscale, drm_rect_hscale_cases, drm_rect_scale_case_desc);
406 :
407 6 : static void drm_test_rect_calc_hscale(struct kunit *test)
408 : {
409 6 : const struct drm_rect_scale_case *params = test->param_value;
410 : int scaling_factor;
411 :
412 6 : scaling_factor = drm_rect_calc_hscale(¶ms->src, ¶ms->dst,
413 : params->min_range, params->max_range);
414 :
415 6 : KUNIT_EXPECT_EQ(test, scaling_factor, params->expected_scaling_factor);
416 6 : }
417 :
418 : static const struct drm_rect_scale_case drm_rect_vscale_cases[] = {
419 : {
420 : .name = "normal use",
421 : .src = DRM_RECT_INIT(0, 0, 0, 2 << 16),
422 : .dst = DRM_RECT_INIT(0, 0, 0, 1 << 16),
423 : .min_range = 0, .max_range = INT_MAX,
424 : .expected_scaling_factor = 2,
425 : },
426 : {
427 : .name = "out of max range",
428 : .src = DRM_RECT_INIT(0, 0, 0, 10 << 16),
429 : .dst = DRM_RECT_INIT(0, 0, 0, 1 << 16),
430 : .min_range = 3, .max_range = 5,
431 : .expected_scaling_factor = -ERANGE,
432 : },
433 : {
434 : .name = "out of min range",
435 : .src = DRM_RECT_INIT(0, 0, 0, 2 << 16),
436 : .dst = DRM_RECT_INIT(0, 0, 0, 1 << 16),
437 : .min_range = 3, .max_range = 5,
438 : .expected_scaling_factor = -ERANGE,
439 : },
440 : {
441 : .name = "zero dst height",
442 : .src = DRM_RECT_INIT(0, 0, 0, 2 << 16),
443 : .dst = DRM_RECT_INIT(0, 0, 0, 0 << 16),
444 : .min_range = 0, .max_range = INT_MAX,
445 : .expected_scaling_factor = 0,
446 : },
447 : {
448 : .name = "negative src height",
449 : .src = DRM_RECT_INIT(0, 0, 0, -(1 << 16)),
450 : .dst = DRM_RECT_INIT(0, 0, 0, 1 << 16),
451 : .min_range = 0, .max_range = INT_MAX,
452 : .expected_scaling_factor = -EINVAL,
453 : },
454 : {
455 : .name = "negative dst height",
456 : .src = DRM_RECT_INIT(0, 0, 0, 1 << 16),
457 : .dst = DRM_RECT_INIT(0, 0, 0, -(1 << 16)),
458 : .min_range = 0, .max_range = INT_MAX,
459 : .expected_scaling_factor = -EINVAL,
460 : },
461 : };
462 :
463 7 : KUNIT_ARRAY_PARAM(drm_rect_vscale, drm_rect_vscale_cases, drm_rect_scale_case_desc);
464 :
465 6 : static void drm_test_rect_calc_vscale(struct kunit *test)
466 : {
467 6 : const struct drm_rect_scale_case *params = test->param_value;
468 : int scaling_factor;
469 :
470 6 : scaling_factor = drm_rect_calc_vscale(¶ms->src, ¶ms->dst,
471 : params->min_range, params->max_range);
472 :
473 6 : KUNIT_EXPECT_EQ(test, scaling_factor, params->expected_scaling_factor);
474 6 : }
475 :
476 : struct drm_rect_rotate_case {
477 : const char *name;
478 : unsigned int rotation;
479 : struct drm_rect rect;
480 : int width, height;
481 : struct drm_rect expected;
482 : };
483 :
484 : static const struct drm_rect_rotate_case drm_rect_rotate_cases[] = {
485 : {
486 : .name = "reflect-x",
487 : .rotation = DRM_MODE_REFLECT_X,
488 : .rect = DRM_RECT_INIT(0, 0, 5, 5),
489 : .width = 5, .height = 10,
490 : .expected = DRM_RECT_INIT(0, 0, 5, 5),
491 : },
492 : {
493 : .name = "reflect-y",
494 : .rotation = DRM_MODE_REFLECT_Y,
495 : .rect = DRM_RECT_INIT(0, 0, 5, 5),
496 : .width = 5, .height = 10,
497 : .expected = DRM_RECT_INIT(0, 5, 5, 5),
498 : },
499 : {
500 : .name = "rotate-0",
501 : .rotation = DRM_MODE_ROTATE_0,
502 : .rect = DRM_RECT_INIT(0, 0, 5, 5),
503 : .width = 5, .height = 10,
504 : .expected = DRM_RECT_INIT(0, 0, 5, 5),
505 : },
506 : {
507 : .name = "rotate-90",
508 : .rotation = DRM_MODE_ROTATE_90,
509 : .rect = DRM_RECT_INIT(0, 0, 5, 10),
510 : .width = 5, .height = 10,
511 : .expected = DRM_RECT_INIT(0, 0, 10, 5),
512 : },
513 : {
514 : .name = "rotate-180",
515 : .rotation = DRM_MODE_ROTATE_180,
516 : .rect = DRM_RECT_INIT(0, 0, 5, 10),
517 : .width = 5, .height = 10,
518 : .expected = DRM_RECT_INIT(0, 0, 5, 10),
519 : },
520 : {
521 : .name = "rotate-270",
522 : .rotation = DRM_MODE_ROTATE_270,
523 : .rect = DRM_RECT_INIT(0, 0, 5, 10),
524 : .width = 5, .height = 10,
525 : .expected = DRM_RECT_INIT(0, 0, 10, 5),
526 : },
527 : };
528 :
529 12 : static void drm_rect_rotate_case_desc(const struct drm_rect_rotate_case *t, char *desc)
530 : {
531 12 : strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
532 12 : }
533 :
534 14 : KUNIT_ARRAY_PARAM(drm_rect_rotate, drm_rect_rotate_cases, drm_rect_rotate_case_desc);
535 :
536 6 : static void drm_test_rect_rotate(struct kunit *test)
537 : {
538 6 : const struct drm_rect_rotate_case *params = test->param_value;
539 6 : struct drm_rect r = params->rect;
540 :
541 6 : drm_rect_rotate(&r, params->width, params->height, params->rotation);
542 :
543 6 : drm_rect_compare(test, &r, ¶ms->expected);
544 6 : }
545 :
546 6 : static void drm_test_rect_rotate_inv(struct kunit *test)
547 : {
548 6 : const struct drm_rect_rotate_case *params = test->param_value;
549 6 : struct drm_rect r = params->expected;
550 :
551 6 : drm_rect_rotate_inv(&r, params->width, params->height, params->rotation);
552 :
553 6 : drm_rect_compare(test, &r, ¶ms->rect);
554 6 : }
555 :
556 : static struct kunit_case drm_rect_tests[] = {
557 : KUNIT_CASE(drm_test_rect_clip_scaled_div_by_zero),
558 : KUNIT_CASE(drm_test_rect_clip_scaled_not_clipped),
559 : KUNIT_CASE(drm_test_rect_clip_scaled_clipped),
560 : KUNIT_CASE(drm_test_rect_clip_scaled_signed_vs_unsigned),
561 : KUNIT_CASE_PARAM(drm_test_rect_intersect, drm_rect_intersect_gen_params),
562 : KUNIT_CASE_PARAM(drm_test_rect_calc_hscale, drm_rect_hscale_gen_params),
563 : KUNIT_CASE_PARAM(drm_test_rect_calc_vscale, drm_rect_vscale_gen_params),
564 : KUNIT_CASE_PARAM(drm_test_rect_rotate, drm_rect_rotate_gen_params),
565 : KUNIT_CASE_PARAM(drm_test_rect_rotate_inv, drm_rect_rotate_gen_params),
566 : { }
567 : };
568 :
569 : static struct kunit_suite drm_rect_test_suite = {
570 : .name = "drm_rect",
571 : .test_cases = drm_rect_tests,
572 : };
573 :
574 : kunit_test_suite(drm_rect_test_suite);
575 :
576 : MODULE_LICENSE("GPL");
|