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_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 73 static 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 82 static 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 89 static 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 95 static 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 119 static 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 137 static 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 158 static 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 177 static 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 197 static 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 215 static 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 233 static 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 251 static 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 274 static 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 296 static 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 319 static 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 341 static 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 366 static 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 393 static 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 418 static 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 443 static 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 470 static 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 498 static 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 528 static 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 552 static 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 579 static 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 606 static 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 631 static 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 637 kunit_test_suite(drm_damage_helper_test_suite); 638 639 MODULE_DESCRIPTION("Test case for drm_damage_helper functions"); 640 MODULE_LICENSE("GPL"); 641