video: sandbox: Enable truetype fonts for sandbox
[platform/kernel/u-boot.git] / test / dm / video.c
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
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  */
27 DECLARE_GLOBAL_DATA_PTR;
28
29 /* Basic test of the video uclass */
30 static int dm_test_video_base(struct unit_test_state *uts)
31 {
32         struct video_priv *priv;
33         struct udevice *dev;
34
35         ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
36         ut_asserteq(1366, video_get_xsize(dev));
37         ut_asserteq(768, video_get_ysize(dev));
38         priv = dev_get_uclass_priv(dev);
39         ut_asserteq(priv->fb_size, 1366 * 768 * 2);
40
41         return 0;
42 }
43 DM_TEST(dm_test_video_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
44
45 /**
46  * compress_frame_buffer() - Compress the frame buffer and return its size
47  *
48  * We want to write tests which perform operations on the video console and
49  * check that the frame buffer ends up with the correct contents. But it is
50  * painful to store 'known good' images for comparison with the frame
51  * buffer. As an alternative, we can compress the frame buffer and check the
52  * size of the compressed data. This provides a pretty good level of
53  * certainty and the resulting tests need only check a single value.
54  *
55  * @dev:        Video device
56  * @return compressed size of the frame buffer, or -ve on error
57  */
58 static int compress_frame_buffer(struct udevice *dev)
59 {
60         struct video_priv *priv = dev_get_uclass_priv(dev);
61         uint destlen;
62         void *dest;
63         int ret;
64
65         destlen = priv->fb_size;
66         dest = malloc(priv->fb_size);
67         if (!dest)
68                 return -ENOMEM;
69         ret = BZ2_bzBuffToBuffCompress(dest, &destlen,
70                                        priv->fb, priv->fb_size,
71                                        3, 0, 0);
72         free(dest);
73         if (ret)
74                 return ret;
75
76         return destlen;
77 }
78
79 /*
80  * Call this function at any point to halt and show the current display. Be
81  * sure to run the test with the -l flag.
82  */
83 static void __maybe_unused see_output(void)
84 {
85         video_sync_all();
86         while (1);
87 }
88
89 /* Select the video console driver to use for a video device */
90 static int select_vidconsole(struct unit_test_state *uts, const char *drv_name)
91 {
92         struct sandbox_sdl_plat *plat;
93         struct udevice *dev;
94
95         ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
96         ut_assert(!device_active(dev));
97         plat = dev_get_platdata(dev);
98         plat->vidconsole_drv_name = "vidconsole0";
99
100         return 0;
101 }
102
103 /* Test text output works on the video console */
104 static int dm_test_video_text(struct unit_test_state *uts)
105 {
106         struct udevice *dev, *con;
107         int i;
108
109 #define WHITE           0xffff
110 #define SCROLL_LINES    100
111
112         ut_assertok(select_vidconsole(uts, "vidconsole0"));
113         ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
114         ut_asserteq(46, compress_frame_buffer(dev));
115
116         ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
117         vidconsole_putc_xy(con, 0, 0, 'a');
118         ut_asserteq(79, compress_frame_buffer(dev));
119
120         vidconsole_putc_xy(con, 0, 0, ' ');
121         ut_asserteq(46, compress_frame_buffer(dev));
122
123         for (i = 0; i < 20; i++)
124                 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
125         ut_asserteq(273, compress_frame_buffer(dev));
126
127         vidconsole_set_row(con, 0, WHITE);
128         ut_asserteq(46, compress_frame_buffer(dev));
129
130         for (i = 0; i < 20; i++)
131                 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
132         ut_asserteq(273, compress_frame_buffer(dev));
133
134         return 0;
135 }
136 DM_TEST(dm_test_video_text, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
137
138 /* Test handling of special characters in the console */
139 static int dm_test_video_chars(struct unit_test_state *uts)
140 {
141         struct udevice *dev, *con;
142         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.";
143         const char *s;
144
145         ut_assertok(select_vidconsole(uts, "vidconsole0"));
146         ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
147         ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
148         for (s = test_string; *s; s++)
149                 vidconsole_put_char(con, *s);
150         ut_asserteq(466, compress_frame_buffer(dev));
151
152         return 0;
153 }
154 DM_TEST(dm_test_video_chars, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
155
156 /**
157  * check_vidconsole_output() - Run a text console test
158  *
159  * @uts:        Test state
160  * @rot:        Console rotation (0, 90, 180, 270)
161  * @wrap_size:  Expected size of compressed frame buffer for the wrap test
162  * @scroll_size: Same for the scroll test
163  * @return 0 on success
164  */
165 static int check_vidconsole_output(struct unit_test_state *uts, int rot,
166                                    int wrap_size, int scroll_size)
167 {
168         struct udevice *dev, *con;
169         struct sandbox_sdl_plat *plat;
170         int i;
171
172         ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
173         ut_assert(!device_active(dev));
174         plat = dev_get_platdata(dev);
175         plat->rot = rot;
176
177         ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
178         ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
179         ut_asserteq(46, compress_frame_buffer(dev));
180
181         /* Check display wrap */
182         for (i = 0; i < 120; i++)
183                 vidconsole_put_char(con, 'A' + i % 50);
184         ut_asserteq(wrap_size, compress_frame_buffer(dev));
185
186         /* Check display scrolling */
187         for (i = 0; i < SCROLL_LINES; i++) {
188                 vidconsole_put_char(con, 'A' + i % 50);
189                 vidconsole_put_char(con, '\n');
190         }
191         ut_asserteq(scroll_size, compress_frame_buffer(dev));
192
193         /* If we scroll enough, the screen becomes blank again */
194         for (i = 0; i < SCROLL_LINES; i++)
195                 vidconsole_put_char(con, '\n');
196         ut_asserteq(46, compress_frame_buffer(dev));
197
198         return 0;
199 }
200
201 /* Test text output through the console uclass */
202 static int dm_test_video_context(struct unit_test_state *uts)
203 {
204         ut_assertok(select_vidconsole(uts, "vidconsole0"));
205         ut_assertok(check_vidconsole_output(uts, 0, 788, 453));
206
207         return 0;
208 }
209 DM_TEST(dm_test_video_context, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
210
211 /* Test rotated text output through the console uclass */
212 static int dm_test_video_rotation1(struct unit_test_state *uts)
213 {
214         ut_assertok(check_vidconsole_output(uts, 1, 1112, 680));
215
216         return 0;
217 }
218 DM_TEST(dm_test_video_rotation1, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
219
220 /* Test rotated text output through the console uclass */
221 static int dm_test_video_rotation2(struct unit_test_state *uts)
222 {
223         ut_assertok(check_vidconsole_output(uts, 2, 785, 446));
224
225         return 0;
226 }
227 DM_TEST(dm_test_video_rotation2, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
228
229 /* Test rotated text output through the console uclass */
230 static int dm_test_video_rotation3(struct unit_test_state *uts)
231 {
232         ut_assertok(check_vidconsole_output(uts, 3, 1134, 681));
233
234         return 0;
235 }
236 DM_TEST(dm_test_video_rotation3, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
237
238 /* Read a file into memory and return a pointer to it */
239 static int read_file(struct unit_test_state *uts, const char *fname,
240                      ulong *addrp)
241 {
242         int buf_size = 100000;
243         ulong addr = 0;
244         int size, fd;
245         char *buf;
246
247         buf = map_sysmem(addr, 0);
248         ut_assert(buf != NULL);
249         fd = os_open(fname, OS_O_RDONLY);
250         ut_assert(fd >= 0);
251         size = os_read(fd, buf, buf_size);
252         ut_assert(size >= 0);
253         ut_assert(size < buf_size);
254         os_close(fd);
255         *addrp = addr;
256
257         return 0;
258 }
259
260 /* Test drawing a bitmap file */
261 static int dm_test_video_bmp(struct unit_test_state *uts)
262 {
263         struct udevice *dev;
264         ulong addr;
265
266         ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
267         ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
268
269         ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
270         ut_asserteq(1368, compress_frame_buffer(dev));
271
272         return 0;
273 }
274 DM_TEST(dm_test_video_bmp, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
275
276 /* Test drawing a compressed bitmap file */
277 static int dm_test_video_bmp_comp(struct unit_test_state *uts)
278 {
279         struct udevice *dev;
280         ulong addr;
281
282         ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
283         ut_assertok(read_file(uts, "tools/logos/denx-comp.bmp", &addr));
284
285         ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
286         ut_asserteq(1368, compress_frame_buffer(dev));
287
288         return 0;
289 }
290 DM_TEST(dm_test_video_bmp_comp, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);