blob: a9b2482631f266ec36dc7cddf28e3221fdca93bf [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>
22
23/*
24 * These tests use the standard sandbox frame buffer, the resolution of which
25 * is defined in the device tree. This only supports 16bpp so the tests only
26 * test that code path. It would be possible to adjust this fairly easily,
27 * by adjusting the bpix value in struct sandbox_sdl_plat. However the code
28 * in sandbox_sdl_sync() would also need to change to handle the different
29 * surface depth.
30 */
Simon Glass90b6fef2016-01-18 19:52:26 -070031/* Basic test of the video uclass */
32static int dm_test_video_base(struct unit_test_state *uts)
33{
34 struct video_priv *priv;
35 struct udevice *dev;
36
37 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
38 ut_asserteq(1366, video_get_xsize(dev));
39 ut_asserteq(768, video_get_ysize(dev));
40 priv = dev_get_uclass_priv(dev);
41 ut_asserteq(priv->fb_size, 1366 * 768 * 2);
42
43 return 0;
44}
Simon Glass1a92f832024-08-22 07:57:48 -060045DM_TEST(dm_test_video_base, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass90b6fef2016-01-18 19:52:26 -070046
47/**
48 * compress_frame_buffer() - Compress the frame buffer and return its size
49 *
50 * We want to write tests which perform operations on the video console and
51 * check that the frame buffer ends up with the correct contents. But it is
52 * painful to store 'known good' images for comparison with the frame
53 * buffer. As an alternative, we can compress the frame buffer and check the
54 * size of the compressed data. This provides a pretty good level of
55 * certainty and the resulting tests need only check a single value.
56 *
Simon Glass2a0f8e32020-07-02 21:12:29 -060057 * @uts: Test state
Simon Glass90b6fef2016-01-18 19:52:26 -070058 * @dev: Video device
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +030059 * @use_copy: Use copy frame buffer if available
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +010060 * Return: compressed size of the frame buffer, or -ve on error
Simon Glass90b6fef2016-01-18 19:52:26 -070061 */
Simon Glass2a0f8e32020-07-02 21:12:29 -060062static int compress_frame_buffer(struct unit_test_state *uts,
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +030063 struct udevice *dev,
64 bool use_copy)
Simon Glass90b6fef2016-01-18 19:52:26 -070065{
66 struct video_priv *priv = dev_get_uclass_priv(dev);
67 uint destlen;
68 void *dest;
69 int ret;
70
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +030071 if (!IS_ENABLED(CONFIG_VIDEO_COPY))
72 use_copy = false;
73
Simon Glass90b6fef2016-01-18 19:52:26 -070074 destlen = priv->fb_size;
75 dest = malloc(priv->fb_size);
76 if (!dest)
77 return -ENOMEM;
78 ret = BZ2_bzBuffToBuffCompress(dest, &destlen,
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +030079 use_copy ? priv->copy_fb : priv->fb,
80 priv->fb_size,
Simon Glass90b6fef2016-01-18 19:52:26 -070081 3, 0, 0);
82 free(dest);
83 if (ret)
84 return ret;
85
86 return destlen;
87}
88
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +030089/**
90 * check_copy_frame_buffer() - Compare main frame buffer to copy
91 *
92 * If the copy frame buffer is enabled, this compares it to the main
93 * frame buffer. Normally they should have the same contents after a
94 * sync.
95 *
96 * @uts: Test state
97 * @dev: Video device
98 * Return: 0, or -ve on error
99 */
100static int check_copy_frame_buffer(struct unit_test_state *uts,
101 struct udevice *dev)
102{
103 struct video_priv *priv = dev_get_uclass_priv(dev);
104
105 if (!IS_ENABLED(CONFIG_VIDEO_COPY))
106 return 0;
107
Alexander Graff88b6a22022-06-10 00:59:21 +0200108 video_sync(dev, false);
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300109 ut_assertf(!memcmp(priv->fb, priv->copy_fb, priv->fb_size),
110 "Copy framebuffer does not match fb");
111
112 return 0;
113}
114
Simon Glass90b6fef2016-01-18 19:52:26 -0700115/*
116 * Call this function at any point to halt and show the current display. Be
117 * sure to run the test with the -l flag.
118 */
119static void __maybe_unused see_output(void)
120{
121 video_sync_all();
122 while (1);
123}
124
Simon Glassdaac9c72016-01-14 18:10:50 -0700125/* Select the video console driver to use for a video device */
126static int select_vidconsole(struct unit_test_state *uts, const char *drv_name)
127{
128 struct sandbox_sdl_plat *plat;
129 struct udevice *dev;
130
131 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
132 ut_assert(!device_active(dev));
Simon Glassfa20e932020-12-03 16:55:20 -0700133 plat = dev_get_plat(dev);
Simon Glassdaac9c72016-01-14 18:10:50 -0700134 plat->vidconsole_drv_name = "vidconsole0";
135
136 return 0;
137}
138
Simon Glass87a3cd72021-11-19 13:24:03 -0700139/**
140 * video_get_nologo() - Disable the logo on the video device and return it
141 *
142 * @uts: Test state
143 * @devp: Returns video device
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100144 * Return: 0 if OK, -ve on error
Simon Glass87a3cd72021-11-19 13:24:03 -0700145 */
146static int video_get_nologo(struct unit_test_state *uts, struct udevice **devp)
147{
148 struct video_uc_plat *uc_plat;
149 struct udevice *dev;
150
151 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
152 ut_assertnonnull(dev);
153 uc_plat = dev_get_uclass_plat(dev);
154 uc_plat->hide_logo = true;
155
156 /* now probe it */
157 ut_assertok(uclass_first_device_err(UCLASS_VIDEO, &dev));
158 ut_assertnonnull(dev);
159 *devp = dev;
160
161 return 0;
162}
163
Simon Glass90b6fef2016-01-18 19:52:26 -0700164/* Test text output works on the video console */
165static int dm_test_video_text(struct unit_test_state *uts)
166{
167 struct udevice *dev, *con;
168 int i;
169
170#define WHITE 0xffff
171#define SCROLL_LINES 100
172
Simon Glassdaac9c72016-01-14 18:10:50 -0700173 ut_assertok(select_vidconsole(uts, "vidconsole0"));
Simon Glass87a3cd72021-11-19 13:24:03 -0700174 ut_assertok(video_get_nologo(uts, &dev));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300175 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
176 ut_assertok(vidconsole_select_font(con, "8x16", 0));
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300177 ut_asserteq(46, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300178 ut_assertok(check_copy_frame_buffer(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700179
180 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
181 vidconsole_putc_xy(con, 0, 0, 'a');
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300182 ut_asserteq(79, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300183 ut_assertok(check_copy_frame_buffer(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700184
185 vidconsole_putc_xy(con, 0, 0, ' ');
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300186 ut_asserteq(46, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300187 ut_assertok(check_copy_frame_buffer(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700188
189 for (i = 0; i < 20; i++)
Simon Glass52c10c52016-01-14 18:10:37 -0700190 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300191 ut_asserteq(273, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300192 ut_assertok(check_copy_frame_buffer(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700193
194 vidconsole_set_row(con, 0, WHITE);
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300195 ut_asserteq(46, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300196 ut_assertok(check_copy_frame_buffer(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700197
198 for (i = 0; i < 20; i++)
Simon Glass52c10c52016-01-14 18:10:37 -0700199 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300200 ut_asserteq(273, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300201 ut_assertok(check_copy_frame_buffer(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700202
203 return 0;
204}
Simon Glass1a92f832024-08-22 07:57:48 -0600205DM_TEST(dm_test_video_text, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass90b6fef2016-01-18 19:52:26 -0700206
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300207static int dm_test_video_text_12x22(struct unit_test_state *uts)
208{
209 struct udevice *dev, *con;
210 int i;
211
212#define WHITE 0xffff
213#define SCROLL_LINES 100
214
215 ut_assertok(select_vidconsole(uts, "vidconsole0"));
216 ut_assertok(video_get_nologo(uts, &dev));
217 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
218 ut_assertok(vidconsole_select_font(con, "12x22", 0));
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300219 ut_asserteq(46, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300220 ut_assertok(check_copy_frame_buffer(uts, dev));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300221
222 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
223 vidconsole_putc_xy(con, 0, 0, 'a');
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300224 ut_asserteq(89, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300225 ut_assertok(check_copy_frame_buffer(uts, dev));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300226
227 vidconsole_putc_xy(con, 0, 0, ' ');
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300228 ut_asserteq(46, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300229 ut_assertok(check_copy_frame_buffer(uts, dev));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300230
231 for (i = 0; i < 20; i++)
232 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300233 ut_asserteq(363, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300234 ut_assertok(check_copy_frame_buffer(uts, dev));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300235
236 vidconsole_set_row(con, 0, WHITE);
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300237 ut_asserteq(46, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300238 ut_assertok(check_copy_frame_buffer(uts, dev));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300239
240 for (i = 0; i < 20; i++)
241 vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300242 ut_asserteq(363, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300243 ut_assertok(check_copy_frame_buffer(uts, dev));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300244
245 return 0;
246}
Simon Glass1a92f832024-08-22 07:57:48 -0600247DM_TEST(dm_test_video_text_12x22, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300248
Simon Glass90b6fef2016-01-18 19:52:26 -0700249/* Test handling of special characters in the console */
250static int dm_test_video_chars(struct unit_test_state *uts)
251{
252 struct udevice *dev, *con;
Simon Glass37b80202016-01-14 18:10:38 -0700253 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 -0700254
Simon Glassdaac9c72016-01-14 18:10:50 -0700255 ut_assertok(select_vidconsole(uts, "vidconsole0"));
Simon Glass87a3cd72021-11-19 13:24:03 -0700256 ut_assertok(video_get_nologo(uts, &dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700257 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300258 ut_assertok(vidconsole_select_font(con, "8x16", 0));
Rob Clark985935b2017-09-25 15:45:08 -0400259 vidconsole_put_string(con, test_string);
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300260 ut_asserteq(466, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300261 ut_assertok(check_copy_frame_buffer(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700262
263 return 0;
264}
Simon Glass1a92f832024-08-22 07:57:48 -0600265DM_TEST(dm_test_video_chars, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass90b6fef2016-01-18 19:52:26 -0700266
Rob Clark09d64b32017-09-25 15:45:09 -0400267#ifdef CONFIG_VIDEO_ANSI
268#define ANSI_ESC "\x1b"
269/* Test handling of ANSI escape sequences */
270static int dm_test_video_ansi(struct unit_test_state *uts)
271{
272 struct udevice *dev, *con;
273
274 ut_assertok(select_vidconsole(uts, "vidconsole0"));
Simon Glass87a3cd72021-11-19 13:24:03 -0700275 ut_assertok(video_get_nologo(uts, &dev));
Rob Clark09d64b32017-09-25 15:45:09 -0400276 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300277 ut_assertok(vidconsole_select_font(con, "8x16", 0));
Rob Clark09d64b32017-09-25 15:45:09 -0400278
279 /* reference clear: */
280 video_clear(con->parent);
Simon Glass0806dcc2018-10-01 11:55:14 -0600281 video_sync(con->parent, false);
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300282 ut_asserteq(46, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300283 ut_assertok(check_copy_frame_buffer(uts, dev));
Rob Clark09d64b32017-09-25 15:45:09 -0400284
285 /* test clear escape sequence: [2J */
286 vidconsole_put_string(con, "A\tB\tC"ANSI_ESC"[2J");
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300287 ut_asserteq(46, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300288 ut_assertok(check_copy_frame_buffer(uts, dev));
Rob Clark09d64b32017-09-25 15:45:09 -0400289
290 /* test set-cursor: [%d;%df */
291 vidconsole_put_string(con, "abc"ANSI_ESC"[2;2fab"ANSI_ESC"[4;4fcd");
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300292 ut_asserteq(143, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300293 ut_assertok(check_copy_frame_buffer(uts, dev));
Rob Clark09d64b32017-09-25 15:45:09 -0400294
295 /* test colors (30-37 fg color, 40-47 bg color) */
296 vidconsole_put_string(con, ANSI_ESC"[30;41mfoo"); /* black on red */
297 vidconsole_put_string(con, ANSI_ESC"[33;44mbar"); /* yellow on blue */
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300298 ut_asserteq(272, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300299 ut_assertok(check_copy_frame_buffer(uts, dev));
Rob Clark09d64b32017-09-25 15:45:09 -0400300
301 return 0;
302}
Simon Glass1a92f832024-08-22 07:57:48 -0600303DM_TEST(dm_test_video_ansi, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Rob Clark09d64b32017-09-25 15:45:09 -0400304#endif
305
Simon Glass90b6fef2016-01-18 19:52:26 -0700306/**
307 * check_vidconsole_output() - Run a text console test
308 *
309 * @uts: Test state
Simon Glass4425bf42020-07-02 21:12:28 -0600310 * @rot: Console rotation (0=normal orientation, 1=90 degrees clockwise,
311 * 2=upside down, 3=90 degree counterclockwise)
Simon Glass90b6fef2016-01-18 19:52:26 -0700312 * @wrap_size: Expected size of compressed frame buffer for the wrap test
313 * @scroll_size: Same for the scroll test
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100314 * Return: 0 on success
Simon Glass90b6fef2016-01-18 19:52:26 -0700315 */
316static int check_vidconsole_output(struct unit_test_state *uts, int rot,
317 int wrap_size, int scroll_size)
318{
319 struct udevice *dev, *con;
320 struct sandbox_sdl_plat *plat;
321 int i;
322
323 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
324 ut_assert(!device_active(dev));
Simon Glassfa20e932020-12-03 16:55:20 -0700325 plat = dev_get_plat(dev);
Simon Glass90b6fef2016-01-18 19:52:26 -0700326 plat->rot = rot;
327
Simon Glass87a3cd72021-11-19 13:24:03 -0700328 ut_assertok(video_get_nologo(uts, &dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700329 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
Dzmitry Sankouskifc785c52023-03-07 13:21:20 +0300330 ut_assertok(vidconsole_select_font(con, "8x16", 0));
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300331 ut_asserteq(46, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300332 ut_assertok(check_copy_frame_buffer(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700333
334 /* Check display wrap */
335 for (i = 0; i < 120; i++)
336 vidconsole_put_char(con, 'A' + i % 50);
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300337 ut_asserteq(wrap_size, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300338 ut_assertok(check_copy_frame_buffer(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700339
340 /* Check display scrolling */
341 for (i = 0; i < SCROLL_LINES; i++) {
342 vidconsole_put_char(con, 'A' + i % 50);
343 vidconsole_put_char(con, '\n');
344 }
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300345 ut_asserteq(scroll_size, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300346 ut_assertok(check_copy_frame_buffer(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700347
348 /* If we scroll enough, the screen becomes blank again */
349 for (i = 0; i < SCROLL_LINES; i++)
350 vidconsole_put_char(con, '\n');
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300351 ut_asserteq(46, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300352 ut_assertok(check_copy_frame_buffer(uts, dev));
Simon Glass90b6fef2016-01-18 19:52:26 -0700353
354 return 0;
355}
356
357/* Test text output through the console uclass */
358static int dm_test_video_context(struct unit_test_state *uts)
359{
Simon Glassdaac9c72016-01-14 18:10:50 -0700360 ut_assertok(select_vidconsole(uts, "vidconsole0"));
361 ut_assertok(check_vidconsole_output(uts, 0, 788, 453));
362
363 return 0;
Simon Glass90b6fef2016-01-18 19:52:26 -0700364}
Simon Glass1a92f832024-08-22 07:57:48 -0600365DM_TEST(dm_test_video_context, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glassa0f1efe2016-01-18 19:52:27 -0700366
367/* Test rotated text output through the console uclass */
368static int dm_test_video_rotation1(struct unit_test_state *uts)
369{
370 ut_assertok(check_vidconsole_output(uts, 1, 1112, 680));
371
372 return 0;
373}
Simon Glass1a92f832024-08-22 07:57:48 -0600374DM_TEST(dm_test_video_rotation1, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glassa0f1efe2016-01-18 19:52:27 -0700375
376/* Test rotated text output through the console uclass */
377static int dm_test_video_rotation2(struct unit_test_state *uts)
378{
Simon Glassf50a6b92020-07-02 21:12:17 -0600379 ut_assertok(check_vidconsole_output(uts, 2, 783, 445));
Simon Glassa0f1efe2016-01-18 19:52:27 -0700380
381 return 0;
382}
Simon Glass1a92f832024-08-22 07:57:48 -0600383DM_TEST(dm_test_video_rotation2, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glassa0f1efe2016-01-18 19:52:27 -0700384
385/* Test rotated text output through the console uclass */
386static int dm_test_video_rotation3(struct unit_test_state *uts)
387{
388 ut_assertok(check_vidconsole_output(uts, 3, 1134, 681));
389
390 return 0;
391}
Simon Glass1a92f832024-08-22 07:57:48 -0600392DM_TEST(dm_test_video_rotation3, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass7a1cb292016-01-18 19:52:28 -0700393
394/* Read a file into memory and return a pointer to it */
395static int read_file(struct unit_test_state *uts, const char *fname,
396 ulong *addrp)
397{
398 int buf_size = 100000;
399 ulong addr = 0;
400 int size, fd;
401 char *buf;
402
403 buf = map_sysmem(addr, 0);
404 ut_assert(buf != NULL);
405 fd = os_open(fname, OS_O_RDONLY);
406 ut_assert(fd >= 0);
407 size = os_read(fd, buf, buf_size);
Simon Glass9050c5f2016-01-30 15:45:17 -0700408 os_close(fd);
Simon Glass7a1cb292016-01-18 19:52:28 -0700409 ut_assert(size >= 0);
410 ut_assert(size < buf_size);
Simon Glass7a1cb292016-01-18 19:52:28 -0700411 *addrp = addr;
412
413 return 0;
414}
415
416/* Test drawing a bitmap file */
417static int dm_test_video_bmp(struct unit_test_state *uts)
418{
419 struct udevice *dev;
420 ulong addr;
421
Simon Glass87a3cd72021-11-19 13:24:03 -0700422 ut_assertok(video_get_nologo(uts, &dev));
Simon Glass7a1cb292016-01-18 19:52:28 -0700423 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
424
425 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300426 ut_asserteq(1368, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300427 ut_assertok(check_copy_frame_buffer(uts, dev));
Simon Glass7a1cb292016-01-18 19:52:28 -0700428
429 return 0;
430}
Simon Glass1a92f832024-08-22 07:57:48 -0600431DM_TEST(dm_test_video_bmp, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass7a1cb292016-01-18 19:52:28 -0700432
Simon Glassc3b5adf2021-11-19 13:23:50 -0700433/* Test drawing a bitmap file on a 8bpp display */
434static int dm_test_video_bmp8(struct unit_test_state *uts)
435{
436 struct udevice *dev;
437 ulong addr;
438
439 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
440 ut_assertnonnull(dev);
441 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP8));
442
443 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
444
445 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300446 ut_asserteq(1247, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300447 ut_assertok(check_copy_frame_buffer(uts, dev));
Simon Glassc3b5adf2021-11-19 13:23:50 -0700448
449 return 0;
450}
Simon Glass1a92f832024-08-22 07:57:48 -0600451DM_TEST(dm_test_video_bmp8, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glassc3b5adf2021-11-19 13:23:50 -0700452
Simon Glass8bd7f602021-11-19 13:23:58 -0700453/* Test drawing a bitmap file on a 16bpp display */
454static int dm_test_video_bmp16(struct unit_test_state *uts)
455{
456 ulong src, src_len = ~0UL;
457 uint dst_len = ~0U;
458 struct udevice *dev;
459 ulong dst = 0x10000;
460
461 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
462 ut_assertnonnull(dev);
463 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP16));
464
465 ut_assertok(read_file(uts, "tools/logos/denx-16bpp.bmp.gz", &src));
466 ut_assertok(gunzip(map_sysmem(dst, 0), dst_len, map_sysmem(src, 0),
467 &src_len));
468
469 ut_assertok(video_bmp_display(dev, dst, 0, 0, false));
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300470 ut_asserteq(3700, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300471 ut_assertok(check_copy_frame_buffer(uts, dev));
Simon Glass8bd7f602021-11-19 13:23:58 -0700472
473 return 0;
474}
Simon Glass1a92f832024-08-22 07:57:48 -0600475DM_TEST(dm_test_video_bmp16, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass8bd7f602021-11-19 13:23:58 -0700476
Simon Glass6a92e882021-11-19 13:23:59 -0700477/* Test drawing a 24bpp bitmap file on a 16bpp display */
478static int dm_test_video_bmp24(struct unit_test_state *uts)
479{
480 ulong src, src_len = ~0UL;
481 uint dst_len = ~0U;
482 struct udevice *dev;
483 ulong dst = 0x10000;
484
485 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
486 ut_assertnonnull(dev);
487 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP16));
488
489 ut_assertok(read_file(uts, "tools/logos/denx-24bpp.bmp.gz", &src));
490 ut_assertok(gunzip(map_sysmem(dst, 0), dst_len, map_sysmem(src, 0),
491 &src_len));
492
493 ut_assertok(video_bmp_display(dev, dst, 0, 0, false));
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300494 ut_asserteq(3656, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300495 ut_assertok(check_copy_frame_buffer(uts, dev));
Simon Glass6a92e882021-11-19 13:23:59 -0700496
497 return 0;
498}
Simon Glass1a92f832024-08-22 07:57:48 -0600499DM_TEST(dm_test_video_bmp24, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass6a92e882021-11-19 13:23:59 -0700500
501/* Test drawing a 24bpp bitmap file on a 32bpp display */
502static int dm_test_video_bmp24_32(struct unit_test_state *uts)
503{
504 ulong src, src_len = ~0UL;
505 uint dst_len = ~0U;
506 struct udevice *dev;
507 ulong dst = 0x10000;
508
509 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
510 ut_assertnonnull(dev);
511 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP32));
512
513 ut_assertok(read_file(uts, "tools/logos/denx-24bpp.bmp.gz", &src));
514 ut_assertok(gunzip(map_sysmem(dst, 0), dst_len, map_sysmem(src, 0),
515 &src_len));
516
517 ut_assertok(video_bmp_display(dev, dst, 0, 0, false));
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300518 ut_asserteq(6827, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300519 ut_assertok(check_copy_frame_buffer(uts, dev));
Simon Glass6a92e882021-11-19 13:23:59 -0700520
521 return 0;
522}
Simon Glass1a92f832024-08-22 07:57:48 -0600523DM_TEST(dm_test_video_bmp24_32, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass6a92e882021-11-19 13:23:59 -0700524
Simon Glassc3b5adf2021-11-19 13:23:50 -0700525/* Test drawing a bitmap file on a 32bpp display */
526static int dm_test_video_bmp32(struct unit_test_state *uts)
527{
528 struct udevice *dev;
529 ulong addr;
530
531 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
532 ut_assertnonnull(dev);
533 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP32));
534 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
535
536 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300537 ut_asserteq(2024, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300538 ut_assertok(check_copy_frame_buffer(uts, dev));
Simon Glassc3b5adf2021-11-19 13:23:50 -0700539
540 return 0;
541}
Simon Glass1a92f832024-08-22 07:57:48 -0600542DM_TEST(dm_test_video_bmp32, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glassc3b5adf2021-11-19 13:23:50 -0700543
Simon Glass7a1cb292016-01-18 19:52:28 -0700544/* Test drawing a compressed bitmap file */
545static int dm_test_video_bmp_comp(struct unit_test_state *uts)
546{
547 struct udevice *dev;
548 ulong addr;
549
Simon Glass87a3cd72021-11-19 13:24:03 -0700550 ut_assertok(video_get_nologo(uts, &dev));
Simon Glass7a1cb292016-01-18 19:52:28 -0700551 ut_assertok(read_file(uts, "tools/logos/denx-comp.bmp", &addr));
552
553 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300554 ut_asserteq(1368, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300555 ut_assertok(check_copy_frame_buffer(uts, dev));
Simon Glass7a1cb292016-01-18 19:52:28 -0700556
557 return 0;
558}
Simon Glass1a92f832024-08-22 07:57:48 -0600559DM_TEST(dm_test_video_bmp_comp, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass32337982016-01-14 18:10:51 -0700560
Simon Glass490bb992021-11-19 13:23:55 -0700561/* Test drawing a bitmap file on a 32bpp display */
562static int dm_test_video_comp_bmp32(struct unit_test_state *uts)
563{
564 struct udevice *dev;
565 ulong addr;
566
567 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
568 ut_assertnonnull(dev);
569 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP32));
570
571 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
572
573 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300574 ut_asserteq(2024, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300575 ut_assertok(check_copy_frame_buffer(uts, dev));
Simon Glass490bb992021-11-19 13:23:55 -0700576
577 return 0;
578}
Simon Glass1a92f832024-08-22 07:57:48 -0600579DM_TEST(dm_test_video_comp_bmp32, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass490bb992021-11-19 13:23:55 -0700580
581/* Test drawing a bitmap file on a 8bpp display */
582static int dm_test_video_comp_bmp8(struct unit_test_state *uts)
583{
584 struct udevice *dev;
585 ulong addr;
586
587 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
588 ut_assertnonnull(dev);
589 ut_assertok(sandbox_sdl_set_bpp(dev, VIDEO_BPP8));
590
591 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
592
593 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300594 ut_asserteq(1247, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300595 ut_assertok(check_copy_frame_buffer(uts, dev));
Simon Glass490bb992021-11-19 13:23:55 -0700596
597 return 0;
598}
Simon Glass1a92f832024-08-22 07:57:48 -0600599DM_TEST(dm_test_video_comp_bmp8, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass490bb992021-11-19 13:23:55 -0700600
Simon Glass32337982016-01-14 18:10:51 -0700601/* Test TrueType console */
602static int dm_test_video_truetype(struct unit_test_state *uts)
603{
604 struct udevice *dev, *con;
605 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 -0700606
Simon Glass87a3cd72021-11-19 13:24:03 -0700607 ut_assertok(video_get_nologo(uts, &dev));
Simon Glass32337982016-01-14 18:10:51 -0700608 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
Rob Clark985935b2017-09-25 15:45:08 -0400609 vidconsole_put_string(con, test_string);
Simon Glass6f5a8642025-04-02 06:29:40 +1300610 vidconsole_put_stringn(con, test_string, 30);
611 ut_asserteq(13184, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300612 ut_assertok(check_copy_frame_buffer(uts, dev));
Simon Glass32337982016-01-14 18:10:51 -0700613
614 return 0;
615}
Simon Glass1a92f832024-08-22 07:57:48 -0600616DM_TEST(dm_test_video_truetype, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass32337982016-01-14 18:10:51 -0700617
618/* Test scrolling TrueType console */
619static int dm_test_video_truetype_scroll(struct unit_test_state *uts)
620{
621 struct sandbox_sdl_plat *plat;
622 struct udevice *dev, *con;
623 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 -0700624
625 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
626 ut_assert(!device_active(dev));
Simon Glassfa20e932020-12-03 16:55:20 -0700627 plat = dev_get_plat(dev);
Simon Glass32337982016-01-14 18:10:51 -0700628 plat->font_size = 100;
629
Simon Glass87a3cd72021-11-19 13:24:03 -0700630 ut_assertok(video_get_nologo(uts, &dev));
Simon Glass32337982016-01-14 18:10:51 -0700631 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
Rob Clark985935b2017-09-25 15:45:08 -0400632 vidconsole_put_string(con, test_string);
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300633 ut_asserteq(34287, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300634 ut_assertok(check_copy_frame_buffer(uts, dev));
Simon Glass32337982016-01-14 18:10:51 -0700635
636 return 0;
637}
Simon Glass1a92f832024-08-22 07:57:48 -0600638DM_TEST(dm_test_video_truetype_scroll, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glass32337982016-01-14 18:10:51 -0700639
640/* Test TrueType backspace, within and across lines */
641static int dm_test_video_truetype_bs(struct unit_test_state *uts)
642{
643 struct sandbox_sdl_plat *plat;
644 struct udevice *dev, *con;
645 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 -0700646
647 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
648 ut_assert(!device_active(dev));
Simon Glassfa20e932020-12-03 16:55:20 -0700649 plat = dev_get_plat(dev);
Simon Glass32337982016-01-14 18:10:51 -0700650 plat->font_size = 100;
651
Simon Glass87a3cd72021-11-19 13:24:03 -0700652 ut_assertok(video_get_nologo(uts, &dev));
Simon Glass32337982016-01-14 18:10:51 -0700653 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
Rob Clark985935b2017-09-25 15:45:08 -0400654 vidconsole_put_string(con, test_string);
Alper Nebi Yasaka29b0f92023-08-20 17:46:46 +0300655 ut_asserteq(29471, compress_frame_buffer(uts, dev, false));
Alper Nebi Yasake85a8d02023-08-18 13:31:36 +0300656 ut_assertok(check_copy_frame_buffer(uts, dev));
Simon Glass32337982016-01-14 18:10:51 -0700657
658 return 0;
659}
Simon Glass1a92f832024-08-22 07:57:48 -0600660DM_TEST(dm_test_video_truetype_bs, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Alper Nebi Yasak5e8253d2023-08-18 17:31:27 +0300661
662/* Test partial rendering onto hardware frame buffer */
663static int dm_test_video_copy(struct unit_test_state *uts)
664{
665 struct sandbox_sdl_plat *plat;
666 struct video_uc_plat *uc_plat;
667 struct udevice *dev, *con;
668 struct video_priv *priv;
669 const char *test_string = "\n\tCriticism may not be agreeable, but it is necessary.\t";
670 ulong addr;
671
672 if (!IS_ENABLED(CONFIG_VIDEO_COPY))
673 return -EAGAIN;
674
675 ut_assertok(uclass_find_first_device(UCLASS_VIDEO, &dev));
676 ut_assertnonnull(dev);
677 uc_plat = dev_get_uclass_plat(dev);
678 uc_plat->hide_logo = true;
679 plat = dev_get_plat(dev);
680 plat->font_size = 32;
681 ut_assert(!device_active(dev));
682 ut_assertok(uclass_first_device_err(UCLASS_VIDEO, &dev));
683 ut_assertnonnull(dev);
684 priv = dev_get_uclass_priv(dev);
685
686 ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
687 ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
688
689 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
690 vidconsole_put_string(con, "\n\n\n\n\n");
691 vidconsole_put_string(con, test_string);
692 vidconsole_put_string(con, test_string);
693
694 ut_asserteq(6678, compress_frame_buffer(uts, dev, false));
695 ut_assertok(check_copy_frame_buffer(uts, dev));
696
697 /*
698 * Secretly clear the hardware frame buffer, but in a different
699 * color (black) to see which parts will be overwritten.
700 */
701 memset(priv->copy_fb, 0, priv->fb_size);
702
703 /*
704 * We should have the full content on the main buffer, but only
Alexander Graff88b6a22022-06-10 00:59:21 +0200705 * 'damage' should have been copied to the copy buffer. This consists
706 * of a while rectangle with the Denx logo and four lines of text. The
707 * rest of the display is black.
708 *
709 * An easy way to try this is by changing video_sync() to call
710 * sandbox_sdl_sync(priv->copy_fb) instead of priv->fb then running the
711 * unit test:
712 *
713 * ./u-boot -Tl
714 * ut dm dm_test_video_copy
Alper Nebi Yasak5e8253d2023-08-18 17:31:27 +0300715 */
716 vidconsole_put_string(con, test_string);
717 vidconsole_put_string(con, test_string);
Alexander Graff88b6a22022-06-10 00:59:21 +0200718 video_sync(dev, true);
Alper Nebi Yasak5e8253d2023-08-18 17:31:27 +0300719 ut_asserteq(7589, compress_frame_buffer(uts, dev, false));
Alexander Graff88b6a22022-06-10 00:59:21 +0200720 ut_asserteq(7704, compress_frame_buffer(uts, dev, true));
Alper Nebi Yasak5e8253d2023-08-18 17:31:27 +0300721
722 return 0;
723}
724DM_TEST(dm_test_video_copy, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Alper Nebi Yasakfc5740a2023-08-18 17:55:08 +0300725
726/* Test video damage tracking */
727static int dm_test_video_damage(struct unit_test_state *uts)
728{
729 struct sandbox_sdl_plat *plat;
730 struct udevice *dev, *con;
731 struct video_priv *priv;
732 const char *test_string_1 = "Criticism may not be agreeable, ";
733 const char *test_string_2 = "but it is necessary.";
734 const char *test_string_3 = "It fulfils the same function as pain in the human body.";
735
736 if (!IS_ENABLED(CONFIG_VIDEO_DAMAGE))
737 return -EAGAIN;
738
739 ut_assertok(uclass_find_device(UCLASS_VIDEO, 0, &dev));
740 ut_assert(!device_active(dev));
741 plat = dev_get_plat(dev);
742 plat->font_size = 32;
743
744 ut_assertok(video_get_nologo(uts, &dev));
745 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
746 priv = dev_get_uclass_priv(dev);
747
748 vidconsole_position_cursor(con, 14, 10);
749 vidconsole_put_string(con, test_string_2);
750 ut_asserteq(449, priv->damage.xstart);
751 ut_asserteq(325, priv->damage.ystart);
752 ut_asserteq(661, priv->damage.xend);
753 ut_asserteq(350, priv->damage.yend);
754
755 vidconsole_position_cursor(con, 7, 5);
756 vidconsole_put_string(con, test_string_1);
757 ut_asserteq(225, priv->damage.xstart);
758 ut_asserteq(164, priv->damage.ystart);
759 ut_asserteq(661, priv->damage.xend);
760 ut_asserteq(350, priv->damage.yend);
761
762 vidconsole_position_cursor(con, 21, 15);
763 vidconsole_put_string(con, test_string_3);
764 ut_asserteq(225, priv->damage.xstart);
765 ut_asserteq(164, priv->damage.ystart);
766 ut_asserteq(1280, priv->damage.xend);
767 ut_asserteq(510, priv->damage.yend);
768
769 video_sync(dev, true);
770 ut_asserteq(priv->xsize, priv->damage.xstart);
771 ut_asserteq(priv->ysize, priv->damage.ystart);
772 ut_asserteq(0, priv->damage.xend);
773 ut_asserteq(0, priv->damage.yend);
774
775 ut_asserteq(7339, compress_frame_buffer(uts, dev, false));
776 ut_assertok(check_copy_frame_buffer(uts, dev));
777
778 return 0;
779}
780DM_TEST(dm_test_video_damage, UTF_SCAN_PDATA | UTF_SCAN_FDT);
Simon Glassfff57f62025-04-02 06:29:35 +1300781
782/* Test font measurement */
783static int dm_test_font_measure(struct unit_test_state *uts)
784{
Simon Glass3c686e62025-04-02 06:29:38 +1300785 const char *test_string = "There is always much\nto be said for not "
Simon Glassfff57f62025-04-02 06:29:35 +1300786 "attempting more than you can do and for making a certainty of "
787 "what you try. But this principle, like others in life and "
788 "war, has its exceptions.";
Simon Glasseb4efc62025-04-02 06:29:37 +1300789 const struct vidconsole_mline *line;
Simon Glassfff57f62025-04-02 06:29:35 +1300790 struct vidconsole_bbox bbox;
791 struct video_priv *priv;
792 struct udevice *dev, *con;
Simon Glass3aa33582025-04-02 06:29:39 +1300793 const int limit = 0x320;
Simon Glass95bcad42025-04-02 06:29:36 +1300794 struct alist lines;
Simon Glass3c686e62025-04-02 06:29:38 +1300795 int nl;
Simon Glassfff57f62025-04-02 06:29:35 +1300796
797 ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
798 priv = dev_get_uclass_priv(dev);
799 ut_asserteq(1366, priv->xsize);
800 ut_asserteq(768, priv->ysize);
801
802 /* this is using the Nimbus font with size of 18 pixels */
803 ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
804 vidconsole_position_cursor(con, 0, 0);
Simon Glasseb4efc62025-04-02 06:29:37 +1300805 alist_init_struct(&lines, struct vidconsole_mline);
Simon Glass3aa33582025-04-02 06:29:39 +1300806 ut_assertok(vidconsole_measure(con, NULL, 0, test_string, -1, &bbox,
Simon Glass95bcad42025-04-02 06:29:36 +1300807 &lines));
Simon Glassfff57f62025-04-02 06:29:35 +1300808 ut_asserteq(0, bbox.x0);
809 ut_asserteq(0, bbox.y0);
Simon Glass3c686e62025-04-02 06:29:38 +1300810 ut_asserteq(0x3ea, bbox.x1);
811 ut_asserteq(0x24, bbox.y1);
812 ut_asserteq(2, lines.count);
813
814 nl = strchr(test_string, '\n') - test_string;
Simon Glasseb4efc62025-04-02 06:29:37 +1300815
816 line = alist_get(&lines, 0, struct vidconsole_mline);
817 ut_assertnonnull(line);
818 ut_asserteq(0, line->bbox.x0);
819 ut_asserteq(0, line->bbox.y0);
Simon Glass3c686e62025-04-02 06:29:38 +1300820 ut_asserteq(0x8c, line->bbox.x1);
Simon Glasseb4efc62025-04-02 06:29:37 +1300821 ut_asserteq(0x12, line->bbox.y1);
822 ut_asserteq(0, line->start);
Simon Glass3c686e62025-04-02 06:29:38 +1300823 ut_asserteq(20, line->len);
824 ut_asserteq(nl, line->len);
825
826 line++;
827 ut_asserteq(0x0, line->bbox.x0);
828 ut_asserteq(0x12, line->bbox.y0);
829 ut_asserteq(0x3ea, line->bbox.x1);
830 ut_asserteq(0x24, line->bbox.y1);
831 ut_asserteq(21, line->start);
832 ut_asserteq(nl + 1, line->start);
833 ut_asserteq(163, line->len);
834 ut_asserteq(strlen(test_string + nl + 1), line->len);
Simon Glassfff57f62025-04-02 06:29:35 +1300835
Simon Glass3aa33582025-04-02 06:29:39 +1300836 /* now use a limit on the width */
837 ut_assertok(vidconsole_measure(con, NULL, 0, test_string, limit, &bbox,
838 &lines));
839 ut_asserteq(0, bbox.x0);
840 ut_asserteq(0, bbox.y0);
841 ut_asserteq(0x31e, bbox.x1);
842 ut_asserteq(0x36, bbox.y1);
843 ut_asserteq(3, lines.count);
844
845 nl = strchr(test_string, '\n') - test_string;
846
847 line = alist_get(&lines, 0, struct vidconsole_mline);
848 ut_assertnonnull(line);
849 ut_asserteq(0, line->bbox.x0);
850 ut_asserteq(0, line->bbox.y0);
851 ut_asserteq(0x8c, line->bbox.x1);
852 ut_asserteq(0x12, line->bbox.y1);
853 ut_asserteq(0, line->start);
854 ut_asserteq(20, line->len);
855 ut_asserteq(nl, line->len);
856 printf("line0 '%.*s'\n", line->len, test_string + line->start);
857 ut_asserteq_strn("There is always much",
858 test_string + line->start);
859
860 line++;
861 ut_asserteq(0x0, line->bbox.x0);
862 ut_asserteq(0x12, line->bbox.y0);
863 ut_asserteq(0x31e, line->bbox.x1);
864 ut_asserteq(0x24, line->bbox.y1);
865 ut_asserteq(21, line->start);
866 ut_asserteq(nl + 1, line->start);
867 ut_asserteq(129, line->len);
868 printf("line1 '%.*s'\n", line->len, test_string + line->start);
869 ut_asserteq_strn("to be said for not attempting more than you can do "
870 "and for making a certainty of what you try. But this "
871 "principle, like others in",
872 test_string + line->start);
873
874 line++;
875 ut_asserteq(0x0, line->bbox.x0);
876 ut_asserteq(0x24, line->bbox.y0);
877 ut_asserteq(0xc8, line->bbox.x1);
878 ut_asserteq(0x36, line->bbox.y1);
879 ut_asserteq(21 + 130, line->start);
880 ut_asserteq(33, line->len);
881 printf("line2 '%.*s'\n", line->len, test_string + line->start);
882 ut_asserteq_strn("life and war, has its exceptions.",
883 test_string + line->start);
884
885 /*
886 * all characters should be accounted for, except the newline and the
887 * space which is consumed in the wordwrap
888 */
889 ut_asserteq(strlen(test_string) - 2,
890 line[-2].len + line[-1].len + line->len);
891
Simon Glassfff57f62025-04-02 06:29:35 +1300892 return 0;
893}
894DM_TEST(dm_test_font_measure, UTF_SCAN_FDT);