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 | static void drm_rect_compare(struct kunit *test, const struct drm_rect *r, |
17 | const struct drm_rect *expected) |
18 | { |
19 | KUNIT_EXPECT_EQ(test, r->x1, expected->x1); |
20 | KUNIT_EXPECT_EQ(test, r->y1, expected->y1); |
21 | KUNIT_EXPECT_EQ(test, drm_rect_width(r), drm_rect_width(expected)); |
22 | KUNIT_EXPECT_EQ(test, drm_rect_height(r), drm_rect_height(expected)); |
23 | } |
24 | |
25 | 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 | drm_rect_init(r: &src, x: 0, y: 0, width: 0, height: 0); |
35 | drm_rect_init(r: &dst, x: 0, y: 0, width: 0, height: 0); |
36 | drm_rect_init(r: &clip, x: 1, y: 1, width: 1, height: 1); |
37 | visible = drm_rect_clip_scaled(src: &src, dst: &dst, clip: &clip); |
38 | |
39 | KUNIT_EXPECT_FALSE_MSG(test, visible, "Destination not be visible\n" ); |
40 | KUNIT_EXPECT_FALSE_MSG(test, drm_rect_visible(&src), "Source should not be visible\n" ); |
41 | |
42 | drm_rect_init(r: &src, x: 0, y: 0, width: 0, height: 0); |
43 | drm_rect_init(r: &dst, x: 3, y: 3, width: 0, height: 0); |
44 | drm_rect_init(r: &clip, x: 1, y: 1, width: 1, height: 1); |
45 | visible = drm_rect_clip_scaled(src: &src, dst: &dst, clip: &clip); |
46 | |
47 | KUNIT_EXPECT_FALSE_MSG(test, visible, "Destination not be visible\n" ); |
48 | KUNIT_EXPECT_FALSE_MSG(test, drm_rect_visible(&src), "Source should not be visible\n" ); |
49 | } |
50 | |
51 | 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 | drm_rect_init(r: &src, x: 0, y: 0, width: 1 << 16, height: 1 << 16); |
58 | drm_rect_init(r: &dst, x: 0, y: 0, width: 1, height: 1); |
59 | drm_rect_init(r: &clip, x: 0, y: 0, width: 1, height: 1); |
60 | |
61 | visible = drm_rect_clip_scaled(src: &src, dst: &dst, clip: &clip); |
62 | |
63 | 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 | KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 || |
66 | dst.y1 != 0 || dst.y2 != 1, "Destination badly clipped\n" ); |
67 | KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n" ); |
68 | KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n" ); |
69 | |
70 | /* 2:1 scaling */ |
71 | drm_rect_init(r: &src, x: 0, y: 0, width: 2 << 16, height: 2 << 16); |
72 | drm_rect_init(r: &dst, x: 0, y: 0, width: 1, height: 1); |
73 | drm_rect_init(r: &clip, x: 0, y: 0, width: 1, height: 1); |
74 | |
75 | visible = drm_rect_clip_scaled(src: &src, dst: &dst, clip: &clip); |
76 | |
77 | 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 | KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 || |
80 | dst.y1 != 0 || dst.y2 != 1, "Destination badly clipped\n" ); |
81 | KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n" ); |
82 | KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n" ); |
83 | |
84 | /* 1:2 scaling */ |
85 | drm_rect_init(r: &src, x: 0, y: 0, width: 1 << 16, height: 1 << 16); |
86 | drm_rect_init(r: &dst, x: 0, y: 0, width: 2, height: 2); |
87 | drm_rect_init(r: &clip, x: 0, y: 0, width: 2, height: 2); |
88 | |
89 | visible = drm_rect_clip_scaled(src: &src, dst: &dst, clip: &clip); |
90 | |
91 | 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 | KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 2 || |
94 | dst.y1 != 0 || dst.y2 != 2, "Destination badly clipped\n" ); |
95 | KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n" ); |
96 | KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n" ); |
97 | } |
98 | |
99 | 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 | drm_rect_init(r: &src, x: 0, y: 0, width: 2 << 16, height: 2 << 16); |
106 | drm_rect_init(r: &dst, x: 0, y: 0, width: 2, height: 2); |
107 | drm_rect_init(r: &clip, x: 0, y: 0, width: 1, height: 1); |
108 | |
109 | visible = drm_rect_clip_scaled(src: &src, dst: &dst, clip: &clip); |
110 | |
111 | 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 | KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 || |
114 | dst.y1 != 0 || dst.y2 != 1, "Destination badly clipped\n" ); |
115 | KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n" ); |
116 | KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n" ); |
117 | |
118 | /* 1:1 scaling bottom/right clip */ |
119 | drm_rect_init(r: &src, x: 0, y: 0, width: 2 << 16, height: 2 << 16); |
120 | drm_rect_init(r: &dst, x: 0, y: 0, width: 2, height: 2); |
121 | drm_rect_init(r: &clip, x: 1, y: 1, width: 1, height: 1); |
122 | |
123 | visible = drm_rect_clip_scaled(src: &src, dst: &dst, clip: &clip); |
124 | |
125 | 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 | KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 1 || dst.x2 != 2 || dst.y1 != 1 || |
128 | dst.y2 != 2, "Destination badly clipped\n" ); |
129 | KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n" ); |
130 | KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n" ); |
131 | |
132 | /* 2:1 scaling top/left clip */ |
133 | drm_rect_init(r: &src, x: 0, y: 0, width: 4 << 16, height: 4 << 16); |
134 | drm_rect_init(r: &dst, x: 0, y: 0, width: 2, height: 2); |
135 | drm_rect_init(r: &clip, x: 0, y: 0, width: 1, height: 1); |
136 | |
137 | visible = drm_rect_clip_scaled(src: &src, dst: &dst, clip: &clip); |
138 | |
139 | 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 | KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 || dst.y1 != 0 || |
142 | dst.y2 != 1, "Destination badly clipped\n" ); |
143 | KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n" ); |
144 | KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n" ); |
145 | |
146 | /* 2:1 scaling bottom/right clip */ |
147 | drm_rect_init(r: &src, x: 0, y: 0, width: 4 << 16, height: 4 << 16); |
148 | drm_rect_init(r: &dst, x: 0, y: 0, width: 2, height: 2); |
149 | drm_rect_init(r: &clip, x: 1, y: 1, width: 1, height: 1); |
150 | |
151 | visible = drm_rect_clip_scaled(src: &src, dst: &dst, clip: &clip); |
152 | |
153 | 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 | KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 1 || dst.x2 != 2 || dst.y1 != 1 || |
156 | dst.y2 != 2, "Destination badly clipped\n" ); |
157 | KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n" ); |
158 | KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n" ); |
159 | |
160 | /* 1:2 scaling top/left clip */ |
161 | drm_rect_init(r: &src, x: 0, y: 0, width: 2 << 16, height: 2 << 16); |
162 | drm_rect_init(r: &dst, x: 0, y: 0, width: 4, height: 4); |
163 | drm_rect_init(r: &clip, x: 0, y: 0, width: 2, height: 2); |
164 | |
165 | visible = drm_rect_clip_scaled(src: &src, dst: &dst, clip: &clip); |
166 | |
167 | 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 | KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 2 || dst.y1 != 0 || |
170 | dst.y2 != 2, "Destination badly clipped\n" ); |
171 | KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n" ); |
172 | KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n" ); |
173 | |
174 | /* 1:2 scaling bottom/right clip */ |
175 | drm_rect_init(r: &src, x: 0, y: 0, width: 2 << 16, height: 2 << 16); |
176 | drm_rect_init(r: &dst, x: 0, y: 0, width: 4, height: 4); |
177 | drm_rect_init(r: &clip, x: 2, y: 2, width: 2, height: 2); |
178 | |
179 | visible = drm_rect_clip_scaled(src: &src, dst: &dst, clip: &clip); |
180 | |
181 | 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 | KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 2 || dst.x2 != 4 || dst.y1 != 2 || |
184 | dst.y2 != 4, "Destination badly clipped\n" ); |
185 | KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n" ); |
186 | KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n" ); |
187 | } |
188 | |
189 | 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 | drm_rect_init(r: &src, x: 0, y: 0, INT_MAX, INT_MAX); |
203 | drm_rect_init(r: &dst, x: 0, y: 0, width: 2, height: 2); |
204 | drm_rect_init(r: &clip, x: 3, y: 3, width: 1, height: 1); |
205 | |
206 | visible = drm_rect_clip_scaled(src: &src, dst: &dst, clip: &clip); |
207 | |
208 | KUNIT_EXPECT_FALSE_MSG(test, visible, "Destination should not be visible\n" ); |
209 | KUNIT_EXPECT_FALSE_MSG(test, drm_rect_visible(&src), "Source should not be visible\n" ); |
210 | } |
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 | static void drm_rect_intersect_case_desc(const struct drm_rect_intersect_case *t, char *desc) |
328 | { |
329 | snprintf(buf: desc, KUNIT_PARAM_DESC_SIZE, |
330 | fmt: "%s: " DRM_RECT_FMT " x " DRM_RECT_FMT, |
331 | t->description, DRM_RECT_ARG(&t->r1), DRM_RECT_ARG(&t->r2)); |
332 | } |
333 | |
334 | KUNIT_ARRAY_PARAM(drm_rect_intersect, drm_rect_intersect_cases, drm_rect_intersect_case_desc); |
335 | |
336 | static void drm_test_rect_intersect(struct kunit *test) |
337 | { |
338 | const struct drm_rect_intersect_case *params = test->param_value; |
339 | struct drm_rect r1_aux = params->r1; |
340 | bool visible; |
341 | |
342 | visible = drm_rect_intersect(r: &r1_aux, clip: ¶ms->r2); |
343 | |
344 | KUNIT_EXPECT_EQ(test, visible, params->should_be_visible); |
345 | drm_rect_compare(test, r: &r1_aux, expected: ¶ms->expected_intersection); |
346 | } |
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_scale_cases[] = { |
356 | { |
357 | .name = "normal use" , |
358 | .src = DRM_RECT_INIT(0, 0, 2 << 16, 2 << 16), |
359 | .dst = DRM_RECT_INIT(0, 0, 1 << 16, 1 << 16), |
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, 10 << 16), |
366 | .dst = DRM_RECT_INIT(0, 0, 1 << 16, 1 << 16), |
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, 2 << 16), |
373 | .dst = DRM_RECT_INIT(0, 0, 1 << 16, 1 << 16), |
374 | .min_range = 3, .max_range = 5, |
375 | .expected_scaling_factor = -ERANGE, |
376 | }, |
377 | { |
378 | .name = "zero dst" , |
379 | .src = DRM_RECT_INIT(0, 0, 2 << 16, 2 << 16), |
380 | .dst = DRM_RECT_INIT(0, 0, 0 << 16, 0 << 16), |
381 | .min_range = 0, .max_range = INT_MAX, |
382 | .expected_scaling_factor = 0, |
383 | }, |
384 | { |
385 | .name = "negative src" , |
386 | .src = DRM_RECT_INIT(0, 0, -(1 << 16), -(1 << 16)), |
387 | .dst = DRM_RECT_INIT(0, 0, 1 << 16, 1 << 16), |
388 | .min_range = 0, .max_range = INT_MAX, |
389 | .expected_scaling_factor = -EINVAL, |
390 | }, |
391 | { |
392 | .name = "negative dst" , |
393 | .src = DRM_RECT_INIT(0, 0, 1 << 16, 1 << 16), |
394 | .dst = DRM_RECT_INIT(0, 0, -(1 << 16), -(1 << 16)), |
395 | .min_range = 0, .max_range = INT_MAX, |
396 | .expected_scaling_factor = -EINVAL, |
397 | }, |
398 | }; |
399 | |
400 | static void drm_rect_scale_case_desc(const struct drm_rect_scale_case *t, char *desc) |
401 | { |
402 | strscpy(p: desc, q: t->name, KUNIT_PARAM_DESC_SIZE); |
403 | } |
404 | |
405 | KUNIT_ARRAY_PARAM(drm_rect_scale, drm_rect_scale_cases, drm_rect_scale_case_desc); |
406 | |
407 | static void drm_test_rect_calc_hscale(struct kunit *test) |
408 | { |
409 | const struct drm_rect_scale_case *params = test->param_value; |
410 | int scaling_factor; |
411 | |
412 | scaling_factor = drm_rect_calc_hscale(src: ¶ms->src, dst: ¶ms->dst, |
413 | min_hscale: params->min_range, max_hscale: params->max_range); |
414 | |
415 | KUNIT_EXPECT_EQ(test, scaling_factor, params->expected_scaling_factor); |
416 | } |
417 | |
418 | static void drm_test_rect_calc_vscale(struct kunit *test) |
419 | { |
420 | const struct drm_rect_scale_case *params = test->param_value; |
421 | int scaling_factor; |
422 | |
423 | scaling_factor = drm_rect_calc_vscale(src: ¶ms->src, dst: ¶ms->dst, |
424 | min_vscale: params->min_range, max_vscale: params->max_range); |
425 | |
426 | KUNIT_EXPECT_EQ(test, scaling_factor, params->expected_scaling_factor); |
427 | } |
428 | |
429 | struct drm_rect_rotate_case { |
430 | const char *name; |
431 | unsigned int rotation; |
432 | struct drm_rect rect; |
433 | int width, height; |
434 | struct drm_rect expected; |
435 | }; |
436 | |
437 | static const struct drm_rect_rotate_case drm_rect_rotate_cases[] = { |
438 | { |
439 | .name = "reflect-x" , |
440 | .rotation = DRM_MODE_REFLECT_X, |
441 | .rect = DRM_RECT_INIT(0, 0, 5, 5), |
442 | .width = 5, .height = 10, |
443 | .expected = DRM_RECT_INIT(0, 0, 5, 5), |
444 | }, |
445 | { |
446 | .name = "reflect-y" , |
447 | .rotation = DRM_MODE_REFLECT_Y, |
448 | .rect = DRM_RECT_INIT(2, 0, 5, 5), |
449 | .width = 5, .height = 10, |
450 | .expected = DRM_RECT_INIT(2, 5, 5, 5), |
451 | }, |
452 | { |
453 | .name = "rotate-0" , |
454 | .rotation = DRM_MODE_ROTATE_0, |
455 | .rect = DRM_RECT_INIT(0, 2, 5, 5), |
456 | .width = 5, .height = 10, |
457 | .expected = DRM_RECT_INIT(0, 2, 5, 5), |
458 | }, |
459 | { |
460 | .name = "rotate-90" , |
461 | .rotation = DRM_MODE_ROTATE_90, |
462 | .rect = DRM_RECT_INIT(0, 0, 5, 10), |
463 | .width = 5, .height = 10, |
464 | .expected = DRM_RECT_INIT(0, 0, 10, 5), |
465 | }, |
466 | { |
467 | .name = "rotate-180" , |
468 | .rotation = DRM_MODE_ROTATE_180, |
469 | .rect = DRM_RECT_INIT(11, 3, 5, 10), |
470 | .width = 5, .height = 10, |
471 | .expected = DRM_RECT_INIT(-11, -3, 5, 10), |
472 | }, |
473 | { |
474 | .name = "rotate-270" , |
475 | .rotation = DRM_MODE_ROTATE_270, |
476 | .rect = DRM_RECT_INIT(6, 3, 5, 10), |
477 | .width = 5, .height = 10, |
478 | .expected = DRM_RECT_INIT(-3, 6, 10, 5), |
479 | }, |
480 | }; |
481 | |
482 | static void drm_rect_rotate_case_desc(const struct drm_rect_rotate_case *t, char *desc) |
483 | { |
484 | strscpy(p: desc, q: t->name, KUNIT_PARAM_DESC_SIZE); |
485 | } |
486 | |
487 | KUNIT_ARRAY_PARAM(drm_rect_rotate, drm_rect_rotate_cases, drm_rect_rotate_case_desc); |
488 | |
489 | static void drm_test_rect_rotate(struct kunit *test) |
490 | { |
491 | const struct drm_rect_rotate_case *params = test->param_value; |
492 | struct drm_rect r = params->rect; |
493 | |
494 | drm_rect_rotate(r: &r, width: params->width, height: params->height, rotation: params->rotation); |
495 | |
496 | drm_rect_compare(test, r: &r, expected: ¶ms->expected); |
497 | } |
498 | |
499 | static void drm_test_rect_rotate_inv(struct kunit *test) |
500 | { |
501 | const struct drm_rect_rotate_case *params = test->param_value; |
502 | struct drm_rect r = params->expected; |
503 | |
504 | drm_rect_rotate_inv(r: &r, width: params->width, height: params->height, rotation: params->rotation); |
505 | |
506 | drm_rect_compare(test, r: &r, expected: ¶ms->rect); |
507 | } |
508 | |
509 | static struct kunit_case drm_rect_tests[] = { |
510 | KUNIT_CASE(drm_test_rect_clip_scaled_div_by_zero), |
511 | KUNIT_CASE(drm_test_rect_clip_scaled_not_clipped), |
512 | KUNIT_CASE(drm_test_rect_clip_scaled_clipped), |
513 | KUNIT_CASE(drm_test_rect_clip_scaled_signed_vs_unsigned), |
514 | KUNIT_CASE_PARAM(drm_test_rect_intersect, drm_rect_intersect_gen_params), |
515 | KUNIT_CASE_PARAM(drm_test_rect_calc_hscale, drm_rect_scale_gen_params), |
516 | KUNIT_CASE_PARAM(drm_test_rect_calc_vscale, drm_rect_scale_gen_params), |
517 | KUNIT_CASE_PARAM(drm_test_rect_rotate, drm_rect_rotate_gen_params), |
518 | KUNIT_CASE_PARAM(drm_test_rect_rotate_inv, drm_rect_rotate_gen_params), |
519 | { } |
520 | }; |
521 | |
522 | static struct kunit_suite drm_rect_test_suite = { |
523 | .name = "drm_rect" , |
524 | .test_cases = drm_rect_tests, |
525 | }; |
526 | |
527 | kunit_test_suite(drm_rect_test_suite); |
528 | |
529 | MODULE_LICENSE("GPL" ); |
530 | |