Linux Audio

Check our new training course

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