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