test-drm-helper.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /*
  2. * Test cases for the drm_kms_helper functions
  3. */
  4. #define pr_fmt(fmt) "drm_kms_helper: " fmt
  5. #include <linux/module.h>
  6. #include <drm/drm_atomic_helper.h>
  7. #include <drm/drm_plane_helper.h>
  8. #include <drm/drm_modes.h>
  9. #define TESTS "drm_helper_selftests.h"
  10. #include "drm_selftest.h"
  11. #define FAIL(test, msg, ...) \
  12. do { \
  13. if (test) { \
  14. pr_err("%s/%u: " msg, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
  15. return -EINVAL; \
  16. } \
  17. } while (0)
  18. #define FAIL_ON(x) FAIL((x), "%s", "FAIL_ON(" __stringify(x) ")\n")
  19. static void set_src(struct drm_plane_state *plane_state,
  20. unsigned src_x, unsigned src_y,
  21. unsigned src_w, unsigned src_h)
  22. {
  23. plane_state->src_x = src_x;
  24. plane_state->src_y = src_y;
  25. plane_state->src_w = src_w;
  26. plane_state->src_h = src_h;
  27. }
  28. static bool check_src_eq(struct drm_plane_state *plane_state,
  29. unsigned src_x, unsigned src_y,
  30. unsigned src_w, unsigned src_h)
  31. {
  32. if (plane_state->src.x1 < 0) {
  33. pr_err("src x coordinate %x should never be below 0.\n", plane_state->src.x1);
  34. drm_rect_debug_print("src: ", &plane_state->src, true);
  35. return false;
  36. }
  37. if (plane_state->src.y1 < 0) {
  38. pr_err("src y coordinate %x should never be below 0.\n", plane_state->src.y1);
  39. drm_rect_debug_print("src: ", &plane_state->src, true);
  40. return false;
  41. }
  42. if (plane_state->src.x1 != src_x ||
  43. plane_state->src.y1 != src_y ||
  44. drm_rect_width(&plane_state->src) != src_w ||
  45. drm_rect_height(&plane_state->src) != src_h) {
  46. drm_rect_debug_print("src: ", &plane_state->src, true);
  47. return false;
  48. }
  49. return true;
  50. }
  51. static void set_crtc(struct drm_plane_state *plane_state,
  52. int crtc_x, int crtc_y,
  53. unsigned crtc_w, unsigned crtc_h)
  54. {
  55. plane_state->crtc_x = crtc_x;
  56. plane_state->crtc_y = crtc_y;
  57. plane_state->crtc_w = crtc_w;
  58. plane_state->crtc_h = crtc_h;
  59. }
  60. static bool check_crtc_eq(struct drm_plane_state *plane_state,
  61. int crtc_x, int crtc_y,
  62. unsigned crtc_w, unsigned crtc_h)
  63. {
  64. if (plane_state->dst.x1 != crtc_x ||
  65. plane_state->dst.y1 != crtc_y ||
  66. drm_rect_width(&plane_state->dst) != crtc_w ||
  67. drm_rect_height(&plane_state->dst) != crtc_h) {
  68. drm_rect_debug_print("dst: ", &plane_state->dst, false);
  69. return false;
  70. }
  71. return true;
  72. }
  73. static int igt_check_plane_state(void *ignored)
  74. {
  75. int ret;
  76. const struct drm_crtc_state crtc_state = {
  77. .crtc = ZERO_SIZE_PTR,
  78. .enable = true,
  79. .active = true,
  80. .mode = {
  81. DRM_MODE("1024x768", 0, 65000, 1024, 1048,
  82. 1184, 1344, 0, 768, 771, 777, 806, 0,
  83. DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC)
  84. },
  85. };
  86. struct drm_framebuffer fb = {
  87. .width = 2048,
  88. .height = 2048
  89. };
  90. struct drm_plane_state plane_state = {
  91. .crtc = ZERO_SIZE_PTR,
  92. .fb = &fb,
  93. .rotation = DRM_MODE_ROTATE_0
  94. };
  95. /* Simple clipping, no scaling. */
  96. set_src(&plane_state, 0, 0, fb.width << 16, fb.height << 16);
  97. set_crtc(&plane_state, 0, 0, fb.width, fb.height);
  98. ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
  99. DRM_PLANE_HELPER_NO_SCALING,
  100. DRM_PLANE_HELPER_NO_SCALING,
  101. false, false);
  102. FAIL(ret < 0, "Simple clipping check should pass\n");
  103. FAIL_ON(!plane_state.visible);
  104. FAIL_ON(!check_src_eq(&plane_state, 0, 0, 1024 << 16, 768 << 16));
  105. FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
  106. /* Rotated clipping + reflection, no scaling. */
  107. plane_state.rotation = DRM_MODE_ROTATE_90 | DRM_MODE_REFLECT_X;
  108. ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
  109. DRM_PLANE_HELPER_NO_SCALING,
  110. DRM_PLANE_HELPER_NO_SCALING,
  111. false, false);
  112. FAIL(ret < 0, "Rotated clipping check should pass\n");
  113. FAIL_ON(!plane_state.visible);
  114. FAIL_ON(!check_src_eq(&plane_state, 0, 0, 768 << 16, 1024 << 16));
  115. FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
  116. plane_state.rotation = DRM_MODE_ROTATE_0;
  117. /* Check whether positioning works correctly. */
  118. set_src(&plane_state, 0, 0, 1023 << 16, 767 << 16);
  119. set_crtc(&plane_state, 0, 0, 1023, 767);
  120. ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
  121. DRM_PLANE_HELPER_NO_SCALING,
  122. DRM_PLANE_HELPER_NO_SCALING,
  123. false, false);
  124. FAIL(!ret, "Should not be able to position on the crtc with can_position=false\n");
  125. ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
  126. DRM_PLANE_HELPER_NO_SCALING,
  127. DRM_PLANE_HELPER_NO_SCALING,
  128. true, false);
  129. FAIL(ret < 0, "Simple positioning should work\n");
  130. FAIL_ON(!plane_state.visible);
  131. FAIL_ON(!check_src_eq(&plane_state, 0, 0, 1023 << 16, 767 << 16));
  132. FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1023, 767));
  133. /* Simple scaling tests. */
  134. set_src(&plane_state, 0, 0, 512 << 16, 384 << 16);
  135. set_crtc(&plane_state, 0, 0, 1024, 768);
  136. ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
  137. 0x8001,
  138. DRM_PLANE_HELPER_NO_SCALING,
  139. false, false);
  140. FAIL(!ret, "Upscaling out of range should fail.\n");
  141. ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
  142. 0x8000,
  143. DRM_PLANE_HELPER_NO_SCALING,
  144. false, false);
  145. FAIL(ret < 0, "Upscaling exactly 2x should work\n");
  146. FAIL_ON(!plane_state.visible);
  147. FAIL_ON(!check_src_eq(&plane_state, 0, 0, 512 << 16, 384 << 16));
  148. FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
  149. set_src(&plane_state, 0, 0, 2048 << 16, 1536 << 16);
  150. ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
  151. DRM_PLANE_HELPER_NO_SCALING,
  152. 0x1ffff, false, false);
  153. FAIL(!ret, "Downscaling out of range should fail.\n");
  154. ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
  155. DRM_PLANE_HELPER_NO_SCALING,
  156. 0x20000, false, false);
  157. FAIL(ret < 0, "Should succeed with exact scaling limit\n");
  158. FAIL_ON(!plane_state.visible);
  159. FAIL_ON(!check_src_eq(&plane_state, 0, 0, 2048 << 16, 1536 << 16));
  160. FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
  161. /* Testing rounding errors. */
  162. set_src(&plane_state, 0, 0, 0x40001, 0x40001);
  163. set_crtc(&plane_state, 1022, 766, 4, 4);
  164. ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
  165. DRM_PLANE_HELPER_NO_SCALING,
  166. 0x10001,
  167. true, false);
  168. FAIL(ret < 0, "Should succeed by clipping to exact multiple");
  169. FAIL_ON(!plane_state.visible);
  170. FAIL_ON(!check_src_eq(&plane_state, 0, 0, 2 << 16, 2 << 16));
  171. FAIL_ON(!check_crtc_eq(&plane_state, 1022, 766, 2, 2));
  172. set_src(&plane_state, 0x20001, 0x20001, 0x4040001, 0x3040001);
  173. set_crtc(&plane_state, -2, -2, 1028, 772);
  174. ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
  175. DRM_PLANE_HELPER_NO_SCALING,
  176. 0x10001,
  177. false, false);
  178. FAIL(ret < 0, "Should succeed by clipping to exact multiple");
  179. FAIL_ON(!plane_state.visible);
  180. FAIL_ON(!check_src_eq(&plane_state, 0x40002, 0x40002, 1024 << 16, 768 << 16));
  181. FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
  182. set_src(&plane_state, 0, 0, 0x3ffff, 0x3ffff);
  183. set_crtc(&plane_state, 1022, 766, 4, 4);
  184. ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
  185. 0xffff,
  186. DRM_PLANE_HELPER_NO_SCALING,
  187. true, false);
  188. FAIL(ret < 0, "Should succeed by clipping to exact multiple");
  189. FAIL_ON(!plane_state.visible);
  190. /* Should not be rounded to 0x20001, which would be upscaling. */
  191. FAIL_ON(!check_src_eq(&plane_state, 0, 0, 2 << 16, 2 << 16));
  192. FAIL_ON(!check_crtc_eq(&plane_state, 1022, 766, 2, 2));
  193. set_src(&plane_state, 0x1ffff, 0x1ffff, 0x403ffff, 0x303ffff);
  194. set_crtc(&plane_state, -2, -2, 1028, 772);
  195. ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
  196. 0xffff,
  197. DRM_PLANE_HELPER_NO_SCALING,
  198. false, false);
  199. FAIL(ret < 0, "Should succeed by clipping to exact multiple");
  200. FAIL_ON(!plane_state.visible);
  201. FAIL_ON(!check_src_eq(&plane_state, 0x3fffe, 0x3fffe, 1024 << 16, 768 << 16));
  202. FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
  203. return 0;
  204. }
  205. #include "drm_selftest.c"
  206. static int __init test_drm_helper_init(void)
  207. {
  208. int err;
  209. err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL);
  210. return err > 0 ? 0 : err;
  211. }
  212. module_init(test_drm_helper_init);
  213. MODULE_AUTHOR("Intel Corporation");
  214. MODULE_LICENSE("GPL");