video.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. * Copyright (c) 2014 Google, Inc
  3. * Written by Simon Glass <sjg@chromium.org>
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. #include <common.h>
  8. #include <bzlib.h>
  9. #include <dm.h>
  10. #include <mapmem.h>
  11. #include <os.h>
  12. #include <video.h>
  13. #include <video_console.h>
  14. #include <dm/test.h>
  15. #include <dm/uclass-internal.h>
  16. #include <test/ut.h>
  17. /*
  18. * These tests use the standard sandbox frame buffer, the resolution of which
  19. * is defined in the device tree. This only supports 16bpp so the tests only
  20. * test that code path. It would be possible to adjust this fairly easily,
  21. * by adjusting the bpix value in struct sandbox_sdl_plat. However the code
  22. * in sandbox_sdl_sync() would also need to change to handle the different
  23. * surface depth.
  24. */
  25. DECLARE_GLOBAL_DATA_PTR;
  26. /* Basic test of the video uclass */
  27. static int dm_test_video_base(struct unit_test_state *uts)
  28. {
  29. struct video_priv *priv;
  30. struct udevice *dev;
  31. ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
  32. ut_asserteq(1366, video_get_xsize(dev));
  33. ut_asserteq(768, video_get_ysize(dev));
  34. priv = dev_get_uclass_priv(dev);
  35. ut_asserteq(priv->fb_size, 1366 * 768 * 2);
  36. return 0;
  37. }
  38. DM_TEST(dm_test_video_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
  39. /**
  40. * compress_frame_buffer() - Compress the frame buffer and return its size
  41. *
  42. * We want to write tests which perform operations on the video console and
  43. * check that the frame buffer ends up with the correct contents. But it is
  44. * painful to store 'known good' images for comparison with the frame
  45. * buffer. As an alternative, we can compress the frame buffer and check the
  46. * size of the compressed data. This provides a pretty good level of
  47. * certainty and the resulting tests need only check a single value.
  48. *
  49. * @dev: Video device
  50. * @return compressed size of the frame buffer, or -ve on error
  51. */
  52. static int compress_frame_buffer(struct udevice *dev)
  53. {
  54. struct video_priv *priv = dev_get_uclass_priv(dev);
  55. uint destlen;
  56. void *dest;
  57. int ret;
  58. destlen = priv->fb_size;
  59. dest = malloc(priv->fb_size);
  60. if (!dest)
  61. return -ENOMEM;
  62. ret = BZ2_bzBuffToBuffCompress(dest, &destlen,
  63. priv->fb, priv->fb_size,
  64. 3, 0, 0);
  65. free(dest);
  66. if (ret)
  67. return ret;
  68. return destlen;
  69. }
  70. /*
  71. * Call this function at any point to halt and show the current display. Be
  72. * sure to run the test with the -l flag.
  73. */
  74. static void __maybe_unused see_output(void)
  75. {
  76. video_sync_all();
  77. while (1);
  78. }
  79. /* Test text output works on the video console */
  80. static int dm_test_video_text(struct unit_test_state *uts)
  81. {
  82. struct udevice *dev, *con;
  83. int i;
  84. #define WHITE 0xffff
  85. #define SCROLL_LINES 100
  86. ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
  87. ut_asserteq(46, compress_frame_buffer(dev));
  88. ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
  89. vidconsole_putc_xy(con, 0, 0, 'a');
  90. ut_asserteq(79, compress_frame_buffer(dev));
  91. vidconsole_putc_xy(con, 0, 0, ' ');
  92. ut_asserteq(46, compress_frame_buffer(dev));
  93. for (i = 0; i < 20; i++)
  94. vidconsole_putc_xy(con, i * 8, 0, ' ' + i);
  95. ut_asserteq(273, compress_frame_buffer(dev));
  96. vidconsole_set_row(con, 0, WHITE);
  97. ut_asserteq(46, compress_frame_buffer(dev));
  98. for (i = 0; i < 20; i++)
  99. vidconsole_putc_xy(con, i * 8, 0, ' ' + i);
  100. ut_asserteq(273, compress_frame_buffer(dev));
  101. return 0;
  102. }
  103. DM_TEST(dm_test_video_text, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
  104. /* Test handling of special characters in the console */
  105. static int dm_test_video_chars(struct unit_test_state *uts)
  106. {
  107. struct udevice *dev, *con;
  108. const char *test_string = "Well\b\b\b\bxhe is\r \n\ta very modest \bman\n\t\tand Has much to\b\bto be modest about.";
  109. const char *s;
  110. ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
  111. ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
  112. for (s = test_string; *s; s++)
  113. vidconsole_put_char(con, *s);
  114. ut_asserteq(466, compress_frame_buffer(dev));
  115. return 0;
  116. }
  117. DM_TEST(dm_test_video_chars, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
  118. /**
  119. * check_vidconsole_output() - Run a text console test
  120. *
  121. * @uts: Test state
  122. * @rot: Console rotation (0, 90, 180, 270)
  123. * @wrap_size: Expected size of compressed frame buffer for the wrap test
  124. * @scroll_size: Same for the scroll test
  125. * @return 0 on success
  126. */
  127. static int check_vidconsole_output(struct unit_test_state *uts, int rot,
  128. int wrap_size, int scroll_size)
  129. {
  130. struct udevice *dev, *con;
  131. struct sandbox_sdl_plat *plat;
  132. int i;
  133. ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
  134. ut_assert(!device_active(dev));
  135. plat = dev_get_platdata(dev);
  136. plat->rot = rot;
  137. ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
  138. ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
  139. ut_asserteq(46, compress_frame_buffer(dev));
  140. /* Check display wrap */
  141. for (i = 0; i < 120; i++)
  142. vidconsole_put_char(con, 'A' + i % 50);
  143. ut_asserteq(wrap_size, compress_frame_buffer(dev));
  144. /* Check display scrolling */
  145. for (i = 0; i < SCROLL_LINES; i++) {
  146. vidconsole_put_char(con, 'A' + i % 50);
  147. vidconsole_put_char(con, '\n');
  148. }
  149. ut_asserteq(scroll_size, compress_frame_buffer(dev));
  150. /* If we scroll enough, the screen becomes blank again */
  151. for (i = 0; i < SCROLL_LINES; i++)
  152. vidconsole_put_char(con, '\n');
  153. ut_asserteq(46, compress_frame_buffer(dev));
  154. return 0;
  155. }
  156. /* Test text output through the console uclass */
  157. static int dm_test_video_context(struct unit_test_state *uts)
  158. {
  159. return check_vidconsole_output(uts, 0, 788, 453);
  160. }
  161. DM_TEST(dm_test_video_context, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
  162. /* Test rotated text output through the console uclass */
  163. static int dm_test_video_rotation1(struct unit_test_state *uts)
  164. {
  165. ut_assertok(check_vidconsole_output(uts, 1, 1112, 680));
  166. return 0;
  167. }
  168. DM_TEST(dm_test_video_rotation1, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
  169. /* Test rotated text output through the console uclass */
  170. static int dm_test_video_rotation2(struct unit_test_state *uts)
  171. {
  172. ut_assertok(check_vidconsole_output(uts, 2, 785, 446));
  173. return 0;
  174. }
  175. DM_TEST(dm_test_video_rotation2, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
  176. /* Test rotated text output through the console uclass */
  177. static int dm_test_video_rotation3(struct unit_test_state *uts)
  178. {
  179. ut_assertok(check_vidconsole_output(uts, 3, 1134, 681));
  180. return 0;
  181. }
  182. DM_TEST(dm_test_video_rotation3, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
  183. /* Read a file into memory and return a pointer to it */
  184. static int read_file(struct unit_test_state *uts, const char *fname,
  185. ulong *addrp)
  186. {
  187. int buf_size = 100000;
  188. ulong addr = 0;
  189. int size, fd;
  190. char *buf;
  191. buf = map_sysmem(addr, 0);
  192. ut_assert(buf != NULL);
  193. fd = os_open(fname, OS_O_RDONLY);
  194. ut_assert(fd >= 0);
  195. size = os_read(fd, buf, buf_size);
  196. ut_assert(size >= 0);
  197. ut_assert(size < buf_size);
  198. os_close(fd);
  199. *addrp = addr;
  200. return 0;
  201. }
  202. /* Test drawing a bitmap file */
  203. static int dm_test_video_bmp(struct unit_test_state *uts)
  204. {
  205. struct udevice *dev;
  206. ulong addr;
  207. ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
  208. ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
  209. ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
  210. ut_asserteq(1368, compress_frame_buffer(dev));
  211. return 0;
  212. }
  213. DM_TEST(dm_test_video_bmp, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
  214. /* Test drawing a compressed bitmap file */
  215. static int dm_test_video_bmp_comp(struct unit_test_state *uts)
  216. {
  217. struct udevice *dev;
  218. ulong addr;
  219. ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
  220. ut_assertok(read_file(uts, "tools/logos/denx-comp.bmp", &addr));
  221. ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
  222. ut_asserteq(1368, compress_frame_buffer(dev));
  223. return 0;
  224. }
  225. DM_TEST(dm_test_video_bmp_comp, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);