1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2014 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
15 #include <video_console.h>
17 #include <dm/uclass-internal.h>
21 * These tests use the standard sandbox frame buffer, the resolution of which
22 * is defined in the device tree. This only supports 16bpp so the tests only
23 * test that code path. It would be possible to adjust this fairly easily,
24 * by adjusting the bpix value in struct sandbox_sdl_plat. However the code
25 * in sandbox_sdl_sync() would also need to change to handle the different
28 /* Basic test of the video uclass */
29 static int dm_test_video_base(struct unit_test_state *uts)
31 struct video_priv *priv;
34 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
35 ut_asserteq(1366, video_get_xsize(dev));
36 ut_asserteq(768, video_get_ysize(dev));
37 priv = dev_get_uclass_priv(dev);
38 ut_asserteq(priv->fb_size, 1366 * 768 * 2);
42 DM_TEST(dm_test_video_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
45 * compress_frame_buffer() - Compress the frame buffer and return its size
47 * We want to write tests which perform operations on the video console and
48 * check that the frame buffer ends up with the correct contents. But it is
49 * painful to store 'known good' images for comparison with the frame
50 * buffer. As an alternative, we can compress the frame buffer and check the
51 * size of the compressed data. This provides a pretty good level of
52 * certainty and the resulting tests need only check a single value.
54 * If the copy framebuffer is enabled, this compares it to the main framebuffer
59 * @return compressed size of the frame buffer, or -ve on error
61 static int compress_frame_buffer(struct unit_test_state *uts,
64 struct video_priv *priv = dev_get_uclass_priv(dev);
65 struct video_priv *uc_priv = dev_get_uclass_priv(dev);
70 destlen = priv->fb_size;
71 dest = malloc(priv->fb_size);
74 ret = BZ2_bzBuffToBuffCompress(dest, &destlen,
75 priv->fb, priv->fb_size,
81 /* Check here that the copy frame buffer is working correctly */
82 if (IS_ENABLED(CONFIG_VIDEO_COPY)) {
83 ut_assertf(!memcmp(uc_priv->fb, uc_priv->copy_fb,
85 "Copy framebuffer does not match fb");
92 * Call this function at any point to halt and show the current display. Be
93 * sure to run the test with the -l flag.
95 static void __maybe_unused see_output(void)
101 /* Select the video console driver to use for a video device */
102 static int select_vidconsole(struct unit_test_state *uts, const char *drv_name)
104 struct sandbox_sdl_plat *plat;
107 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
108 ut_assert(!device_active(dev));
109 plat = dev_get_platdata(dev);
110 plat->vidconsole_drv_name = "vidconsole0";
115 /* Test text output works on the video console */
116 static int dm_test_video_text(struct unit_test_state *uts)
118 struct udevice *dev, *con;
122 #define SCROLL_LINES 100
124 ut_assertok(select_vidconsole(uts, "vidconsole0"));
125 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
126 ut_asserteq(46, compress_frame_buffer(uts, dev));
128 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
129 vidconsole_putc_xy(con, 0, 0, 'a');
130 ut_asserteq(79, compress_frame_buffer(uts, dev));
132 vidconsole_putc_xy(con, 0, 0, ' ');
133 ut_asserteq(46, compress_frame_buffer(uts, dev));
135 for (i = 0; i < 20; i++)
136 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
137 ut_asserteq(273, compress_frame_buffer(uts, dev));
139 vidconsole_set_row(con, 0, WHITE);
140 ut_asserteq(46, compress_frame_buffer(uts, dev));
142 for (i = 0; i < 20; i++)
143 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
144 ut_asserteq(273, compress_frame_buffer(uts, dev));
148 DM_TEST(dm_test_video_text, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
150 /* Test handling of special characters in the console */
151 static int dm_test_video_chars(struct unit_test_state *uts)
153 struct udevice *dev, *con;
154 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.";
156 ut_assertok(select_vidconsole(uts, "vidconsole0"));
157 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
158 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
159 vidconsole_put_string(con, test_string);
160 ut_asserteq(466, compress_frame_buffer(uts, dev));
164 DM_TEST(dm_test_video_chars, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
166 #ifdef CONFIG_VIDEO_ANSI
167 #define ANSI_ESC "\x1b"
168 /* Test handling of ANSI escape sequences */
169 static int dm_test_video_ansi(struct unit_test_state *uts)
171 struct udevice *dev, *con;
173 ut_assertok(select_vidconsole(uts, "vidconsole0"));
174 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
175 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
177 /* reference clear: */
178 video_clear(con->parent);
179 video_sync(con->parent, false);
180 ut_asserteq(46, compress_frame_buffer(uts, dev));
182 /* test clear escape sequence: [2J */
183 vidconsole_put_string(con, "A\tB\tC"ANSI_ESC"[2J");
184 ut_asserteq(46, compress_frame_buffer(uts, dev));
186 /* test set-cursor: [%d;%df */
187 vidconsole_put_string(con, "abc"ANSI_ESC"[2;2fab"ANSI_ESC"[4;4fcd");
188 ut_asserteq(143, compress_frame_buffer(uts, dev));
190 /* test colors (30-37 fg color, 40-47 bg color) */
191 vidconsole_put_string(con, ANSI_ESC"[30;41mfoo"); /* black on red */
192 vidconsole_put_string(con, ANSI_ESC"[33;44mbar"); /* yellow on blue */
193 ut_asserteq(272, compress_frame_buffer(uts, dev));
197 DM_TEST(dm_test_video_ansi, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
201 * check_vidconsole_output() - Run a text console test
204 * @rot: Console rotation (0=normal orientation, 1=90 degrees clockwise,
205 * 2=upside down, 3=90 degree counterclockwise)
206 * @wrap_size: Expected size of compressed frame buffer for the wrap test
207 * @scroll_size: Same for the scroll test
208 * @return 0 on success
210 static int check_vidconsole_output(struct unit_test_state *uts, int rot,
211 int wrap_size, int scroll_size)
213 struct udevice *dev, *con;
214 struct sandbox_sdl_plat *plat;
217 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
218 ut_assert(!device_active(dev));
219 plat = dev_get_platdata(dev);
222 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
223 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
224 ut_asserteq(46, compress_frame_buffer(uts, dev));
226 /* Check display wrap */
227 for (i = 0; i < 120; i++)
228 vidconsole_put_char(con, 'A' + i % 50);
229 ut_asserteq(wrap_size, compress_frame_buffer(uts, dev));
231 /* Check display scrolling */
232 for (i = 0; i < SCROLL_LINES; i++) {
233 vidconsole_put_char(con, 'A' + i % 50);
234 vidconsole_put_char(con, '\n');
236 ut_asserteq(scroll_size, compress_frame_buffer(uts, dev));
238 /* If we scroll enough, the screen becomes blank again */
239 for (i = 0; i < SCROLL_LINES; i++)
240 vidconsole_put_char(con, '\n');
241 ut_asserteq(46, compress_frame_buffer(uts, dev));
246 /* Test text output through the console uclass */
247 static int dm_test_video_context(struct unit_test_state *uts)
249 ut_assertok(select_vidconsole(uts, "vidconsole0"));
250 ut_assertok(check_vidconsole_output(uts, 0, 788, 453));
254 DM_TEST(dm_test_video_context, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
256 /* Test rotated text output through the console uclass */
257 static int dm_test_video_rotation1(struct unit_test_state *uts)
259 ut_assertok(check_vidconsole_output(uts, 1, 1112, 680));
263 DM_TEST(dm_test_video_rotation1, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
265 /* Test rotated text output through the console uclass */
266 static int dm_test_video_rotation2(struct unit_test_state *uts)
268 ut_assertok(check_vidconsole_output(uts, 2, 783, 445));
272 DM_TEST(dm_test_video_rotation2, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
274 /* Test rotated text output through the console uclass */
275 static int dm_test_video_rotation3(struct unit_test_state *uts)
277 ut_assertok(check_vidconsole_output(uts, 3, 1134, 681));
281 DM_TEST(dm_test_video_rotation3, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
283 /* Read a file into memory and return a pointer to it */
284 static int read_file(struct unit_test_state *uts, const char *fname,
287 int buf_size = 100000;
292 buf = map_sysmem(addr, 0);
293 ut_assert(buf != NULL);
294 fd = os_open(fname, OS_O_RDONLY);
296 size = os_read(fd, buf, buf_size);
298 ut_assert(size >= 0);
299 ut_assert(size < buf_size);
305 /* Test drawing a bitmap file */
306 static int dm_test_video_bmp(struct unit_test_state *uts)
311 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
312 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
314 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
315 ut_asserteq(1368, compress_frame_buffer(uts, dev));
319 DM_TEST(dm_test_video_bmp, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
321 /* Test drawing a compressed bitmap file */
322 static int dm_test_video_bmp_comp(struct unit_test_state *uts)
327 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
328 ut_assertok(read_file(uts, "tools/logos/denx-comp.bmp", &addr));
330 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
331 ut_asserteq(1368, compress_frame_buffer(uts, dev));
335 DM_TEST(dm_test_video_bmp_comp, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
337 /* Test TrueType console */
338 static int dm_test_video_truetype(struct unit_test_state *uts)
340 struct udevice *dev, *con;
341 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";
343 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
344 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
345 vidconsole_put_string(con, test_string);
346 ut_asserteq(12237, compress_frame_buffer(uts, dev));
350 DM_TEST(dm_test_video_truetype, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
352 /* Test scrolling TrueType console */
353 static int dm_test_video_truetype_scroll(struct unit_test_state *uts)
355 struct sandbox_sdl_plat *plat;
356 struct udevice *dev, *con;
357 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";
359 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
360 ut_assert(!device_active(dev));
361 plat = dev_get_platdata(dev);
362 plat->font_size = 100;
364 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
365 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
366 vidconsole_put_string(con, test_string);
367 ut_asserteq(35030, compress_frame_buffer(uts, dev));
371 DM_TEST(dm_test_video_truetype_scroll, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
373 /* Test TrueType backspace, within and across lines */
374 static int dm_test_video_truetype_bs(struct unit_test_state *uts)
376 struct sandbox_sdl_plat *plat;
377 struct udevice *dev, *con;
378 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.";
380 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
381 ut_assert(!device_active(dev));
382 plat = dev_get_platdata(dev);
383 plat->font_size = 100;
385 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
386 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
387 vidconsole_put_string(con, test_string);
388 ut_asserteq(29018, compress_frame_buffer(uts, dev));
392 DM_TEST(dm_test_video_truetype_bs, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);