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