drm_damage_helper_test.c 22 KB

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