1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2014 Google, Inc
16 #include <video_console.h>
19 #include <dm/uclass-internal.h>
20 #include <test/test.h>
24 * These tests use the standard sandbox frame buffer, the resolution of which
25 * is defined in the device tree. This only supports 16bpp so the tests only
26 * test that code path. It would be possible to adjust this fairly easily,
27 * by adjusting the bpix value in struct sandbox_sdl_plat. However the code
28 * in sandbox_sdl_sync() would also need to change to handle the different
31 /* Basic test of the video uclass */
32 static int dm_test_video_base(struct unit_test_state *uts)
34 struct video_priv *priv;
37 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
38 ut_asserteq(1366, video_get_xsize(dev));
39 ut_asserteq(768, video_get_ysize(dev));
40 priv = dev_get_uclass_priv(dev);
41 ut_asserteq(priv->fb_size, 1366 * 768 * 2);
45 DM_TEST(dm_test_video_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
48 * compress_frame_buffer() - Compress the frame buffer and return its size
50 * We want to write tests which perform operations on the video console and
51 * check that the frame buffer ends up with the correct contents. But it is
52 * painful to store 'known good' images for comparison with the frame
53 * buffer. As an alternative, we can compress the frame buffer and check the
54 * size of the compressed data. This provides a pretty good level of
55 * certainty and the resulting tests need only check a single value.
57 * If the copy framebuffer is enabled, this compares it to the main framebuffer
62 * Return: compressed size of the frame buffer, or -ve on error
64 static int compress_frame_buffer(struct unit_test_state *uts,
67 struct video_priv *priv = dev_get_uclass_priv(dev);
68 struct video_priv *uc_priv = dev_get_uclass_priv(dev);
73 destlen = priv->fb_size;
74 dest = malloc(priv->fb_size);
77 ret = BZ2_bzBuffToBuffCompress(dest, &destlen,
78 priv->fb, priv->fb_size,
84 /* Check here that the copy frame buffer is working correctly */
85 if (IS_ENABLED(CONFIG_VIDEO_COPY)) {
86 ut_assertf(!memcmp(uc_priv->fb, uc_priv->copy_fb,
88 "Copy framebuffer does not match fb");
95 * Call this function at any point to halt and show the current display. Be
96 * sure to run the test with the -l flag.
98 static void __maybe_unused see_output(void)
104 /* Select the video console driver to use for a video device */
105 static int select_vidconsole(struct unit_test_state *uts, const char *drv_name)
107 struct sandbox_sdl_plat *plat;
110 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
111 ut_assert(!device_active(dev));
112 plat = dev_get_plat(dev);
113 plat->vidconsole_drv_name = "vidconsole0";
119 * video_get_nologo() - Disable the logo on the video device and return it
122 * @devp: Returns video device
123 * Return: 0 if OK, -ve on error
125 static int video_get_nologo(struct unit_test_state *uts, struct udevice **devp)
127 struct video_uc_plat *uc_plat;
130 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
131 ut_assertnonnull(dev);
132 uc_plat = dev_get_uclass_plat(dev);
133 uc_plat->hide_logo = true;
136 ut_assertok(uclass_first_device_err(UCLASS_VIDEO, &dev));
137 ut_assertnonnull(dev);
143 /* Test text output works on the video console */
144 static int dm_test_video_text(struct unit_test_state *uts)
146 struct udevice *dev, *con;
150 #define SCROLL_LINES 100
152 ut_assertok(select_vidconsole(uts, "vidconsole0"));
153 ut_assertok(video_get_nologo(uts, &dev));
154 ut_asserteq(46, compress_frame_buffer(uts, dev));
156 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
157 vidconsole_putc_xy(con, 0, 0, 'a');
158 ut_asserteq(79, compress_frame_buffer(uts, dev));
160 vidconsole_putc_xy(con, 0, 0, ' ');
161 ut_asserteq(46, compress_frame_buffer(uts, dev));
163 for (i = 0; i < 20; i++)
164 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
165 ut_asserteq(273, compress_frame_buffer(uts, dev));
167 vidconsole_set_row(con, 0, WHITE);
168 ut_asserteq(46, compress_frame_buffer(uts, dev));
170 for (i = 0; i < 20; i++)
171 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
172 ut_asserteq(273, compress_frame_buffer(uts, dev));
176 DM_TEST(dm_test_video_text, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
178 /* Test handling of special characters in the console */
179 static int dm_test_video_chars(struct unit_test_state *uts)
181 struct udevice *dev, *con;
182 const char *test_string = "Well\b\b\b\bxhe is\r \n\ta very \amodest \bman\n\t\tand Has much to\b\bto be modest about.";
184 ut_assertok(select_vidconsole(uts, "vidconsole0"));
185 ut_assertok(video_get_nologo(uts, &dev));
186 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
187 vidconsole_put_string(con, test_string);
188 ut_asserteq(466, compress_frame_buffer(uts, dev));
192 DM_TEST(dm_test_video_chars, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
194 #ifdef CONFIG_VIDEO_ANSI
195 #define ANSI_ESC "\x1b"
196 /* Test handling of ANSI escape sequences */
197 static int dm_test_video_ansi(struct unit_test_state *uts)
199 struct udevice *dev, *con;
201 ut_assertok(select_vidconsole(uts, "vidconsole0"));
202 ut_assertok(video_get_nologo(uts, &dev));
203 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
205 /* reference clear: */
206 video_clear(con->parent);
207 video_sync(con->parent, false);
208 ut_asserteq(46, compress_frame_buffer(uts, dev));
210 /* test clear escape sequence: [2J */
211 vidconsole_put_string(con, "A\tB\tC"ANSI_ESC"[2J");
212 ut_asserteq(46, compress_frame_buffer(uts, dev));
214 /* test set-cursor: [%d;%df */
215 vidconsole_put_string(con, "abc"ANSI_ESC"[2;2fab"ANSI_ESC"[4;4fcd");
216 ut_asserteq(143, compress_frame_buffer(uts, dev));
218 /* test colors (30-37 fg color, 40-47 bg color) */
219 vidconsole_put_string(con, ANSI_ESC"[30;41mfoo"); /* black on red */
220 vidconsole_put_string(con, ANSI_ESC"[33;44mbar"); /* yellow on blue */
221 ut_asserteq(272, compress_frame_buffer(uts, dev));
225 DM_TEST(dm_test_video_ansi, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
229 * check_vidconsole_output() - Run a text console test
232 * @rot: Console rotation (0=normal orientation, 1=90 degrees clockwise,
233 * 2=upside down, 3=90 degree counterclockwise)
234 * @wrap_size: Expected size of compressed frame buffer for the wrap test
235 * @scroll_size: Same for the scroll test
236 * Return: 0 on success
238 static int check_vidconsole_output(struct unit_test_state *uts, int rot,
239 int wrap_size, int scroll_size)
241 struct udevice *dev, *con;
242 struct sandbox_sdl_plat *plat;
245 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
246 ut_assert(!device_active(dev));
247 plat = dev_get_plat(dev);
250 ut_assertok(video_get_nologo(uts, &dev));
251 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
252 ut_asserteq(46, compress_frame_buffer(uts, dev));
254 /* Check display wrap */
255 for (i = 0; i < 120; i++)
256 vidconsole_put_char(con, 'A' + i % 50);
257 ut_asserteq(wrap_size, compress_frame_buffer(uts, dev));
259 /* Check display scrolling */
260 for (i = 0; i < SCROLL_LINES; i++) {
261 vidconsole_put_char(con, 'A' + i % 50);
262 vidconsole_put_char(con, '\n');
264 ut_asserteq(scroll_size, compress_frame_buffer(uts, dev));
266 /* If we scroll enough, the screen becomes blank again */
267 for (i = 0; i < SCROLL_LINES; i++)
268 vidconsole_put_char(con, '\n');
269 ut_asserteq(46, compress_frame_buffer(uts, dev));
274 /* Test text output through the console uclass */
275 static int dm_test_video_context(struct unit_test_state *uts)
277 ut_assertok(select_vidconsole(uts, "vidconsole0"));
278 ut_assertok(check_vidconsole_output(uts, 0, 788, 453));
282 DM_TEST(dm_test_video_context, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
284 /* Test rotated text output through the console uclass */
285 static int dm_test_video_rotation1(struct unit_test_state *uts)
287 ut_assertok(check_vidconsole_output(uts, 1, 1112, 680));
291 DM_TEST(dm_test_video_rotation1, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
293 /* Test rotated text output through the console uclass */
294 static int dm_test_video_rotation2(struct unit_test_state *uts)
296 ut_assertok(check_vidconsole_output(uts, 2, 783, 445));
300 DM_TEST(dm_test_video_rotation2, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
302 /* Test rotated text output through the console uclass */
303 static int dm_test_video_rotation3(struct unit_test_state *uts)
305 ut_assertok(check_vidconsole_output(uts, 3, 1134, 681));
309 DM_TEST(dm_test_video_rotation3, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
311 /* Read a file into memory and return a pointer to it */
312 static int read_file(struct unit_test_state *uts, const char *fname,
315 int buf_size = 100000;
320 buf = map_sysmem(addr, 0);
321 ut_assert(buf != NULL);
322 fd = os_open(fname, OS_O_RDONLY);
324 size = os_read(fd, buf, buf_size);
326 ut_assert(size >= 0);
327 ut_assert(size < buf_size);
333 /* Test drawing a bitmap file */
334 static int dm_test_video_bmp(struct unit_test_state *uts)
339 ut_assertok(video_get_nologo(uts, &dev));
340 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
342 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
343 ut_asserteq(1368, compress_frame_buffer(uts, dev));
347 DM_TEST(dm_test_video_bmp, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
349 /* Test drawing a bitmap file on a 8bpp display */
350 static int dm_test_video_bmp8(struct unit_test_state *uts)
355 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
356 ut_assertnonnull(dev);
357 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP8));
359 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
361 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
362 ut_asserteq(1247, compress_frame_buffer(uts, dev));
366 DM_TEST(dm_test_video_bmp8, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
368 /* Test drawing a bitmap file on a 16bpp display */
369 static int dm_test_video_bmp16(struct unit_test_state *uts)
371 ulong src, src_len = ~0UL;
376 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
377 ut_assertnonnull(dev);
378 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP16));
380 ut_assertok(read_file(uts, "tools/logos/denx-16bpp.bmp.gz", &src));
381 ut_assertok(gunzip(map_sysmem(dst, 0), dst_len, map_sysmem(src, 0),
384 ut_assertok(video_bmp_display(dev, dst, 0, 0, false));
385 ut_asserteq(3700, compress_frame_buffer(uts, dev));
389 DM_TEST(dm_test_video_bmp16, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
391 /* Test drawing a 24bpp bitmap file on a 16bpp display */
392 static int dm_test_video_bmp24(struct unit_test_state *uts)
394 ulong src, src_len = ~0UL;
399 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
400 ut_assertnonnull(dev);
401 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP16));
403 ut_assertok(read_file(uts, "tools/logos/denx-24bpp.bmp.gz", &src));
404 ut_assertok(gunzip(map_sysmem(dst, 0), dst_len, map_sysmem(src, 0),
407 ut_assertok(video_bmp_display(dev, dst, 0, 0, false));
408 ut_asserteq(3656, compress_frame_buffer(uts, dev));
412 DM_TEST(dm_test_video_bmp24, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
414 /* Test drawing a 24bpp bitmap file on a 32bpp display */
415 static int dm_test_video_bmp24_32(struct unit_test_state *uts)
417 ulong src, src_len = ~0UL;
422 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
423 ut_assertnonnull(dev);
424 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP32));
426 ut_assertok(read_file(uts, "tools/logos/denx-24bpp.bmp.gz", &src));
427 ut_assertok(gunzip(map_sysmem(dst, 0), dst_len, map_sysmem(src, 0),
430 ut_assertok(video_bmp_display(dev, dst, 0, 0, false));
431 ut_asserteq(6827, compress_frame_buffer(uts, dev));
435 DM_TEST(dm_test_video_bmp24_32, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
437 /* Test drawing a bitmap file on a 32bpp display */
438 static int dm_test_video_bmp32(struct unit_test_state *uts)
443 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
444 ut_assertnonnull(dev);
445 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP32));
446 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
448 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
449 ut_asserteq(2024, compress_frame_buffer(uts, dev));
453 DM_TEST(dm_test_video_bmp32, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
455 /* Test drawing a compressed bitmap file */
456 static int dm_test_video_bmp_comp(struct unit_test_state *uts)
461 ut_assertok(video_get_nologo(uts, &dev));
462 ut_assertok(read_file(uts, "tools/logos/denx-comp.bmp", &addr));
464 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
465 ut_asserteq(1368, compress_frame_buffer(uts, dev));
469 DM_TEST(dm_test_video_bmp_comp, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
471 /* Test drawing a bitmap file on a 32bpp display */
472 static int dm_test_video_comp_bmp32(struct unit_test_state *uts)
477 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
478 ut_assertnonnull(dev);
479 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP32));
481 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
483 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
484 ut_asserteq(2024, compress_frame_buffer(uts, dev));
488 DM_TEST(dm_test_video_comp_bmp32, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
490 /* Test drawing a bitmap file on a 8bpp display */
491 static int dm_test_video_comp_bmp8(struct unit_test_state *uts)
496 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
497 ut_assertnonnull(dev);
498 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP8));
500 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
502 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
503 ut_asserteq(1247, compress_frame_buffer(uts, dev));
507 DM_TEST(dm_test_video_comp_bmp8, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
509 /* Test TrueType console */
510 static int dm_test_video_truetype(struct unit_test_state *uts)
512 struct udevice *dev, *con;
513 const char *test_string = "Criticism may not be agreeable, but it is necessary. It fulfils the same function as pain in the human body. It calls attention to an unhealthy state of things. Some see private enterprise as a predatory target to be shot, others as a cow to be milked, but few are those who see it as a sturdy horse pulling the wagon. The \aprice OF\b\bof greatness\n\tis responsibility.\n\nBye";
515 ut_assertok(video_get_nologo(uts, &dev));
516 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
517 vidconsole_put_string(con, test_string);
518 ut_asserteq(12237, compress_frame_buffer(uts, dev));
522 DM_TEST(dm_test_video_truetype, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
524 /* Test scrolling TrueType console */
525 static int dm_test_video_truetype_scroll(struct unit_test_state *uts)
527 struct sandbox_sdl_plat *plat;
528 struct udevice *dev, *con;
529 const char *test_string = "Criticism may not be agreeable, but it is necessary. It fulfils the same function as pain in the human body. It calls attention to an unhealthy state of things. Some see private enterprise as a predatory target to be shot, others as a cow to be milked, but few are those who see it as a sturdy horse pulling the wagon. The \aprice OF\b\bof greatness\n\tis responsibility.\n\nBye";
531 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
532 ut_assert(!device_active(dev));
533 plat = dev_get_plat(dev);
534 plat->font_size = 100;
536 ut_assertok(video_get_nologo(uts, &dev));
537 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
538 vidconsole_put_string(con, test_string);
539 ut_asserteq(35030, compress_frame_buffer(uts, dev));
543 DM_TEST(dm_test_video_truetype_scroll, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
545 /* Test TrueType backspace, within and across lines */
546 static int dm_test_video_truetype_bs(struct unit_test_state *uts)
548 struct sandbox_sdl_plat *plat;
549 struct udevice *dev, *con;
550 const char *test_string = "...Criticism may or may\b\b\b\b\b\bnot be agreeable, but seldom it is necessary\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bit is necessary. It fulfils the same function as pain in the human body. It calls attention to an unhealthy state of things.";
552 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
553 ut_assert(!device_active(dev));
554 plat = dev_get_plat(dev);
555 plat->font_size = 100;
557 ut_assertok(video_get_nologo(uts, &dev));
558 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
559 vidconsole_put_string(con, test_string);
560 ut_asserteq(29018, compress_frame_buffer(uts, dev));
564 DM_TEST(dm_test_video_truetype_bs, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);