blob: 2f7df4e61150b1766261ced8c5313993d789366c [file] [log] [blame]
Simon Glass3c97c4f2016-01-18 19:52:26 -07001/*
2 * Copyright (c) 2014 Google, Inc
3 * Written by Simon Glass <sjg@chromium.org>
4 *
5 * SPDX-License-Identifier: GPL-2.0+
6 */
7
8#include <common.h>
9#include <bzlib.h>
10#include <dm.h>
11#include <mapmem.h>
12#include <os.h>
13#include <video.h>
14#include <video_console.h>
15#include <dm/test.h>
16#include <dm/uclass-internal.h>
17#include <test/ut.h>
18
19/*
20 * These tests use the standard sandbox frame buffer, the resolution of which
21 * is defined in the device tree. This only supports 16bpp so the tests only
22 * test that code path. It would be possible to adjust this fairly easily,
23 * by adjusting the bpix value in struct sandbox_sdl_plat. However the code
24 * in sandbox_sdl_sync() would also need to change to handle the different
25 * surface depth.
26 */
Simon Glass3c97c4f2016-01-18 19:52:26 -070027/* Basic test of the video uclass */
28static int dm_test_video_base(struct unit_test_state *uts)
29{
30 struct video_priv *priv;
31 struct udevice *dev;
32
33 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
34 ut_asserteq(1366, video_get_xsize(dev));
35 ut_asserteq(768, video_get_ysize(dev));
36 priv = dev_get_uclass_priv(dev);
37 ut_asserteq(priv->fb_size, 1366 * 768 * 2);
38
39 return 0;
40}
41DM_TEST(dm_test_video_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
42
43/**
44 * compress_frame_buffer() - Compress the frame buffer and return its size
45 *
46 * We want to write tests which perform operations on the video console and
47 * check that the frame buffer ends up with the correct contents. But it is
48 * painful to store 'known good' images for comparison with the frame
49 * buffer. As an alternative, we can compress the frame buffer and check the
50 * size of the compressed data. This provides a pretty good level of
51 * certainty and the resulting tests need only check a single value.
52 *
53 * @dev: Video device
54 * @return compressed size of the frame buffer, or -ve on error
55 */
56static int compress_frame_buffer(struct udevice *dev)
57{
58 struct video_priv *priv = dev_get_uclass_priv(dev);
59 uint destlen;
60 void *dest;
61 int ret;
62
63 destlen = priv->fb_size;
64 dest = malloc(priv->fb_size);
65 if (!dest)
66 return -ENOMEM;
67 ret = BZ2_bzBuffToBuffCompress(dest, &destlen,
68 priv->fb, priv->fb_size,
69 3, 0, 0);
70 free(dest);
71 if (ret)
72 return ret;
73
74 return destlen;
75}
76
77/*
78 * Call this function at any point to halt and show the current display. Be
79 * sure to run the test with the -l flag.
80 */
81static void __maybe_unused see_output(void)
82{
83 video_sync_all();
84 while (1);
85}
86
Simon Glass8df8dad2016-01-14 18:10:50 -070087/* Select the video console driver to use for a video device */
88static int select_vidconsole(struct unit_test_state *uts, const char *drv_name)
89{
90 struct sandbox_sdl_plat *plat;
91 struct udevice *dev;
92
93 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
94 ut_assert(!device_active(dev));
95 plat = dev_get_platdata(dev);
96 plat->vidconsole_drv_name = "vidconsole0";
97
98 return 0;
99}
100
Rob Clarka7495ac2017-09-25 15:45:08 -0400101static void vidconsole_put_string(struct udevice *dev, const char *str)
102{
103 const char *s;
104
105 for (s = str; *s; s++)
106 vidconsole_put_char(dev, *s);
107}
108
Simon Glass3c97c4f2016-01-18 19:52:26 -0700109/* Test text output works on the video console */
110static int dm_test_video_text(struct unit_test_state *uts)
111{
112 struct udevice *dev, *con;
113 int i;
114
115#define WHITE 0xffff
116#define SCROLL_LINES 100
117
Simon Glass8df8dad2016-01-14 18:10:50 -0700118 ut_assertok(select_vidconsole(uts, "vidconsole0"));
Simon Glass3c97c4f2016-01-18 19:52:26 -0700119 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
120 ut_asserteq(46, compress_frame_buffer(dev));
121
122 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
123 vidconsole_putc_xy(con, 0, 0, 'a');
124 ut_asserteq(79, compress_frame_buffer(dev));
125
126 vidconsole_putc_xy(con, 0, 0, ' ');
127 ut_asserteq(46, compress_frame_buffer(dev));
128
129 for (i = 0; i < 20; i++)
Simon Glassf2661782016-01-14 18:10:37 -0700130 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
Simon Glass3c97c4f2016-01-18 19:52:26 -0700131 ut_asserteq(273, compress_frame_buffer(dev));
132
133 vidconsole_set_row(con, 0, WHITE);
134 ut_asserteq(46, compress_frame_buffer(dev));
135
136 for (i = 0; i < 20; i++)
Simon Glassf2661782016-01-14 18:10:37 -0700137 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
Simon Glass3c97c4f2016-01-18 19:52:26 -0700138 ut_asserteq(273, compress_frame_buffer(dev));
139
140 return 0;
141}
142DM_TEST(dm_test_video_text, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
143
144/* Test handling of special characters in the console */
145static int dm_test_video_chars(struct unit_test_state *uts)
146{
147 struct udevice *dev, *con;
Simon Glass5508f102016-01-14 18:10:38 -0700148 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.";
Simon Glass3c97c4f2016-01-18 19:52:26 -0700149
Simon Glass8df8dad2016-01-14 18:10:50 -0700150 ut_assertok(select_vidconsole(uts, "vidconsole0"));
Simon Glass3c97c4f2016-01-18 19:52:26 -0700151 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
152 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
Rob Clarka7495ac2017-09-25 15:45:08 -0400153 vidconsole_put_string(con, test_string);
Simon Glass3c97c4f2016-01-18 19:52:26 -0700154 ut_asserteq(466, compress_frame_buffer(dev));
155
156 return 0;
157}
158DM_TEST(dm_test_video_chars, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
159
Rob Clark40186ee2017-09-25 15:45:09 -0400160#ifdef CONFIG_VIDEO_ANSI
161#define ANSI_ESC "\x1b"
162/* Test handling of ANSI escape sequences */
163static int dm_test_video_ansi(struct unit_test_state *uts)
164{
165 struct udevice *dev, *con;
166
167 ut_assertok(select_vidconsole(uts, "vidconsole0"));
168 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
169 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
170
171 /* reference clear: */
172 video_clear(con->parent);
173 video_sync(con->parent);
174 ut_asserteq(46, compress_frame_buffer(dev));
175
176 /* test clear escape sequence: [2J */
177 vidconsole_put_string(con, "A\tB\tC"ANSI_ESC"[2J");
178 ut_asserteq(46, compress_frame_buffer(dev));
179
180 /* test set-cursor: [%d;%df */
181 vidconsole_put_string(con, "abc"ANSI_ESC"[2;2fab"ANSI_ESC"[4;4fcd");
182 ut_asserteq(142, compress_frame_buffer(dev));
183
184 /* test colors (30-37 fg color, 40-47 bg color) */
185 vidconsole_put_string(con, ANSI_ESC"[30;41mfoo"); /* black on red */
186 vidconsole_put_string(con, ANSI_ESC"[33;44mbar"); /* yellow on blue */
Heinrich Schuchardt9ffa4d12018-02-08 21:47:12 +0100187 ut_asserteq(265, compress_frame_buffer(dev));
Rob Clark40186ee2017-09-25 15:45:09 -0400188
189 return 0;
190}
191DM_TEST(dm_test_video_ansi, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
192#endif
193
Simon Glass3c97c4f2016-01-18 19:52:26 -0700194/**
195 * check_vidconsole_output() - Run a text console test
196 *
197 * @uts: Test state
198 * @rot: Console rotation (0, 90, 180, 270)
199 * @wrap_size: Expected size of compressed frame buffer for the wrap test
200 * @scroll_size: Same for the scroll test
201 * @return 0 on success
202 */
203static int check_vidconsole_output(struct unit_test_state *uts, int rot,
204 int wrap_size, int scroll_size)
205{
206 struct udevice *dev, *con;
207 struct sandbox_sdl_plat *plat;
208 int i;
209
210 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
211 ut_assert(!device_active(dev));
212 plat = dev_get_platdata(dev);
213 plat->rot = rot;
214
215 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
216 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
217 ut_asserteq(46, compress_frame_buffer(dev));
218
219 /* Check display wrap */
220 for (i = 0; i < 120; i++)
221 vidconsole_put_char(con, 'A' + i % 50);
222 ut_asserteq(wrap_size, compress_frame_buffer(dev));
223
224 /* Check display scrolling */
225 for (i = 0; i < SCROLL_LINES; i++) {
226 vidconsole_put_char(con, 'A' + i % 50);
227 vidconsole_put_char(con, '\n');
228 }
229 ut_asserteq(scroll_size, compress_frame_buffer(dev));
230
231 /* If we scroll enough, the screen becomes blank again */
232 for (i = 0; i < SCROLL_LINES; i++)
233 vidconsole_put_char(con, '\n');
234 ut_asserteq(46, compress_frame_buffer(dev));
235
236 return 0;
237}
238
239/* Test text output through the console uclass */
240static int dm_test_video_context(struct unit_test_state *uts)
241{
Simon Glass8df8dad2016-01-14 18:10:50 -0700242 ut_assertok(select_vidconsole(uts, "vidconsole0"));
243 ut_assertok(check_vidconsole_output(uts, 0, 788, 453));
244
245 return 0;
Simon Glass3c97c4f2016-01-18 19:52:26 -0700246}
247DM_TEST(dm_test_video_context, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
Simon Glass85e08db2016-01-18 19:52:27 -0700248
249/* Test rotated text output through the console uclass */
250static int dm_test_video_rotation1(struct unit_test_state *uts)
251{
252 ut_assertok(check_vidconsole_output(uts, 1, 1112, 680));
253
254 return 0;
255}
256DM_TEST(dm_test_video_rotation1, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
257
258/* Test rotated text output through the console uclass */
259static int dm_test_video_rotation2(struct unit_test_state *uts)
260{
261 ut_assertok(check_vidconsole_output(uts, 2, 785, 446));
262
263 return 0;
264}
265DM_TEST(dm_test_video_rotation2, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
266
267/* Test rotated text output through the console uclass */
268static int dm_test_video_rotation3(struct unit_test_state *uts)
269{
270 ut_assertok(check_vidconsole_output(uts, 3, 1134, 681));
271
272 return 0;
273}
274DM_TEST(dm_test_video_rotation3, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
Simon Glass747440d2016-01-18 19:52:28 -0700275
276/* Read a file into memory and return a pointer to it */
277static int read_file(struct unit_test_state *uts, const char *fname,
278 ulong *addrp)
279{
280 int buf_size = 100000;
281 ulong addr = 0;
282 int size, fd;
283 char *buf;
284
285 buf = map_sysmem(addr, 0);
286 ut_assert(buf != NULL);
287 fd = os_open(fname, OS_O_RDONLY);
288 ut_assert(fd >= 0);
289 size = os_read(fd, buf, buf_size);
Simon Glassa1080822016-01-30 15:45:17 -0700290 os_close(fd);
Simon Glass747440d2016-01-18 19:52:28 -0700291 ut_assert(size >= 0);
292 ut_assert(size < buf_size);
Simon Glass747440d2016-01-18 19:52:28 -0700293 *addrp = addr;
294
295 return 0;
296}
297
298/* Test drawing a bitmap file */
299static int dm_test_video_bmp(struct unit_test_state *uts)
300{
301 struct udevice *dev;
302 ulong addr;
303
304 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
305 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
306
307 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
308 ut_asserteq(1368, compress_frame_buffer(dev));
309
310 return 0;
311}
312DM_TEST(dm_test_video_bmp, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
313
314/* Test drawing a compressed bitmap file */
315static int dm_test_video_bmp_comp(struct unit_test_state *uts)
316{
317 struct udevice *dev;
318 ulong addr;
319
320 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
321 ut_assertok(read_file(uts, "tools/logos/denx-comp.bmp", &addr));
322
323 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
324 ut_asserteq(1368, compress_frame_buffer(dev));
325
326 return 0;
327}
328DM_TEST(dm_test_video_bmp_comp, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
Simon Glass5674ead2016-01-14 18:10:51 -0700329
330/* Test TrueType console */
331static int dm_test_video_truetype(struct unit_test_state *uts)
332{
333 struct udevice *dev, *con;
334 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";
Simon Glass5674ead2016-01-14 18:10:51 -0700335
336 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
337 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
Rob Clarka7495ac2017-09-25 15:45:08 -0400338 vidconsole_put_string(con, test_string);
Simon Glass5674ead2016-01-14 18:10:51 -0700339 ut_asserteq(12619, compress_frame_buffer(dev));
340
341 return 0;
342}
343DM_TEST(dm_test_video_truetype, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
344
345/* Test scrolling TrueType console */
346static int dm_test_video_truetype_scroll(struct unit_test_state *uts)
347{
348 struct sandbox_sdl_plat *plat;
349 struct udevice *dev, *con;
350 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";
Simon Glass5674ead2016-01-14 18:10:51 -0700351
352 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
353 ut_assert(!device_active(dev));
354 plat = dev_get_platdata(dev);
355 plat->font_size = 100;
356
357 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
358 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
Rob Clarka7495ac2017-09-25 15:45:08 -0400359 vidconsole_put_string(con, test_string);
Simon Glass5674ead2016-01-14 18:10:51 -0700360 ut_asserteq(33849, compress_frame_buffer(dev));
361
362 return 0;
363}
364DM_TEST(dm_test_video_truetype_scroll, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
365
366/* Test TrueType backspace, within and across lines */
367static int dm_test_video_truetype_bs(struct unit_test_state *uts)
368{
369 struct sandbox_sdl_plat *plat;
370 struct udevice *dev, *con;
371 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.";
Simon Glass5674ead2016-01-14 18:10:51 -0700372
373 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
374 ut_assert(!device_active(dev));
375 plat = dev_get_platdata(dev);
376 plat->font_size = 100;
377
378 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
379 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
Rob Clarka7495ac2017-09-25 15:45:08 -0400380 vidconsole_put_string(con, test_string);
Simon Glass5674ead2016-01-14 18:10:51 -0700381 ut_asserteq(34871, compress_frame_buffer(dev));
382
383 return 0;
384}
385DM_TEST(dm_test_video_truetype_bs, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);