blob: 737ab915f4167d07668b688955fcbb07fd70db45 [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 Glass75c4d412020-07-19 10:15:37 -060020#include <test/test.h>
Simon Glass90b6fef2016-01-18 19:52:26 -070021#include <test/ut.h>
Simon Glassd5099b42025-04-02 06:29:41 +130022#include <test/video.h>
Simon Glass90b6fef2016-01-18 19:52:26 -070023
24/*
25 * These tests use the standard sandbox frame buffer, the resolution of which
26 * is defined in the device tree. This only supports 16bpp so the tests only
27 * test that code path. It would be possible to adjust this fairly easily,
28 * by adjusting the bpix value in struct sandbox_sdl_plat. However the code
29 * in sandbox_sdl_sync() would also need to change to handle the different
30 * surface depth.
31 */
Simon Glass90b6fef2016-01-18 19:52:26 -070032/* Basic test of the video uclass */
33static int dm_test_video_base(struct unit_test_state *uts)
34{
35 struct video_priv *priv;
36 struct udevice *dev;
37
38 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
39 ut_asserteq(1366, video_get_xsize(dev));
40 ut_asserteq(768, video_get_ysize(dev));
41 priv = dev_get_uclass_priv(dev);
42 ut_asserteq(priv->fb_size, 1366 * 768 * 2);
43
44 return 0;
45}
Simon Glass1a92f832024-08-22 07:57:48 -060046DM_TEST(dm_test_video_base, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass90b6fef2016-01-18 19:52:26 -070047
Simon Glassd5099b42025-04-02 06:29:41 +130048int video_compress_fb(struct unit_test_state *uts, struct udevice *dev,
49 bool use_copy)
Simon Glass90b6fef2016-01-18 19:52:26 -070050{
51 struct video_priv *priv = dev_get_uclass_priv(dev);
52 uint destlen;
53 void *dest;
54 int ret;
55
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +030056 if (!IS_ENABLED(CONFIG_VIDEO_COPY))
57 use_copy = false;
58
Simon Glass90b6fef2016-01-18 19:52:26 -070059 destlen = priv->fb_size;
60 dest = malloc(priv->fb_size);
61 if (!dest)
62 return -ENOMEM;
63 ret = BZ2_bzBuffToBuffCompress(dest, &destlen,
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +030064 use_copy ? priv->copy_fb : priv->fb,
65 priv->fb_size,
Simon Glass90b6fef2016-01-18 19:52:26 -070066 3, 0, 0);
67 free(dest);
68 if (ret)
69 return ret;
70
71 return destlen;
72}
73
Simon Glassd5099b42025-04-02 06:29:41 +130074int video_check_copy_fb(struct unit_test_state *uts, struct udevice *dev)
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +030075{
76 struct video_priv *priv = dev_get_uclass_priv(dev);
77
78 if (!IS_ENABLED(CONFIG_VIDEO_COPY))
79 return 0;
80
Alexander Graff88b6a22022-06-10 00:59:21 +020081 video_sync(dev, false);
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +030082 ut_assertf(!memcmp(priv->fb, priv->copy_fb, priv->fb_size),
83 "Copy framebuffer does not match fb");
84
85 return 0;
86}
87
Simon Glass90b6fef2016-01-18 19:52:26 -070088/*
89 * Call this function at any point to halt and show the current display. Be
90 * sure to run the test with the -l flag.
91 */
92static void __maybe_unused see_output(void)
93{
94 video_sync_all();
95 while (1);
96}
97
Simon Glassdaac9c72016-01-14 18:10:50 -070098/* Select the video console driver to use for a video device */
99static int select_vidconsole(struct unit_test_state *uts, const char *drv_name)
100{
101 struct sandbox_sdl_plat *plat;
102 struct udevice *dev;
103
104 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
105 ut_assert(!device_active(dev));
Simon Glassfa20e932020-12-03 16:55:20 -0700106 plat = dev_get_plat(dev);
Simon Glassdaac9c72016-01-14 18:10:50 -0700107 plat->vidconsole_drv_name = "vidconsole0";
108
109 return 0;
110}
111
Simon Glass87a3cd72021-11-19 13:24:03 -0700112/**
113 * video_get_nologo() - Disable the logo on the video device and return it
114 *
115 * @uts: Test state
116 * @devp: Returns video device
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100117 * Return: 0 if OK, -ve on error
Simon Glass87a3cd72021-11-19 13:24:03 -0700118 */
119static int video_get_nologo(struct unit_test_state *uts, struct udevice **devp)
120{
121 struct video_uc_plat *uc_plat;
122 struct udevice *dev;
123
124 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
125 ut_assertnonnull(dev);
126 uc_plat = dev_get_uclass_plat(dev);
127 uc_plat->hide_logo = true;
128
129 /* now probe it */
130 ut_assertok(uclass_first_device_err(UCLASS_VIDEO, &dev));
131 ut_assertnonnull(dev);
132 *devp = dev;
133
134 return 0;
135}
136
Simon Glass90b6fef2016-01-18 19:52:26 -0700137/* Test text output works on the video console */
138static int dm_test_video_text(struct unit_test_state *uts)
139{
140 struct udevice *dev, *con;
141 int i;
142
143#define WHITE 0xffff
144#define SCROLL_LINES 100
145
Simon Glassdaac9c72016-01-14 18:10:50 -0700146 ut_assertok(select_vidconsole(uts, "vidconsole0"));
Simon Glass87a3cd72021-11-19 13:24:03 -0700147 ut_assertok(video_get_nologo(uts, &dev));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300148 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
149 ut_assertok(vidconsole_select_font(con, "8x16", 0));
Simon Glassd5099b42025-04-02 06:29:41 +1300150 ut_asserteq(46, video_compress_fb(uts, dev, false));
151 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700152
153 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
154 vidconsole_putc_xy(con, 0, 0, 'a');
Simon Glassd5099b42025-04-02 06:29:41 +1300155 ut_asserteq(79, video_compress_fb(uts, dev, false));
156 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700157
158 vidconsole_putc_xy(con, 0, 0, ' ');
Simon Glassd5099b42025-04-02 06:29:41 +1300159 ut_asserteq(46, video_compress_fb(uts, dev, false));
160 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700161
162 for (i = 0; i < 20; i++)
Simon Glass52c10c52016-01-14 18:10:37 -0700163 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
Simon Glassd5099b42025-04-02 06:29:41 +1300164 ut_asserteq(273, video_compress_fb(uts, dev, false));
165 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700166
167 vidconsole_set_row(con, 0, WHITE);
Simon Glassd5099b42025-04-02 06:29:41 +1300168 ut_asserteq(46, video_compress_fb(uts, dev, false));
169 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700170
171 for (i = 0; i < 20; i++)
Simon Glass52c10c52016-01-14 18:10:37 -0700172 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
Simon Glassd5099b42025-04-02 06:29:41 +1300173 ut_asserteq(273, video_compress_fb(uts, dev, false));
174 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700175
176 return 0;
177}
Simon Glass1a92f832024-08-22 07:57:48 -0600178DM_TEST(dm_test_video_text, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass90b6fef2016-01-18 19:52:26 -0700179
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300180static int dm_test_video_text_12x22(struct unit_test_state *uts)
181{
182 struct udevice *dev, *con;
183 int i;
184
185#define WHITE 0xffff
186#define SCROLL_LINES 100
187
188 ut_assertok(select_vidconsole(uts, "vidconsole0"));
189 ut_assertok(video_get_nologo(uts, &dev));
190 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
191 ut_assertok(vidconsole_select_font(con, "12x22", 0));
Simon Glassd5099b42025-04-02 06:29:41 +1300192 ut_asserteq(46, video_compress_fb(uts, dev, false));
193 ut_assertok(video_check_copy_fb(uts, dev));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300194
195 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
196 vidconsole_putc_xy(con, 0, 0, 'a');
Simon Glassd5099b42025-04-02 06:29:41 +1300197 ut_asserteq(89, video_compress_fb(uts, dev, false));
198 ut_assertok(video_check_copy_fb(uts, dev));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300199
200 vidconsole_putc_xy(con, 0, 0, ' ');
Simon Glassd5099b42025-04-02 06:29:41 +1300201 ut_asserteq(46, video_compress_fb(uts, dev, false));
202 ut_assertok(video_check_copy_fb(uts, dev));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300203
204 for (i = 0; i < 20; i++)
205 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
Simon Glassd5099b42025-04-02 06:29:41 +1300206 ut_asserteq(363, video_compress_fb(uts, dev, false));
207 ut_assertok(video_check_copy_fb(uts, dev));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300208
209 vidconsole_set_row(con, 0, WHITE);
Simon Glassd5099b42025-04-02 06:29:41 +1300210 ut_asserteq(46, video_compress_fb(uts, dev, false));
211 ut_assertok(video_check_copy_fb(uts, dev));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300212
213 for (i = 0; i < 20; i++)
214 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
Simon Glassd5099b42025-04-02 06:29:41 +1300215 ut_asserteq(363, video_compress_fb(uts, dev, false));
216 ut_assertok(video_check_copy_fb(uts, dev));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300217
218 return 0;
219}
Simon Glass1a92f832024-08-22 07:57:48 -0600220DM_TEST(dm_test_video_text_12x22, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300221
Simon Glass90b6fef2016-01-18 19:52:26 -0700222/* Test handling of special characters in the console */
223static int dm_test_video_chars(struct unit_test_state *uts)
224{
225 struct udevice *dev, *con;
Simon Glass37b80202016-01-14 18:10:38 -0700226 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 -0700227
Simon Glassdaac9c72016-01-14 18:10:50 -0700228 ut_assertok(select_vidconsole(uts, "vidconsole0"));
Simon Glass87a3cd72021-11-19 13:24:03 -0700229 ut_assertok(video_get_nologo(uts, &dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700230 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300231 ut_assertok(vidconsole_select_font(con, "8x16", 0));
Rob Clark985935b2017-09-25 15:45:08 -0400232 vidconsole_put_string(con, test_string);
Simon Glassd5099b42025-04-02 06:29:41 +1300233 ut_asserteq(466, video_compress_fb(uts, dev, false));
234 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700235
236 return 0;
237}
Simon Glass1a92f832024-08-22 07:57:48 -0600238DM_TEST(dm_test_video_chars, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass90b6fef2016-01-18 19:52:26 -0700239
Rob Clark09d64b32017-09-25 15:45:09 -0400240#ifdef CONFIG_VIDEO_ANSI
241#define ANSI_ESC "\x1b"
242/* Test handling of ANSI escape sequences */
243static int dm_test_video_ansi(struct unit_test_state *uts)
244{
245 struct udevice *dev, *con;
246
247 ut_assertok(select_vidconsole(uts, "vidconsole0"));
Simon Glass87a3cd72021-11-19 13:24:03 -0700248 ut_assertok(video_get_nologo(uts, &dev));
Rob Clark09d64b32017-09-25 15:45:09 -0400249 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300250 ut_assertok(vidconsole_select_font(con, "8x16", 0));
Rob Clark09d64b32017-09-25 15:45:09 -0400251
252 /* reference clear: */
253 video_clear(con->parent);
Simon Glass0806dcc2018-10-01 11:55:14 -0600254 video_sync(con->parent, false);
Simon Glassd5099b42025-04-02 06:29:41 +1300255 ut_asserteq(46, video_compress_fb(uts, dev, false));
256 ut_assertok(video_check_copy_fb(uts, dev));
Rob Clark09d64b32017-09-25 15:45:09 -0400257
258 /* test clear escape sequence: [2J */
259 vidconsole_put_string(con, "A\tB\tC"ANSI_ESC"[2J");
Simon Glassd5099b42025-04-02 06:29:41 +1300260 ut_asserteq(46, video_compress_fb(uts, dev, false));
261 ut_assertok(video_check_copy_fb(uts, dev));
Rob Clark09d64b32017-09-25 15:45:09 -0400262
263 /* test set-cursor: [%d;%df */
264 vidconsole_put_string(con, "abc"ANSI_ESC"[2;2fab"ANSI_ESC"[4;4fcd");
Simon Glassd5099b42025-04-02 06:29:41 +1300265 ut_asserteq(143, video_compress_fb(uts, dev, false));
266 ut_assertok(video_check_copy_fb(uts, dev));
Rob Clark09d64b32017-09-25 15:45:09 -0400267
268 /* test colors (30-37 fg color, 40-47 bg color) */
269 vidconsole_put_string(con, ANSI_ESC"[30;41mfoo"); /* black on red */
270 vidconsole_put_string(con, ANSI_ESC"[33;44mbar"); /* yellow on blue */
Simon Glassd5099b42025-04-02 06:29:41 +1300271 ut_asserteq(272, video_compress_fb(uts, dev, false));
272 ut_assertok(video_check_copy_fb(uts, dev));
Rob Clark09d64b32017-09-25 15:45:09 -0400273
274 return 0;
275}
Simon Glass1a92f832024-08-22 07:57:48 -0600276DM_TEST(dm_test_video_ansi, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Rob Clark09d64b32017-09-25 15:45:09 -0400277#endif
278
Simon Glass90b6fef2016-01-18 19:52:26 -0700279/**
280 * check_vidconsole_output() - Run a text console test
281 *
282 * @uts: Test state
Simon Glass4425bf42020-07-02 21:12:28 -0600283 * @rot: Console rotation (0=normal orientation, 1=90 degrees clockwise,
284 * 2=upside down, 3=90 degree counterclockwise)
Simon Glass90b6fef2016-01-18 19:52:26 -0700285 * @wrap_size: Expected size of compressed frame buffer for the wrap test
286 * @scroll_size: Same for the scroll test
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100287 * Return: 0 on success
Simon Glass90b6fef2016-01-18 19:52:26 -0700288 */
289static int check_vidconsole_output(struct unit_test_state *uts, int rot,
290 int wrap_size, int scroll_size)
291{
292 struct udevice *dev, *con;
293 struct sandbox_sdl_plat *plat;
294 int i;
295
296 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
297 ut_assert(!device_active(dev));
Simon Glassfa20e932020-12-03 16:55:20 -0700298 plat = dev_get_plat(dev);
Simon Glass90b6fef2016-01-18 19:52:26 -0700299 plat->rot = rot;
300
Simon Glass87a3cd72021-11-19 13:24:03 -0700301 ut_assertok(video_get_nologo(uts, &dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700302 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300303 ut_assertok(vidconsole_select_font(con, "8x16", 0));
Simon Glassd5099b42025-04-02 06:29:41 +1300304 ut_asserteq(46, video_compress_fb(uts, dev, false));
305 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700306
307 /* Check display wrap */
308 for (i = 0; i < 120; i++)
309 vidconsole_put_char(con, 'A' + i % 50);
Simon Glassd5099b42025-04-02 06:29:41 +1300310 ut_asserteq(wrap_size, video_compress_fb(uts, dev, false));
311 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700312
313 /* Check display scrolling */
314 for (i = 0; i < SCROLL_LINES; i++) {
315 vidconsole_put_char(con, 'A' + i % 50);
316 vidconsole_put_char(con, '\n');
317 }
Simon Glassd5099b42025-04-02 06:29:41 +1300318 ut_asserteq(scroll_size, video_compress_fb(uts, dev, false));
319 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700320
321 /* If we scroll enough, the screen becomes blank again */
322 for (i = 0; i < SCROLL_LINES; i++)
323 vidconsole_put_char(con, '\n');
Simon Glassd5099b42025-04-02 06:29:41 +1300324 ut_asserteq(46, video_compress_fb(uts, dev, false));
325 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700326
327 return 0;
328}
329
330/* Test text output through the console uclass */
331static int dm_test_video_context(struct unit_test_state *uts)
332{
Simon Glassdaac9c72016-01-14 18:10:50 -0700333 ut_assertok(select_vidconsole(uts, "vidconsole0"));
334 ut_assertok(check_vidconsole_output(uts, 0, 788, 453));
335
336 return 0;
Simon Glass90b6fef2016-01-18 19:52:26 -0700337}
Simon Glass1a92f832024-08-22 07:57:48 -0600338DM_TEST(dm_test_video_context, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glassa0f1efe2016-01-18 19:52:27 -0700339
340/* Test rotated text output through the console uclass */
341static int dm_test_video_rotation1(struct unit_test_state *uts)
342{
343 ut_assertok(check_vidconsole_output(uts, 1, 1112, 680));
344
345 return 0;
346}
Simon Glass1a92f832024-08-22 07:57:48 -0600347DM_TEST(dm_test_video_rotation1, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glassa0f1efe2016-01-18 19:52:27 -0700348
349/* Test rotated text output through the console uclass */
350static int dm_test_video_rotation2(struct unit_test_state *uts)
351{
Simon Glassf50a6b92020-07-02 21:12:17 -0600352 ut_assertok(check_vidconsole_output(uts, 2, 783, 445));
Simon Glassa0f1efe2016-01-18 19:52:27 -0700353
354 return 0;
355}
Simon Glass1a92f832024-08-22 07:57:48 -0600356DM_TEST(dm_test_video_rotation2, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glassa0f1efe2016-01-18 19:52:27 -0700357
358/* Test rotated text output through the console uclass */
359static int dm_test_video_rotation3(struct unit_test_state *uts)
360{
361 ut_assertok(check_vidconsole_output(uts, 3, 1134, 681));
362
363 return 0;
364}
Simon Glass1a92f832024-08-22 07:57:48 -0600365DM_TEST(dm_test_video_rotation3, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass7a1cb292016-01-18 19:52:28 -0700366
367/* Read a file into memory and return a pointer to it */
368static int read_file(struct unit_test_state *uts, const char *fname,
369 ulong *addrp)
370{
371 int buf_size = 100000;
372 ulong addr = 0;
373 int size, fd;
374 char *buf;
375
376 buf = map_sysmem(addr, 0);
377 ut_assert(buf != NULL);
378 fd = os_open(fname, OS_O_RDONLY);
379 ut_assert(fd >= 0);
380 size = os_read(fd, buf, buf_size);
Simon Glass9050c5f2016-01-30 15:45:17 -0700381 os_close(fd);
Simon Glass7a1cb292016-01-18 19:52:28 -0700382 ut_assert(size >= 0);
383 ut_assert(size < buf_size);
Simon Glass7a1cb292016-01-18 19:52:28 -0700384 *addrp = addr;
385
386 return 0;
387}
388
389/* Test drawing a bitmap file */
390static int dm_test_video_bmp(struct unit_test_state *uts)
391{
392 struct udevice *dev;
393 ulong addr;
394
Simon Glass87a3cd72021-11-19 13:24:03 -0700395 ut_assertok(video_get_nologo(uts, &dev));
Simon Glass7a1cb292016-01-18 19:52:28 -0700396 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
397
398 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
Simon Glassd5099b42025-04-02 06:29:41 +1300399 ut_asserteq(1368, video_compress_fb(uts, dev, false));
400 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass7a1cb292016-01-18 19:52:28 -0700401
402 return 0;
403}
Simon Glass1a92f832024-08-22 07:57:48 -0600404DM_TEST(dm_test_video_bmp, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass7a1cb292016-01-18 19:52:28 -0700405
Simon Glassc3b5adf2021-11-19 13:23:50 -0700406/* Test drawing a bitmap file on a 8bpp display */
407static int dm_test_video_bmp8(struct unit_test_state *uts)
408{
409 struct udevice *dev;
410 ulong addr;
411
412 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
413 ut_assertnonnull(dev);
414 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP8));
415
416 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
417
418 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
Simon Glassd5099b42025-04-02 06:29:41 +1300419 ut_asserteq(1247, video_compress_fb(uts, dev, false));
420 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glassc3b5adf2021-11-19 13:23:50 -0700421
422 return 0;
423}
Simon Glass1a92f832024-08-22 07:57:48 -0600424DM_TEST(dm_test_video_bmp8, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glassc3b5adf2021-11-19 13:23:50 -0700425
Simon Glass8bd7f602021-11-19 13:23:58 -0700426/* Test drawing a bitmap file on a 16bpp display */
427static int dm_test_video_bmp16(struct unit_test_state *uts)
428{
429 ulong src, src_len = ~0UL;
430 uint dst_len = ~0U;
431 struct udevice *dev;
432 ulong dst = 0x10000;
433
434 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
435 ut_assertnonnull(dev);
436 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP16));
437
438 ut_assertok(read_file(uts, "tools/logos/denx-16bpp.bmp.gz", &src));
439 ut_assertok(gunzip(map_sysmem(dst, 0), dst_len, map_sysmem(src, 0),
440 &src_len));
441
442 ut_assertok(video_bmp_display(dev, dst, 0, 0, false));
Simon Glassd5099b42025-04-02 06:29:41 +1300443 ut_asserteq(3700, video_compress_fb(uts, dev, false));
444 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass8bd7f602021-11-19 13:23:58 -0700445
446 return 0;
447}
Simon Glass1a92f832024-08-22 07:57:48 -0600448DM_TEST(dm_test_video_bmp16, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass8bd7f602021-11-19 13:23:58 -0700449
Simon Glass6a92e882021-11-19 13:23:59 -0700450/* Test drawing a 24bpp bitmap file on a 16bpp display */
451static int dm_test_video_bmp24(struct unit_test_state *uts)
452{
453 ulong src, src_len = ~0UL;
454 uint dst_len = ~0U;
455 struct udevice *dev;
456 ulong dst = 0x10000;
457
458 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
459 ut_assertnonnull(dev);
460 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP16));
461
462 ut_assertok(read_file(uts, "tools/logos/denx-24bpp.bmp.gz", &src));
463 ut_assertok(gunzip(map_sysmem(dst, 0), dst_len, map_sysmem(src, 0),
464 &src_len));
465
466 ut_assertok(video_bmp_display(dev, dst, 0, 0, false));
Simon Glassd5099b42025-04-02 06:29:41 +1300467 ut_asserteq(3656, video_compress_fb(uts, dev, false));
468 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass6a92e882021-11-19 13:23:59 -0700469
470 return 0;
471}
Simon Glass1a92f832024-08-22 07:57:48 -0600472DM_TEST(dm_test_video_bmp24, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass6a92e882021-11-19 13:23:59 -0700473
474/* Test drawing a 24bpp bitmap file on a 32bpp display */
475static int dm_test_video_bmp24_32(struct unit_test_state *uts)
476{
477 ulong src, src_len = ~0UL;
478 uint dst_len = ~0U;
479 struct udevice *dev;
480 ulong dst = 0x10000;
481
482 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
483 ut_assertnonnull(dev);
484 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP32));
485
486 ut_assertok(read_file(uts, "tools/logos/denx-24bpp.bmp.gz", &src));
487 ut_assertok(gunzip(map_sysmem(dst, 0), dst_len, map_sysmem(src, 0),
488 &src_len));
489
490 ut_assertok(video_bmp_display(dev, dst, 0, 0, false));
Simon Glassd5099b42025-04-02 06:29:41 +1300491 ut_asserteq(6827, video_compress_fb(uts, dev, false));
492 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass6a92e882021-11-19 13:23:59 -0700493
494 return 0;
495}
Simon Glass1a92f832024-08-22 07:57:48 -0600496DM_TEST(dm_test_video_bmp24_32, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass6a92e882021-11-19 13:23:59 -0700497
Simon Glassc3b5adf2021-11-19 13:23:50 -0700498/* Test drawing a bitmap file on a 32bpp display */
499static int dm_test_video_bmp32(struct unit_test_state *uts)
500{
501 struct udevice *dev;
502 ulong addr;
503
504 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
505 ut_assertnonnull(dev);
506 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP32));
507 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
508
509 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
Simon Glassd5099b42025-04-02 06:29:41 +1300510 ut_asserteq(2024, video_compress_fb(uts, dev, false));
511 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glassc3b5adf2021-11-19 13:23:50 -0700512
513 return 0;
514}
Simon Glass1a92f832024-08-22 07:57:48 -0600515DM_TEST(dm_test_video_bmp32, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glassc3b5adf2021-11-19 13:23:50 -0700516
Simon Glass7a1cb292016-01-18 19:52:28 -0700517/* Test drawing a compressed bitmap file */
518static int dm_test_video_bmp_comp(struct unit_test_state *uts)
519{
520 struct udevice *dev;
521 ulong addr;
522
Simon Glass87a3cd72021-11-19 13:24:03 -0700523 ut_assertok(video_get_nologo(uts, &dev));
Simon Glass7a1cb292016-01-18 19:52:28 -0700524 ut_assertok(read_file(uts, "tools/logos/denx-comp.bmp", &addr));
525
526 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
Simon Glassd5099b42025-04-02 06:29:41 +1300527 ut_asserteq(1368, video_compress_fb(uts, dev, false));
528 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass7a1cb292016-01-18 19:52:28 -0700529
530 return 0;
531}
Simon Glass1a92f832024-08-22 07:57:48 -0600532DM_TEST(dm_test_video_bmp_comp, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass32337982016-01-14 18:10:51 -0700533
Simon Glass490bb992021-11-19 13:23:55 -0700534/* Test drawing a bitmap file on a 32bpp display */
535static int dm_test_video_comp_bmp32(struct unit_test_state *uts)
536{
537 struct udevice *dev;
538 ulong addr;
539
540 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
541 ut_assertnonnull(dev);
542 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP32));
543
544 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
545
546 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
Simon Glassd5099b42025-04-02 06:29:41 +1300547 ut_asserteq(2024, video_compress_fb(uts, dev, false));
548 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass490bb992021-11-19 13:23:55 -0700549
550 return 0;
551}
Simon Glass1a92f832024-08-22 07:57:48 -0600552DM_TEST(dm_test_video_comp_bmp32, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass490bb992021-11-19 13:23:55 -0700553
554/* Test drawing a bitmap file on a 8bpp display */
555static int dm_test_video_comp_bmp8(struct unit_test_state *uts)
556{
557 struct udevice *dev;
558 ulong addr;
559
560 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
561 ut_assertnonnull(dev);
562 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP8));
563
564 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
565
566 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
Simon Glassd5099b42025-04-02 06:29:41 +1300567 ut_asserteq(1247, video_compress_fb(uts, dev, false));
568 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass490bb992021-11-19 13:23:55 -0700569
570 return 0;
571}
Simon Glass1a92f832024-08-22 07:57:48 -0600572DM_TEST(dm_test_video_comp_bmp8, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass490bb992021-11-19 13:23:55 -0700573
Simon Glass32337982016-01-14 18:10:51 -0700574/* Test TrueType console */
575static int dm_test_video_truetype(struct unit_test_state *uts)
576{
577 struct udevice *dev, *con;
578 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 -0700579
Simon Glass87a3cd72021-11-19 13:24:03 -0700580 ut_assertok(video_get_nologo(uts, &dev));
Simon Glass32337982016-01-14 18:10:51 -0700581 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
Rob Clark985935b2017-09-25 15:45:08 -0400582 vidconsole_put_string(con, test_string);
Simon Glass6f5a8642025-04-02 06:29:40 +1300583 vidconsole_put_stringn(con, test_string, 30);
Simon Glassd5099b42025-04-02 06:29:41 +1300584 ut_asserteq(13184, video_compress_fb(uts, dev, false));
585 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass32337982016-01-14 18:10:51 -0700586
587 return 0;
588}
Simon Glass1a92f832024-08-22 07:57:48 -0600589DM_TEST(dm_test_video_truetype, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass32337982016-01-14 18:10:51 -0700590
591/* Test scrolling TrueType console */
592static int dm_test_video_truetype_scroll(struct unit_test_state *uts)
593{
594 struct sandbox_sdl_plat *plat;
595 struct udevice *dev, *con;
596 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 -0700597
598 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
599 ut_assert(!device_active(dev));
Simon Glassfa20e932020-12-03 16:55:20 -0700600 plat = dev_get_plat(dev);
Simon Glass32337982016-01-14 18:10:51 -0700601 plat->font_size = 100;
602
Simon Glass87a3cd72021-11-19 13:24:03 -0700603 ut_assertok(video_get_nologo(uts, &dev));
Simon Glass32337982016-01-14 18:10:51 -0700604 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
Rob Clark985935b2017-09-25 15:45:08 -0400605 vidconsole_put_string(con, test_string);
Simon Glassd5099b42025-04-02 06:29:41 +1300606 ut_asserteq(34287, video_compress_fb(uts, dev, false));
607 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass32337982016-01-14 18:10:51 -0700608
609 return 0;
610}
Simon Glass1a92f832024-08-22 07:57:48 -0600611DM_TEST(dm_test_video_truetype_scroll, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass32337982016-01-14 18:10:51 -0700612
613/* Test TrueType backspace, within and across lines */
614static int dm_test_video_truetype_bs(struct unit_test_state *uts)
615{
616 struct sandbox_sdl_plat *plat;
617 struct udevice *dev, *con;
618 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 -0700619
620 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
621 ut_assert(!device_active(dev));
Simon Glassfa20e932020-12-03 16:55:20 -0700622 plat = dev_get_plat(dev);
Simon Glass32337982016-01-14 18:10:51 -0700623 plat->font_size = 100;
624
Simon Glass87a3cd72021-11-19 13:24:03 -0700625 ut_assertok(video_get_nologo(uts, &dev));
Simon Glass32337982016-01-14 18:10:51 -0700626 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
Rob Clark985935b2017-09-25 15:45:08 -0400627 vidconsole_put_string(con, test_string);
Simon Glassd5099b42025-04-02 06:29:41 +1300628 ut_asserteq(29471, video_compress_fb(uts, dev, false));
629 ut_assertok(video_check_copy_fb(uts, dev));
Simon Glass32337982016-01-14 18:10:51 -0700630
631 return 0;
632}
Simon Glass1a92f832024-08-22 07:57:48 -0600633DM_TEST(dm_test_video_truetype_bs, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Alper Nebi Yasak5e8253d2023-08-18 17:31:27 +0300634
635/* Test partial rendering onto hardware frame buffer */
636static int dm_test_video_copy(struct unit_test_state *uts)
637{
638 struct sandbox_sdl_plat *plat;
639 struct video_uc_plat *uc_plat;
640 struct udevice *dev, *con;
641 struct video_priv *priv;
642 const char *test_string = "\n\tCriticism may not be agreeable, but it is necessary.\t";
643 ulong addr;
644
645 if (!IS_ENABLED(CONFIG_VIDEO_COPY))
646 return -EAGAIN;
647
648 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
649 ut_assertnonnull(dev);
650 uc_plat = dev_get_uclass_plat(dev);
651 uc_plat->hide_logo = true;
652 plat = dev_get_plat(dev);
653 plat->font_size = 32;
654 ut_assert(!device_active(dev));
655 ut_assertok(uclass_first_device_err(UCLASS_VIDEO, &dev));
656 ut_assertnonnull(dev);
657 priv = dev_get_uclass_priv(dev);
658
659 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
660 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
661
662 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
663 vidconsole_put_string(con, "\n\n\n\n\n");
664 vidconsole_put_string(con, test_string);
665 vidconsole_put_string(con, test_string);
666
Simon Glassd5099b42025-04-02 06:29:41 +1300667 ut_asserteq(6678, video_compress_fb(uts, dev, false));
668 ut_assertok(video_check_copy_fb(uts, dev));
Alper Nebi Yasak5e8253d2023-08-18 17:31:27 +0300669
670 /*
671 * Secretly clear the hardware frame buffer, but in a different
672 * color (black) to see which parts will be overwritten.
673 */
674 memset(priv->copy_fb, 0, priv->fb_size);
675
676 /*
677 * We should have the full content on the main buffer, but only
Alexander Graff88b6a22022-06-10 00:59:21 +0200678 * 'damage' should have been copied to the copy buffer. This consists
679 * of a while rectangle with the Denx logo and four lines of text. The
680 * rest of the display is black.
681 *
682 * An easy way to try this is by changing video_sync() to call
683 * sandbox_sdl_sync(priv->copy_fb) instead of priv->fb then running the
684 * unit test:
685 *
686 * ./u-boot -Tl
687 * ut dm dm_test_video_copy
Alper Nebi Yasak5e8253d2023-08-18 17:31:27 +0300688 */
689 vidconsole_put_string(con, test_string);
690 vidconsole_put_string(con, test_string);
Alexander Graff88b6a22022-06-10 00:59:21 +0200691 video_sync(dev, true);
Simon Glassd5099b42025-04-02 06:29:41 +1300692 ut_asserteq(7589, video_compress_fb(uts, dev, false));
693 ut_asserteq(7704, video_compress_fb(uts, dev, true));
Alper Nebi Yasak5e8253d2023-08-18 17:31:27 +0300694
695 return 0;
696}
697DM_TEST(dm_test_video_copy, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Alper Nebi Yasakfc5740a2023-08-18 17:55:08 +0300698
699/* Test video damage tracking */
700static int dm_test_video_damage(struct unit_test_state *uts)
701{
702 struct sandbox_sdl_plat *plat;
703 struct udevice *dev, *con;
704 struct video_priv *priv;
705 const char *test_string_1 = "Criticism may not be agreeable, ";
706 const char *test_string_2 = "but it is necessary.";
707 const char *test_string_3 = "It fulfils the same function as pain in the human body.";
708
709 if (!IS_ENABLED(CONFIG_VIDEO_DAMAGE))
710 return -EAGAIN;
711
712 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
713 ut_assert(!device_active(dev));
714 plat = dev_get_plat(dev);
715 plat->font_size = 32;
716
717 ut_assertok(video_get_nologo(uts, &dev));
718 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
719 priv = dev_get_uclass_priv(dev);
720
721 vidconsole_position_cursor(con, 14, 10);
722 vidconsole_put_string(con, test_string_2);
723 ut_asserteq(449, priv->damage.xstart);
724 ut_asserteq(325, priv->damage.ystart);
725 ut_asserteq(661, priv->damage.xend);
726 ut_asserteq(350, priv->damage.yend);
727
728 vidconsole_position_cursor(con, 7, 5);
729 vidconsole_put_string(con, test_string_1);
730 ut_asserteq(225, priv->damage.xstart);
731 ut_asserteq(164, priv->damage.ystart);
732 ut_asserteq(661, priv->damage.xend);
733 ut_asserteq(350, priv->damage.yend);
734
735 vidconsole_position_cursor(con, 21, 15);
736 vidconsole_put_string(con, test_string_3);
737 ut_asserteq(225, priv->damage.xstart);
738 ut_asserteq(164, priv->damage.ystart);
739 ut_asserteq(1280, priv->damage.xend);
740 ut_asserteq(510, priv->damage.yend);
741
742 video_sync(dev, true);
743 ut_asserteq(priv->xsize, priv->damage.xstart);
744 ut_asserteq(priv->ysize, priv->damage.ystart);
745 ut_asserteq(0, priv->damage.xend);
746 ut_asserteq(0, priv->damage.yend);
747
Simon Glassd5099b42025-04-02 06:29:41 +1300748 ut_asserteq(7339, video_compress_fb(uts, dev, false));
749 ut_assertok(video_check_copy_fb(uts, dev));
Alper Nebi Yasakfc5740a2023-08-18 17:55:08 +0300750
751 return 0;
752}
753DM_TEST(dm_test_video_damage, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glassfff57f62025-04-02 06:29:35 +1300754
755/* Test font measurement */
756static int dm_test_font_measure(struct unit_test_state *uts)
757{
Simon Glass3c686e62025-04-02 06:29:38 +1300758 const char *test_string = "There is always much\nto be said for not "
Simon Glassfff57f62025-04-02 06:29:35 +1300759 "attempting more than you can do and for making a certainty of "
760 "what you try. But this principle, like others in life and "
761 "war, has its exceptions.";
Simon Glasseb4efc62025-04-02 06:29:37 +1300762 const struct vidconsole_mline *line;
Simon Glassfff57f62025-04-02 06:29:35 +1300763 struct vidconsole_bbox bbox;
764 struct video_priv *priv;
765 struct udevice *dev, *con;
Simon Glass3aa33582025-04-02 06:29:39 +1300766 const int limit = 0x320;
Simon Glass95bcad42025-04-02 06:29:36 +1300767 struct alist lines;
Simon Glass3c686e62025-04-02 06:29:38 +1300768 int nl;
Simon Glassfff57f62025-04-02 06:29:35 +1300769
770 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
771 priv = dev_get_uclass_priv(dev);
772 ut_asserteq(1366, priv->xsize);
773 ut_asserteq(768, priv->ysize);
774
775 /* this is using the Nimbus font with size of 18 pixels */
776 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
777 vidconsole_position_cursor(con, 0, 0);
Simon Glasseb4efc62025-04-02 06:29:37 +1300778 alist_init_struct(&lines, struct vidconsole_mline);
Simon Glass3aa33582025-04-02 06:29:39 +1300779 ut_assertok(vidconsole_measure(con, NULL, 0, test_string, -1, &bbox,
Simon Glass95bcad42025-04-02 06:29:36 +1300780 &lines));
Simon Glassfff57f62025-04-02 06:29:35 +1300781 ut_asserteq(0, bbox.x0);
782 ut_asserteq(0, bbox.y0);
Simon Glass3c686e62025-04-02 06:29:38 +1300783 ut_asserteq(0x3ea, bbox.x1);
784 ut_asserteq(0x24, bbox.y1);
785 ut_asserteq(2, lines.count);
786
787 nl = strchr(test_string, '\n') - test_string;
Simon Glasseb4efc62025-04-02 06:29:37 +1300788
789 line = alist_get(&lines, 0, struct vidconsole_mline);
790 ut_assertnonnull(line);
791 ut_asserteq(0, line->bbox.x0);
792 ut_asserteq(0, line->bbox.y0);
Simon Glass3c686e62025-04-02 06:29:38 +1300793 ut_asserteq(0x8c, line->bbox.x1);
Simon Glasseb4efc62025-04-02 06:29:37 +1300794 ut_asserteq(0x12, line->bbox.y1);
795 ut_asserteq(0, line->start);
Simon Glass3c686e62025-04-02 06:29:38 +1300796 ut_asserteq(20, line->len);
797 ut_asserteq(nl, line->len);
798
799 line++;
800 ut_asserteq(0x0, line->bbox.x0);
801 ut_asserteq(0x12, line->bbox.y0);
802 ut_asserteq(0x3ea, line->bbox.x1);
803 ut_asserteq(0x24, line->bbox.y1);
804 ut_asserteq(21, line->start);
805 ut_asserteq(nl + 1, line->start);
806 ut_asserteq(163, line->len);
807 ut_asserteq(strlen(test_string + nl + 1), line->len);
Simon Glassfff57f62025-04-02 06:29:35 +1300808
Simon Glass3aa33582025-04-02 06:29:39 +1300809 /* now use a limit on the width */
810 ut_assertok(vidconsole_measure(con, NULL, 0, test_string, limit, &bbox,
811 &lines));
812 ut_asserteq(0, bbox.x0);
813 ut_asserteq(0, bbox.y0);
814 ut_asserteq(0x31e, bbox.x1);
815 ut_asserteq(0x36, bbox.y1);
816 ut_asserteq(3, lines.count);
817
818 nl = strchr(test_string, '\n') - test_string;
819
820 line = alist_get(&lines, 0, struct vidconsole_mline);
821 ut_assertnonnull(line);
822 ut_asserteq(0, line->bbox.x0);
823 ut_asserteq(0, line->bbox.y0);
824 ut_asserteq(0x8c, line->bbox.x1);
825 ut_asserteq(0x12, line->bbox.y1);
826 ut_asserteq(0, line->start);
827 ut_asserteq(20, line->len);
828 ut_asserteq(nl, line->len);
829 printf("line0 '%.*s'\n", line->len, test_string + line->start);
830 ut_asserteq_strn("There is always much",
831 test_string + line->start);
832
833 line++;
834 ut_asserteq(0x0, line->bbox.x0);
835 ut_asserteq(0x12, line->bbox.y0);
836 ut_asserteq(0x31e, line->bbox.x1);
837 ut_asserteq(0x24, line->bbox.y1);
838 ut_asserteq(21, line->start);
839 ut_asserteq(nl + 1, line->start);
840 ut_asserteq(129, line->len);
841 printf("line1 '%.*s'\n", line->len, test_string + line->start);
842 ut_asserteq_strn("to be said for not attempting more than you can do "
843 "and for making a certainty of what you try. But this "
844 "principle, like others in",
845 test_string + line->start);
846
847 line++;
848 ut_asserteq(0x0, line->bbox.x0);
849 ut_asserteq(0x24, line->bbox.y0);
850 ut_asserteq(0xc8, line->bbox.x1);
851 ut_asserteq(0x36, line->bbox.y1);
852 ut_asserteq(21 + 130, line->start);
853 ut_asserteq(33, line->len);
854 printf("line2 '%.*s'\n", line->len, test_string + line->start);
855 ut_asserteq_strn("life and war, has its exceptions.",
856 test_string + line->start);
857
858 /*
859 * all characters should be accounted for, except the newline and the
860 * space which is consumed in the wordwrap
861 */
862 ut_asserteq(strlen(test_string) - 2,
863 line[-2].len + line[-1].len + line->len);
864
Simon Glassfff57f62025-04-02 06:29:35 +1300865 return 0;
866}
867DM_TEST(dm_test_font_measure, UTF_SCAN_FDT);