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
10 #include "test-drm_modeset_common.h"
11
set_plane_src(struct drm_plane_state * state,int x1,int y1,int x2,int y2)12 static void set_plane_src(struct drm_plane_state *state, int x1, int y1, int x2,
13 int y2)
14 {
15 state->src.x1 = x1;
16 state->src.y1 = y1;
17 state->src.x2 = x2;
18 state->src.y2 = y2;
19 }
20
set_damage_clip(struct drm_mode_rect * r,int x1,int y1,int x2,int y2)21 static void set_damage_clip(struct drm_mode_rect *r, int x1, int y1, int x2,
22 int y2)
23 {
24 r->x1 = x1;
25 r->y1 = y1;
26 r->x2 = x2;
27 r->y2 = y2;
28 }
29
set_damage_blob(struct drm_property_blob * damage_blob,struct drm_mode_rect * r,uint32_t size)30 static void set_damage_blob(struct drm_property_blob *damage_blob,
31 struct drm_mode_rect *r, uint32_t size)
32 {
33 damage_blob->length = size;
34 damage_blob->data = r;
35 }
36
set_plane_damage(struct drm_plane_state * state,struct drm_property_blob * damage_blob)37 static void set_plane_damage(struct drm_plane_state *state,
38 struct drm_property_blob *damage_blob)
39 {
40 state->fb_damage_clips = damage_blob;
41 }
42
check_damage_clip(struct drm_plane_state * state,struct drm_rect * r,int x1,int y1,int x2,int y2)43 static bool check_damage_clip(struct drm_plane_state *state, struct drm_rect *r,
44 int x1, int y1, int x2, int y2)
45 {
46 /*
47 * Round down x1/y1 and round up x2/y2. This is because damage is not in
48 * 16.16 fixed point so to catch all pixels.
49 */
50 int src_x1 = state->src.x1 >> 16;
51 int src_y1 = state->src.y1 >> 16;
52 int src_x2 = (state->src.x2 >> 16) + !!(state->src.x2 & 0xFFFF);
53 int src_y2 = (state->src.y2 >> 16) + !!(state->src.y2 & 0xFFFF);
54
55 if (x1 >= x2 || y1 >= y2) {
56 pr_err("Cannot have damage clip with no dimension.\n");
57 return false;
58 }
59
60 if (x1 < src_x1 || y1 < src_y1 || x2 > src_x2 || y2 > src_y2) {
61 pr_err("Damage cannot be outside rounded plane src.\n");
62 return false;
63 }
64
65 if (r->x1 != x1 || r->y1 != y1 || r->x2 != x2 || r->y2 != y2) {
66 pr_err("Damage = %d %d %d %d\n", r->x1, r->y1, r->x2, r->y2);
67 return false;
68 }
69
70 return true;
71 }
72
igt_damage_iter_no_damage(void * ignored)73 int igt_damage_iter_no_damage(void *ignored)
74 {
75 struct drm_atomic_helper_damage_iter iter;
76 struct drm_plane_state old_state;
77 struct drm_rect clip;
78 uint32_t num_hits = 0;
79
80 struct drm_framebuffer fb = {
81 .width = 2048,
82 .height = 2048
83 };
84
85 struct drm_plane_state state = {
86 .crtc = ZERO_SIZE_PTR,
87 .fb = &fb,
88 .visible = true,
89 };
90
91 /* Plane src same as fb size. */
92 set_plane_src(&old_state, 0, 0, fb.width << 16, fb.height << 16);
93 set_plane_src(&state, 0, 0, fb.width << 16, fb.height << 16);
94 drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
95 drm_atomic_for_each_plane_damage(&iter, &clip)
96 num_hits++;
97
98 FAIL(num_hits != 1, "Should return plane src as damage.");
99 FAIL_ON(!check_damage_clip(&state, &clip, 0, 0, 2048, 2048));
100
101 return 0;
102 }
103
igt_damage_iter_no_damage_fractional_src(void * ignored)104 int igt_damage_iter_no_damage_fractional_src(void *ignored)
105 {
106 struct drm_atomic_helper_damage_iter iter;
107 struct drm_plane_state old_state;
108 struct drm_rect clip;
109 uint32_t num_hits = 0;
110
111 struct drm_framebuffer fb = {
112 .width = 2048,
113 .height = 2048
114 };
115
116 struct drm_plane_state state = {
117 .crtc = ZERO_SIZE_PTR,
118 .fb = &fb,
119 .visible = true,
120 };
121
122 /* Plane src has fractional part. */
123 set_plane_src(&old_state, 0x3fffe, 0x3fffe,
124 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
125 set_plane_src(&state, 0x3fffe, 0x3fffe,
126 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
127 drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
128 drm_atomic_for_each_plane_damage(&iter, &clip)
129 num_hits++;
130
131 FAIL(num_hits != 1, "Should return rounded off plane src as damage.");
132 FAIL_ON(!check_damage_clip(&state, &clip, 3, 3, 1028, 772));
133
134 return 0;
135 }
136
igt_damage_iter_no_damage_src_moved(void * ignored)137 int igt_damage_iter_no_damage_src_moved(void *ignored)
138 {
139 struct drm_atomic_helper_damage_iter iter;
140 struct drm_plane_state old_state;
141 struct drm_rect clip;
142 uint32_t num_hits = 0;
143
144 struct drm_framebuffer fb = {
145 .width = 2048,
146 .height = 2048
147 };
148
149 struct drm_plane_state state = {
150 .crtc = ZERO_SIZE_PTR,
151 .fb = &fb,
152 .visible = true,
153 };
154
155 /* Plane src moved since old plane state. */
156 set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
157 set_plane_src(&state, 10 << 16, 10 << 16,
158 (10 + 1024) << 16, (10 + 768) << 16);
159 drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
160 drm_atomic_for_each_plane_damage(&iter, &clip)
161 num_hits++;
162
163 FAIL(num_hits != 1, "Should return plane src as damage.");
164 FAIL_ON(!check_damage_clip(&state, &clip, 10, 10, 1034, 778));
165
166 return 0;
167 }
168
igt_damage_iter_no_damage_fractional_src_moved(void * ignored)169 int igt_damage_iter_no_damage_fractional_src_moved(void *ignored)
170 {
171 struct drm_atomic_helper_damage_iter iter;
172 struct drm_plane_state old_state;
173 struct drm_rect clip;
174 uint32_t num_hits = 0;
175
176 struct drm_framebuffer fb = {
177 .width = 2048,
178 .height = 2048
179 };
180
181 struct drm_plane_state state = {
182 .crtc = ZERO_SIZE_PTR,
183 .fb = &fb,
184 .visible = true,
185 };
186
187 /* Plane src has fractional part and it moved since old plane state. */
188 set_plane_src(&old_state, 0x3fffe, 0x3fffe,
189 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
190 set_plane_src(&state, 0x40002, 0x40002,
191 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
192 drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
193 drm_atomic_for_each_plane_damage(&iter, &clip)
194 num_hits++;
195
196 FAIL(num_hits != 1, "Should return plane src as damage.");
197 FAIL_ON(!check_damage_clip(&state, &clip, 4, 4, 1029, 773));
198
199 return 0;
200 }
201
igt_damage_iter_no_damage_not_visible(void * ignored)202 int igt_damage_iter_no_damage_not_visible(void *ignored)
203 {
204 struct drm_atomic_helper_damage_iter iter;
205 struct drm_plane_state old_state;
206 struct drm_rect clip;
207 uint32_t num_hits = 0;
208
209 struct drm_framebuffer fb = {
210 .width = 2048,
211 .height = 2048
212 };
213
214 struct drm_plane_state state = {
215 .crtc = ZERO_SIZE_PTR,
216 .fb = &fb,
217 .visible = false,
218 };
219
220 set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
221 set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
222 drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
223 drm_atomic_for_each_plane_damage(&iter, &clip)
224 num_hits++;
225
226 FAIL(num_hits != 0, "Should have no damage.");
227
228 return 0;
229 }
230
igt_damage_iter_no_damage_no_crtc(void * ignored)231 int igt_damage_iter_no_damage_no_crtc(void *ignored)
232 {
233 struct drm_atomic_helper_damage_iter iter;
234 struct drm_plane_state old_state;
235 struct drm_rect clip;
236 uint32_t num_hits = 0;
237
238 struct drm_framebuffer fb = {
239 .width = 2048,
240 .height = 2048
241 };
242
243 struct drm_plane_state state = {
244 .crtc = 0,
245 .fb = &fb,
246 };
247
248 set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
249 set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
250 drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
251 drm_atomic_for_each_plane_damage(&iter, &clip)
252 num_hits++;
253
254 FAIL(num_hits != 0, "Should have no damage.");
255
256 return 0;
257 }
258
igt_damage_iter_no_damage_no_fb(void * ignored)259 int igt_damage_iter_no_damage_no_fb(void *ignored)
260 {
261 struct drm_atomic_helper_damage_iter iter;
262 struct drm_plane_state old_state;
263 struct drm_rect clip;
264 uint32_t num_hits = 0;
265
266 struct drm_plane_state state = {
267 .crtc = ZERO_SIZE_PTR,
268 .fb = 0,
269 };
270
271 set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
272 set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
273 drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
274 drm_atomic_for_each_plane_damage(&iter, &clip)
275 num_hits++;
276
277 FAIL(num_hits != 0, "Should have no damage.");
278
279 return 0;
280 }
281
igt_damage_iter_simple_damage(void * ignored)282 int igt_damage_iter_simple_damage(void *ignored)
283 {
284 struct drm_atomic_helper_damage_iter iter;
285 struct drm_plane_state old_state;
286 struct drm_property_blob damage_blob;
287 struct drm_mode_rect damage;
288 struct drm_rect clip;
289 uint32_t num_hits = 0;
290
291 struct drm_framebuffer fb = {
292 .width = 2048,
293 .height = 2048
294 };
295
296 struct drm_plane_state state = {
297 .crtc = ZERO_SIZE_PTR,
298 .fb = &fb,
299 .visible = true,
300 };
301
302 set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
303 set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
304 /* Damage set to plane src */
305 set_damage_clip(&damage, 0, 0, 1024, 768);
306 set_damage_blob(&damage_blob, &damage, sizeof(damage));
307 set_plane_damage(&state, &damage_blob);
308 drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
309 drm_atomic_for_each_plane_damage(&iter, &clip)
310 num_hits++;
311
312 FAIL(num_hits != 1, "Should return damage when set.");
313 FAIL_ON(!check_damage_clip(&state, &clip, 0, 0, 1024, 768));
314
315 return 0;
316 }
317
igt_damage_iter_single_damage(void * ignored)318 int igt_damage_iter_single_damage(void *ignored)
319 {
320 struct drm_atomic_helper_damage_iter iter;
321 struct drm_plane_state old_state;
322 struct drm_property_blob damage_blob;
323 struct drm_mode_rect damage;
324 struct drm_rect clip;
325 uint32_t num_hits = 0;
326
327 struct drm_framebuffer fb = {
328 .width = 2048,
329 .height = 2048
330 };
331
332 struct drm_plane_state state = {
333 .crtc = ZERO_SIZE_PTR,
334 .fb = &fb,
335 .visible = true,
336 };
337
338 set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
339 set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
340 set_damage_clip(&damage, 256, 192, 768, 576);
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 when set.");
348 FAIL_ON(!check_damage_clip(&state, &clip, 256, 192, 768, 576));
349
350 return 0;
351 }
352
igt_damage_iter_single_damage_intersect_src(void * ignored)353 int igt_damage_iter_single_damage_intersect_src(void *ignored)
354 {
355 struct drm_atomic_helper_damage_iter iter;
356 struct drm_plane_state old_state;
357 struct drm_property_blob damage_blob;
358 struct drm_mode_rect damage;
359 struct drm_rect clip;
360 uint32_t num_hits = 0;
361
362 struct drm_framebuffer fb = {
363 .width = 2048,
364 .height = 2048
365 };
366
367 struct drm_plane_state state = {
368 .crtc = ZERO_SIZE_PTR,
369 .fb = &fb,
370 .visible = true,
371 };
372
373 set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
374 set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
375 /* Damage intersect with plane src. */
376 set_damage_clip(&damage, 256, 192, 1360, 768);
377 set_damage_blob(&damage_blob, &damage, sizeof(damage));
378 set_plane_damage(&state, &damage_blob);
379 drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
380 drm_atomic_for_each_plane_damage(&iter, &clip)
381 num_hits++;
382
383 FAIL(num_hits != 1, "Should return damage clipped to src.");
384 FAIL_ON(!check_damage_clip(&state, &clip, 256, 192, 1024, 768));
385
386 return 0;
387 }
388
igt_damage_iter_single_damage_outside_src(void * ignored)389 int igt_damage_iter_single_damage_outside_src(void *ignored)
390 {
391 struct drm_atomic_helper_damage_iter iter;
392 struct drm_plane_state old_state;
393 struct drm_property_blob damage_blob;
394 struct drm_mode_rect damage;
395 struct drm_rect clip;
396 uint32_t num_hits = 0;
397
398 struct drm_framebuffer fb = {
399 .width = 2048,
400 .height = 2048
401 };
402
403 struct drm_plane_state state = {
404 .crtc = ZERO_SIZE_PTR,
405 .fb = &fb,
406 .visible = true,
407 };
408
409 set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
410 set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
411 /* Damage clip outside plane src */
412 set_damage_clip(&damage, 1360, 1360, 1380, 1380);
413 set_damage_blob(&damage_blob, &damage, sizeof(damage));
414 set_plane_damage(&state, &damage_blob);
415 drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
416 drm_atomic_for_each_plane_damage(&iter, &clip)
417 num_hits++;
418
419 FAIL(num_hits != 0, "Should have no damage.");
420
421 return 0;
422 }
423
igt_damage_iter_single_damage_fractional_src(void * ignored)424 int igt_damage_iter_single_damage_fractional_src(void *ignored)
425 {
426 struct drm_atomic_helper_damage_iter iter;
427 struct drm_plane_state old_state;
428 struct drm_property_blob damage_blob;
429 struct drm_mode_rect damage;
430 struct drm_rect clip;
431 uint32_t num_hits = 0;
432
433 struct drm_framebuffer fb = {
434 .width = 2048,
435 .height = 2048
436 };
437
438 struct drm_plane_state state = {
439 .crtc = ZERO_SIZE_PTR,
440 .fb = &fb,
441 .visible = true,
442 };
443
444 /* Plane src has fractional part. */
445 set_plane_src(&old_state, 0x40002, 0x40002,
446 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
447 set_plane_src(&state, 0x40002, 0x40002,
448 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
449 set_damage_clip(&damage, 10, 10, 256, 330);
450 set_damage_blob(&damage_blob, &damage, sizeof(damage));
451 set_plane_damage(&state, &damage_blob);
452 drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
453 drm_atomic_for_each_plane_damage(&iter, &clip)
454 num_hits++;
455
456 FAIL(num_hits != 1, "Should return damage when set.");
457 FAIL_ON(!check_damage_clip(&state, &clip, 10, 10, 256, 330));
458
459 return 0;
460 }
461
igt_damage_iter_single_damage_intersect_fractional_src(void * ignored)462 int igt_damage_iter_single_damage_intersect_fractional_src(void *ignored)
463 {
464 struct drm_atomic_helper_damage_iter iter;
465 struct drm_plane_state old_state;
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 struct drm_framebuffer fb = {
472 .width = 2048,
473 .height = 2048
474 };
475
476 struct drm_plane_state state = {
477 .crtc = ZERO_SIZE_PTR,
478 .fb = &fb,
479 .visible = true,
480 };
481
482 /* Plane src has fractional part. */
483 set_plane_src(&old_state, 0x40002, 0x40002,
484 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
485 set_plane_src(&state, 0x40002, 0x40002,
486 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
487 /* Damage intersect with plane src. */
488 set_damage_clip(&damage, 10, 1, 1360, 330);
489 set_damage_blob(&damage_blob, &damage, sizeof(damage));
490 set_plane_damage(&state, &damage_blob);
491 drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
492 drm_atomic_for_each_plane_damage(&iter, &clip)
493 num_hits++;
494
495 FAIL(num_hits != 1, "Should return damage clipped to rounded off src.");
496 FAIL_ON(!check_damage_clip(&state, &clip, 10, 4, 1029, 330));
497
498 return 0;
499 }
500
igt_damage_iter_single_damage_outside_fractional_src(void * ignored)501 int igt_damage_iter_single_damage_outside_fractional_src(void *ignored)
502 {
503 struct drm_atomic_helper_damage_iter iter;
504 struct drm_plane_state old_state;
505 struct drm_property_blob damage_blob;
506 struct drm_mode_rect damage;
507 struct drm_rect clip;
508 uint32_t num_hits = 0;
509
510 struct drm_framebuffer fb = {
511 .width = 2048,
512 .height = 2048
513 };
514
515 struct drm_plane_state state = {
516 .crtc = ZERO_SIZE_PTR,
517 .fb = &fb,
518 .visible = true,
519 };
520
521 /* Plane src has fractional part. */
522 set_plane_src(&old_state, 0x40002, 0x40002,
523 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
524 set_plane_src(&state, 0x40002, 0x40002,
525 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
526 /* Damage clip outside plane src */
527 set_damage_clip(&damage, 1360, 1360, 1380, 1380);
528 set_damage_blob(&damage_blob, &damage, sizeof(damage));
529 set_plane_damage(&state, &damage_blob);
530 drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
531 drm_atomic_for_each_plane_damage(&iter, &clip)
532 num_hits++;
533
534 FAIL(num_hits != 0, "Should have no damage.");
535
536 return 0;
537 }
538
igt_damage_iter_single_damage_src_moved(void * ignored)539 int igt_damage_iter_single_damage_src_moved(void *ignored)
540 {
541 struct drm_atomic_helper_damage_iter iter;
542 struct drm_plane_state old_state;
543 struct drm_property_blob damage_blob;
544 struct drm_mode_rect damage;
545 struct drm_rect clip;
546 uint32_t num_hits = 0;
547
548 struct drm_framebuffer fb = {
549 .width = 2048,
550 .height = 2048
551 };
552
553 struct drm_plane_state state = {
554 .crtc = ZERO_SIZE_PTR,
555 .fb = &fb,
556 .visible = true,
557 };
558
559 /* Plane src moved since old plane state. */
560 set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
561 set_plane_src(&state, 10 << 16, 10 << 16,
562 (10 + 1024) << 16, (10 + 768) << 16);
563 set_damage_clip(&damage, 20, 30, 256, 256);
564 set_damage_blob(&damage_blob, &damage, sizeof(damage));
565 set_plane_damage(&state, &damage_blob);
566 drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
567 drm_atomic_for_each_plane_damage(&iter, &clip)
568 num_hits++;
569
570 FAIL(num_hits != 1, "Should return plane src as damage.");
571 FAIL_ON(!check_damage_clip(&state, &clip, 10, 10, 1034, 778));
572
573 return 0;
574 }
575
igt_damage_iter_single_damage_fractional_src_moved(void * ignored)576 int igt_damage_iter_single_damage_fractional_src_moved(void *ignored)
577 {
578 struct drm_atomic_helper_damage_iter iter;
579 struct drm_plane_state old_state;
580 struct drm_property_blob damage_blob;
581 struct drm_mode_rect damage;
582 struct drm_rect clip;
583 uint32_t num_hits = 0;
584
585 struct drm_framebuffer fb = {
586 .width = 2048,
587 .height = 2048
588 };
589
590 struct drm_plane_state state = {
591 .crtc = ZERO_SIZE_PTR,
592 .fb = &fb,
593 .visible = true,
594 };
595
596 /* Plane src with fractional part moved since old plane state. */
597 set_plane_src(&old_state, 0x3fffe, 0x3fffe,
598 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
599 set_plane_src(&state, 0x40002, 0x40002,
600 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
601 /* Damage intersect with plane src. */
602 set_damage_clip(&damage, 20, 30, 1360, 256);
603 set_damage_blob(&damage_blob, &damage, sizeof(damage));
604 set_plane_damage(&state, &damage_blob);
605 drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
606 drm_atomic_for_each_plane_damage(&iter, &clip)
607 num_hits++;
608
609 FAIL(num_hits != 1, "Should return rounded off plane src as damage.");
610 FAIL_ON(!check_damage_clip(&state, &clip, 4, 4, 1029, 773));
611
612 return 0;
613 }
614
igt_damage_iter_damage(void * ignored)615 int igt_damage_iter_damage(void *ignored)
616 {
617 struct drm_atomic_helper_damage_iter iter;
618 struct drm_plane_state old_state;
619 struct drm_property_blob damage_blob;
620 struct drm_mode_rect damage[2];
621 struct drm_rect clip;
622 uint32_t num_hits = 0;
623
624 struct drm_framebuffer fb = {
625 .width = 2048,
626 .height = 2048
627 };
628
629 struct drm_plane_state state = {
630 .crtc = ZERO_SIZE_PTR,
631 .fb = &fb,
632 .visible = true,
633 };
634
635 set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
636 set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
637 /* 2 damage clips. */
638 set_damage_clip(&damage[0], 20, 30, 200, 180);
639 set_damage_clip(&damage[1], 240, 200, 280, 250);
640 set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
641 set_plane_damage(&state, &damage_blob);
642 drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
643 drm_atomic_for_each_plane_damage(&iter, &clip) {
644 if (num_hits == 0)
645 FAIL_ON(!check_damage_clip(&state, &clip, 20, 30, 200, 180));
646 if (num_hits == 1)
647 FAIL_ON(!check_damage_clip(&state, &clip, 240, 200, 280, 250));
648 num_hits++;
649 }
650
651 FAIL(num_hits != 2, "Should return damage when set.");
652
653 return 0;
654 }
655
igt_damage_iter_damage_one_intersect(void * ignored)656 int igt_damage_iter_damage_one_intersect(void *ignored)
657 {
658 struct drm_atomic_helper_damage_iter iter;
659 struct drm_plane_state old_state;
660 struct drm_property_blob damage_blob;
661 struct drm_mode_rect damage[2];
662 struct drm_rect clip;
663 uint32_t num_hits = 0;
664
665 struct drm_framebuffer fb = {
666 .width = 2048,
667 .height = 2048
668 };
669
670 struct drm_plane_state state = {
671 .crtc = ZERO_SIZE_PTR,
672 .fb = &fb,
673 .visible = true,
674 };
675
676 set_plane_src(&old_state, 0x40002, 0x40002,
677 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
678 set_plane_src(&state, 0x40002, 0x40002,
679 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
680 /* 2 damage clips, one intersect plane src. */
681 set_damage_clip(&damage[0], 20, 30, 200, 180);
682 set_damage_clip(&damage[1], 2, 2, 1360, 1360);
683 set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
684 set_plane_damage(&state, &damage_blob);
685 drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
686 drm_atomic_for_each_plane_damage(&iter, &clip) {
687 if (num_hits == 0)
688 FAIL_ON(!check_damage_clip(&state, &clip, 20, 30, 200, 180));
689 if (num_hits == 1)
690 FAIL_ON(!check_damage_clip(&state, &clip, 4, 4, 1029, 773));
691 num_hits++;
692 }
693
694 FAIL(num_hits != 2, "Should return damage when set.");
695
696 return 0;
697 }
698
igt_damage_iter_damage_one_outside(void * ignored)699 int igt_damage_iter_damage_one_outside(void *ignored)
700 {
701 struct drm_atomic_helper_damage_iter iter;
702 struct drm_plane_state old_state;
703 struct drm_property_blob damage_blob;
704 struct drm_mode_rect damage[2];
705 struct drm_rect clip;
706 uint32_t num_hits = 0;
707
708 struct drm_framebuffer fb = {
709 .width = 2048,
710 .height = 2048
711 };
712
713 struct drm_plane_state state = {
714 .crtc = ZERO_SIZE_PTR,
715 .fb = &fb,
716 .visible = true,
717 };
718
719 set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
720 set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
721 /* 2 damage clips, one outside plane src. */
722 set_damage_clip(&damage[0], 1360, 1360, 1380, 1380);
723 set_damage_clip(&damage[1], 240, 200, 280, 250);
724 set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
725 set_plane_damage(&state, &damage_blob);
726 drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
727 drm_atomic_for_each_plane_damage(&iter, &clip)
728 num_hits++;
729
730 FAIL(num_hits != 1, "Should return damage when set.");
731 FAIL_ON(!check_damage_clip(&state, &clip, 240, 200, 280, 250));
732
733 return 0;
734 }
735
igt_damage_iter_damage_src_moved(void * ignored)736 int igt_damage_iter_damage_src_moved(void *ignored)
737 {
738 struct drm_atomic_helper_damage_iter iter;
739 struct drm_plane_state old_state;
740 struct drm_property_blob damage_blob;
741 struct drm_mode_rect damage[2];
742 struct drm_rect clip;
743 uint32_t num_hits = 0;
744
745 struct drm_framebuffer fb = {
746 .width = 2048,
747 .height = 2048
748 };
749
750 struct drm_plane_state state = {
751 .crtc = ZERO_SIZE_PTR,
752 .fb = &fb,
753 .visible = true,
754 };
755
756 set_plane_src(&old_state, 0x40002, 0x40002,
757 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
758 set_plane_src(&state, 0x3fffe, 0x3fffe,
759 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
760 /* 2 damage clips, one outside plane src. */
761 set_damage_clip(&damage[0], 1360, 1360, 1380, 1380);
762 set_damage_clip(&damage[1], 240, 200, 280, 250);
763 set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
764 set_plane_damage(&state, &damage_blob);
765 drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
766 drm_atomic_for_each_plane_damage(&iter, &clip)
767 num_hits++;
768
769 FAIL(num_hits != 1, "Should return round off plane src as damage.");
770 FAIL_ON(!check_damage_clip(&state, &clip, 3, 3, 1028, 772));
771
772 return 0;
773 }
774
igt_damage_iter_damage_not_visible(void * ignored)775 int igt_damage_iter_damage_not_visible(void *ignored)
776 {
777 struct drm_atomic_helper_damage_iter iter;
778 struct drm_plane_state old_state;
779 struct drm_property_blob damage_blob;
780 struct drm_mode_rect damage[2];
781 struct drm_rect clip;
782 uint32_t num_hits = 0;
783
784 struct drm_framebuffer fb = {
785 .width = 2048,
786 .height = 2048
787 };
788
789 struct drm_plane_state state = {
790 .crtc = ZERO_SIZE_PTR,
791 .fb = &fb,
792 .visible = false,
793 };
794
795 set_plane_src(&old_state, 0x40002, 0x40002,
796 0x40002 + (1024 << 16), 0x40002 + (768 << 16));
797 set_plane_src(&state, 0x3fffe, 0x3fffe,
798 0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
799 /* 2 damage clips, one outside plane src. */
800 set_damage_clip(&damage[0], 1360, 1360, 1380, 1380);
801 set_damage_clip(&damage[1], 240, 200, 280, 250);
802 set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
803 set_plane_damage(&state, &damage_blob);
804 drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
805 drm_atomic_for_each_plane_damage(&iter, &clip)
806 num_hits++;
807
808 FAIL(num_hits != 0, "Should not return any damage.");
809
810 return 0;
811 }
812