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