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
16static 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
25static 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(&src, 0, 0, 0, 0);
35	drm_rect_init(&dst, 0, 0, 0, 0);
36	drm_rect_init(&clip, 1, 1, 1, 1);
37	visible = drm_rect_clip_scaled(&src, &dst, &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(&src, 0, 0, 0, 0);
43	drm_rect_init(&dst, 3, 3, 0, 0);
44	drm_rect_init(&clip, 1, 1, 1, 1);
45	visible = drm_rect_clip_scaled(&src, &dst, &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
51static 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(&src, 0, 0, 1 << 16, 1 << 16);
58	drm_rect_init(&dst, 0, 0, 1, 1);
59	drm_rect_init(&clip, 0, 0, 1, 1);
60
61	visible = drm_rect_clip_scaled(&src, &dst, &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(&src, 0, 0, 2 << 16, 2 << 16);
72	drm_rect_init(&dst, 0, 0, 1, 1);
73	drm_rect_init(&clip, 0, 0, 1, 1);
74
75	visible = drm_rect_clip_scaled(&src, &dst, &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(&src, 0, 0, 1 << 16, 1 << 16);
86	drm_rect_init(&dst, 0, 0, 2, 2);
87	drm_rect_init(&clip, 0, 0, 2, 2);
88
89	visible = drm_rect_clip_scaled(&src, &dst, &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
99static 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(&src, 0, 0, 2 << 16, 2 << 16);
106	drm_rect_init(&dst, 0, 0, 2, 2);
107	drm_rect_init(&clip, 0, 0, 1, 1);
108
109	visible = drm_rect_clip_scaled(&src, &dst, &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(&src, 0, 0, 2 << 16, 2 << 16);
120	drm_rect_init(&dst, 0, 0, 2, 2);
121	drm_rect_init(&clip, 1, 1, 1, 1);
122
123	visible = drm_rect_clip_scaled(&src, &dst, &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(&src, 0, 0, 4 << 16, 4 << 16);
134	drm_rect_init(&dst, 0, 0, 2, 2);
135	drm_rect_init(&clip, 0, 0, 1, 1);
136
137	visible = drm_rect_clip_scaled(&src, &dst, &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(&src, 0, 0, 4 << 16, 4 << 16);
148	drm_rect_init(&dst, 0, 0, 2, 2);
149	drm_rect_init(&clip, 1, 1, 1, 1);
150
151	visible = drm_rect_clip_scaled(&src, &dst, &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(&src, 0, 0, 2 << 16, 2 << 16);
162	drm_rect_init(&dst, 0, 0, 4, 4);
163	drm_rect_init(&clip, 0, 0, 2, 2);
164
165	visible = drm_rect_clip_scaled(&src, &dst, &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(&src, 0, 0, 2 << 16, 2 << 16);
176	drm_rect_init(&dst, 0, 0, 4, 4);
177	drm_rect_init(&clip, 2, 2, 2, 2);
178
179	visible = drm_rect_clip_scaled(&src, &dst, &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
189static 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(&src, 0, 0, INT_MAX, INT_MAX);
203	drm_rect_init(&dst, 0, 0, 2, 2);
204	drm_rect_init(&clip, 3, 3, 1, 1);
205
206	visible = drm_rect_clip_scaled(&src, &dst, &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
212struct 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
219static 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
327static void drm_rect_intersect_case_desc(const struct drm_rect_intersect_case *t, char *desc)
328{
329	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}
333
334KUNIT_ARRAY_PARAM(drm_rect_intersect, drm_rect_intersect_cases, drm_rect_intersect_case_desc);
335
336static 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(&r1_aux, &params->r2);
343
344	KUNIT_EXPECT_EQ(test, visible, params->should_be_visible);
345	drm_rect_compare(test, &r1_aux, &params->expected_intersection);
346}
347
348struct 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
355static 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
400static void drm_rect_scale_case_desc(const struct drm_rect_scale_case *t, char *desc)
401{
402	strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
403}
404
405KUNIT_ARRAY_PARAM(drm_rect_scale, drm_rect_scale_cases, drm_rect_scale_case_desc);
406
407static 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(&params->src, &params->dst,
413					      params->min_range, params->max_range);
414
415	KUNIT_EXPECT_EQ(test, scaling_factor, params->expected_scaling_factor);
416}
417
418static 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(&params->src, &params->dst,
424					      params->min_range, params->max_range);
425
426	KUNIT_EXPECT_EQ(test, scaling_factor, params->expected_scaling_factor);
427}
428
429struct 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
437static 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
482static void drm_rect_rotate_case_desc(const struct drm_rect_rotate_case *t, char *desc)
483{
484	strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
485}
486
487KUNIT_ARRAY_PARAM(drm_rect_rotate, drm_rect_rotate_cases, drm_rect_rotate_case_desc);
488
489static 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, params->width, params->height, params->rotation);
495
496	drm_rect_compare(test, &r, &params->expected);
497}
498
499static 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, params->width, params->height, params->rotation);
505
506	drm_rect_compare(test, &r, &params->rect);
507}
508
509static 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
522static struct kunit_suite drm_rect_test_suite = {
523	.name = "drm_rect",
524	.test_cases = drm_rect_tests,
525};
526
527kunit_test_suite(drm_rect_test_suite);
528
529MODULE_LICENSE("GPL");
530