1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Test cases for the drm_rect functions
4  */
5 
6 #define pr_fmt(fmt) "drm_rect: " fmt
7 
8 #include <linux/limits.h>
9 
10 #include <drm/drm_rect.h>
11 
12 #include "test-drm_modeset_common.h"
13 
igt_drm_rect_clip_scaled_div_by_zero(void * ignored)14 int igt_drm_rect_clip_scaled_div_by_zero(void *ignored)
15 {
16 	struct drm_rect src, dst, clip;
17 	bool visible;
18 
19 	/*
20 	 * Make sure we don't divide by zero when dst
21 	 * width/height is zero and dst and clip do not intersect.
22 	 */
23 	drm_rect_init(&src, 0, 0, 0, 0);
24 	drm_rect_init(&dst, 0, 0, 0, 0);
25 	drm_rect_init(&clip, 1, 1, 1, 1);
26 	visible = drm_rect_clip_scaled(&src, &dst, &clip);
27 	FAIL(visible, "Destination not be visible\n");
28 	FAIL(drm_rect_visible(&src), "Source should not be visible\n");
29 
30 	drm_rect_init(&src, 0, 0, 0, 0);
31 	drm_rect_init(&dst, 3, 3, 0, 0);
32 	drm_rect_init(&clip, 1, 1, 1, 1);
33 	visible = drm_rect_clip_scaled(&src, &dst, &clip);
34 	FAIL(visible, "Destination not be visible\n");
35 	FAIL(drm_rect_visible(&src), "Source should not be visible\n");
36 
37 	return 0;
38 }
39 
igt_drm_rect_clip_scaled_not_clipped(void * ignored)40 int igt_drm_rect_clip_scaled_not_clipped(void *ignored)
41 {
42 	struct drm_rect src, dst, clip;
43 	bool visible;
44 
45 	/* 1:1 scaling */
46 	drm_rect_init(&src, 0, 0, 1 << 16, 1 << 16);
47 	drm_rect_init(&dst, 0, 0, 1, 1);
48 	drm_rect_init(&clip, 0, 0, 1, 1);
49 
50 	visible = drm_rect_clip_scaled(&src, &dst, &clip);
51 
52 	FAIL(src.x1 != 0 || src.x2 != 1 << 16 ||
53 	     src.y1 != 0 || src.y2 != 1 << 16,
54 	     "Source badly clipped\n");
55 	FAIL(dst.x1 != 0 || dst.x2 != 1 ||
56 	     dst.y1 != 0 || dst.y2 != 1,
57 	     "Destination badly clipped\n");
58 	FAIL(!visible, "Destination should be visible\n");
59 	FAIL(!drm_rect_visible(&src), "Source should be visible\n");
60 
61 	/* 2:1 scaling */
62 	drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
63 	drm_rect_init(&dst, 0, 0, 1, 1);
64 	drm_rect_init(&clip, 0, 0, 1, 1);
65 
66 	visible = drm_rect_clip_scaled(&src, &dst, &clip);
67 
68 	FAIL(src.x1 != 0 || src.x2 != 2 << 16 ||
69 	     src.y1 != 0 || src.y2 != 2 << 16,
70 	     "Source badly clipped\n");
71 	FAIL(dst.x1 != 0 || dst.x2 != 1 ||
72 	     dst.y1 != 0 || dst.y2 != 1,
73 	     "Destination badly clipped\n");
74 	FAIL(!visible, "Destination should be visible\n");
75 	FAIL(!drm_rect_visible(&src), "Source should be visible\n");
76 
77 	/* 1:2 scaling */
78 	drm_rect_init(&src, 0, 0, 1 << 16, 1 << 16);
79 	drm_rect_init(&dst, 0, 0, 2, 2);
80 	drm_rect_init(&clip, 0, 0, 2, 2);
81 
82 	visible = drm_rect_clip_scaled(&src, &dst, &clip);
83 
84 	FAIL(src.x1 != 0 || src.x2 != 1 << 16 ||
85 	     src.y1 != 0 || src.y2 != 1 << 16,
86 	     "Source badly clipped\n");
87 	FAIL(dst.x1 != 0 || dst.x2 != 2 ||
88 	     dst.y1 != 0 || dst.y2 != 2,
89 	     "Destination badly clipped\n");
90 	FAIL(!visible, "Destination should be visible\n");
91 	FAIL(!drm_rect_visible(&src), "Source should be visible\n");
92 
93 	return 0;
94 }
95 
igt_drm_rect_clip_scaled_clipped(void * ignored)96 int igt_drm_rect_clip_scaled_clipped(void *ignored)
97 {
98 	struct drm_rect src, dst, clip;
99 	bool visible;
100 
101 	/* 1:1 scaling top/left clip */
102 	drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
103 	drm_rect_init(&dst, 0, 0, 2, 2);
104 	drm_rect_init(&clip, 0, 0, 1, 1);
105 
106 	visible = drm_rect_clip_scaled(&src, &dst, &clip);
107 
108 	FAIL(src.x1 != 0 || src.x2 != 1 << 16 ||
109 	     src.y1 != 0 || src.y2 != 1 << 16,
110 	     "Source badly clipped\n");
111 	FAIL(dst.x1 != 0 || dst.x2 != 1 ||
112 	     dst.y1 != 0 || dst.y2 != 1,
113 	     "Destination badly clipped\n");
114 	FAIL(!visible, "Destination should be visible\n");
115 	FAIL(!drm_rect_visible(&src), "Source should be visible\n");
116 
117 	/* 1:1 scaling bottom/right clip */
118 	drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
119 	drm_rect_init(&dst, 0, 0, 2, 2);
120 	drm_rect_init(&clip, 1, 1, 1, 1);
121 
122 	visible = drm_rect_clip_scaled(&src, &dst, &clip);
123 
124 	FAIL(src.x1 != 1 << 16 || src.x2 != 2 << 16 ||
125 	     src.y1 != 1 << 16 || src.y2 != 2 << 16,
126 	     "Source badly clipped\n");
127 	FAIL(dst.x1 != 1 || dst.x2 != 2 ||
128 	     dst.y1 != 1 || dst.y2 != 2,
129 	     "Destination badly clipped\n");
130 	FAIL(!visible, "Destination should be visible\n");
131 	FAIL(!drm_rect_visible(&src), "Source should be visible\n");
132 
133 	/* 2:1 scaling top/left clip */
134 	drm_rect_init(&src, 0, 0, 4 << 16, 4 << 16);
135 	drm_rect_init(&dst, 0, 0, 2, 2);
136 	drm_rect_init(&clip, 0, 0, 1, 1);
137 
138 	visible = drm_rect_clip_scaled(&src, &dst, &clip);
139 
140 	FAIL(src.x1 != 0 || src.x2 != 2 << 16 ||
141 	     src.y1 != 0 || src.y2 != 2 << 16,
142 	     "Source badly clipped\n");
143 	FAIL(dst.x1 != 0 || dst.x2 != 1 ||
144 	     dst.y1 != 0 || dst.y2 != 1,
145 	     "Destination badly clipped\n");
146 	FAIL(!visible, "Destination should be visible\n");
147 	FAIL(!drm_rect_visible(&src), "Source should be visible\n");
148 
149 	/* 2:1 scaling bottom/right clip */
150 	drm_rect_init(&src, 0, 0, 4 << 16, 4 << 16);
151 	drm_rect_init(&dst, 0, 0, 2, 2);
152 	drm_rect_init(&clip, 1, 1, 1, 1);
153 
154 	visible = drm_rect_clip_scaled(&src, &dst, &clip);
155 
156 	FAIL(src.x1 != 2 << 16 || src.x2 != 4 << 16 ||
157 	     src.y1 != 2 << 16 || src.y2 != 4 << 16,
158 	     "Source badly clipped\n");
159 	FAIL(dst.x1 != 1 || dst.x2 != 2 ||
160 	     dst.y1 != 1 || dst.y2 != 2,
161 	     "Destination badly clipped\n");
162 	FAIL(!visible, "Destination should be visible\n");
163 	FAIL(!drm_rect_visible(&src), "Source should be visible\n");
164 
165 	/* 1:2 scaling top/left clip */
166 	drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
167 	drm_rect_init(&dst, 0, 0, 4, 4);
168 	drm_rect_init(&clip, 0, 0, 2, 2);
169 
170 	visible = drm_rect_clip_scaled(&src, &dst, &clip);
171 
172 	FAIL(src.x1 != 0 || src.x2 != 1 << 16 ||
173 	     src.y1 != 0 || src.y2 != 1 << 16,
174 	     "Source badly clipped\n");
175 	FAIL(dst.x1 != 0 || dst.x2 != 2 ||
176 	     dst.y1 != 0 || dst.y2 != 2,
177 	     "Destination badly clipped\n");
178 	FAIL(!visible, "Destination should be visible\n");
179 	FAIL(!drm_rect_visible(&src), "Source should be visible\n");
180 
181 	/* 1:2 scaling bottom/right clip */
182 	drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
183 	drm_rect_init(&dst, 0, 0, 4, 4);
184 	drm_rect_init(&clip, 2, 2, 2, 2);
185 
186 	visible = drm_rect_clip_scaled(&src, &dst, &clip);
187 
188 	FAIL(src.x1 != 1 << 16 || src.x2 != 2 << 16 ||
189 	     src.y1 != 1 << 16 || src.y2 != 2 << 16,
190 	     "Source badly clipped\n");
191 	FAIL(dst.x1 != 2 || dst.x2 != 4 ||
192 	     dst.y1 != 2 || dst.y2 != 4,
193 	     "Destination badly clipped\n");
194 	FAIL(!visible, "Destination should be visible\n");
195 	FAIL(!drm_rect_visible(&src), "Source should be visible\n");
196 
197 	return 0;
198 }
199 
igt_drm_rect_clip_scaled_signed_vs_unsigned(void * ignored)200 int igt_drm_rect_clip_scaled_signed_vs_unsigned(void *ignored)
201 {
202 	struct drm_rect src, dst, clip;
203 	bool visible;
204 
205 	/*
206 	 * 'clip.x2 - dst.x1 >= dst width' could result a negative
207 	 * src rectangle width which is no longer expected by the
208 	 * code as it's using unsigned types. This could lead to
209 	 * the clipped source rectangle appering visible when it
210 	 * should have been fully clipped. Make sure both rectangles
211 	 * end up invisible.
212 	 */
213 	drm_rect_init(&src, 0, 0, INT_MAX, INT_MAX);
214 	drm_rect_init(&dst, 0, 0, 2, 2);
215 	drm_rect_init(&clip, 3, 3, 1, 1);
216 
217 	visible = drm_rect_clip_scaled(&src, &dst, &clip);
218 
219 	FAIL(visible, "Destination should not be visible\n");
220 	FAIL(drm_rect_visible(&src), "Source should not be visible\n");
221 
222 	return 0;
223 }
224