Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / drivers / gpu / drm / selftests / test-drm_damage_helper.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }