blob: ecf74605b5c57996d96d50bde5e3313acdab4850 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glass90b6fef2016-01-18 19:52:26 -07002/*
3 * Copyright (c) 2014 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
Simon Glass90b6fef2016-01-18 19:52:26 -07005 */
6
Simon Glass90b6fef2016-01-18 19:52:26 -07007#include <bzlib.h>
8#include <dm.h>
Simon Glass8bd7f602021-11-19 13:23:58 -07009#include <gzip.h>
Simon Glass0f2af882020-05-10 11:40:05 -060010#include <log.h>
Simon Glass9bc15642020-02-03 07:36:16 -070011#include <malloc.h>
Simon Glass90b6fef2016-01-18 19:52:26 -070012#include <mapmem.h>
13#include <os.h>
14#include <video.h>
15#include <video_console.h>
Simon Glassc3b5adf2021-11-19 13:23:50 -070016#include <asm/test.h>
Sergei Antonov5da2b462023-06-13 00:19:04 +030017#include <asm/sdl.h>
Simon Glass90b6fef2016-01-18 19:52:26 -070018#include <dm/test.h>
19#include <dm/uclass-internal.h>
Simon Glassbe4fbd42025-04-02 06:29:42 +130020#include <test/lib.h>
Simon Glass75c4d412020-07-19 10:15:37 -060021#include <test/test.h>
Simon Glass90b6fef2016-01-18 19:52:26 -070022#include <test/ut.h>
Simon Glassd5099b42025-04-02 06:29:41 +130023#include <test/video.h>
Simon Glass90b6fef2016-01-18 19:52:26 -070024
25/*
26 * These tests use the standard sandbox frame buffer, the resolution of which
27 * is defined in the device tree. This only supports 16bpp so the tests only
28 * test that code path. It would be possible to adjust this fairly easily,
29 * by adjusting the bpix value in struct sandbox_sdl_plat. However the code
30 * in sandbox_sdl_sync() would also need to change to handle the different
31 * surface depth.
32 */
Simon Glass90b6fef2016-01-18 19:52:26 -070033/* Basic test of the video uclass */
34static int dm_test_video_base(struct unit_test_state *uts)
35{
36 struct video_priv *priv;
37 struct udevice *dev;
38
39 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
40 ut_asserteq(1366, video_get_xsize(dev));
41 ut_asserteq(768, video_get_ysize(dev));
42 priv = dev_get_uclass_priv(dev);
43 ut_asserteq(priv->fb_size, 1366 * 768 * 2);
44
45 return 0;
46}
Simon Glass1a92f832024-08-22 07:57:48 -060047DM_TEST(dm_test_video_base, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass90b6fef2016-01-18 19:52:26 -070048
Simon Glassd5099b42025-04-02 06:29:41 +130049int video_compress_fb(struct unit_test_state *uts, struct udevice *dev,
50 bool use_copy)
Simon Glass90b6fef2016-01-18 19:52:26 -070051{
52 struct video_priv *priv = dev_get_uclass_priv(dev);
53 uint destlen;
54 void *dest;
55 int ret;
56
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +030057 if (!IS_ENABLED(CONFIG_VIDEO_COPY))
58 use_copy = false;
59
Simon Glass90b6fef2016-01-18 19:52:26 -070060 destlen = priv->fb_size;
61 dest = malloc(priv->fb_size);
62 if (!dest)
63 return -ENOMEM;
64 ret = BZ2_bzBuffToBuffCompress(dest, &destlen,
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +030065 use_copy ? priv->copy_fb : priv->fb,
66 priv->fb_size,
Simon Glass90b6fef2016-01-18 19:52:26 -070067 3, 0, 0);
68 free(dest);
69 if (ret)
70 return ret;
71
72 return destlen;
73}
74
Simon Glassd5099b42025-04-02 06:29:41 +130075int video_check_copy_fb(struct unit_test_state *uts, struct udevice *dev)
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +030076{
77 struct video_priv *priv = dev_get_uclass_priv(dev);
78
79 if (!IS_ENABLED(CONFIG_VIDEO_COPY))
80 return 0;
81
Alexander Graff88b6a22022-06-10 00:59:21 +020082 video_sync(dev, false);
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +030083 ut_assertf(!memcmp(priv->fb, priv->copy_fb, priv->fb_size),
84 "Copy framebuffer does not match fb");
85
86 return 0;
87}
88
Simon Glass90b6fef2016-01-18 19:52:26 -070089/*
90 * Call this function at any point to halt and show the current display. Be
91 * sure to run the test with the -l flag.
92 */
93static void __maybe_unused see_output(void)
94{
95 video_sync_all();
96 while (1);
97}
98
Simon Glassdaac9c72016-01-14 18:10:50 -070099/* Select the video console driver to use for a video device */
100static int select_vidconsole(struct unit_test_state *uts, const char *drv_name)
101{
102 struct sandbox_sdl_plat *plat;
103 struct udevice *dev;
104
105 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
106 ut_assert(!device_active(dev));
Simon Glassfa20e932020-12-03 16:55:20 -0700107 plat = dev_get_plat(dev);
Simon Glassdaac9c72016-01-14 18:10:50 -0700108 plat->vidconsole_drv_name = "vidconsole0";
109
110 return 0;
111}
112
Simon Glass87a3cd72021-11-19 13:24:03 -0700113/**
114 * video_get_nologo() - Disable the logo on the video device and return it
115 *
116 * @uts: Test state
117 * @devp: Returns video device
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100118 * Return: 0 if OK, -ve on error
Simon Glass87a3cd72021-11-19 13:24:03 -0700119 */
120static int video_get_nologo(struct unit_test_state *uts, struct udevice **devp)
121{
122 struct video_uc_plat *uc_plat;
123 struct udevice *dev;
124
125 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
126 ut_assertnonnull(dev);
127 uc_plat = dev_get_uclass_plat(dev);
128 uc_plat->hide_logo = true;
129
130 /* now probe it */
131 ut_assertok(uclass_first_device_err(UCLASS_VIDEO, &dev));
132 ut_assertnonnull(dev);
133 *devp = dev;
134
135 return 0;
136}
137
Simon Glass90b6fef2016-01-18 19:52:26 -0700138/* Test text output works on the video console */
139static int dm_test_video_text(struct unit_test_state *uts)
140{
141 struct udevice *dev, *con;
142 int i;
143
144#define WHITE 0xffff
145#define SCROLL_LINES 100
146
Simon Glassdaac9c72016-01-14 18:10:50 -0700147 ut_assertok(select_vidconsole(uts, "vidconsole0"));
Simon Glass87a3cd72021-11-19 13:24:03 -0700148 ut_assertok(video_get_nologo(uts, &dev));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300149 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
150 ut_assertok(vidconsole_select_font(con, "8x16", 0));
Simon Glassd5099b42025-04-02 06:29:41 +1300151 ut_asserteq(46, video_compress_fb(uts, dev, false));
152 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700153
154 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
155 vidconsole_putc_xy(con, 0, 0, 'a');
Simon Glassd5099b42025-04-02 06:29:41 +1300156 ut_asserteq(79, video_compress_fb(uts, dev, false));
157 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700158
159 vidconsole_putc_xy(con, 0, 0, ' ');
Simon Glassd5099b42025-04-02 06:29:41 +1300160 ut_asserteq(46, video_compress_fb(uts, dev, false));
161 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700162
163 for (i = 0; i < 20; i++)
Simon Glass52c10c52016-01-14 18:10:37 -0700164 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
Simon Glassd5099b42025-04-02 06:29:41 +1300165 ut_asserteq(273, video_compress_fb(uts, dev, false));
166 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700167
168 vidconsole_set_row(con, 0, WHITE);
Simon Glassd5099b42025-04-02 06:29:41 +1300169 ut_asserteq(46, video_compress_fb(uts, dev, false));
170 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700171
172 for (i = 0; i < 20; i++)
Simon Glass52c10c52016-01-14 18:10:37 -0700173 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
Simon Glassd5099b42025-04-02 06:29:41 +1300174 ut_asserteq(273, video_compress_fb(uts, dev, false));
175 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700176
177 return 0;
178}
Simon Glass1a92f832024-08-22 07:57:48 -0600179DM_TEST(dm_test_video_text, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass90b6fef2016-01-18 19:52:26 -0700180
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300181static int dm_test_video_text_12x22(struct unit_test_state *uts)
182{
183 struct udevice *dev, *con;
184 int i;
185
186#define WHITE 0xffff
187#define SCROLL_LINES 100
188
189 ut_assertok(select_vidconsole(uts, "vidconsole0"));
190 ut_assertok(video_get_nologo(uts, &dev));
191 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
192 ut_assertok(vidconsole_select_font(con, "12x22", 0));
Simon Glassd5099b42025-04-02 06:29:41 +1300193 ut_asserteq(46, video_compress_fb(uts, dev, false));
194 ut_assertok(video_check_copy_fb(uts, dev));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300195
196 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
197 vidconsole_putc_xy(con, 0, 0, 'a');
Simon Glassd5099b42025-04-02 06:29:41 +1300198 ut_asserteq(89, video_compress_fb(uts, dev, false));
199 ut_assertok(video_check_copy_fb(uts, dev));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300200
201 vidconsole_putc_xy(con, 0, 0, ' ');
Simon Glassd5099b42025-04-02 06:29:41 +1300202 ut_asserteq(46, video_compress_fb(uts, dev, false));
203 ut_assertok(video_check_copy_fb(uts, dev));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300204
205 for (i = 0; i < 20; i++)
206 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
Simon Glassd5099b42025-04-02 06:29:41 +1300207 ut_asserteq(363, video_compress_fb(uts, dev, false));
208 ut_assertok(video_check_copy_fb(uts, dev));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300209
210 vidconsole_set_row(con, 0, WHITE);
Simon Glassd5099b42025-04-02 06:29:41 +1300211 ut_asserteq(46, video_compress_fb(uts, dev, false));
212 ut_assertok(video_check_copy_fb(uts, dev));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300213
214 for (i = 0; i < 20; i++)
215 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
Simon Glassd5099b42025-04-02 06:29:41 +1300216 ut_asserteq(363, video_compress_fb(uts, dev, false));
217 ut_assertok(video_check_copy_fb(uts, dev));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300218
219 return 0;
220}
Simon Glass1a92f832024-08-22 07:57:48 -0600221DM_TEST(dm_test_video_text_12x22, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300222
Simon Glass90b6fef2016-01-18 19:52:26 -0700223/* Test handling of special characters in the console */
224static int dm_test_video_chars(struct unit_test_state *uts)
225{
226 struct udevice *dev, *con;
Simon Glass37b80202016-01-14 18:10:38 -0700227 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 Glass90b6fef2016-01-18 19:52:26 -0700228
Simon Glassdaac9c72016-01-14 18:10:50 -0700229 ut_assertok(select_vidconsole(uts, "vidconsole0"));
Simon Glass87a3cd72021-11-19 13:24:03 -0700230 ut_assertok(video_get_nologo(uts, &dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700231 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300232 ut_assertok(vidconsole_select_font(con, "8x16", 0));
Rob Clark985935b2017-09-25 15:45:08 -0400233 vidconsole_put_string(con, test_string);
Simon Glassd5099b42025-04-02 06:29:41 +1300234 ut_asserteq(466, video_compress_fb(uts, dev, false));
235 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700236
237 return 0;
238}
Simon Glass1a92f832024-08-22 07:57:48 -0600239DM_TEST(dm_test_video_chars, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass90b6fef2016-01-18 19:52:26 -0700240
Rob Clark09d64b32017-09-25 15:45:09 -0400241#ifdef CONFIG_VIDEO_ANSI
242#define ANSI_ESC "\x1b"
243/* Test handling of ANSI escape sequences */
244static int dm_test_video_ansi(struct unit_test_state *uts)
245{
246 struct udevice *dev, *con;
247
248 ut_assertok(select_vidconsole(uts, "vidconsole0"));
Simon Glass87a3cd72021-11-19 13:24:03 -0700249 ut_assertok(video_get_nologo(uts, &dev));
Rob Clark09d64b32017-09-25 15:45:09 -0400250 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300251 ut_assertok(vidconsole_select_font(con, "8x16", 0));
Rob Clark09d64b32017-09-25 15:45:09 -0400252
253 /* reference clear: */
254 video_clear(con->parent);
Simon Glass0806dcc2018-10-01 11:55:14 -0600255 video_sync(con->parent, false);
Simon Glassd5099b42025-04-02 06:29:41 +1300256 ut_asserteq(46, video_compress_fb(uts, dev, false));
257 ut_assertok(video_check_copy_fb(uts, dev));
Rob Clark09d64b32017-09-25 15:45:09 -0400258
259 /* test clear escape sequence: [2J */
260 vidconsole_put_string(con, "A\tB\tC"ANSI_ESC"[2J");
Simon Glassd5099b42025-04-02 06:29:41 +1300261 ut_asserteq(46, video_compress_fb(uts, dev, false));
262 ut_assertok(video_check_copy_fb(uts, dev));
Rob Clark09d64b32017-09-25 15:45:09 -0400263
264 /* test set-cursor: [%d;%df */
265 vidconsole_put_string(con, "abc"ANSI_ESC"[2;2fab"ANSI_ESC"[4;4fcd");
Simon Glassd5099b42025-04-02 06:29:41 +1300266 ut_asserteq(143, video_compress_fb(uts, dev, false));
267 ut_assertok(video_check_copy_fb(uts, dev));
Rob Clark09d64b32017-09-25 15:45:09 -0400268
269 /* test colors (30-37 fg color, 40-47 bg color) */
270 vidconsole_put_string(con, ANSI_ESC"[30;41mfoo"); /* black on red */
271 vidconsole_put_string(con, ANSI_ESC"[33;44mbar"); /* yellow on blue */
Simon Glassd5099b42025-04-02 06:29:41 +1300272 ut_asserteq(272, video_compress_fb(uts, dev, false));
273 ut_assertok(video_check_copy_fb(uts, dev));
Rob Clark09d64b32017-09-25 15:45:09 -0400274
275 return 0;
276}
Simon Glass1a92f832024-08-22 07:57:48 -0600277DM_TEST(dm_test_video_ansi, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Rob Clark09d64b32017-09-25 15:45:09 -0400278#endif
279
Simon Glass90b6fef2016-01-18 19:52:26 -0700280/**
281 * check_vidconsole_output() - Run a text console test
282 *
283 * @uts: Test state
Simon Glass4425bf42020-07-02 21:12:28 -0600284 * @rot: Console rotation (0=normal orientation, 1=90 degrees clockwise,
285 * 2=upside down, 3=90 degree counterclockwise)
Simon Glass90b6fef2016-01-18 19:52:26 -0700286 * @wrap_size: Expected size of compressed frame buffer for the wrap test
287 * @scroll_size: Same for the scroll test
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100288 * Return: 0 on success
Simon Glass90b6fef2016-01-18 19:52:26 -0700289 */
290static int check_vidconsole_output(struct unit_test_state *uts, int rot,
291 int wrap_size, int scroll_size)
292{
293 struct udevice *dev, *con;
294 struct sandbox_sdl_plat *plat;
295 int i;
296
297 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
298 ut_assert(!device_active(dev));
Simon Glassfa20e932020-12-03 16:55:20 -0700299 plat = dev_get_plat(dev);
Simon Glass90b6fef2016-01-18 19:52:26 -0700300 plat->rot = rot;
301
Simon Glass87a3cd72021-11-19 13:24:03 -0700302 ut_assertok(video_get_nologo(uts, &dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700303 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300304 ut_assertok(vidconsole_select_font(con, "8x16", 0));
Simon Glassd5099b42025-04-02 06:29:41 +1300305 ut_asserteq(46, video_compress_fb(uts, dev, false));
306 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700307
308 /* Check display wrap */
309 for (i = 0; i < 120; i++)
310 vidconsole_put_char(con, 'A' + i % 50);
Simon Glassd5099b42025-04-02 06:29:41 +1300311 ut_asserteq(wrap_size, video_compress_fb(uts, dev, false));
312 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700313
314 /* Check display scrolling */
315 for (i = 0; i < SCROLL_LINES; i++) {
316 vidconsole_put_char(con, 'A' + i % 50);
317 vidconsole_put_char(con, '\n');
318 }
Simon Glassd5099b42025-04-02 06:29:41 +1300319 ut_asserteq(scroll_size, video_compress_fb(uts, dev, false));
320 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700321
322 /* If we scroll enough, the screen becomes blank again */
323 for (i = 0; i < SCROLL_LINES; i++)
324 vidconsole_put_char(con, '\n');
Simon Glassd5099b42025-04-02 06:29:41 +1300325 ut_asserteq(46, video_compress_fb(uts, dev, false));
326 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700327
328 return 0;
329}
330
331/* Test text output through the console uclass */
332static int dm_test_video_context(struct unit_test_state *uts)
333{
Simon Glassdaac9c72016-01-14 18:10:50 -0700334 ut_assertok(select_vidconsole(uts, "vidconsole0"));
335 ut_assertok(check_vidconsole_output(uts, 0, 788, 453));
336
337 return 0;
Simon Glass90b6fef2016-01-18 19:52:26 -0700338}
Simon Glass1a92f832024-08-22 07:57:48 -0600339DM_TEST(dm_test_video_context, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glassa0f1efe2016-01-18 19:52:27 -0700340
341/* Test rotated text output through the console uclass */
342static int dm_test_video_rotation1(struct unit_test_state *uts)
343{
344 ut_assertok(check_vidconsole_output(uts, 1, 1112, 680));
345
346 return 0;
347}
Simon Glass1a92f832024-08-22 07:57:48 -0600348DM_TEST(dm_test_video_rotation1, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glassa0f1efe2016-01-18 19:52:27 -0700349
350/* Test rotated text output through the console uclass */
351static int dm_test_video_rotation2(struct unit_test_state *uts)
352{
Simon Glassf50a6b92020-07-02 21:12:17 -0600353 ut_assertok(check_vidconsole_output(uts, 2, 783, 445));
Simon Glassa0f1efe2016-01-18 19:52:27 -0700354
355 return 0;
356}
Simon Glass1a92f832024-08-22 07:57:48 -0600357DM_TEST(dm_test_video_rotation2, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glassa0f1efe2016-01-18 19:52:27 -0700358
359/* Test rotated text output through the console uclass */
360static int dm_test_video_rotation3(struct unit_test_state *uts)
361{
362 ut_assertok(check_vidconsole_output(uts, 3, 1134, 681));
363
364 return 0;
365}
Simon Glass1a92f832024-08-22 07:57:48 -0600366DM_TEST(dm_test_video_rotation3, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass7a1cb292016-01-18 19:52:28 -0700367
368/* Read a file into memory and return a pointer to it */
369static int read_file(struct unit_test_state *uts, const char *fname,
370 ulong *addrp)
371{
372 int buf_size = 100000;
373 ulong addr = 0;
374 int size, fd;
375 char *buf;
376
377 buf = map_sysmem(addr, 0);
378 ut_assert(buf != NULL);
379 fd = os_open(fname, OS_O_RDONLY);
380 ut_assert(fd >= 0);
381 size = os_read(fd, buf, buf_size);
Simon Glass9050c5f2016-01-30 15:45:17 -0700382 os_close(fd);
Simon Glass7a1cb292016-01-18 19:52:28 -0700383 ut_assert(size >= 0);
384 ut_assert(size < buf_size);
Simon Glass7a1cb292016-01-18 19:52:28 -0700385 *addrp = addr;
386
387 return 0;
388}
389
390/* Test drawing a bitmap file */
391static int dm_test_video_bmp(struct unit_test_state *uts)
392{
393 struct udevice *dev;
394 ulong addr;
395
Simon Glass87a3cd72021-11-19 13:24:03 -0700396 ut_assertok(video_get_nologo(uts, &dev));
Simon Glass7a1cb292016-01-18 19:52:28 -0700397 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
398
399 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
Simon Glassd5099b42025-04-02 06:29:41 +1300400 ut_asserteq(1368, video_compress_fb(uts, dev, false));
401 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass7a1cb292016-01-18 19:52:28 -0700402
403 return 0;
404}
Simon Glass1a92f832024-08-22 07:57:48 -0600405DM_TEST(dm_test_video_bmp, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass7a1cb292016-01-18 19:52:28 -0700406
Simon Glassc3b5adf2021-11-19 13:23:50 -0700407/* Test drawing a bitmap file on a 8bpp display */
408static int dm_test_video_bmp8(struct unit_test_state *uts)
409{
410 struct udevice *dev;
411 ulong addr;
412
413 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
414 ut_assertnonnull(dev);
415 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP8));
416
417 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
418
419 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
Simon Glassd5099b42025-04-02 06:29:41 +1300420 ut_asserteq(1247, video_compress_fb(uts, dev, false));
421 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glassc3b5adf2021-11-19 13:23:50 -0700422
423 return 0;
424}
Simon Glass1a92f832024-08-22 07:57:48 -0600425DM_TEST(dm_test_video_bmp8, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glassc3b5adf2021-11-19 13:23:50 -0700426
Simon Glass8bd7f602021-11-19 13:23:58 -0700427/* Test drawing a bitmap file on a 16bpp display */
428static int dm_test_video_bmp16(struct unit_test_state *uts)
429{
430 ulong src, src_len = ~0UL;
431 uint dst_len = ~0U;
432 struct udevice *dev;
433 ulong dst = 0x10000;
434
435 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
436 ut_assertnonnull(dev);
437 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP16));
438
439 ut_assertok(read_file(uts, "tools/logos/denx-16bpp.bmp.gz", &src));
440 ut_assertok(gunzip(map_sysmem(dst, 0), dst_len, map_sysmem(src, 0),
441 &src_len));
442
443 ut_assertok(video_bmp_display(dev, dst, 0, 0, false));
Simon Glassd5099b42025-04-02 06:29:41 +1300444 ut_asserteq(3700, video_compress_fb(uts, dev, false));
445 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass8bd7f602021-11-19 13:23:58 -0700446
447 return 0;
448}
Simon Glass1a92f832024-08-22 07:57:48 -0600449DM_TEST(dm_test_video_bmp16, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass8bd7f602021-11-19 13:23:58 -0700450
Simon Glass6a92e882021-11-19 13:23:59 -0700451/* Test drawing a 24bpp bitmap file on a 16bpp display */
452static int dm_test_video_bmp24(struct unit_test_state *uts)
453{
454 ulong src, src_len = ~0UL;
455 uint dst_len = ~0U;
456 struct udevice *dev;
457 ulong dst = 0x10000;
458
459 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
460 ut_assertnonnull(dev);
461 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP16));
462
463 ut_assertok(read_file(uts, "tools/logos/denx-24bpp.bmp.gz", &src));
464 ut_assertok(gunzip(map_sysmem(dst, 0), dst_len, map_sysmem(src, 0),
465 &src_len));
466
467 ut_assertok(video_bmp_display(dev, dst, 0, 0, false));
Simon Glassd5099b42025-04-02 06:29:41 +1300468 ut_asserteq(3656, video_compress_fb(uts, dev, false));
469 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass6a92e882021-11-19 13:23:59 -0700470
471 return 0;
472}
Simon Glass1a92f832024-08-22 07:57:48 -0600473DM_TEST(dm_test_video_bmp24, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass6a92e882021-11-19 13:23:59 -0700474
475/* Test drawing a 24bpp bitmap file on a 32bpp display */
476static int dm_test_video_bmp24_32(struct unit_test_state *uts)
477{
478 ulong src, src_len = ~0UL;
479 uint dst_len = ~0U;
480 struct udevice *dev;
481 ulong dst = 0x10000;
482
483 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
484 ut_assertnonnull(dev);
485 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP32));
486
487 ut_assertok(read_file(uts, "tools/logos/denx-24bpp.bmp.gz", &src));
488 ut_assertok(gunzip(map_sysmem(dst, 0), dst_len, map_sysmem(src, 0),
489 &src_len));
490
491 ut_assertok(video_bmp_display(dev, dst, 0, 0, false));
Simon Glassd5099b42025-04-02 06:29:41 +1300492 ut_asserteq(6827, video_compress_fb(uts, dev, false));
493 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass6a92e882021-11-19 13:23:59 -0700494
495 return 0;
496}
Simon Glass1a92f832024-08-22 07:57:48 -0600497DM_TEST(dm_test_video_bmp24_32, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass6a92e882021-11-19 13:23:59 -0700498
Simon Glassc3b5adf2021-11-19 13:23:50 -0700499/* Test drawing a bitmap file on a 32bpp display */
500static int dm_test_video_bmp32(struct unit_test_state *uts)
501{
502 struct udevice *dev;
503 ulong addr;
504
505 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
506 ut_assertnonnull(dev);
507 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP32));
508 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
509
510 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
Simon Glassd5099b42025-04-02 06:29:41 +1300511 ut_asserteq(2024, video_compress_fb(uts, dev, false));
512 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glassc3b5adf2021-11-19 13:23:50 -0700513
514 return 0;
515}
Simon Glass1a92f832024-08-22 07:57:48 -0600516DM_TEST(dm_test_video_bmp32, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glassc3b5adf2021-11-19 13:23:50 -0700517
Simon Glass7a1cb292016-01-18 19:52:28 -0700518/* Test drawing a compressed bitmap file */
519static int dm_test_video_bmp_comp(struct unit_test_state *uts)
520{
521 struct udevice *dev;
522 ulong addr;
523
Simon Glass87a3cd72021-11-19 13:24:03 -0700524 ut_assertok(video_get_nologo(uts, &dev));
Simon Glass7a1cb292016-01-18 19:52:28 -0700525 ut_assertok(read_file(uts, "tools/logos/denx-comp.bmp", &addr));
526
527 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
Simon Glassd5099b42025-04-02 06:29:41 +1300528 ut_asserteq(1368, video_compress_fb(uts, dev, false));
529 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass7a1cb292016-01-18 19:52:28 -0700530
531 return 0;
532}
Simon Glass1a92f832024-08-22 07:57:48 -0600533DM_TEST(dm_test_video_bmp_comp, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass32337982016-01-14 18:10:51 -0700534
Simon Glass490bb992021-11-19 13:23:55 -0700535/* Test drawing a bitmap file on a 32bpp display */
536static int dm_test_video_comp_bmp32(struct unit_test_state *uts)
537{
538 struct udevice *dev;
539 ulong addr;
540
541 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
542 ut_assertnonnull(dev);
543 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP32));
544
545 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
546
547 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
Simon Glassd5099b42025-04-02 06:29:41 +1300548 ut_asserteq(2024, video_compress_fb(uts, dev, false));
549 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass490bb992021-11-19 13:23:55 -0700550
551 return 0;
552}
Simon Glass1a92f832024-08-22 07:57:48 -0600553DM_TEST(dm_test_video_comp_bmp32, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass490bb992021-11-19 13:23:55 -0700554
555/* Test drawing a bitmap file on a 8bpp display */
556static int dm_test_video_comp_bmp8(struct unit_test_state *uts)
557{
558 struct udevice *dev;
559 ulong addr;
560
561 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
562 ut_assertnonnull(dev);
563 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP8));
564
565 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
566
567 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
Simon Glassd5099b42025-04-02 06:29:41 +1300568 ut_asserteq(1247, video_compress_fb(uts, dev, false));
569 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass490bb992021-11-19 13:23:55 -0700570
571 return 0;
572}
Simon Glass1a92f832024-08-22 07:57:48 -0600573DM_TEST(dm_test_video_comp_bmp8, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass490bb992021-11-19 13:23:55 -0700574
Simon Glass32337982016-01-14 18:10:51 -0700575/* Test TrueType console */
576static int dm_test_video_truetype(struct unit_test_state *uts)
577{
578 struct udevice *dev, *con;
579 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 Glass32337982016-01-14 18:10:51 -0700580
Simon Glass87a3cd72021-11-19 13:24:03 -0700581 ut_assertok(video_get_nologo(uts, &dev));
Simon Glass32337982016-01-14 18:10:51 -0700582 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
Rob Clark985935b2017-09-25 15:45:08 -0400583 vidconsole_put_string(con, test_string);
Simon Glass6f5a8642025-04-02 06:29:40 +1300584 vidconsole_put_stringn(con, test_string, 30);
Simon Glassd5099b42025-04-02 06:29:41 +1300585 ut_asserteq(13184, video_compress_fb(uts, dev, false));
586 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass32337982016-01-14 18:10:51 -0700587
588 return 0;
589}
Simon Glass1a92f832024-08-22 07:57:48 -0600590DM_TEST(dm_test_video_truetype, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass32337982016-01-14 18:10:51 -0700591
592/* Test scrolling TrueType console */
593static int dm_test_video_truetype_scroll(struct unit_test_state *uts)
594{
595 struct sandbox_sdl_plat *plat;
596 struct udevice *dev, *con;
597 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 Glass32337982016-01-14 18:10:51 -0700598
599 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
600 ut_assert(!device_active(dev));
Simon Glassfa20e932020-12-03 16:55:20 -0700601 plat = dev_get_plat(dev);
Simon Glass32337982016-01-14 18:10:51 -0700602 plat->font_size = 100;
603
Simon Glass87a3cd72021-11-19 13:24:03 -0700604 ut_assertok(video_get_nologo(uts, &dev));
Simon Glass32337982016-01-14 18:10:51 -0700605 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
Rob Clark985935b2017-09-25 15:45:08 -0400606 vidconsole_put_string(con, test_string);
Simon Glassd5099b42025-04-02 06:29:41 +1300607 ut_asserteq(34287, video_compress_fb(uts, dev, false));
608 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass32337982016-01-14 18:10:51 -0700609
610 return 0;
611}
Simon Glass1a92f832024-08-22 07:57:48 -0600612DM_TEST(dm_test_video_truetype_scroll, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass32337982016-01-14 18:10:51 -0700613
614/* Test TrueType backspace, within and across lines */
615static int dm_test_video_truetype_bs(struct unit_test_state *uts)
616{
617 struct sandbox_sdl_plat *plat;
618 struct udevice *dev, *con;
619 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 Glass32337982016-01-14 18:10:51 -0700620
621 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
622 ut_assert(!device_active(dev));
Simon Glassfa20e932020-12-03 16:55:20 -0700623 plat = dev_get_plat(dev);
Simon Glass32337982016-01-14 18:10:51 -0700624 plat->font_size = 100;
625
Simon Glass87a3cd72021-11-19 13:24:03 -0700626 ut_assertok(video_get_nologo(uts, &dev));
Simon Glass32337982016-01-14 18:10:51 -0700627 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
Rob Clark985935b2017-09-25 15:45:08 -0400628 vidconsole_put_string(con, test_string);
Simon Glassd5099b42025-04-02 06:29:41 +1300629 ut_asserteq(29471, video_compress_fb(uts, dev, false));
630 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass32337982016-01-14 18:10:51 -0700631
632 return 0;
633}
Simon Glass1a92f832024-08-22 07:57:48 -0600634DM_TEST(dm_test_video_truetype_bs, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Alper Nebi Yasak5e8253d2023-08-18 17:31:27 +0300635
636/* Test partial rendering onto hardware frame buffer */
637static int dm_test_video_copy(struct unit_test_state *uts)
638{
639 struct sandbox_sdl_plat *plat;
640 struct video_uc_plat *uc_plat;
641 struct udevice *dev, *con;
642 struct video_priv *priv;
643 const char *test_string = "\n\tCriticism may not be agreeable, but it is necessary.\t";
644 ulong addr;
645
646 if (!IS_ENABLED(CONFIG_VIDEO_COPY))
647 return -EAGAIN;
648
649 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
650 ut_assertnonnull(dev);
651 uc_plat = dev_get_uclass_plat(dev);
652 uc_plat->hide_logo = true;
653 plat = dev_get_plat(dev);
654 plat->font_size = 32;
655 ut_assert(!device_active(dev));
656 ut_assertok(uclass_first_device_err(UCLASS_VIDEO, &dev));
657 ut_assertnonnull(dev);
658 priv = dev_get_uclass_priv(dev);
659
660 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
661 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
662
663 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
664 vidconsole_put_string(con, "\n\n\n\n\n");
665 vidconsole_put_string(con, test_string);
666 vidconsole_put_string(con, test_string);
667
Simon Glassd5099b42025-04-02 06:29:41 +1300668 ut_asserteq(6678, video_compress_fb(uts, dev, false));
669 ut_assertok(video_check_copy_fb(uts, dev));
Alper Nebi Yasak5e8253d2023-08-18 17:31:27 +0300670
671 /*
672 * Secretly clear the hardware frame buffer, but in a different
673 * color (black) to see which parts will be overwritten.
674 */
675 memset(priv->copy_fb, 0, priv->fb_size);
676
677 /*
678 * We should have the full content on the main buffer, but only
Alexander Graff88b6a22022-06-10 00:59:21 +0200679 * 'damage' should have been copied to the copy buffer. This consists
680 * of a while rectangle with the Denx logo and four lines of text. The
681 * rest of the display is black.
682 *
683 * An easy way to try this is by changing video_sync() to call
684 * sandbox_sdl_sync(priv->copy_fb) instead of priv->fb then running the
685 * unit test:
686 *
687 * ./u-boot -Tl
688 * ut dm dm_test_video_copy
Alper Nebi Yasak5e8253d2023-08-18 17:31:27 +0300689 */
690 vidconsole_put_string(con, test_string);
691 vidconsole_put_string(con, test_string);
Alexander Graff88b6a22022-06-10 00:59:21 +0200692 video_sync(dev, true);
Simon Glassd5099b42025-04-02 06:29:41 +1300693 ut_asserteq(7589, video_compress_fb(uts, dev, false));
694 ut_asserteq(7704, video_compress_fb(uts, dev, true));
Alper Nebi Yasak5e8253d2023-08-18 17:31:27 +0300695
696 return 0;
697}
698DM_TEST(dm_test_video_copy, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Alper Nebi Yasakfc5740a2023-08-18 17:55:08 +0300699
700/* Test video damage tracking */
701static int dm_test_video_damage(struct unit_test_state *uts)
702{
703 struct sandbox_sdl_plat *plat;
704 struct udevice *dev, *con;
705 struct video_priv *priv;
706 const char *test_string_1 = "Criticism may not be agreeable, ";
707 const char *test_string_2 = "but it is necessary.";
708 const char *test_string_3 = "It fulfils the same function as pain in the human body.";
709
710 if (!IS_ENABLED(CONFIG_VIDEO_DAMAGE))
711 return -EAGAIN;
712
713 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
714 ut_assert(!device_active(dev));
715 plat = dev_get_plat(dev);
716 plat->font_size = 32;
717
718 ut_assertok(video_get_nologo(uts, &dev));
719 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
720 priv = dev_get_uclass_priv(dev);
721
722 vidconsole_position_cursor(con, 14, 10);
723 vidconsole_put_string(con, test_string_2);
724 ut_asserteq(449, priv->damage.xstart);
725 ut_asserteq(325, priv->damage.ystart);
726 ut_asserteq(661, priv->damage.xend);
727 ut_asserteq(350, priv->damage.yend);
728
729 vidconsole_position_cursor(con, 7, 5);
730 vidconsole_put_string(con, test_string_1);
731 ut_asserteq(225, priv->damage.xstart);
732 ut_asserteq(164, priv->damage.ystart);
733 ut_asserteq(661, priv->damage.xend);
734 ut_asserteq(350, priv->damage.yend);
735
736 vidconsole_position_cursor(con, 21, 15);
737 vidconsole_put_string(con, test_string_3);
738 ut_asserteq(225, priv->damage.xstart);
739 ut_asserteq(164, priv->damage.ystart);
740 ut_asserteq(1280, priv->damage.xend);
741 ut_asserteq(510, priv->damage.yend);
742
743 video_sync(dev, true);
744 ut_asserteq(priv->xsize, priv->damage.xstart);
745 ut_asserteq(priv->ysize, priv->damage.ystart);
746 ut_asserteq(0, priv->damage.xend);
747 ut_asserteq(0, priv->damage.yend);
748
Simon Glassd5099b42025-04-02 06:29:41 +1300749 ut_asserteq(7339, video_compress_fb(uts, dev, false));
750 ut_assertok(video_check_copy_fb(uts, dev));
Alper Nebi Yasakfc5740a2023-08-18 17:55:08 +0300751
752 return 0;
753}
754DM_TEST(dm_test_video_damage, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glassfff57f62025-04-02 06:29:35 +1300755
756/* Test font measurement */
757static int dm_test_font_measure(struct unit_test_state *uts)
758{
Simon Glass3c686e62025-04-02 06:29:38 +1300759 const char *test_string = "There is always much\nto be said for not "
Simon Glassfff57f62025-04-02 06:29:35 +1300760 "attempting more than you can do and for making a certainty of "
761 "what you try. But this principle, like others in life and "
762 "war, has its exceptions.";
Simon Glasseb4efc62025-04-02 06:29:37 +1300763 const struct vidconsole_mline *line;
Simon Glassfff57f62025-04-02 06:29:35 +1300764 struct vidconsole_bbox bbox;
765 struct video_priv *priv;
766 struct udevice *dev, *con;
Simon Glass3aa33582025-04-02 06:29:39 +1300767 const int limit = 0x320;
Simon Glass95bcad42025-04-02 06:29:36 +1300768 struct alist lines;
Simon Glass3c686e62025-04-02 06:29:38 +1300769 int nl;
Simon Glassfff57f62025-04-02 06:29:35 +1300770
771 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
772 priv = dev_get_uclass_priv(dev);
773 ut_asserteq(1366, priv->xsize);
774 ut_asserteq(768, priv->ysize);
775
776 /* this is using the Nimbus font with size of 18 pixels */
777 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
778 vidconsole_position_cursor(con, 0, 0);
Simon Glasseb4efc62025-04-02 06:29:37 +1300779 alist_init_struct(&lines, struct vidconsole_mline);
Simon Glass3aa33582025-04-02 06:29:39 +1300780 ut_assertok(vidconsole_measure(con, NULL, 0, test_string, -1, &bbox,
Simon Glass95bcad42025-04-02 06:29:36 +1300781 &lines));
Simon Glassfff57f62025-04-02 06:29:35 +1300782 ut_asserteq(0, bbox.x0);
783 ut_asserteq(0, bbox.y0);
Simon Glass3c686e62025-04-02 06:29:38 +1300784 ut_asserteq(0x3ea, bbox.x1);
785 ut_asserteq(0x24, bbox.y1);
786 ut_asserteq(2, lines.count);
787
788 nl = strchr(test_string, '\n') - test_string;
Simon Glasseb4efc62025-04-02 06:29:37 +1300789
790 line = alist_get(&lines, 0, struct vidconsole_mline);
791 ut_assertnonnull(line);
792 ut_asserteq(0, line->bbox.x0);
793 ut_asserteq(0, line->bbox.y0);
Simon Glass3c686e62025-04-02 06:29:38 +1300794 ut_asserteq(0x8c, line->bbox.x1);
Simon Glasseb4efc62025-04-02 06:29:37 +1300795 ut_asserteq(0x12, line->bbox.y1);
796 ut_asserteq(0, line->start);
Simon Glass3c686e62025-04-02 06:29:38 +1300797 ut_asserteq(20, line->len);
798 ut_asserteq(nl, line->len);
799
800 line++;
801 ut_asserteq(0x0, line->bbox.x0);
802 ut_asserteq(0x12, line->bbox.y0);
803 ut_asserteq(0x3ea, line->bbox.x1);
804 ut_asserteq(0x24, line->bbox.y1);
805 ut_asserteq(21, line->start);
806 ut_asserteq(nl + 1, line->start);
807 ut_asserteq(163, line->len);
808 ut_asserteq(strlen(test_string + nl + 1), line->len);
Simon Glassfff57f62025-04-02 06:29:35 +1300809
Simon Glass3aa33582025-04-02 06:29:39 +1300810 /* now use a limit on the width */
811 ut_assertok(vidconsole_measure(con, NULL, 0, test_string, limit, &bbox,
812 &lines));
813 ut_asserteq(0, bbox.x0);
814 ut_asserteq(0, bbox.y0);
815 ut_asserteq(0x31e, bbox.x1);
816 ut_asserteq(0x36, bbox.y1);
817 ut_asserteq(3, lines.count);
818
819 nl = strchr(test_string, '\n') - test_string;
820
821 line = alist_get(&lines, 0, struct vidconsole_mline);
822 ut_assertnonnull(line);
823 ut_asserteq(0, line->bbox.x0);
824 ut_asserteq(0, line->bbox.y0);
825 ut_asserteq(0x8c, line->bbox.x1);
826 ut_asserteq(0x12, line->bbox.y1);
827 ut_asserteq(0, line->start);
828 ut_asserteq(20, line->len);
829 ut_asserteq(nl, line->len);
830 printf("line0 '%.*s'\n", line->len, test_string + line->start);
831 ut_asserteq_strn("There is always much",
832 test_string + line->start);
833
834 line++;
835 ut_asserteq(0x0, line->bbox.x0);
836 ut_asserteq(0x12, line->bbox.y0);
837 ut_asserteq(0x31e, line->bbox.x1);
838 ut_asserteq(0x24, line->bbox.y1);
839 ut_asserteq(21, line->start);
840 ut_asserteq(nl + 1, line->start);
841 ut_asserteq(129, line->len);
842 printf("line1 '%.*s'\n", line->len, test_string + line->start);
843 ut_asserteq_strn("to be said for not attempting more than you can do "
844 "and for making a certainty of what you try. But this "
845 "principle, like others in",
846 test_string + line->start);
847
848 line++;
849 ut_asserteq(0x0, line->bbox.x0);
850 ut_asserteq(0x24, line->bbox.y0);
851 ut_asserteq(0xc8, line->bbox.x1);
852 ut_asserteq(0x36, line->bbox.y1);
853 ut_asserteq(21 + 130, line->start);
854 ut_asserteq(33, line->len);
855 printf("line2 '%.*s'\n", line->len, test_string + line->start);
856 ut_asserteq_strn("life and war, has its exceptions.",
857 test_string + line->start);
858
859 /*
860 * all characters should be accounted for, except the newline and the
861 * space which is consumed in the wordwrap
862 */
863 ut_asserteq(strlen(test_string) - 2,
864 line[-2].len + line[-1].len + line->len);
865
Simon Glassfff57f62025-04-02 06:29:35 +1300866 return 0;
867}
868DM_TEST(dm_test_font_measure, UTF_SCAN_FDT);
Simon Glassbe4fbd42025-04-02 06:29:42 +1300869
870/* Test silencing the video console */
871static int dm_test_video_silence(struct unit_test_state *uts)
872{
873 struct udevice *dev, *con;
874 struct stdio_dev *sdev;
875
876 ut_assertok(uclass_first_device_err(UCLASS_VIDEO, &dev));
877
878 /*
879 * use the old console device from before when dm_test_pre_run() was
880 * called, since that is what is in stdio / console
881 */
882 sdev = stdio_get_by_name("vidconsole");
883 ut_assertnonnull(sdev);
884 con = sdev->priv;
885 ut_assertok(vidconsole_clear_and_reset(con));
886 ut_unsilence_console(uts);
887
888 printf("message 1: console\n");
889 vidconsole_put_string(con, "message 1: video\n");
890
891 vidconsole_set_quiet(con, true);
892 printf("second message: console\n");
893 vidconsole_put_string(con, "second message: video\n");
894
895 vidconsole_set_quiet(con, false);
896 printf("final message: console\n");
897 vidconsole_put_string(con, "final message: video\n");
898
899 ut_asserteq(3892, video_compress_fb(uts, dev, false));
900 ut_assertok(video_check_copy_fb(uts, dev));
901
902 return 0;
903}
904DM_TEST(dm_test_video_silence, UTF_SCAN_FDT);
Simon Glassaef8c792025-04-02 06:29:43 +1300905
906/* test drawing a box */
907static int dm_test_video_box(struct unit_test_state *uts)
908{
909 struct video_priv *priv;
910 struct udevice *dev;
911
912 ut_assertok(video_get_nologo(uts, &dev));
913 priv = dev_get_uclass_priv(dev);
914 video_draw_box(dev, 100, 100, 200, 200, 3,
915 video_index_to_colour(priv, VID_LIGHT_BLUE));
916 video_draw_box(dev, 300, 100, 400, 200, 1,
917 video_index_to_colour(priv, VID_MAGENTA));
918 video_draw_box(dev, 500, 100, 600, 200, 20,
919 video_index_to_colour(priv, VID_LIGHT_RED));
920 ut_asserteq(133, video_compress_fb(uts, dev, false));
921 ut_assertok(video_check_copy_fb(uts, dev));
922
923 return 0;
924}
925DM_TEST(dm_test_video_box, UTF_SCAN_FDT);