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
drm_damage_helper_init(struct kunit * test)26 static int drm_damage_helper_init(struct kunit *test)
27 {
28 struct drm_damage_mock *mock;
29
30 mock = kunit_kzalloc(test, sizeof(*mock), GFP_KERNEL);
31 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mock);
32
33 mock->fb.width = 2048;
34 mock->fb.height = 2048;
35
36 mock->state.crtc = ZERO_SIZE_PTR;
37 mock->state.fb = &mock->fb;
38 mock->state.visible = true;
39
40 mock->old_state.plane = &mock->plane;
41 mock->state.plane = &mock->plane;
42
43 /* just enough so that drm_plane_enable_fb_damage_clips() works */
44 mock->device.driver = &mock->driver;
45 mock->device.mode_config.prop_fb_damage_clips = &mock->prop;
46 mock->plane.dev = &mock->device;
47 mock->obj_props.count = 0;
48 mock->plane.base.properties = &mock->obj_props;
49 mock->prop.base.id = 1; /* 0 is an invalid id */
50 mock->prop.dev = &mock->device;
51
52 drm_plane_enable_fb_damage_clips(&mock->plane);
53
54 test->priv = mock;
55
56 return 0;
57 }
58
set_plane_src(struct drm_plane_state * state,int x1,int y1,int x2,int y2)59 static void set_plane_src(struct drm_plane_state *state, int x1, int y1, int x2,
60 int y2)
61 {
62 state->src_x = x1;
63 state->src_y = y1;
64 state->src_w = x2 - x1;
65 state->src_h = y2 - y1;
66
67 state->src.x1 = x1;
68 state->src.y1 = y1;
69 state->src.x2 = x2;
70 state->src.y2 = y2;
71 }
72
set_damage_clip(struct drm_mode_rect * r,int x1,int y1,int x2,int y2)73 static void set_damage_clip(struct drm_mode_rect *r, int x1, int y1, int x2,
74 int y2)
75 {
76 r->x1 = x1;
77 r->y1 = y1;
78 r->x2 = x2;
79 r->y2 = y2;
80 }
81
set_damage_blob(struct drm_property_blob * damage_blob,struct drm_mode_rect * r,u32 size)82 static void set_damage_blob(struct drm_property_blob *damage_blob,
83 struct drm_mode_rect *r, u32 size)
84 {
85 damage_blob->length = size;
86 damage_blob->data = r;
87 }
88
set_plane_damage(struct drm_plane_state * state,struct drm_property_blob * damage_blob)89 static void set_plane_damage(struct drm_plane_state *state,
90 struct drm_property_blob *damage_blob)
91 {
92 state->fb_damage_clips = damage_blob;
93 }
94
check_damage_clip(struct kunit * test,struct drm_rect * r,int x1,int y1,int x2,int y2)95 static void check_damage_clip(struct kunit *test, struct drm_rect *r,
96 int x1, int y1, int x2, int y2)
97 {
98 struct drm_damage_mock *mock = test->priv;
99 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 int src_x1 = state.src.x1 >> 16;
106 int src_y1 = state.src.y1 >> 16;
107 int src_x2 = (state.src.x2 >> 16) + !!(state.src.x2 & 0xFFFF);
108 int src_y2 = (state.src.y2 >> 16) + !!(state.src.y2 & 0xFFFF);
109
110 if (x1 >= x2 || y1 >= y2)
111 KUNIT_FAIL(test, "Cannot have damage clip with no dimension.");
112 if (x1 < src_x1 || y1 < src_y1 || x2 > src_x2 || y2 > src_y2)
113 KUNIT_FAIL(test, "Damage cannot be outside rounded plane src.");
114 if (r->x1 != x1 || r->y1 != y1 || r->x2 != x2 || r->y2 != y2)
115 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 }
118
drm_test_damage_iter_no_damage(struct kunit * test)119 static void drm_test_damage_iter_no_damage(struct kunit *test)
120 {
121 struct drm_damage_mock *mock = test->priv;
122 struct drm_atomic_helper_damage_iter iter;
123 struct drm_rect clip;
124 u32 num_hits = 0;
125
126 /* Plane src same as fb size. */
127 set_plane_src(&mock->old_state, 0, 0, mock->fb.width << 16, mock->fb.height << 16);
128 set_plane_src(&mock->state, 0, 0, mock->fb.width << 16, mock->fb.height << 16);
129 drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
130 drm_atomic_for_each_plane_damage(&iter, &clip)
131 num_hits++;
132
133 KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return plane src as damage.");
134 check_damage_clip(test, &clip, 0, 0, 2048, 2048);
135 }
136
drm_test_damage_iter_no_damage_fractional_src(struct kunit * test)137 static void drm_test_damage_iter_no_damage_fractional_src(struct kunit *test)
138 {
139 struct drm_damage_mock *mock = test->priv;
140 struct drm_atomic_helper_damage_iter iter;
141 struct drm_rect clip;
142 u32 num_hits = 0;
143
144 /* Plane src has fractional part. */
145 set_plane_src(&mock->old_state, 0x3fffe, 0x3fffe,
146 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
147 set_plane_src(&mock->state, 0x3fffe, 0x3fffe,
148 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
149 drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
150 drm_atomic_for_each_plane_damage(&iter, &clip)
151 num_hits++;
152
153 KUNIT_EXPECT_EQ_MSG(test, num_hits, 1,
154 "Should return rounded off plane src as damage.");
155 check_damage_clip(test, &clip, 3, 3, 1028, 772);
156 }
157
drm_test_damage_iter_no_damage_src_moved(struct kunit * test)158 static void drm_test_damage_iter_no_damage_src_moved(struct kunit *test)
159 {
160 struct drm_damage_mock *mock = test->priv;
161 struct drm_atomic_helper_damage_iter iter;
162 struct drm_rect clip;
163 u32 num_hits = 0;
164
165 /* Plane src moved since old plane state. */
166 set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
167 set_plane_src(&mock->state, 10 << 16, 10 << 16,
168 (10 + 1024) << 16, (10 + 768) << 16);
169 drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
170 drm_atomic_for_each_plane_damage(&iter, &clip)
171 num_hits++;
172
173 KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return plane src as damage.");
174 check_damage_clip(test, &clip, 10, 10, 1034, 778);
175 }
176
drm_test_damage_iter_no_damage_fractional_src_moved(struct kunit * test)177 static void drm_test_damage_iter_no_damage_fractional_src_moved(struct kunit *test)
178 {
179 struct drm_damage_mock *mock = test->priv;
180 struct drm_atomic_helper_damage_iter iter;
181 struct drm_rect clip;
182 u32 num_hits = 0;
183
184 /* Plane src has fractional part and it moved since old plane state. */
185 set_plane_src(&mock->old_state, 0x3fffe, 0x3fffe,
186 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
187 set_plane_src(&mock->state, 0x40002, 0x40002,
188 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
189 drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
190 drm_atomic_for_each_plane_damage(&iter, &clip)
191 num_hits++;
192
193 KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return plane src as damage.");
194 check_damage_clip(test, &clip, 4, 4, 1029, 773);
195 }
196
drm_test_damage_iter_no_damage_not_visible(struct kunit * test)197 static void drm_test_damage_iter_no_damage_not_visible(struct kunit *test)
198 {
199 struct drm_damage_mock *mock = test->priv;
200 struct drm_atomic_helper_damage_iter iter;
201 struct drm_rect clip;
202 u32 num_hits = 0;
203
204 mock->state.visible = false;
205
206 set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
207 set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
208 drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
209 drm_atomic_for_each_plane_damage(&iter, &clip)
210 num_hits++;
211
212 KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage.");
213 }
214
drm_test_damage_iter_no_damage_no_crtc(struct kunit * test)215 static void drm_test_damage_iter_no_damage_no_crtc(struct kunit *test)
216 {
217 struct drm_damage_mock *mock = test->priv;
218 struct drm_atomic_helper_damage_iter iter;
219 struct drm_rect clip;
220 u32 num_hits = 0;
221
222 mock->state.crtc = NULL;
223
224 set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
225 set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
226 drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
227 drm_atomic_for_each_plane_damage(&iter, &clip)
228 num_hits++;
229
230 KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage.");
231 }
232
drm_test_damage_iter_no_damage_no_fb(struct kunit * test)233 static void drm_test_damage_iter_no_damage_no_fb(struct kunit *test)
234 {
235 struct drm_damage_mock *mock = test->priv;
236 struct drm_atomic_helper_damage_iter iter;
237 struct drm_rect clip;
238 u32 num_hits = 0;
239
240 mock->state.fb = NULL;
241
242 set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
243 set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
244 drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
245 drm_atomic_for_each_plane_damage(&iter, &clip)
246 num_hits++;
247
248 KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage.");
249 }
250
drm_test_damage_iter_simple_damage(struct kunit * test)251 static void drm_test_damage_iter_simple_damage(struct kunit *test)
252 {
253 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 u32 num_hits = 0;
259
260 set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
261 set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
262 /* Damage set to plane src */
263 set_damage_clip(&damage, 0, 0, 1024, 768);
264 set_damage_blob(&damage_blob, &damage, sizeof(damage));
265 set_plane_damage(&mock->state, &damage_blob);
266 drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
267 drm_atomic_for_each_plane_damage(&iter, &clip)
268 num_hits++;
269
270 KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return damage when set.");
271 check_damage_clip(test, &clip, 0, 0, 1024, 768);
272 }
273
drm_test_damage_iter_single_damage(struct kunit * test)274 static void drm_test_damage_iter_single_damage(struct kunit *test)
275 {
276 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 u32 num_hits = 0;
282
283 set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
284 set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
285 set_damage_clip(&damage, 256, 192, 768, 576);
286 set_damage_blob(&damage_blob, &damage, sizeof(damage));
287 set_plane_damage(&mock->state, &damage_blob);
288 drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
289 drm_atomic_for_each_plane_damage(&iter, &clip)
290 num_hits++;
291
292 KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return damage when set.");
293 check_damage_clip(test, &clip, 256, 192, 768, 576);
294 }
295
drm_test_damage_iter_single_damage_intersect_src(struct kunit * test)296 static void drm_test_damage_iter_single_damage_intersect_src(struct kunit *test)
297 {
298 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 u32 num_hits = 0;
304
305 set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
306 set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
307 /* Damage intersect with plane src. */
308 set_damage_clip(&damage, 256, 192, 1360, 768);
309 set_damage_blob(&damage_blob, &damage, sizeof(damage));
310 set_plane_damage(&mock->state, &damage_blob);
311 drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
312 drm_atomic_for_each_plane_damage(&iter, &clip)
313 num_hits++;
314
315 KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return damage clipped to src.");
316 check_damage_clip(test, &clip, 256, 192, 1024, 768);
317 }
318
drm_test_damage_iter_single_damage_outside_src(struct kunit * test)319 static void drm_test_damage_iter_single_damage_outside_src(struct kunit *test)
320 {
321 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 u32 num_hits = 0;
327
328 set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
329 set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
330 /* Damage clip outside plane src */
331 set_damage_clip(&damage, 1360, 1360, 1380, 1380);
332 set_damage_blob(&damage_blob, &damage, sizeof(damage));
333 set_plane_damage(&mock->state, &damage_blob);
334 drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
335 drm_atomic_for_each_plane_damage(&iter, &clip)
336 num_hits++;
337
338 KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage.");
339 }
340
drm_test_damage_iter_single_damage_fractional_src(struct kunit * test)341 static void drm_test_damage_iter_single_damage_fractional_src(struct kunit *test)
342 {
343 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 u32 num_hits = 0;
349
350 /* Plane src has fractional part. */
351 set_plane_src(&mock->old_state, 0x40002, 0x40002,
352 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
353 set_plane_src(&mock->state, 0x40002, 0x40002,
354 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
355 set_damage_clip(&damage, 10, 10, 256, 330);
356 set_damage_blob(&damage_blob, &damage, sizeof(damage));
357 set_plane_damage(&mock->state, &damage_blob);
358 drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
359 drm_atomic_for_each_plane_damage(&iter, &clip)
360 num_hits++;
361
362 KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return damage when set.");
363 check_damage_clip(test, &clip, 10, 10, 256, 330);
364 }
365
drm_test_damage_iter_single_damage_intersect_fractional_src(struct kunit * test)366 static void drm_test_damage_iter_single_damage_intersect_fractional_src(struct kunit *test)
367 {
368 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 u32 num_hits = 0;
374
375 /* Plane src has fractional part. */
376 set_plane_src(&mock->old_state, 0x40002, 0x40002,
377 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
378 set_plane_src(&mock->state, 0x40002, 0x40002,
379 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
380 /* Damage intersect with plane src. */
381 set_damage_clip(&damage, 10, 1, 1360, 330);
382 set_damage_blob(&damage_blob, &damage, sizeof(damage));
383 set_plane_damage(&mock->state, &damage_blob);
384 drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
385 drm_atomic_for_each_plane_damage(&iter, &clip)
386 num_hits++;
387
388 KUNIT_EXPECT_EQ_MSG(test, num_hits, 1,
389 "Should return damage clipped to rounded off src.");
390 check_damage_clip(test, &clip, 10, 4, 1029, 330);
391 }
392
drm_test_damage_iter_single_damage_outside_fractional_src(struct kunit * test)393 static void drm_test_damage_iter_single_damage_outside_fractional_src(struct kunit *test)
394 {
395 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 u32 num_hits = 0;
401
402 /* Plane src has fractional part. */
403 set_plane_src(&mock->old_state, 0x40002, 0x40002,
404 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
405 set_plane_src(&mock->state, 0x40002, 0x40002,
406 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
407 /* Damage clip outside plane src */
408 set_damage_clip(&damage, 1360, 1360, 1380, 1380);
409 set_damage_blob(&damage_blob, &damage, sizeof(damage));
410 set_plane_damage(&mock->state, &damage_blob);
411 drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
412 drm_atomic_for_each_plane_damage(&iter, &clip)
413 num_hits++;
414
415 KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage.");
416 }
417
drm_test_damage_iter_single_damage_src_moved(struct kunit * test)418 static void drm_test_damage_iter_single_damage_src_moved(struct kunit *test)
419 {
420 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 u32 num_hits = 0;
426
427 /* Plane src moved since old plane state. */
428 set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
429 set_plane_src(&mock->state, 10 << 16, 10 << 16,
430 (10 + 1024) << 16, (10 + 768) << 16);
431 set_damage_clip(&damage, 20, 30, 256, 256);
432 set_damage_blob(&damage_blob, &damage, sizeof(damage));
433 set_plane_damage(&mock->state, &damage_blob);
434 drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
435 drm_atomic_for_each_plane_damage(&iter, &clip)
436 num_hits++;
437
438 KUNIT_EXPECT_EQ_MSG(test, num_hits, 1,
439 "Should return plane src as damage.");
440 check_damage_clip(test, &clip, 10, 10, 1034, 778);
441 }
442
drm_test_damage_iter_single_damage_fractional_src_moved(struct kunit * test)443 static void drm_test_damage_iter_single_damage_fractional_src_moved(struct kunit *test)
444 {
445 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 u32 num_hits = 0;
451
452 /* Plane src with fractional part moved since old plane state. */
453 set_plane_src(&mock->old_state, 0x3fffe, 0x3fffe,
454 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
455 set_plane_src(&mock->state, 0x40002, 0x40002,
456 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
457 /* Damage intersect with plane src. */
458 set_damage_clip(&damage, 20, 30, 1360, 256);
459 set_damage_blob(&damage_blob, &damage, sizeof(damage));
460 set_plane_damage(&mock->state, &damage_blob);
461 drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
462 drm_atomic_for_each_plane_damage(&iter, &clip)
463 num_hits++;
464
465 KUNIT_EXPECT_EQ_MSG(test, num_hits, 1,
466 "Should return rounded off plane as damage.");
467 check_damage_clip(test, &clip, 4, 4, 1029, 773);
468 }
469
drm_test_damage_iter_damage(struct kunit * test)470 static void drm_test_damage_iter_damage(struct kunit *test)
471 {
472 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 u32 num_hits = 0;
478
479 set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
480 set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
481 /* 2 damage clips. */
482 set_damage_clip(&damage[0], 20, 30, 200, 180);
483 set_damage_clip(&damage[1], 240, 200, 280, 250);
484 set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
485 set_plane_damage(&mock->state, &damage_blob);
486 drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
487 drm_atomic_for_each_plane_damage(&iter, &clip) {
488 if (num_hits == 0)
489 check_damage_clip(test, &clip, 20, 30, 200, 180);
490 if (num_hits == 1)
491 check_damage_clip(test, &clip, 240, 200, 280, 250);
492 num_hits++;
493 }
494
495 KUNIT_EXPECT_EQ_MSG(test, num_hits, 2, "Should return damage when set.");
496 }
497
drm_test_damage_iter_damage_one_intersect(struct kunit * test)498 static void drm_test_damage_iter_damage_one_intersect(struct kunit *test)
499 {
500 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 u32 num_hits = 0;
506
507 set_plane_src(&mock->old_state, 0x40002, 0x40002,
508 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
509 set_plane_src(&mock->state, 0x40002, 0x40002,
510 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
511 /* 2 damage clips, one intersect plane src. */
512 set_damage_clip(&damage[0], 20, 30, 200, 180);
513 set_damage_clip(&damage[1], 2, 2, 1360, 1360);
514 set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
515 set_plane_damage(&mock->state, &damage_blob);
516 drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
517 drm_atomic_for_each_plane_damage(&iter, &clip) {
518 if (num_hits == 0)
519 check_damage_clip(test, &clip, 20, 30, 200, 180);
520 if (num_hits == 1)
521 check_damage_clip(test, &clip, 4, 4, 1029, 773);
522 num_hits++;
523 }
524
525 KUNIT_EXPECT_EQ_MSG(test, num_hits, 2, "Should return damage when set.");
526 }
527
drm_test_damage_iter_damage_one_outside(struct kunit * test)528 static void drm_test_damage_iter_damage_one_outside(struct kunit *test)
529 {
530 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 u32 num_hits = 0;
536
537 set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
538 set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
539 /* 2 damage clips, one outside plane src. */
540 set_damage_clip(&damage[0], 1360, 1360, 1380, 1380);
541 set_damage_clip(&damage[1], 240, 200, 280, 250);
542 set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
543 set_plane_damage(&mock->state, &damage_blob);
544 drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
545 drm_atomic_for_each_plane_damage(&iter, &clip)
546 num_hits++;
547
548 KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return damage when set.");
549 check_damage_clip(test, &clip, 240, 200, 280, 250);
550 }
551
drm_test_damage_iter_damage_src_moved(struct kunit * test)552 static void drm_test_damage_iter_damage_src_moved(struct kunit *test)
553 {
554 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 u32 num_hits = 0;
560
561 set_plane_src(&mock->old_state, 0x40002, 0x40002,
562 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
563 set_plane_src(&mock->state, 0x3fffe, 0x3fffe,
564 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
565 /* 2 damage clips, one outside plane src. */
566 set_damage_clip(&damage[0], 1360, 1360, 1380, 1380);
567 set_damage_clip(&damage[1], 240, 200, 280, 250);
568 set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
569 set_plane_damage(&mock->state, &damage_blob);
570 drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
571 drm_atomic_for_each_plane_damage(&iter, &clip)
572 num_hits++;
573
574 KUNIT_EXPECT_EQ_MSG(test, num_hits, 1,
575 "Should return round off plane src as damage.");
576 check_damage_clip(test, &clip, 3, 3, 1028, 772);
577 }
578
drm_test_damage_iter_damage_not_visible(struct kunit * test)579 static void drm_test_damage_iter_damage_not_visible(struct kunit *test)
580 {
581 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 u32 num_hits = 0;
587
588 mock->state.visible = false;
589
590 set_plane_src(&mock->old_state, 0x40002, 0x40002,
591 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
592 set_plane_src(&mock->state, 0x3fffe, 0x3fffe,
593 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
594 /* 2 damage clips, one outside plane src. */
595 set_damage_clip(&damage[0], 1360, 1360, 1380, 1380);
596 set_damage_clip(&damage[1], 240, 200, 280, 250);
597 set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
598 set_plane_damage(&mock->state, &damage_blob);
599 drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
600 drm_atomic_for_each_plane_damage(&iter, &clip)
601 num_hits++;
602
603 KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should not return any damage.");
604 }
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");
640