Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0
2 : /*
3 : * Test case for drm_damage_helper functions
4 : *
5 : * Copyright (c) 2022 MaĆra Canal <mairacanal@riseup.net>
6 : */
7 :
8 : #include <kunit/test.h>
9 :
10 : #include <drm/drm_damage_helper.h>
11 : #include <drm/drm_framebuffer.h>
12 : #include <drm/drm_plane.h>
13 : #include <drm/drm_drv.h>
14 :
15 : struct drm_damage_mock {
16 : struct drm_driver driver;
17 : struct drm_device device;
18 : struct drm_object_properties obj_props;
19 : struct drm_plane plane;
20 : struct drm_property prop;
21 : struct drm_framebuffer fb;
22 : struct drm_plane_state state;
23 : struct drm_plane_state old_state;
24 : };
25 :
26 0 : static int drm_damage_helper_init(struct kunit *test)
27 : {
28 : struct drm_damage_mock *mock;
29 :
30 0 : mock = kunit_kzalloc(test, sizeof(*mock), GFP_KERNEL);
31 0 : KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mock);
32 :
33 0 : mock->fb.width = 2048;
34 0 : mock->fb.height = 2048;
35 :
36 0 : mock->state.crtc = ZERO_SIZE_PTR;
37 0 : mock->state.fb = &mock->fb;
38 0 : mock->state.visible = true;
39 :
40 0 : mock->old_state.plane = &mock->plane;
41 0 : mock->state.plane = &mock->plane;
42 :
43 : /* just enough so that drm_plane_enable_fb_damage_clips() works */
44 0 : mock->device.driver = &mock->driver;
45 0 : mock->device.mode_config.prop_fb_damage_clips = &mock->prop;
46 0 : mock->plane.dev = &mock->device;
47 0 : mock->obj_props.count = 0;
48 0 : mock->plane.base.properties = &mock->obj_props;
49 0 : mock->prop.base.id = 1; /* 0 is an invalid id */
50 0 : mock->prop.dev = &mock->device;
51 :
52 0 : drm_plane_enable_fb_damage_clips(&mock->plane);
53 :
54 0 : test->priv = mock;
55 :
56 0 : return 0;
57 : }
58 :
59 : static void set_plane_src(struct drm_plane_state *state, int x1, int y1, int x2,
60 : int y2)
61 : {
62 0 : state->src_x = x1;
63 0 : state->src_y = y1;
64 0 : state->src_w = x2 - x1;
65 0 : state->src_h = y2 - y1;
66 :
67 0 : state->src.x1 = x1;
68 0 : state->src.y1 = y1;
69 0 : state->src.x2 = x2;
70 0 : state->src.y2 = y2;
71 : }
72 :
73 : static void set_damage_clip(struct drm_mode_rect *r, int x1, int y1, int x2,
74 : int y2)
75 : {
76 0 : r->x1 = x1;
77 0 : r->y1 = y1;
78 0 : r->x2 = x2;
79 0 : r->y2 = y2;
80 : }
81 :
82 : static void set_damage_blob(struct drm_property_blob *damage_blob,
83 : struct drm_mode_rect *r, u32 size)
84 : {
85 0 : damage_blob->length = size;
86 0 : damage_blob->data = r;
87 : }
88 :
89 : static void set_plane_damage(struct drm_plane_state *state,
90 : struct drm_property_blob *damage_blob)
91 : {
92 0 : state->fb_damage_clips = damage_blob;
93 : }
94 :
95 0 : static void check_damage_clip(struct kunit *test, struct drm_rect *r,
96 : int x1, int y1, int x2, int y2)
97 : {
98 0 : struct drm_damage_mock *mock = test->priv;
99 0 : struct drm_plane_state state = mock->state;
100 :
101 : /*
102 : * Round down x1/y1 and round up x2/y2. This is because damage is not in
103 : * 16.16 fixed point so to catch all pixels.
104 : */
105 0 : int src_x1 = state.src.x1 >> 16;
106 0 : int src_y1 = state.src.y1 >> 16;
107 0 : int src_x2 = (state.src.x2 >> 16) + !!(state.src.x2 & 0xFFFF);
108 0 : int src_y2 = (state.src.y2 >> 16) + !!(state.src.y2 & 0xFFFF);
109 :
110 0 : if (x1 >= x2 || y1 >= y2)
111 0 : KUNIT_FAIL(test, "Cannot have damage clip with no dimension.");
112 0 : if (x1 < src_x1 || y1 < src_y1 || x2 > src_x2 || y2 > src_y2)
113 0 : KUNIT_FAIL(test, "Damage cannot be outside rounded plane src.");
114 0 : if (r->x1 != x1 || r->y1 != y1 || r->x2 != x2 || r->y2 != y2)
115 0 : KUNIT_FAIL(test, "Damage = %d %d %d %d, want = %d %d %d %d",
116 : r->x1, r->y1, r->x2, r->y2, x1, y1, x2, y2);
117 0 : }
118 :
119 0 : static void drm_test_damage_iter_no_damage(struct kunit *test)
120 : {
121 0 : struct drm_damage_mock *mock = test->priv;
122 : struct drm_atomic_helper_damage_iter iter;
123 : struct drm_rect clip;
124 0 : u32 num_hits = 0;
125 :
126 : /* Plane src same as fb size. */
127 0 : set_plane_src(&mock->old_state, 0, 0, mock->fb.width << 16, mock->fb.height << 16);
128 0 : set_plane_src(&mock->state, 0, 0, mock->fb.width << 16, mock->fb.height << 16);
129 0 : drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
130 0 : drm_atomic_for_each_plane_damage(&iter, &clip)
131 0 : num_hits++;
132 :
133 0 : KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return plane src as damage.");
134 0 : check_damage_clip(test, &clip, 0, 0, 2048, 2048);
135 0 : }
136 :
137 0 : static void drm_test_damage_iter_no_damage_fractional_src(struct kunit *test)
138 : {
139 0 : struct drm_damage_mock *mock = test->priv;
140 : struct drm_atomic_helper_damage_iter iter;
141 : struct drm_rect clip;
142 0 : u32 num_hits = 0;
143 :
144 : /* Plane src has fractional part. */
145 0 : set_plane_src(&mock->old_state, 0x3fffe, 0x3fffe,
146 : 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
147 0 : set_plane_src(&mock->state, 0x3fffe, 0x3fffe,
148 : 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
149 0 : drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
150 0 : drm_atomic_for_each_plane_damage(&iter, &clip)
151 0 : num_hits++;
152 :
153 0 : KUNIT_EXPECT_EQ_MSG(test, num_hits, 1,
154 : "Should return rounded off plane src as damage.");
155 0 : check_damage_clip(test, &clip, 3, 3, 1028, 772);
156 0 : }
157 :
158 0 : static void drm_test_damage_iter_no_damage_src_moved(struct kunit *test)
159 : {
160 0 : struct drm_damage_mock *mock = test->priv;
161 : struct drm_atomic_helper_damage_iter iter;
162 : struct drm_rect clip;
163 0 : u32 num_hits = 0;
164 :
165 : /* Plane src moved since old plane state. */
166 0 : set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
167 0 : set_plane_src(&mock->state, 10 << 16, 10 << 16,
168 : (10 + 1024) << 16, (10 + 768) << 16);
169 0 : drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
170 0 : drm_atomic_for_each_plane_damage(&iter, &clip)
171 0 : num_hits++;
172 :
173 0 : KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return plane src as damage.");
174 0 : check_damage_clip(test, &clip, 10, 10, 1034, 778);
175 0 : }
176 :
177 0 : static void drm_test_damage_iter_no_damage_fractional_src_moved(struct kunit *test)
178 : {
179 0 : struct drm_damage_mock *mock = test->priv;
180 : struct drm_atomic_helper_damage_iter iter;
181 : struct drm_rect clip;
182 0 : u32 num_hits = 0;
183 :
184 : /* Plane src has fractional part and it moved since old plane state. */
185 0 : set_plane_src(&mock->old_state, 0x3fffe, 0x3fffe,
186 : 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
187 0 : set_plane_src(&mock->state, 0x40002, 0x40002,
188 : 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
189 0 : drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
190 0 : drm_atomic_for_each_plane_damage(&iter, &clip)
191 0 : num_hits++;
192 :
193 0 : KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return plane src as damage.");
194 0 : check_damage_clip(test, &clip, 4, 4, 1029, 773);
195 0 : }
196 :
197 0 : static void drm_test_damage_iter_no_damage_not_visible(struct kunit *test)
198 : {
199 0 : struct drm_damage_mock *mock = test->priv;
200 : struct drm_atomic_helper_damage_iter iter;
201 : struct drm_rect clip;
202 0 : u32 num_hits = 0;
203 :
204 0 : mock->state.visible = false;
205 :
206 0 : set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
207 0 : set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
208 0 : drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
209 0 : drm_atomic_for_each_plane_damage(&iter, &clip)
210 0 : num_hits++;
211 :
212 0 : KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage.");
213 0 : }
214 :
215 0 : static void drm_test_damage_iter_no_damage_no_crtc(struct kunit *test)
216 : {
217 0 : struct drm_damage_mock *mock = test->priv;
218 : struct drm_atomic_helper_damage_iter iter;
219 : struct drm_rect clip;
220 0 : u32 num_hits = 0;
221 :
222 0 : mock->state.crtc = NULL;
223 :
224 0 : set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
225 0 : set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
226 0 : drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
227 0 : drm_atomic_for_each_plane_damage(&iter, &clip)
228 0 : num_hits++;
229 :
230 0 : KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage.");
231 0 : }
232 :
233 0 : static void drm_test_damage_iter_no_damage_no_fb(struct kunit *test)
234 : {
235 0 : struct drm_damage_mock *mock = test->priv;
236 : struct drm_atomic_helper_damage_iter iter;
237 : struct drm_rect clip;
238 0 : u32 num_hits = 0;
239 :
240 0 : mock->state.fb = NULL;
241 :
242 0 : set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
243 0 : set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
244 0 : drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
245 0 : drm_atomic_for_each_plane_damage(&iter, &clip)
246 0 : num_hits++;
247 :
248 0 : KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage.");
249 0 : }
250 :
251 0 : static void drm_test_damage_iter_simple_damage(struct kunit *test)
252 : {
253 0 : struct drm_damage_mock *mock = test->priv;
254 : struct drm_atomic_helper_damage_iter iter;
255 : struct drm_property_blob damage_blob;
256 : struct drm_mode_rect damage;
257 : struct drm_rect clip;
258 0 : u32 num_hits = 0;
259 :
260 0 : set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
261 0 : set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
262 : /* Damage set to plane src */
263 0 : set_damage_clip(&damage, 0, 0, 1024, 768);
264 0 : set_damage_blob(&damage_blob, &damage, sizeof(damage));
265 0 : set_plane_damage(&mock->state, &damage_blob);
266 0 : drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
267 0 : drm_atomic_for_each_plane_damage(&iter, &clip)
268 0 : num_hits++;
269 :
270 0 : KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return damage when set.");
271 0 : check_damage_clip(test, &clip, 0, 0, 1024, 768);
272 0 : }
273 :
274 0 : static void drm_test_damage_iter_single_damage(struct kunit *test)
275 : {
276 0 : struct drm_damage_mock *mock = test->priv;
277 : struct drm_atomic_helper_damage_iter iter;
278 : struct drm_property_blob damage_blob;
279 : struct drm_mode_rect damage;
280 : struct drm_rect clip;
281 0 : u32 num_hits = 0;
282 :
283 0 : set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
284 0 : set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
285 0 : set_damage_clip(&damage, 256, 192, 768, 576);
286 0 : set_damage_blob(&damage_blob, &damage, sizeof(damage));
287 0 : set_plane_damage(&mock->state, &damage_blob);
288 0 : drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
289 0 : drm_atomic_for_each_plane_damage(&iter, &clip)
290 0 : num_hits++;
291 :
292 0 : KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return damage when set.");
293 0 : check_damage_clip(test, &clip, 256, 192, 768, 576);
294 0 : }
295 :
296 0 : static void drm_test_damage_iter_single_damage_intersect_src(struct kunit *test)
297 : {
298 0 : struct drm_damage_mock *mock = test->priv;
299 : struct drm_atomic_helper_damage_iter iter;
300 : struct drm_property_blob damage_blob;
301 : struct drm_mode_rect damage;
302 : struct drm_rect clip;
303 0 : u32 num_hits = 0;
304 :
305 0 : set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
306 0 : set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
307 : /* Damage intersect with plane src. */
308 0 : set_damage_clip(&damage, 256, 192, 1360, 768);
309 0 : set_damage_blob(&damage_blob, &damage, sizeof(damage));
310 0 : set_plane_damage(&mock->state, &damage_blob);
311 0 : drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
312 0 : drm_atomic_for_each_plane_damage(&iter, &clip)
313 0 : num_hits++;
314 :
315 0 : KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return damage clipped to src.");
316 0 : check_damage_clip(test, &clip, 256, 192, 1024, 768);
317 0 : }
318 :
319 0 : static void drm_test_damage_iter_single_damage_outside_src(struct kunit *test)
320 : {
321 0 : struct drm_damage_mock *mock = test->priv;
322 : struct drm_atomic_helper_damage_iter iter;
323 : struct drm_property_blob damage_blob;
324 : struct drm_mode_rect damage;
325 : struct drm_rect clip;
326 0 : u32 num_hits = 0;
327 :
328 0 : set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
329 0 : set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
330 : /* Damage clip outside plane src */
331 0 : set_damage_clip(&damage, 1360, 1360, 1380, 1380);
332 0 : set_damage_blob(&damage_blob, &damage, sizeof(damage));
333 0 : set_plane_damage(&mock->state, &damage_blob);
334 0 : drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
335 0 : drm_atomic_for_each_plane_damage(&iter, &clip)
336 0 : num_hits++;
337 :
338 0 : KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage.");
339 0 : }
340 :
341 0 : static void drm_test_damage_iter_single_damage_fractional_src(struct kunit *test)
342 : {
343 0 : struct drm_damage_mock *mock = test->priv;
344 : struct drm_atomic_helper_damage_iter iter;
345 : struct drm_property_blob damage_blob;
346 : struct drm_mode_rect damage;
347 : struct drm_rect clip;
348 0 : u32 num_hits = 0;
349 :
350 : /* Plane src has fractional part. */
351 0 : set_plane_src(&mock->old_state, 0x40002, 0x40002,
352 : 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
353 0 : set_plane_src(&mock->state, 0x40002, 0x40002,
354 : 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
355 0 : set_damage_clip(&damage, 10, 10, 256, 330);
356 0 : set_damage_blob(&damage_blob, &damage, sizeof(damage));
357 0 : set_plane_damage(&mock->state, &damage_blob);
358 0 : drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
359 0 : drm_atomic_for_each_plane_damage(&iter, &clip)
360 0 : num_hits++;
361 :
362 0 : KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return damage when set.");
363 0 : check_damage_clip(test, &clip, 10, 10, 256, 330);
364 0 : }
365 :
366 0 : static void drm_test_damage_iter_single_damage_intersect_fractional_src(struct kunit *test)
367 : {
368 0 : struct drm_damage_mock *mock = test->priv;
369 : struct drm_atomic_helper_damage_iter iter;
370 : struct drm_property_blob damage_blob;
371 : struct drm_mode_rect damage;
372 : struct drm_rect clip;
373 0 : u32 num_hits = 0;
374 :
375 : /* Plane src has fractional part. */
376 0 : set_plane_src(&mock->old_state, 0x40002, 0x40002,
377 : 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
378 0 : set_plane_src(&mock->state, 0x40002, 0x40002,
379 : 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
380 : /* Damage intersect with plane src. */
381 0 : set_damage_clip(&damage, 10, 1, 1360, 330);
382 0 : set_damage_blob(&damage_blob, &damage, sizeof(damage));
383 0 : set_plane_damage(&mock->state, &damage_blob);
384 0 : drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
385 0 : drm_atomic_for_each_plane_damage(&iter, &clip)
386 0 : num_hits++;
387 :
388 0 : KUNIT_EXPECT_EQ_MSG(test, num_hits, 1,
389 : "Should return damage clipped to rounded off src.");
390 0 : check_damage_clip(test, &clip, 10, 4, 1029, 330);
391 0 : }
392 :
393 0 : static void drm_test_damage_iter_single_damage_outside_fractional_src(struct kunit *test)
394 : {
395 0 : struct drm_damage_mock *mock = test->priv;
396 : struct drm_atomic_helper_damage_iter iter;
397 : struct drm_property_blob damage_blob;
398 : struct drm_mode_rect damage;
399 : struct drm_rect clip;
400 0 : u32 num_hits = 0;
401 :
402 : /* Plane src has fractional part. */
403 0 : set_plane_src(&mock->old_state, 0x40002, 0x40002,
404 : 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
405 0 : set_plane_src(&mock->state, 0x40002, 0x40002,
406 : 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
407 : /* Damage clip outside plane src */
408 0 : set_damage_clip(&damage, 1360, 1360, 1380, 1380);
409 0 : set_damage_blob(&damage_blob, &damage, sizeof(damage));
410 0 : set_plane_damage(&mock->state, &damage_blob);
411 0 : drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
412 0 : drm_atomic_for_each_plane_damage(&iter, &clip)
413 0 : num_hits++;
414 :
415 0 : KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage.");
416 0 : }
417 :
418 0 : static void drm_test_damage_iter_single_damage_src_moved(struct kunit *test)
419 : {
420 0 : struct drm_damage_mock *mock = test->priv;
421 : struct drm_atomic_helper_damage_iter iter;
422 : struct drm_property_blob damage_blob;
423 : struct drm_mode_rect damage;
424 : struct drm_rect clip;
425 0 : u32 num_hits = 0;
426 :
427 : /* Plane src moved since old plane state. */
428 0 : set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
429 0 : set_plane_src(&mock->state, 10 << 16, 10 << 16,
430 : (10 + 1024) << 16, (10 + 768) << 16);
431 0 : set_damage_clip(&damage, 20, 30, 256, 256);
432 0 : set_damage_blob(&damage_blob, &damage, sizeof(damage));
433 0 : set_plane_damage(&mock->state, &damage_blob);
434 0 : drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
435 0 : drm_atomic_for_each_plane_damage(&iter, &clip)
436 0 : num_hits++;
437 :
438 0 : KUNIT_EXPECT_EQ_MSG(test, num_hits, 1,
439 : "Should return plane src as damage.");
440 0 : check_damage_clip(test, &clip, 10, 10, 1034, 778);
441 0 : }
442 :
443 0 : static void drm_test_damage_iter_single_damage_fractional_src_moved(struct kunit *test)
444 : {
445 0 : struct drm_damage_mock *mock = test->priv;
446 : struct drm_atomic_helper_damage_iter iter;
447 : struct drm_property_blob damage_blob;
448 : struct drm_mode_rect damage;
449 : struct drm_rect clip;
450 0 : u32 num_hits = 0;
451 :
452 : /* Plane src with fractional part moved since old plane state. */
453 0 : set_plane_src(&mock->old_state, 0x3fffe, 0x3fffe,
454 : 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
455 0 : set_plane_src(&mock->state, 0x40002, 0x40002,
456 : 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
457 : /* Damage intersect with plane src. */
458 0 : set_damage_clip(&damage, 20, 30, 1360, 256);
459 0 : set_damage_blob(&damage_blob, &damage, sizeof(damage));
460 0 : set_plane_damage(&mock->state, &damage_blob);
461 0 : drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
462 0 : drm_atomic_for_each_plane_damage(&iter, &clip)
463 0 : num_hits++;
464 :
465 0 : KUNIT_EXPECT_EQ_MSG(test, num_hits, 1,
466 : "Should return rounded off plane as damage.");
467 0 : check_damage_clip(test, &clip, 4, 4, 1029, 773);
468 0 : }
469 :
470 0 : static void drm_test_damage_iter_damage(struct kunit *test)
471 : {
472 0 : struct drm_damage_mock *mock = test->priv;
473 : struct drm_atomic_helper_damage_iter iter;
474 : struct drm_property_blob damage_blob;
475 : struct drm_mode_rect damage[2];
476 : struct drm_rect clip;
477 0 : u32 num_hits = 0;
478 :
479 0 : set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
480 0 : set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
481 : /* 2 damage clips. */
482 0 : set_damage_clip(&damage[0], 20, 30, 200, 180);
483 0 : set_damage_clip(&damage[1], 240, 200, 280, 250);
484 0 : set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
485 0 : set_plane_damage(&mock->state, &damage_blob);
486 0 : drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
487 0 : drm_atomic_for_each_plane_damage(&iter, &clip) {
488 0 : if (num_hits == 0)
489 0 : check_damage_clip(test, &clip, 20, 30, 200, 180);
490 0 : if (num_hits == 1)
491 0 : check_damage_clip(test, &clip, 240, 200, 280, 250);
492 0 : num_hits++;
493 : }
494 :
495 0 : KUNIT_EXPECT_EQ_MSG(test, num_hits, 2, "Should return damage when set.");
496 0 : }
497 :
498 0 : static void drm_test_damage_iter_damage_one_intersect(struct kunit *test)
499 : {
500 0 : struct drm_damage_mock *mock = test->priv;
501 : struct drm_atomic_helper_damage_iter iter;
502 : struct drm_property_blob damage_blob;
503 : struct drm_mode_rect damage[2];
504 : struct drm_rect clip;
505 0 : u32 num_hits = 0;
506 :
507 0 : set_plane_src(&mock->old_state, 0x40002, 0x40002,
508 : 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
509 0 : set_plane_src(&mock->state, 0x40002, 0x40002,
510 : 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
511 : /* 2 damage clips, one intersect plane src. */
512 0 : set_damage_clip(&damage[0], 20, 30, 200, 180);
513 0 : set_damage_clip(&damage[1], 2, 2, 1360, 1360);
514 0 : set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
515 0 : set_plane_damage(&mock->state, &damage_blob);
516 0 : drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
517 0 : drm_atomic_for_each_plane_damage(&iter, &clip) {
518 0 : if (num_hits == 0)
519 0 : check_damage_clip(test, &clip, 20, 30, 200, 180);
520 0 : if (num_hits == 1)
521 0 : check_damage_clip(test, &clip, 4, 4, 1029, 773);
522 0 : num_hits++;
523 : }
524 :
525 0 : KUNIT_EXPECT_EQ_MSG(test, num_hits, 2, "Should return damage when set.");
526 0 : }
527 :
528 0 : static void drm_test_damage_iter_damage_one_outside(struct kunit *test)
529 : {
530 0 : struct drm_damage_mock *mock = test->priv;
531 : struct drm_atomic_helper_damage_iter iter;
532 : struct drm_property_blob damage_blob;
533 : struct drm_mode_rect damage[2];
534 : struct drm_rect clip;
535 0 : u32 num_hits = 0;
536 :
537 0 : set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
538 0 : set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
539 : /* 2 damage clips, one outside plane src. */
540 0 : set_damage_clip(&damage[0], 1360, 1360, 1380, 1380);
541 0 : set_damage_clip(&damage[1], 240, 200, 280, 250);
542 0 : set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
543 0 : set_plane_damage(&mock->state, &damage_blob);
544 0 : drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
545 0 : drm_atomic_for_each_plane_damage(&iter, &clip)
546 0 : num_hits++;
547 :
548 0 : KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return damage when set.");
549 0 : check_damage_clip(test, &clip, 240, 200, 280, 250);
550 0 : }
551 :
552 0 : static void drm_test_damage_iter_damage_src_moved(struct kunit *test)
553 : {
554 0 : struct drm_damage_mock *mock = test->priv;
555 : struct drm_atomic_helper_damage_iter iter;
556 : struct drm_property_blob damage_blob;
557 : struct drm_mode_rect damage[2];
558 : struct drm_rect clip;
559 0 : u32 num_hits = 0;
560 :
561 0 : set_plane_src(&mock->old_state, 0x40002, 0x40002,
562 : 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
563 0 : set_plane_src(&mock->state, 0x3fffe, 0x3fffe,
564 : 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
565 : /* 2 damage clips, one outside plane src. */
566 0 : set_damage_clip(&damage[0], 1360, 1360, 1380, 1380);
567 0 : set_damage_clip(&damage[1], 240, 200, 280, 250);
568 0 : set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
569 0 : set_plane_damage(&mock->state, &damage_blob);
570 0 : drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
571 0 : drm_atomic_for_each_plane_damage(&iter, &clip)
572 0 : num_hits++;
573 :
574 0 : KUNIT_EXPECT_EQ_MSG(test, num_hits, 1,
575 : "Should return round off plane src as damage.");
576 0 : check_damage_clip(test, &clip, 3, 3, 1028, 772);
577 0 : }
578 :
579 0 : static void drm_test_damage_iter_damage_not_visible(struct kunit *test)
580 : {
581 0 : struct drm_damage_mock *mock = test->priv;
582 : struct drm_atomic_helper_damage_iter iter;
583 : struct drm_property_blob damage_blob;
584 : struct drm_mode_rect damage[2];
585 : struct drm_rect clip;
586 0 : u32 num_hits = 0;
587 :
588 0 : mock->state.visible = false;
589 :
590 0 : set_plane_src(&mock->old_state, 0x40002, 0x40002,
591 : 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
592 0 : set_plane_src(&mock->state, 0x3fffe, 0x3fffe,
593 : 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
594 : /* 2 damage clips, one outside plane src. */
595 0 : set_damage_clip(&damage[0], 1360, 1360, 1380, 1380);
596 0 : set_damage_clip(&damage[1], 240, 200, 280, 250);
597 0 : set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
598 0 : set_plane_damage(&mock->state, &damage_blob);
599 0 : drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
600 0 : drm_atomic_for_each_plane_damage(&iter, &clip)
601 0 : num_hits++;
602 :
603 0 : KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should not return any damage.");
604 0 : }
605 :
606 : static struct kunit_case drm_damage_helper_tests[] = {
607 : KUNIT_CASE(drm_test_damage_iter_no_damage),
608 : KUNIT_CASE(drm_test_damage_iter_no_damage_fractional_src),
609 : KUNIT_CASE(drm_test_damage_iter_no_damage_src_moved),
610 : KUNIT_CASE(drm_test_damage_iter_no_damage_fractional_src_moved),
611 : KUNIT_CASE(drm_test_damage_iter_no_damage_not_visible),
612 : KUNIT_CASE(drm_test_damage_iter_no_damage_no_crtc),
613 : KUNIT_CASE(drm_test_damage_iter_no_damage_no_fb),
614 : KUNIT_CASE(drm_test_damage_iter_simple_damage),
615 : KUNIT_CASE(drm_test_damage_iter_single_damage),
616 : KUNIT_CASE(drm_test_damage_iter_single_damage_intersect_src),
617 : KUNIT_CASE(drm_test_damage_iter_single_damage_outside_src),
618 : KUNIT_CASE(drm_test_damage_iter_single_damage_fractional_src),
619 : KUNIT_CASE(drm_test_damage_iter_single_damage_intersect_fractional_src),
620 : KUNIT_CASE(drm_test_damage_iter_single_damage_outside_fractional_src),
621 : KUNIT_CASE(drm_test_damage_iter_single_damage_src_moved),
622 : KUNIT_CASE(drm_test_damage_iter_single_damage_fractional_src_moved),
623 : KUNIT_CASE(drm_test_damage_iter_damage),
624 : KUNIT_CASE(drm_test_damage_iter_damage_one_intersect),
625 : KUNIT_CASE(drm_test_damage_iter_damage_one_outside),
626 : KUNIT_CASE(drm_test_damage_iter_damage_src_moved),
627 : KUNIT_CASE(drm_test_damage_iter_damage_not_visible),
628 : { }
629 : };
630 :
631 : static struct kunit_suite drm_damage_helper_test_suite = {
632 : .name = "drm_damage_helper",
633 : .init = drm_damage_helper_init,
634 : .test_cases = drm_damage_helper_tests,
635 : };
636 :
637 : kunit_test_suite(drm_damage_helper_test_suite);
638 :
639 : MODULE_LICENSE("GPL");
|