* [PATCH v2 01/56] video: Make white-on-black a video-device property
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
@ 2025-03-28 13:05 ` Simon Glass
2025-03-28 13:05 ` [PATCH v2 02/56] sandbox: Select white-on-black Simon Glass
` (55 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:05 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Alexander Graf, Alper Nebi Yasak, Anatolij Gustschin,
Devarsh Thakkar, Miquel Raynal, Nikhil M Jain, Tom Rini
The CONFIG_WHITE_ON_BLACK setting is hard-coded at build-time. It is
useful to be able to control this when showing menus.
Create a property to hold this information, using the CONFIG as the
initial value.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
boot/expo.c | 2 +-
boot/scene.c | 8 ++++----
drivers/video/video-uclass.c | 16 +++++++++++++++-
include/video.h | 12 ++++++++++++
4 files changed, 32 insertions(+), 6 deletions(-)
diff --git a/boot/expo.c b/boot/expo.c
index 786f665f53c..8ce645e5a8f 100644
--- a/boot/expo.c
+++ b/boot/expo.c
@@ -194,7 +194,7 @@ int expo_render(struct expo *exp)
u32 colour;
int ret;
- back = CONFIG_IS_ENABLED(SYS_WHITE_ON_BLACK) ? VID_BLACK : VID_WHITE;
+ back = vid_priv->white_on_black ? VID_BLACK : VID_WHITE;
colour = video_index_to_colour(vid_priv, back);
ret = video_fill(dev, colour);
if (ret)
diff --git a/boot/scene.c b/boot/scene.c
index 3290a40222a..15e7a8b3387 100644
--- a/boot/scene.c
+++ b/boot/scene.c
@@ -330,8 +330,9 @@ static void scene_render_background(struct scene_obj *obj, bool box_only)
enum colour_idx fore, back;
uint inset = theme->menu_inset;
+ vid_priv = dev_get_uclass_priv(dev);
/* draw a background for the object */
- if (CONFIG_IS_ENABLED(SYS_WHITE_ON_BLACK)) {
+ if (vid_priv->white_on_black) {
fore = VID_DARK_GREY;
back = VID_WHITE;
} else {
@@ -344,7 +345,6 @@ static void scene_render_background(struct scene_obj *obj, bool box_only)
return;
vidconsole_push_colour(cons, fore, back, &old);
- vid_priv = dev_get_uclass_priv(dev);
video_fill_part(dev, label_bbox.x0 - inset, label_bbox.y0 - inset,
label_bbox.x1 + inset, label_bbox.y1 + inset,
vid_priv->colour_fg);
@@ -408,7 +408,8 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode)
struct vidconsole_colour old;
enum colour_idx fore, back;
- if (CONFIG_IS_ENABLED(SYS_WHITE_ON_BLACK)) {
+ vid_priv = dev_get_uclass_priv(dev);
+ if (vid_priv->white_on_black) {
fore = VID_BLACK;
back = VID_WHITE;
} else {
@@ -416,7 +417,6 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode)
back = VID_BLACK;
}
- vid_priv = dev_get_uclass_priv(dev);
if (obj->flags & SCENEOF_POINT) {
vidconsole_push_colour(cons, fore, back, &old);
video_fill_part(dev, x - theme->menu_inset, y,
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
index 1e385f12f8e..db40744c196 100644
--- a/drivers/video/video-uclass.c
+++ b/drivers/video/video-uclass.c
@@ -343,7 +343,7 @@ void video_set_default_colors(struct udevice *dev, bool invert)
struct video_priv *priv = dev_get_uclass_priv(dev);
int fore, back;
- if (CONFIG_IS_ENABLED(SYS_WHITE_ON_BLACK)) {
+ if (priv->white_on_black) {
/* White is used when switching to bold, use light gray here */
fore = VID_LIGHT_GRAY;
back = VID_BLACK;
@@ -580,6 +580,18 @@ static void video_idle(struct cyclic_info *cyc)
video_sync_all();
}
+void video_set_white_on_black(struct udevice *dev, bool white_on_black)
+{
+ struct video_priv *priv = dev_get_uclass_priv(dev);
+
+ if (priv->white_on_black != white_on_black) {
+ priv->white_on_black = white_on_black;
+ video_set_default_colors(dev, false);
+
+ video_clear(dev);
+ }
+}
+
/* Set up the display ready for use */
static int video_post_probe(struct udevice *dev)
{
@@ -622,6 +634,8 @@ static int video_post_probe(struct udevice *dev)
if (IS_ENABLED(CONFIG_VIDEO_COPY) && plat->copy_base)
priv->copy_fb = map_sysmem(plat->copy_base, plat->size);
+ priv->white_on_black = CONFIG_IS_ENABLED(SYS_WHITE_ON_BLACK);
+
/* Set up colors */
video_set_default_colors(dev, false);
diff --git a/include/video.h b/include/video.h
index 2fe2f73a865..0ec6b1ca289 100644
--- a/include/video.h
+++ b/include/video.h
@@ -100,6 +100,7 @@ enum video_format {
* @fg_col_idx: Foreground color code (bit 3 = bold, bit 0-2 = color)
* @bg_col_idx: Background color code (bit 3 = bold, bit 0-2 = color)
* @last_sync: Monotonic time of last video sync
+ * @white_on_black: Use a black background
*/
struct video_priv {
/* Things set up by the driver: */
@@ -131,6 +132,7 @@ struct video_priv {
u8 fg_col_idx;
u8 bg_col_idx;
ulong last_sync;
+ bool white_on_black;
};
/**
@@ -346,6 +348,16 @@ void video_set_flush_dcache(struct udevice *dev, bool flush);
*/
void video_set_default_colors(struct udevice *dev, bool invert);
+/**
+ * video_set_white_on_black() - Change the setting for white-on-black
+ *
+ * This does nothing if the setting is already the same.
+ *
+ * @dev: video device
+ * @white_on_black: true to use white-on-black, false for black-on-white
+ */
+void video_set_white_on_black(struct udevice *dev, bool white_on_black);
+
/**
* video_default_font_height() - Get the default font height
*
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 02/56] sandbox: Select white-on-black
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
2025-03-28 13:05 ` [PATCH v2 01/56] video: Make white-on-black a video-device property Simon Glass
@ 2025-03-28 13:05 ` Simon Glass
2025-03-28 13:05 ` [PATCH v2 03/56] video: Add a test for font measurement Simon Glass
` (54 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:05 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Caleb Connolly, Christian Marangi,
Guillaume La Roque, Mattijs Korpershoek, Sughosh Ganu, Tom Rini
Use white on black for the expo menu as it is easier on the eyes.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
arch/sandbox/dts/test.dts | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index caec8c8fd01..2087c91285c 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -130,6 +130,7 @@
font-size = <30>;
menu-inset = <3>;
menuitem-gap-y = <1>;
+ white-on-black;
};
cedit-theme {
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 03/56] video: Add a test for font measurement
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
2025-03-28 13:05 ` [PATCH v2 01/56] video: Make white-on-black a video-device property Simon Glass
2025-03-28 13:05 ` [PATCH v2 02/56] sandbox: Select white-on-black Simon Glass
@ 2025-03-28 13:05 ` Simon Glass
2025-03-28 13:05 ` [PATCH v2 04/56] video: Begin support for measuring multiple lines of text Simon Glass
` (53 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:05 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Alexander Graf, Alper Nebi Yasak, Anatolij Gustschin,
Tom Rini
Add a simple test which measures a line of text using a Truetype font.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
test/dm/video.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/test/dm/video.c b/test/dm/video.c
index 929fc16d0ef..6ce1a756e25 100644
--- a/test/dm/video.c
+++ b/test/dm/video.c
@@ -777,3 +777,32 @@ static int dm_test_video_damage(struct unit_test_state *uts)
return 0;
}
DM_TEST(dm_test_video_damage, UTF_SCAN_PDATA | UTF_SCAN_FDT);
+
+/* Test font measurement */
+static int dm_test_font_measure(struct unit_test_state *uts)
+{
+ const char *test_string = "There is always much to be said for not "
+ "attempting more than you can do and for making a certainty of "
+ "what you try. But this principle, like others in life and "
+ "war, has its exceptions.";
+ struct vidconsole_bbox bbox;
+ struct video_priv *priv;
+ struct udevice *dev, *con;
+
+ ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
+ priv = dev_get_uclass_priv(dev);
+ ut_asserteq(1366, priv->xsize);
+ ut_asserteq(768, priv->ysize);
+
+ /* this is using the Nimbus font with size of 18 pixels */
+ ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
+ vidconsole_position_cursor(con, 0, 0);
+ ut_assertok(vidconsole_measure(con, NULL, 0, test_string, &bbox));
+ ut_asserteq(0, bbox.x0);
+ ut_asserteq(0, bbox.y0);
+ ut_asserteq(0x47a, bbox.x1);
+ ut_asserteq(0x12, bbox.y1);
+
+ return 0;
+}
+DM_TEST(dm_test_font_measure, UTF_SCAN_FDT);
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 04/56] video: Begin support for measuring multiple lines of text
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (2 preceding siblings ...)
2025-03-28 13:05 ` [PATCH v2 03/56] video: Add a test for font measurement Simon Glass
@ 2025-03-28 13:05 ` Simon Glass
2025-03-28 13:05 ` [PATCH v2 05/56] video: truetype: Fill in the measured line Simon Glass
` (52 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:05 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Alexander Graf, Alper Nebi Yasak, Anatolij Gustschin,
Peter Robinson, Tom Rini
Update the vidconsole API so that measure() can measure multiple lines
of text. This will make it easier to implement multi-line fields in
expo.
Tidy up the function comments while we are here.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
boot/scene.c | 2 +-
drivers/video/console_truetype.c | 3 +-
drivers/video/vidconsole-uclass.c | 7 +++--
include/video_console.h | 50 +++++++++++++++++++++++--------
test/dm/video.c | 5 +++-
5 files changed, 49 insertions(+), 18 deletions(-)
diff --git a/boot/scene.c b/boot/scene.c
index 15e7a8b3387..d3ae5816bef 100644
--- a/boot/scene.c
+++ b/boot/scene.c
@@ -298,7 +298,7 @@ int scene_obj_get_hw(struct scene *scn, uint id, int *widthp)
}
ret = vidconsole_measure(scn->expo->cons, txt->font_name,
- txt->font_size, str, &bbox);
+ txt->font_size, str, &bbox, NULL);
if (ret)
return log_msg_ret("mea", ret);
if (widthp)
diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c
index 980baee83cf..7b9033818d3 100644
--- a/drivers/video/console_truetype.c
+++ b/drivers/video/console_truetype.c
@@ -733,7 +733,8 @@ static int truetype_select_font(struct udevice *dev, const char *name,
}
static int truetype_measure(struct udevice *dev, const char *name, uint size,
- const char *text, struct vidconsole_bbox *bbox)
+ const char *text, struct vidconsole_bbox *bbox,
+ struct alist *lines)
{
struct console_tt_metrics *met;
stbtt_fontinfo *font;
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
index a1dfd35b7b8..4ca41dc331e 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -608,14 +608,17 @@ int vidconsole_select_font(struct udevice *dev, const char *name, uint size)
}
int vidconsole_measure(struct udevice *dev, const char *name, uint size,
- const char *text, struct vidconsole_bbox *bbox)
+ const char *text, struct vidconsole_bbox *bbox,
+ struct alist *lines)
{
struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
struct vidconsole_ops *ops = vidconsole_get_ops(dev);
int ret;
if (ops->measure) {
- ret = ops->measure(dev, name, size, text, bbox);
+ if (lines)
+ alist_empty(lines);
+ ret = ops->measure(dev, name, size, text, bbox, lines);
if (ret != -ENOSYS)
return ret;
}
diff --git a/include/video_console.h b/include/video_console.h
index 13197fa4518..ee9ce3c0e37 100644
--- a/include/video_console.h
+++ b/include/video_console.h
@@ -6,6 +6,7 @@
#ifndef __video_console_h
#define __video_console_h
+#include <alist.h>
#include <video.h>
struct abuf;
@@ -119,6 +120,19 @@ struct vidconsole_bbox {
int y1;
};
+/**
+ * vidconsole_mline - Holds information about a line of measured text
+ *
+ * @bbox: Bounding box of the line, assuming it starts at 0,0
+ * @start: String index of the first character in the line
+ * @len: Number of characters in the line
+ */
+struct vidconsole_mline {
+ struct vidconsole_bbox bbox;
+ int start;
+ int len;
+};
+
/**
* struct vidconsole_ops - Video console operations
*
@@ -228,18 +242,23 @@ struct vidconsole_ops {
int (*select_font)(struct udevice *dev, const char *name, uint size);
/**
- * measure() - Measure the bounds of some text
+ * measure() - Measure the bounding box of some text
*
- * @dev: Device to adjust
+ * @dev: Console device to use
* @name: Font name to use (NULL to use default)
* @size: Font size to use (0 to use default)
* @text: Text to measure
* @bbox: Returns bounding box of text, assuming it is positioned
* at 0,0
+ * @lines: If non-NULL, this must be an alist of
+ * struct vidconsole_mline inited by caller. A separate
+ * record is added for each line of text
+ *
* Returns: 0 on success, -ENOENT if no such font
*/
int (*measure)(struct udevice *dev, const char *name, uint size,
- const char *text, struct vidconsole_bbox *bbox);
+ const char *text, struct vidconsole_bbox *bbox,
+ struct alist *lines);
/**
* nominal() - Measure the expected width of a line of text
@@ -320,19 +339,24 @@ int vidconsole_get_font(struct udevice *dev, int seq,
*/
int vidconsole_select_font(struct udevice *dev, const char *name, uint size);
-/*
- * vidconsole_measure() - Measuring the bounding box of some text
+/**
+ * vidconsole_measure() - Measure the bounding box of some text
*
- * @dev: Console device to use
- * @name: Font name, NULL for default
- * @size: Font size, ignored if @name is NULL
- * @text: Text to measure
- * @bbox: Returns nounding box of text
- * Returns: 0 if OK, -ve on error
+ * @dev: Device to adjust
+ * @name: Font name to use (NULL to use default)
+ * @size: Font size to use (0 to use default)
+ * @text: Text to measure
+ * @bbox: Returns bounding box of text, assuming it is positioned
+ * at 0,0
+ * @lines: If non-NULL, this must be an alist of
+ * struct vidconsole_mline inited by caller. The list is emptied
+ * and then a separate record is added for each line of text
+ *
+ * Returns: 0 on success, -ENOENT if no such font
*/
int vidconsole_measure(struct udevice *dev, const char *name, uint size,
- const char *text, struct vidconsole_bbox *bbox);
-
+ const char *text, struct vidconsole_bbox *bbox,
+ struct alist *lines);
/**
* vidconsole_nominal() - Measure the expected width of a line of text
*
diff --git a/test/dm/video.c b/test/dm/video.c
index 6ce1a756e25..cfc831b6931 100644
--- a/test/dm/video.c
+++ b/test/dm/video.c
@@ -788,6 +788,7 @@ static int dm_test_font_measure(struct unit_test_state *uts)
struct vidconsole_bbox bbox;
struct video_priv *priv;
struct udevice *dev, *con;
+ struct alist lines;
ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
priv = dev_get_uclass_priv(dev);
@@ -797,11 +798,13 @@ static int dm_test_font_measure(struct unit_test_state *uts)
/* this is using the Nimbus font with size of 18 pixels */
ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
vidconsole_position_cursor(con, 0, 0);
- ut_assertok(vidconsole_measure(con, NULL, 0, test_string, &bbox));
+ ut_assertok(vidconsole_measure(con, NULL, 0, test_string, &bbox,
+ &lines));
ut_asserteq(0, bbox.x0);
ut_asserteq(0, bbox.y0);
ut_asserteq(0x47a, bbox.x1);
ut_asserteq(0x12, bbox.y1);
+ ut_asserteq(0, lines.count);
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 05/56] video: truetype: Fill in the measured line
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (3 preceding siblings ...)
2025-03-28 13:05 ` [PATCH v2 04/56] video: Begin support for measuring multiple lines of text Simon Glass
@ 2025-03-28 13:05 ` Simon Glass
2025-03-28 13:05 ` [PATCH v2 06/56] video: truetype: Support newlines in the measured string Simon Glass
` (51 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:05 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Alexander Graf, Alper Nebi Yasak, Anatolij Gustschin,
Peter Robinson, Tom Rini
Create a measured line for the (single) line of text.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
drivers/video/console_truetype.c | 36 +++++++++++++++++++++++---------
test/dm/video.c | 13 +++++++++++-
2 files changed, 38 insertions(+), 11 deletions(-)
diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c
index 7b9033818d3..39d77ad9818 100644
--- a/drivers/video/console_truetype.c
+++ b/drivers/video/console_truetype.c
@@ -737,11 +737,13 @@ static int truetype_measure(struct udevice *dev, const char *name, uint size,
struct alist *lines)
{
struct console_tt_metrics *met;
+ struct vidconsole_mline mline;
+ const char *s;
stbtt_fontinfo *font;
int lsb, advance;
- const char *s;
int width;
- int last;
+ int start;
+ int lastch;
int ret;
ret = get_metrics(dev, name, size, &met);
@@ -754,25 +756,39 @@ static int truetype_measure(struct udevice *dev, const char *name, uint size,
font = &met->font;
width = 0;
- for (last = 0, s = text; *s; s++) {
+ bbox->y1 = 0;
+ start = 0;
+ for (lastch = 0, s = text; *s; s++) {
+ int neww;
int ch = *s;
- /* Used kerning to fine-tune the position of this character */
- if (last)
- width += stbtt_GetCodepointKernAdvance(font, last, ch);
-
/* First get some basic metrics about this character */
stbtt_GetCodepointHMetrics(font, ch, &advance, &lsb);
+ neww = width + advance;
- width += advance;
- last = ch;
+ /* Use kerning to fine-tune the position of this character */
+ if (lastch)
+ neww += stbtt_GetCodepointKernAdvance(font, lastch, ch);
+ lastch = ch;
+
+ width = neww;
}
+ /* add the line */
+ mline.bbox.x0 = 0;
+ mline.bbox.y0 = bbox->y1;
+ mline.bbox.x1 = tt_ceil((double)width * met->scale);
+ bbox->y1 += met->font_size;
+ mline.bbox.y1 = bbox->y1;
+ mline.start = start;
+ mline.len = (s - text) - start;
+ if (lines && !alist_add(lines, mline))
+ return log_msg_ret("ttM", -ENOMEM);
+
bbox->valid = true;
bbox->x0 = 0;
bbox->y0 = 0;
bbox->x1 = tt_ceil((double)width * met->scale);
- bbox->y1 = met->font_size;
return 0;
}
diff --git a/test/dm/video.c b/test/dm/video.c
index cfc831b6931..d3fd74a9a9a 100644
--- a/test/dm/video.c
+++ b/test/dm/video.c
@@ -785,6 +785,7 @@ static int dm_test_font_measure(struct unit_test_state *uts)
"attempting more than you can do and for making a certainty of "
"what you try. But this principle, like others in life and "
"war, has its exceptions.";
+ const struct vidconsole_mline *line;
struct vidconsole_bbox bbox;
struct video_priv *priv;
struct udevice *dev, *con;
@@ -798,13 +799,23 @@ static int dm_test_font_measure(struct unit_test_state *uts)
/* this is using the Nimbus font with size of 18 pixels */
ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
vidconsole_position_cursor(con, 0, 0);
+ alist_init_struct(&lines, struct vidconsole_mline);
ut_assertok(vidconsole_measure(con, NULL, 0, test_string, &bbox,
&lines));
ut_asserteq(0, bbox.x0);
ut_asserteq(0, bbox.y0);
ut_asserteq(0x47a, bbox.x1);
ut_asserteq(0x12, bbox.y1);
- ut_asserteq(0, lines.count);
+ ut_asserteq(1, lines.count);
+
+ line = alist_get(&lines, 0, struct vidconsole_mline);
+ ut_assertnonnull(line);
+ ut_asserteq(0, line->bbox.x0);
+ ut_asserteq(0, line->bbox.y0);
+ ut_asserteq(0x47a, line->bbox.x1);
+ ut_asserteq(0x12, line->bbox.y1);
+ ut_asserteq(0, line->start);
+ ut_asserteq(strlen(test_string), line->len);
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 06/56] video: truetype: Support newlines in the measured string
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (4 preceding siblings ...)
2025-03-28 13:05 ` [PATCH v2 05/56] video: truetype: Fill in the measured line Simon Glass
@ 2025-03-28 13:05 ` Simon Glass
2025-03-28 13:05 ` [PATCH v2 07/56] video: truetype: Support a limit on the width of a line Simon Glass
` (50 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:05 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Alexander Graf, Alper Nebi Yasak, Anatolij Gustschin,
Bin Meng, Peter Robinson, Tom Rini
It is useful to be able to embed newline characters in the string and
have the text measured into multiple lines. Add support for this.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
drivers/video/console_truetype.c | 25 ++++++++++++++++++++++++-
include/video_console.h | 4 ++++
test/dm/video.c | 26 ++++++++++++++++++++------
3 files changed, 48 insertions(+), 7 deletions(-)
diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c
index 39d77ad9818..6eca5d7f543 100644
--- a/drivers/video/console_truetype.c
+++ b/drivers/video/console_truetype.c
@@ -771,10 +771,33 @@ static int truetype_measure(struct udevice *dev, const char *name, uint size,
neww += stbtt_GetCodepointKernAdvance(font, lastch, ch);
lastch = ch;
+ /* see if we need to start a new line */
+ if (ch == '\n') {
+ mline.bbox.x0 = 0;
+ mline.bbox.y0 = bbox->y1;
+ mline.bbox.x1 = tt_ceil((double)width * met->scale);
+ bbox->y1 += met->font_size;
+ mline.bbox.y1 = bbox->y1;
+ mline.bbox.valid = true;
+ mline.start = start;
+ mline.len = (s - text) - start;
+ if (lines && !alist_add(lines, mline))
+ return log_msg_ret("ttm", -ENOMEM);
+ log_debug("line x1 %d y0 %d y1 %d start %d len %d text '%.*s'\n",
+ mline.bbox.x1, mline.bbox.y0, mline.bbox.y1,
+ mline.start, mline.len, mline.len, text + mline.start);
+
+ start = s - text;
+ if (ch == '\n')
+ start++;
+ lastch = 0;
+ neww = 0;
+ }
+
width = neww;
}
- /* add the line */
+ /* add the final line */
mline.bbox.x0 = 0;
mline.bbox.y0 = bbox->y1;
mline.bbox.x1 = tt_ceil((double)width * met->scale);
diff --git a/include/video_console.h b/include/video_console.h
index ee9ce3c0e37..a0ee9ab62e9 100644
--- a/include/video_console.h
+++ b/include/video_console.h
@@ -244,6 +244,8 @@ struct vidconsole_ops {
/**
* measure() - Measure the bounding box of some text
*
+ * The text can include newlines
+ *
* @dev: Console device to use
* @name: Font name to use (NULL to use default)
* @size: Font size to use (0 to use default)
@@ -342,6 +344,8 @@ int vidconsole_select_font(struct udevice *dev, const char *name, uint size);
/**
* vidconsole_measure() - Measure the bounding box of some text
*
+ * The text can include newlines
+ *
* @dev: Device to adjust
* @name: Font name to use (NULL to use default)
* @size: Font size to use (0 to use default)
diff --git a/test/dm/video.c b/test/dm/video.c
index d3fd74a9a9a..a3f3b046882 100644
--- a/test/dm/video.c
+++ b/test/dm/video.c
@@ -781,7 +781,7 @@ DM_TEST(dm_test_video_damage, UTF_SCAN_PDATA | UTF_SCAN_FDT);
/* Test font measurement */
static int dm_test_font_measure(struct unit_test_state *uts)
{
- const char *test_string = "There is always much to be said for not "
+ const char *test_string = "There is always much\nto be said for not "
"attempting more than you can do and for making a certainty of "
"what you try. But this principle, like others in life and "
"war, has its exceptions.";
@@ -790,6 +790,7 @@ static int dm_test_font_measure(struct unit_test_state *uts)
struct video_priv *priv;
struct udevice *dev, *con;
struct alist lines;
+ int nl;
ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
priv = dev_get_uclass_priv(dev);
@@ -804,18 +805,31 @@ static int dm_test_font_measure(struct unit_test_state *uts)
&lines));
ut_asserteq(0, bbox.x0);
ut_asserteq(0, bbox.y0);
- ut_asserteq(0x47a, bbox.x1);
- ut_asserteq(0x12, bbox.y1);
- ut_asserteq(1, lines.count);
+ ut_asserteq(0x3ea, bbox.x1);
+ ut_asserteq(0x24, bbox.y1);
+ ut_asserteq(2, lines.count);
+
+ nl = strchr(test_string, '\n') - test_string;
line = alist_get(&lines, 0, struct vidconsole_mline);
ut_assertnonnull(line);
ut_asserteq(0, line->bbox.x0);
ut_asserteq(0, line->bbox.y0);
- ut_asserteq(0x47a, line->bbox.x1);
+ ut_asserteq(0x8c, line->bbox.x1);
ut_asserteq(0x12, line->bbox.y1);
ut_asserteq(0, line->start);
- ut_asserteq(strlen(test_string), line->len);
+ ut_asserteq(20, line->len);
+ ut_asserteq(nl, line->len);
+
+ line++;
+ ut_asserteq(0x0, line->bbox.x0);
+ ut_asserteq(0x12, line->bbox.y0);
+ ut_asserteq(0x3ea, line->bbox.x1);
+ ut_asserteq(0x24, line->bbox.y1);
+ ut_asserteq(21, line->start);
+ ut_asserteq(nl + 1, line->start);
+ ut_asserteq(163, line->len);
+ ut_asserteq(strlen(test_string + nl + 1), line->len);
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 07/56] video: truetype: Support a limit on the width of a line
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (5 preceding siblings ...)
2025-03-28 13:05 ` [PATCH v2 06/56] video: truetype: Support newlines in the measured string Simon Glass
@ 2025-03-28 13:05 ` Simon Glass
2025-03-28 13:05 ` [PATCH v2 08/56] video: Add a way to write a partial string to the console Simon Glass
` (49 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:05 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Alexander Graf, Alper Nebi Yasak, Anatolij Gustschin,
Bin Meng, Peter Robinson, Tom Rini
Expo needs to be able to word-wrap lines so that they are displayed as
the user expects. Add a limit on the width of each line and support this
in the measurement algorithm.
Add a log category to truetype while we are here.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
boot/scene.c | 2 +-
drivers/video/console_truetype.c | 40 ++++++++++++++++-----
drivers/video/vidconsole-uclass.c | 6 ++--
include/video_console.h | 10 +++---
test/dm/video.c | 59 ++++++++++++++++++++++++++++++-
5 files changed, 100 insertions(+), 17 deletions(-)
diff --git a/boot/scene.c b/boot/scene.c
index d3ae5816bef..fb82ffe768c 100644
--- a/boot/scene.c
+++ b/boot/scene.c
@@ -298,7 +298,7 @@ int scene_obj_get_hw(struct scene *scn, uint id, int *widthp)
}
ret = vidconsole_measure(scn->expo->cons, txt->font_name,
- txt->font_size, str, &bbox, NULL);
+ txt->font_size, str, -1, &bbox, NULL);
if (ret)
return log_msg_ret("mea", ret);
if (widthp)
diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c
index 6eca5d7f543..2e3e6f07112 100644
--- a/drivers/video/console_truetype.c
+++ b/drivers/video/console_truetype.c
@@ -3,6 +3,8 @@
* Copyright (c) 2016 Google, Inc
*/
+#define LOG_CATEGORY UCLASS_VIDEO
+
#include <abuf.h>
#include <dm.h>
#include <log.h>
@@ -733,16 +735,17 @@ static int truetype_select_font(struct udevice *dev, const char *name,
}
static int truetype_measure(struct udevice *dev, const char *name, uint size,
- const char *text, struct vidconsole_bbox *bbox,
- struct alist *lines)
+ const char *text, int pixel_limit,
+ struct vidconsole_bbox *bbox, struct alist *lines)
{
struct console_tt_metrics *met;
struct vidconsole_mline mline;
- const char *s;
+ const char *s, *last_space;
+ int width, last_width;
stbtt_fontinfo *font;
int lsb, advance;
- int width;
int start;
+ int limit;
int lastch;
int ret;
@@ -754,14 +757,30 @@ static int truetype_measure(struct udevice *dev, const char *name, uint size,
if (!*text)
return 0;
+ limit = -1;
+ if (pixel_limit != -1)
+ limit = tt_ceil((double)pixel_limit / met->scale);
+
font = &met->font;
width = 0;
bbox->y1 = 0;
+ bbox->x1 = 0;
start = 0;
+ last_space = NULL;
+ last_width = 0;
for (lastch = 0, s = text; *s; s++) {
int neww;
int ch = *s;
+ if (ch == ' ') {
+ /*
+ * store the position and width so we can use it again
+ * if we need to word-wrap
+ */
+ last_space = s;
+ last_width = width;
+ }
+
/* First get some basic metrics about this character */
stbtt_GetCodepointHMetrics(font, ch, &advance, &lsb);
neww = width + advance;
@@ -772,10 +791,16 @@ static int truetype_measure(struct udevice *dev, const char *name, uint size,
lastch = ch;
/* see if we need to start a new line */
- if (ch == '\n') {
+ if (ch == '\n' || (limit != -1 && neww >= limit)) {
+ if (ch != '\n' && last_space) {
+ s = last_space;
+ width = last_width;
+ }
+ last_space = NULL;
mline.bbox.x0 = 0;
mline.bbox.y0 = bbox->y1;
mline.bbox.x1 = tt_ceil((double)width * met->scale);
+ bbox->x1 = max(bbox->x1, mline.bbox.x1);
bbox->y1 += met->font_size;
mline.bbox.y1 = bbox->y1;
mline.bbox.valid = true;
@@ -788,8 +813,7 @@ static int truetype_measure(struct udevice *dev, const char *name, uint size,
mline.start, mline.len, mline.len, text + mline.start);
start = s - text;
- if (ch == '\n')
- start++;
+ start++;
lastch = 0;
neww = 0;
}
@@ -811,7 +835,7 @@ static int truetype_measure(struct udevice *dev, const char *name, uint size,
bbox->valid = true;
bbox->x0 = 0;
bbox->y0 = 0;
- bbox->x1 = tt_ceil((double)width * met->scale);
+ bbox->x1 = max(bbox->x1, mline.bbox.x1);
return 0;
}
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
index 4ca41dc331e..3259bd2ef7d 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -608,8 +608,8 @@ int vidconsole_select_font(struct udevice *dev, const char *name, uint size)
}
int vidconsole_measure(struct udevice *dev, const char *name, uint size,
- const char *text, struct vidconsole_bbox *bbox,
- struct alist *lines)
+ const char *text, int limit,
+ struct vidconsole_bbox *bbox, struct alist *lines)
{
struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
struct vidconsole_ops *ops = vidconsole_get_ops(dev);
@@ -618,7 +618,7 @@ int vidconsole_measure(struct udevice *dev, const char *name, uint size,
if (ops->measure) {
if (lines)
alist_empty(lines);
- ret = ops->measure(dev, name, size, text, bbox, lines);
+ ret = ops->measure(dev, name, size, text, limit, bbox, lines);
if (ret != -ENOSYS)
return ret;
}
diff --git a/include/video_console.h b/include/video_console.h
index a0ee9ab62e9..1bb265dc9da 100644
--- a/include/video_console.h
+++ b/include/video_console.h
@@ -250,6 +250,7 @@ struct vidconsole_ops {
* @name: Font name to use (NULL to use default)
* @size: Font size to use (0 to use default)
* @text: Text to measure
+ * @limit: Width limit for each line, or -1 if none
* @bbox: Returns bounding box of text, assuming it is positioned
* at 0,0
* @lines: If non-NULL, this must be an alist of
@@ -259,8 +260,8 @@ struct vidconsole_ops {
* Returns: 0 on success, -ENOENT if no such font
*/
int (*measure)(struct udevice *dev, const char *name, uint size,
- const char *text, struct vidconsole_bbox *bbox,
- struct alist *lines);
+ const char *text, int limit,
+ struct vidconsole_bbox *bbox, struct alist *lines);
/**
* nominal() - Measure the expected width of a line of text
@@ -350,6 +351,7 @@ int vidconsole_select_font(struct udevice *dev, const char *name, uint size);
* @name: Font name to use (NULL to use default)
* @size: Font size to use (0 to use default)
* @text: Text to measure
+ * @limit: Width limit for each line, or -1 if none
* @bbox: Returns bounding box of text, assuming it is positioned
* at 0,0
* @lines: If non-NULL, this must be an alist of
@@ -359,8 +361,8 @@ int vidconsole_select_font(struct udevice *dev, const char *name, uint size);
* Returns: 0 on success, -ENOENT if no such font
*/
int vidconsole_measure(struct udevice *dev, const char *name, uint size,
- const char *text, struct vidconsole_bbox *bbox,
- struct alist *lines);
+ const char *text, int limit,
+ struct vidconsole_bbox *bbox, struct alist *lines);
/**
* vidconsole_nominal() - Measure the expected width of a line of text
*
diff --git a/test/dm/video.c b/test/dm/video.c
index a3f3b046882..c1b2a502b47 100644
--- a/test/dm/video.c
+++ b/test/dm/video.c
@@ -789,6 +789,7 @@ static int dm_test_font_measure(struct unit_test_state *uts)
struct vidconsole_bbox bbox;
struct video_priv *priv;
struct udevice *dev, *con;
+ const int limit = 0x320;
struct alist lines;
int nl;
@@ -801,7 +802,7 @@ static int dm_test_font_measure(struct unit_test_state *uts)
ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
vidconsole_position_cursor(con, 0, 0);
alist_init_struct(&lines, struct vidconsole_mline);
- ut_assertok(vidconsole_measure(con, NULL, 0, test_string, &bbox,
+ ut_assertok(vidconsole_measure(con, NULL, 0, test_string, -1, &bbox,
&lines));
ut_asserteq(0, bbox.x0);
ut_asserteq(0, bbox.y0);
@@ -831,6 +832,62 @@ static int dm_test_font_measure(struct unit_test_state *uts)
ut_asserteq(163, line->len);
ut_asserteq(strlen(test_string + nl + 1), line->len);
+ /* now use a limit on the width */
+ ut_assertok(vidconsole_measure(con, NULL, 0, test_string, limit, &bbox,
+ &lines));
+ ut_asserteq(0, bbox.x0);
+ ut_asserteq(0, bbox.y0);
+ ut_asserteq(0x31e, bbox.x1);
+ ut_asserteq(0x36, bbox.y1);
+ ut_asserteq(3, lines.count);
+
+ nl = strchr(test_string, '\n') - test_string;
+
+ line = alist_get(&lines, 0, struct vidconsole_mline);
+ ut_assertnonnull(line);
+ ut_asserteq(0, line->bbox.x0);
+ ut_asserteq(0, line->bbox.y0);
+ ut_asserteq(0x8c, line->bbox.x1);
+ ut_asserteq(0x12, line->bbox.y1);
+ ut_asserteq(0, line->start);
+ ut_asserteq(20, line->len);
+ ut_asserteq(nl, line->len);
+ printf("line0 '%.*s'\n", line->len, test_string + line->start);
+ ut_asserteq_strn("There is always much",
+ test_string + line->start);
+
+ line++;
+ ut_asserteq(0x0, line->bbox.x0);
+ ut_asserteq(0x12, line->bbox.y0);
+ ut_asserteq(0x31e, line->bbox.x1);
+ ut_asserteq(0x24, line->bbox.y1);
+ ut_asserteq(21, line->start);
+ ut_asserteq(nl + 1, line->start);
+ ut_asserteq(129, line->len);
+ printf("line1 '%.*s'\n", line->len, test_string + line->start);
+ ut_asserteq_strn("to be said for not attempting more than you can do "
+ "and for making a certainty of what you try. But this "
+ "principle, like others in",
+ test_string + line->start);
+
+ line++;
+ ut_asserteq(0x0, line->bbox.x0);
+ ut_asserteq(0x24, line->bbox.y0);
+ ut_asserteq(0xc8, line->bbox.x1);
+ ut_asserteq(0x36, line->bbox.y1);
+ ut_asserteq(21 + 130, line->start);
+ ut_asserteq(33, line->len);
+ printf("line2 '%.*s'\n", line->len, test_string + line->start);
+ ut_asserteq_strn("life and war, has its exceptions.",
+ test_string + line->start);
+
+ /*
+ * all characters should be accounted for, except the newline and the
+ * space which is consumed in the wordwrap
+ */
+ ut_asserteq(strlen(test_string) - 2,
+ line[-2].len + line[-1].len + line->len);
+
return 0;
}
DM_TEST(dm_test_font_measure, UTF_SCAN_FDT);
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 08/56] video: Add a way to write a partial string to the console
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (6 preceding siblings ...)
2025-03-28 13:05 ` [PATCH v2 07/56] video: truetype: Support a limit on the width of a line Simon Glass
@ 2025-03-28 13:05 ` Simon Glass
2025-03-28 13:05 ` [PATCH v2 09/56] console: Support a format string for stderr output Simon Glass
` (48 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:05 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Alexander Graf, Alper Nebi Yasak, Anatolij Gustschin,
Peter Robinson, Tom Rini
When writing multiple lines of text we need to be able to control which
text goes on each line. Add a new vidconsole_put_stringn() function to
help with this.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
drivers/video/vidconsole-uclass.c | 13 ++++++++++---
include/video_console.h | 17 +++++++++++++++++
test/dm/video.c | 3 ++-
3 files changed, 29 insertions(+), 4 deletions(-)
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
index 3259bd2ef7d..fa329bd1b37 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -508,12 +508,14 @@ int vidconsole_put_char(struct udevice *dev, char ch)
return 0;
}
-int vidconsole_put_string(struct udevice *dev, const char *str)
+int vidconsole_put_stringn(struct udevice *dev, const char *str, int maxlen)
{
- const char *s;
+ const char *s, *end = NULL;
int ret;
- for (s = str; *s; s++) {
+ if (maxlen != -1)
+ end = str + maxlen;
+ for (s = str; *s && (maxlen == -1 || s < end); s++) {
ret = vidconsole_put_char(dev, *s);
if (ret)
return ret;
@@ -522,6 +524,11 @@ int vidconsole_put_string(struct udevice *dev, const char *str)
return 0;
}
+int vidconsole_put_string(struct udevice *dev, const char *str)
+{
+ return vidconsole_put_stringn(dev, str, -1);
+}
+
static void vidconsole_putc(struct stdio_dev *sdev, const char ch)
{
struct udevice *dev = sdev->priv;
diff --git a/include/video_console.h b/include/video_console.h
index 1bb265dc9da..e4fc776e2d3 100644
--- a/include/video_console.h
+++ b/include/video_console.h
@@ -499,6 +499,23 @@ int vidconsole_entry_start(struct udevice *dev);
*/
int vidconsole_put_char(struct udevice *dev, char ch);
+/**
+ * vidconsole_put_stringn() - Output part of a string to the current console pos
+ *
+ * Outputs part of a string to the console and advances the cursor. This
+ * function handles wrapping to new lines and scrolling the console. Special
+ * characters are handled also: \n, \r, \b and \t.
+ *
+ * The device always starts with the cursor at position 0,0 (top left). It
+ * can be adjusted manually using vidconsole_position_cursor().
+ *
+ * @dev: Device to adjust
+ * @str: String to write
+ * @maxlen: Maximum chars to output, or -1 for all
+ * Return: 0 if OK, -ve on error
+ */
+int vidconsole_put_stringn(struct udevice *dev, const char *str, int maxlen);
+
/**
* vidconsole_put_string() - Output a string to the current console position
*
diff --git a/test/dm/video.c b/test/dm/video.c
index c1b2a502b47..a9b2482631f 100644
--- a/test/dm/video.c
+++ b/test/dm/video.c
@@ -607,7 +607,8 @@ static int dm_test_video_truetype(struct unit_test_state *uts)
ut_assertok(video_get_nologo(uts, &dev));
ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
vidconsole_put_string(con, test_string);
- ut_asserteq(12174, compress_frame_buffer(uts, dev, false));
+ vidconsole_put_stringn(con, test_string, 30);
+ ut_asserteq(13184, compress_frame_buffer(uts, dev, false));
ut_assertok(check_copy_frame_buffer(uts, dev));
return 0;
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 09/56] console: Support a format string for stderr output
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (7 preceding siblings ...)
2025-03-28 13:05 ` [PATCH v2 08/56] video: Add a way to write a partial string to the console Simon Glass
@ 2025-03-28 13:05 ` Simon Glass
2025-03-28 13:05 ` [PATCH v2 10/56] test: video: Export the video-checking functions Simon Glass
` (47 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:05 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Alexander Sverdlin, Kever Yang, Mattijs Korpershoek,
Tom Rini
Add a console_printf_select_stderr() function so that it is not
necessary for the caller to process the format string.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
common/console.c | 18 ++++++++++++++++++
include/console.h | 15 +++++++++++++++
2 files changed, 33 insertions(+)
diff --git a/common/console.c b/common/console.c
index 3362a32a7a0..c6dfed6e201 100644
--- a/common/console.c
+++ b/common/console.c
@@ -359,6 +359,24 @@ void console_puts_select_stderr(bool serial_only, const char *s)
console_puts_select(stderr, serial_only, s);
}
+int console_printf_select_stderr(bool serial_only, const char *fmt, ...)
+{
+ char buf[CONFIG_SYS_PBSIZE];
+ va_list args;
+ int ret;
+
+ va_start(args, fmt);
+
+ /* For this to work, buf must be larger than anything we ever want to
+ * print.
+ */
+ ret = vscnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+ console_puts_select_stderr(serial_only, buf);
+
+ return ret;
+}
+
static void console_puts(int file, const char *s)
{
int i;
diff --git a/include/console.h b/include/console.h
index 57fdb0834c1..8d0d7bb8a4c 100644
--- a/include/console.h
+++ b/include/console.h
@@ -169,6 +169,21 @@ int console_announce_r(void);
*/
void console_puts_select_stderr(bool serial_only, const char *s);
+/**
+ * console_printf_select_stderr() - Output a formatted string to selected devs
+ *
+ * This writes to stderr only. It is useful for outputting errors. Note that it
+ * uses its own buffer, separate from the print buffer, to allow printing
+ * messages within console/stdio code
+ *
+ * @serial_only: true to output only to serial, false to output to everything
+ * else
+ * @fmt: Printf format string, followed by format arguments
+ * Return: number of characters written
+ */
+int console_printf_select_stderr(bool serial_only, const char *fmt, ...)
+ __attribute__ ((format (__printf__, 2, 3)));
+
/**
* console_clear() - Clear the console
*
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 10/56] test: video: Export the video-checking functions
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (8 preceding siblings ...)
2025-03-28 13:05 ` [PATCH v2 09/56] console: Support a format string for stderr output Simon Glass
@ 2025-03-28 13:05 ` Simon Glass
2025-03-28 13:05 ` [PATCH v2 11/56] video: Allow console output to be silenced Simon Glass
` (46 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:05 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Alexander Graf, Alper Nebi Yasak, Anatolij Gustschin,
Tom Rini
We want to check the display contents in expo tests, so move the two
needed functions to a new header file.
Rename them to have a video_ prefix.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
include/test/video.h | 45 +++++++++++
test/dm/video.c | 179 ++++++++++++++++++-------------------------
2 files changed, 121 insertions(+), 103 deletions(-)
create mode 100644 include/test/video.h
diff --git a/include/test/video.h b/include/test/video.h
new file mode 100644
index 00000000000..000fd708c86
--- /dev/null
+++ b/include/test/video.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2013 Google, Inc.
+ */
+
+#ifndef __TEST_VIDEO_H
+#define __TEST_VIDEO_H
+
+#include <stdbool.h>
+
+struct udevice;
+struct unit_test_state;
+
+/**
+ * video_compress_fb() - Compress the frame buffer and return its size
+ *
+ * We want to write tests which perform operations on the video console and
+ * check that the frame buffer ends up with the correct contents. But it is
+ * painful to store 'known good' images for comparison with the frame
+ * buffer. As an alternative, we can compress the frame buffer and check the
+ * size of the compressed data. This provides a pretty good level of
+ * certainty and the resulting tests need only check a single value.
+ *
+ * @uts: Test state
+ * @dev: Video device
+ * @use_copy: Use copy frame buffer if available
+ * Return: compressed size of the frame buffer, or -ve on error
+ */
+int video_compress_fb(struct unit_test_state *uts, struct udevice *dev,
+ bool use_copy);
+
+/**
+ * check_copy_frame_buffer() - Compare main frame buffer to copy
+ *
+ * If the copy frame buffer is enabled, this compares it to the main
+ * frame buffer. Normally they should have the same contents after a
+ * sync.
+ *
+ * @uts: Test state
+ * @dev: Video device
+ * Return: 0, or -ve on error
+ */
+int video_check_copy_fb(struct unit_test_state *uts, struct udevice *dev);
+
+#endif
diff --git a/test/dm/video.c b/test/dm/video.c
index a9b2482631f..737ab915f41 100644
--- a/test/dm/video.c
+++ b/test/dm/video.c
@@ -19,6 +19,7 @@
#include <dm/uclass-internal.h>
#include <test/test.h>
#include <test/ut.h>
+#include <test/video.h>
/*
* These tests use the standard sandbox frame buffer, the resolution of which
@@ -44,24 +45,8 @@ static int dm_test_video_base(struct unit_test_state *uts)
}
DM_TEST(dm_test_video_base, UTF_SCAN_PDATA | UTF_SCAN_FDT);
-/**
- * compress_frame_buffer() - Compress the frame buffer and return its size
- *
- * We want to write tests which perform operations on the video console and
- * check that the frame buffer ends up with the correct contents. But it is
- * painful to store 'known good' images for comparison with the frame
- * buffer. As an alternative, we can compress the frame buffer and check the
- * size of the compressed data. This provides a pretty good level of
- * certainty and the resulting tests need only check a single value.
- *
- * @uts: Test state
- * @dev: Video device
- * @use_copy: Use copy frame buffer if available
- * Return: compressed size of the frame buffer, or -ve on error
- */
-static int compress_frame_buffer(struct unit_test_state *uts,
- struct udevice *dev,
- bool use_copy)
+int video_compress_fb(struct unit_test_state *uts, struct udevice *dev,
+ bool use_copy)
{
struct video_priv *priv = dev_get_uclass_priv(dev);
uint destlen;
@@ -86,19 +71,7 @@ static int compress_frame_buffer(struct unit_test_state *uts,
return destlen;
}
-/**
- * check_copy_frame_buffer() - Compare main frame buffer to copy
- *
- * If the copy frame buffer is enabled, this compares it to the main
- * frame buffer. Normally they should have the same contents after a
- * sync.
- *
- * @uts: Test state
- * @dev: Video device
- * Return: 0, or -ve on error
- */
-static int check_copy_frame_buffer(struct unit_test_state *uts,
- struct udevice *dev)
+int video_check_copy_fb(struct unit_test_state *uts, struct udevice *dev)
{
struct video_priv *priv = dev_get_uclass_priv(dev);
@@ -174,31 +147,31 @@ static int dm_test_video_text(struct unit_test_state *uts)
ut_assertok(video_get_nologo(uts, &dev));
ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
ut_assertok(vidconsole_select_font(con, "8x16", 0));
- ut_asserteq(46, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(46, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
vidconsole_putc_xy(con, 0, 0, 'a');
- ut_asserteq(79, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(79, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
vidconsole_putc_xy(con, 0, 0, ' ');
- ut_asserteq(46, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(46, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
for (i = 0; i < 20; i++)
vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
- ut_asserteq(273, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(273, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
vidconsole_set_row(con, 0, WHITE);
- ut_asserteq(46, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(46, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
for (i = 0; i < 20; i++)
vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
- ut_asserteq(273, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(273, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
return 0;
}
@@ -216,31 +189,31 @@ static int dm_test_video_text_12x22(struct unit_test_state *uts)
ut_assertok(video_get_nologo(uts, &dev));
ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
ut_assertok(vidconsole_select_font(con, "12x22", 0));
- ut_asserteq(46, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(46, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
vidconsole_putc_xy(con, 0, 0, 'a');
- ut_asserteq(89, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(89, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
vidconsole_putc_xy(con, 0, 0, ' ');
- ut_asserteq(46, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(46, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
for (i = 0; i < 20; i++)
vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
- ut_asserteq(363, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(363, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
vidconsole_set_row(con, 0, WHITE);
- ut_asserteq(46, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(46, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
for (i = 0; i < 20; i++)
vidconsole_putc_xy(con, VID_TO_POS(i * 8), 0, ' ' + i);
- ut_asserteq(363, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(363, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
return 0;
}
@@ -257,8 +230,8 @@ static int dm_test_video_chars(struct unit_test_state *uts)
ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
ut_assertok(vidconsole_select_font(con, "8x16", 0));
vidconsole_put_string(con, test_string);
- ut_asserteq(466, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(466, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
return 0;
}
@@ -279,24 +252,24 @@ static int dm_test_video_ansi(struct unit_test_state *uts)
/* reference clear: */
video_clear(con->parent);
video_sync(con->parent, false);
- ut_asserteq(46, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(46, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
/* test clear escape sequence: [2J */
vidconsole_put_string(con, "A\tB\tC"ANSI_ESC"[2J");
- ut_asserteq(46, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(46, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
/* test set-cursor: [%d;%df */
vidconsole_put_string(con, "abc"ANSI_ESC"[2;2fab"ANSI_ESC"[4;4fcd");
- ut_asserteq(143, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(143, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
/* test colors (30-37 fg color, 40-47 bg color) */
vidconsole_put_string(con, ANSI_ESC"[30;41mfoo"); /* black on red */
vidconsole_put_string(con, ANSI_ESC"[33;44mbar"); /* yellow on blue */
- ut_asserteq(272, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(272, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
return 0;
}
@@ -328,28 +301,28 @@ static int check_vidconsole_output(struct unit_test_state *uts, int rot,
ut_assertok(video_get_nologo(uts, &dev));
ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
ut_assertok(vidconsole_select_font(con, "8x16", 0));
- ut_asserteq(46, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(46, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
/* Check display wrap */
for (i = 0; i < 120; i++)
vidconsole_put_char(con, 'A' + i % 50);
- ut_asserteq(wrap_size, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(wrap_size, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
/* Check display scrolling */
for (i = 0; i < SCROLL_LINES; i++) {
vidconsole_put_char(con, 'A' + i % 50);
vidconsole_put_char(con, '\n');
}
- ut_asserteq(scroll_size, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(scroll_size, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
/* If we scroll enough, the screen becomes blank again */
for (i = 0; i < SCROLL_LINES; i++)
vidconsole_put_char(con, '\n');
- ut_asserteq(46, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(46, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
return 0;
}
@@ -423,8 +396,8 @@ static int dm_test_video_bmp(struct unit_test_state *uts)
ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
- ut_asserteq(1368, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(1368, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
return 0;
}
@@ -443,8 +416,8 @@ static int dm_test_video_bmp8(struct unit_test_state *uts)
ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
- ut_asserteq(1247, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(1247, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
return 0;
}
@@ -467,8 +440,8 @@ static int dm_test_video_bmp16(struct unit_test_state *uts)
&src_len));
ut_assertok(video_bmp_display(dev, dst, 0, 0, false));
- ut_asserteq(3700, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(3700, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
return 0;
}
@@ -491,8 +464,8 @@ static int dm_test_video_bmp24(struct unit_test_state *uts)
&src_len));
ut_assertok(video_bmp_display(dev, dst, 0, 0, false));
- ut_asserteq(3656, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(3656, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
return 0;
}
@@ -515,8 +488,8 @@ static int dm_test_video_bmp24_32(struct unit_test_state *uts)
&src_len));
ut_assertok(video_bmp_display(dev, dst, 0, 0, false));
- ut_asserteq(6827, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(6827, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
return 0;
}
@@ -534,8 +507,8 @@ static int dm_test_video_bmp32(struct unit_test_state *uts)
ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
- ut_asserteq(2024, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(2024, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
return 0;
}
@@ -551,8 +524,8 @@ static int dm_test_video_bmp_comp(struct unit_test_state *uts)
ut_assertok(read_file(uts, "tools/logos/denx-comp.bmp", &addr));
ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
- ut_asserteq(1368, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(1368, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
return 0;
}
@@ -571,8 +544,8 @@ static int dm_test_video_comp_bmp32(struct unit_test_state *uts)
ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
- ut_asserteq(2024, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(2024, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
return 0;
}
@@ -591,8 +564,8 @@ static int dm_test_video_comp_bmp8(struct unit_test_state *uts)
ut_assertok(read_file(uts, "tools/logos/denx.bmp", &addr));
ut_assertok(video_bmp_display(dev, addr, 0, 0, false));
- ut_asserteq(1247, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(1247, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
return 0;
}
@@ -608,8 +581,8 @@ static int dm_test_video_truetype(struct unit_test_state *uts)
ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
vidconsole_put_string(con, test_string);
vidconsole_put_stringn(con, test_string, 30);
- ut_asserteq(13184, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(13184, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
return 0;
}
@@ -630,8 +603,8 @@ static int dm_test_video_truetype_scroll(struct unit_test_state *uts)
ut_assertok(video_get_nologo(uts, &dev));
ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
vidconsole_put_string(con, test_string);
- ut_asserteq(34287, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(34287, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
return 0;
}
@@ -652,8 +625,8 @@ static int dm_test_video_truetype_bs(struct unit_test_state *uts)
ut_assertok(video_get_nologo(uts, &dev));
ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
vidconsole_put_string(con, test_string);
- ut_asserteq(29471, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(29471, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
return 0;
}
@@ -691,8 +664,8 @@ static int dm_test_video_copy(struct unit_test_state *uts)
vidconsole_put_string(con, test_string);
vidconsole_put_string(con, test_string);
- ut_asserteq(6678, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(6678, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
/*
* Secretly clear the hardware frame buffer, but in a different
@@ -716,8 +689,8 @@ static int dm_test_video_copy(struct unit_test_state *uts)
vidconsole_put_string(con, test_string);
vidconsole_put_string(con, test_string);
video_sync(dev, true);
- ut_asserteq(7589, compress_frame_buffer(uts, dev, false));
- ut_asserteq(7704, compress_frame_buffer(uts, dev, true));
+ ut_asserteq(7589, video_compress_fb(uts, dev, false));
+ ut_asserteq(7704, video_compress_fb(uts, dev, true));
return 0;
}
@@ -772,8 +745,8 @@ static int dm_test_video_damage(struct unit_test_state *uts)
ut_asserteq(0, priv->damage.xend);
ut_asserteq(0, priv->damage.yend);
- ut_asserteq(7339, compress_frame_buffer(uts, dev, false));
- ut_assertok(check_copy_frame_buffer(uts, dev));
+ ut_asserteq(7339, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 11/56] video: Allow console output to be silenced
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (9 preceding siblings ...)
2025-03-28 13:05 ` [PATCH v2 10/56] test: video: Export the video-checking functions Simon Glass
@ 2025-03-28 13:05 ` Simon Glass
2025-03-28 13:05 ` [PATCH v2 12/56] video: Add a function to draw a rectangle Simon Glass
` (45 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:05 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Alexander Graf, Alper Nebi Yasak, Anatolij Gustschin,
Peter Robinson, Tom Rini
When using expo we want to be able to control the information on the
display and avoid other messages (such as USB scanning) appearing.
Add a 'quiet' flag for the console, to help with this.
The test is a little messy since stdio is still using the original
vidconsole create on start-up. So take care to use the same.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
drivers/video/vidconsole-uclass.c | 13 +++++++++++
include/video_console.h | 10 +++++++++
test/dm/video.c | 37 +++++++++++++++++++++++++++++++
3 files changed, 60 insertions(+)
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
index fa329bd1b37..6ba62ec348e 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -532,8 +532,11 @@ int vidconsole_put_string(struct udevice *dev, const char *str)
static void vidconsole_putc(struct stdio_dev *sdev, const char ch)
{
struct udevice *dev = sdev->priv;
+ struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
int ret;
+ if (priv->quiet)
+ return;
ret = vidconsole_put_char(dev, ch);
if (ret) {
#ifdef DEBUG
@@ -551,8 +554,11 @@ static void vidconsole_putc(struct stdio_dev *sdev, const char ch)
static void vidconsole_puts(struct stdio_dev *sdev, const char *s)
{
struct udevice *dev = sdev->priv;
+ struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
int ret;
+ if (priv->quiet)
+ return;
ret = vidconsole_put_string(dev, s);
if (ret) {
#ifdef DEBUG
@@ -794,3 +800,10 @@ void vidconsole_position_cursor(struct udevice *dev, unsigned col, unsigned row)
y = min_t(short, row * priv->y_charsize, vid_priv->ysize - 1);
vidconsole_set_cursor_pos(dev, x, y);
}
+
+void vidconsole_set_quiet(struct udevice *dev, bool quiet)
+{
+ struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
+
+ priv->quiet = quiet;
+}
diff --git a/include/video_console.h b/include/video_console.h
index e4fc776e2d3..8f3f58f3aa9 100644
--- a/include/video_console.h
+++ b/include/video_console.h
@@ -53,6 +53,7 @@ enum {
* @row_saved: Saved Y position in pixels (0=top)
* @escape_buf: Buffer to accumulate escape sequence
* @utf8_buf: Buffer to accumulate UTF-8 byte sequence
+ * @quiet: Suppress all output from stdio
*/
struct vidconsole_priv {
struct stdio_dev sdev;
@@ -77,6 +78,7 @@ struct vidconsole_priv {
int col_saved;
char escape_buf[32];
char utf8_buf[5];
+ bool quiet;
};
/**
@@ -584,4 +586,12 @@ void vidconsole_list_fonts(struct udevice *dev);
*/
int vidconsole_get_font_size(struct udevice *dev, const char **name, uint *sizep);
+/**
+ * vidconsole_set_quiet() - Select whether the console should output stdio
+ *
+ * @dev: vidconsole device
+ * @quiet: true to suppress stdout/stderr output, false to enable it
+ */
+void vidconsole_set_quiet(struct udevice *dev, bool quiet);
+
#endif
diff --git a/test/dm/video.c b/test/dm/video.c
index 737ab915f41..dd06b2f58e8 100644
--- a/test/dm/video.c
+++ b/test/dm/video.c
@@ -17,6 +17,7 @@
#include <asm/sdl.h>
#include <dm/test.h>
#include <dm/uclass-internal.h>
+#include <test/lib.h>
#include <test/test.h>
#include <test/ut.h>
#include <test/video.h>
@@ -865,3 +866,39 @@ static int dm_test_font_measure(struct unit_test_state *uts)
return 0;
}
DM_TEST(dm_test_font_measure, UTF_SCAN_FDT);
+
+/* Test silencing the video console */
+static int dm_test_video_silence(struct unit_test_state *uts)
+{
+ struct udevice *dev, *con;
+ struct stdio_dev *sdev;
+
+ ut_assertok(uclass_first_device_err(UCLASS_VIDEO, &dev));
+
+ /*
+ * use the old console device from before when dm_test_pre_run() was
+ * called, since that is what is in stdio / console
+ */
+ sdev = stdio_get_by_name("vidconsole");
+ ut_assertnonnull(sdev);
+ con = sdev->priv;
+ ut_assertok(vidconsole_clear_and_reset(con));
+ ut_unsilence_console(uts);
+
+ printf("message 1: console\n");
+ vidconsole_put_string(con, "message 1: video\n");
+
+ vidconsole_set_quiet(con, true);
+ printf("second message: console\n");
+ vidconsole_put_string(con, "second message: video\n");
+
+ vidconsole_set_quiet(con, false);
+ printf("final message: console\n");
+ vidconsole_put_string(con, "final message: video\n");
+
+ ut_asserteq(3892, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
+
+ return 0;
+}
+DM_TEST(dm_test_video_silence, UTF_SCAN_FDT);
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 12/56] video: Add a function to draw a rectangle
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (10 preceding siblings ...)
2025-03-28 13:05 ` [PATCH v2 11/56] video: Allow console output to be silenced Simon Glass
@ 2025-03-28 13:05 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 13/56] expo: Add CLI context to the expo Simon Glass
` (44 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:05 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Alexander Graf, Alper Nebi Yasak, Anatolij Gustschin,
Devarsh Thakkar, Miquel Raynal, Peter Robinson, Tom Rini
Provide a way to draw an unfilled box of a certain width. This is useful
for grouping menu items together.
Add a comment showing how to see the copy-framebuffer, for testing.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
drivers/video/video-uclass.c | 36 ++++++++++++++++++++++++++++++++++++
include/video.h | 19 ++++++++++++++++++-
test/dm/video.c | 21 +++++++++++++++++++++
3 files changed, 75 insertions(+), 1 deletion(-)
diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c
index db40744c196..780b2bc6125 100644
--- a/drivers/video/video-uclass.c
+++ b/drivers/video/video-uclass.c
@@ -26,6 +26,7 @@
#ifdef CONFIG_SANDBOX
#include <asm/sdl.h>
#endif
+#include "vidconsole_internal.h"
/*
* Theory of operation:
@@ -216,6 +217,40 @@ int video_fill_part(struct udevice *dev, int xstart, int ystart, int xend,
return 0;
}
+int video_draw_box(struct udevice *dev, int x0, int y0, int x1, int y1,
+ int width, u32 colour)
+{
+ struct video_priv *priv = dev_get_uclass_priv(dev);
+ int pbytes = VNBYTES(priv->bpix);
+ void *start, *line;
+ int pixels = x1 - x0;
+ int row;
+
+ start = priv->fb + y0 * priv->line_length;
+ start += x0 * pbytes;
+ line = start;
+ for (row = y0; row < y1; row++) {
+ void *ptr = line;
+ int i;
+
+ for (i = 0; i < width; i++)
+ fill_pixel_and_goto_next(&ptr, colour, pbytes, pbytes);
+ if (row < y0 + width || row >= y1 - width) {
+ for (i = 0; i < pixels - width * 2; i++)
+ fill_pixel_and_goto_next(&ptr, colour, pbytes,
+ pbytes);
+ } else {
+ ptr += (pixels - width * 2) * pbytes;
+ }
+ for (i = 0; i < width; i++)
+ fill_pixel_and_goto_next(&ptr, colour, pbytes, pbytes);
+ line += priv->line_length;
+ }
+ video_damage(dev, x0, y0, x1 - x0, y1 - y0);
+
+ return 0;
+}
+
int video_reserve_from_bloblist(struct video_handoff *ho)
{
if (!ho->fb || ho->size == 0)
@@ -479,6 +514,7 @@ int video_sync(struct udevice *vid, bool force)
video_flush_dcache(vid, true);
#if defined(CONFIG_VIDEO_SANDBOX_SDL)
+ /* to see the copy framebuffer, use priv->copy_fb */
sandbox_sdl_sync(priv->fb);
#endif
priv->last_sync = get_timer(0);
diff --git a/include/video.h b/include/video.h
index 0ec6b1ca289..9ea6b676463 100644
--- a/include/video.h
+++ b/include/video.h
@@ -249,7 +249,7 @@ int video_fill(struct udevice *dev, u32 colour);
/**
* video_fill_part() - Erase a region
*
- * Erase a rectangle of the display within the given bounds.
+ * Erase a rectangle on the display within the given bounds
*
* @dev: Device to update
* @xstart: X start position in pixels from the left
@@ -262,6 +262,23 @@ int video_fill(struct udevice *dev, u32 colour);
int video_fill_part(struct udevice *dev, int xstart, int ystart, int xend,
int yend, u32 colour);
+/**
+ * video_draw_box() - Draw a box
+ *
+ * Draw a rectangle on the display within the given bounds
+ *
+ * @dev: Device to update
+ * @x0: X start position in pixels from the left
+ * @y0: Y start position in pixels from the top
+ * @x1: X end position in pixels from the left
+ * @y1: Y end position in pixels from the top
+ * @width: width in pixels
+ * @colour: Value to write
+ * Return: 0 if OK, -ENOSYS if the display depth is not supported
+ */
+int video_draw_box(struct udevice *dev, int x0, int y0, int x1, int y1,
+ int width, u32 colour);
+
/**
* video_sync() - Sync a device's frame buffer with its hardware
*
diff --git a/test/dm/video.c b/test/dm/video.c
index dd06b2f58e8..ecf74605b5c 100644
--- a/test/dm/video.c
+++ b/test/dm/video.c
@@ -902,3 +902,24 @@ static int dm_test_video_silence(struct unit_test_state *uts)
return 0;
}
DM_TEST(dm_test_video_silence, UTF_SCAN_FDT);
+
+/* test drawing a box */
+static int dm_test_video_box(struct unit_test_state *uts)
+{
+ struct video_priv *priv;
+ struct udevice *dev;
+
+ ut_assertok(video_get_nologo(uts, &dev));
+ priv = dev_get_uclass_priv(dev);
+ video_draw_box(dev, 100, 100, 200, 200, 3,
+ video_index_to_colour(priv, VID_LIGHT_BLUE));
+ video_draw_box(dev, 300, 100, 400, 200, 1,
+ video_index_to_colour(priv, VID_MAGENTA));
+ video_draw_box(dev, 500, 100, 600, 200, 20,
+ video_index_to_colour(priv, VID_LIGHT_RED));
+ ut_asserteq(133, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
+
+ return 0;
+}
+DM_TEST(dm_test_video_box, UTF_SCAN_FDT);
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 13/56] expo: Add CLI context to the expo
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (11 preceding siblings ...)
2025-03-28 13:05 ` [PATCH v2 12/56] video: Add a function to draw a rectangle Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 14/56] expo: Add a function to poll for input Simon Glass
` (43 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Quentin Schulz, Rasmus Villemoes, Stefan Roese,
Tom Rini
An expo generally needs to keep track of the keyboard state while it is
running, so move the context into struct expo
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
| 9 +++------
boot/cedit.c | 8 +++-----
boot/expo.c | 1 +
include/expo.h | 2 ++
4 files changed, 9 insertions(+), 11 deletions(-)
--git a/boot/bootflow_menu.c b/boot/bootflow_menu.c
index 9d0dc352f97..43125e15832 100644
--- a/boot/bootflow_menu.c
+++ b/boot/bootflow_menu.c
@@ -178,7 +178,6 @@ int bootflow_menu_apply_theme(struct expo *exp, ofnode node)
int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
struct bootflow **bflowp)
{
- struct cli_ch_state s_cch, *cch = &s_cch;
struct bootflow *sel_bflow;
struct udevice *dev;
struct expo *exp;
@@ -186,8 +185,6 @@ int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
bool done;
int ret;
- cli_ch_init(cch);
-
sel_bflow = NULL;
*bflowp = NULL;
@@ -225,16 +222,16 @@ int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
if (ret)
break;
- ichar = cli_ch_process(cch, 0);
+ ichar = cli_ch_process(&exp->cch, 0);
if (!ichar) {
while (!ichar && !tstc()) {
schedule();
mdelay(2);
- ichar = cli_ch_process(cch, -ETIMEDOUT);
+ ichar = cli_ch_process(&exp->cch, -ETIMEDOUT);
}
if (!ichar) {
ichar = getchar();
- ichar = cli_ch_process(cch, ichar);
+ ichar = cli_ch_process(&exp->cch, ichar);
}
}
diff --git a/boot/cedit.c b/boot/cedit.c
index d69290c172e..50d63c8258d 100644
--- a/boot/cedit.c
+++ b/boot/cedit.c
@@ -151,14 +151,12 @@ int cedit_prepare(struct expo *exp, struct video_priv **vid_privp,
int cedit_run(struct expo *exp)
{
- struct cli_ch_state s_cch, *cch = &s_cch;
struct video_priv *vid_priv;
uint scene_id;
struct scene *scn;
bool done, save;
int ret;
- cli_ch_init(cch);
ret = cedit_prepare(exp, &vid_priv, &scn);
if (ret < 0)
return log_msg_ret("prep", ret);
@@ -174,16 +172,16 @@ int cedit_run(struct expo *exp)
if (ret)
break;
- ichar = cli_ch_process(cch, 0);
+ ichar = cli_ch_process(&exp->cch, 0);
if (!ichar) {
while (!ichar && !tstc()) {
schedule();
mdelay(2);
- ichar = cli_ch_process(cch, -ETIMEDOUT);
+ ichar = cli_ch_process(&exp->cch, -ETIMEDOUT);
}
if (!ichar) {
ichar = getchar();
- ichar = cli_ch_process(cch, ichar);
+ ichar = cli_ch_process(&exp->cch, ichar);
}
}
diff --git a/boot/expo.c b/boot/expo.c
index 8ce645e5a8f..9c042f16fe7 100644
--- a/boot/expo.c
+++ b/boot/expo.c
@@ -30,6 +30,7 @@ int expo_new(const char *name, void *priv, struct expo **expp)
INIT_LIST_HEAD(&exp->scene_head);
INIT_LIST_HEAD(&exp->str_head);
exp->next_id = EXPOID_BASE_ID;
+ cli_ch_init(&exp->cch);
*expp = exp;
diff --git a/include/expo.h b/include/expo.h
index 3c383d2e2ee..b3b9c0b8872 100644
--- a/include/expo.h
+++ b/include/expo.h
@@ -108,6 +108,7 @@ struct expo_theme {
* @theme: Information about fonts styles, etc.
* @scene_head: List of scenes
* @str_head: list of strings
+ * @cch: Keyboard context for input
*/
struct expo {
char *name;
@@ -122,6 +123,7 @@ struct expo {
struct expo_theme theme;
struct list_head scene_head;
struct list_head str_head;
+ struct cli_ch_state cch;
};
/**
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 14/56] expo: Add a function to poll for input
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (12 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 13/56] expo: Add CLI context to the expo Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 15/56] expo: Destroy the cedit expo when done Simon Glass
` (42 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Guillaume La Roque, Heinrich Schuchardt,
Igor Opaniuk, Mattijs Korpershoek, Quentin Schulz,
Rasmus Villemoes, Stefan Roese, Tom Rini
Both bootflow_menu and cedit use similar logic to poll an expo. Move
this into the expo library so the code can be shared.
Update bootflow_menu_run() to return -EPIPE when the user quits without
choosing anything, since -EAGAIN is ambiguous and elsewhere means that
there is no input yet.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
| 41 ++++-------------------------------------
boot/cedit.c | 35 +++--------------------------------
boot/expo.c | 38 ++++++++++++++++++++++++++++++++++++++
cmd/bootflow.c | 2 +-
include/bootflow.h | 2 +-
include/expo.h | 13 +++++++++++++
6 files changed, 60 insertions(+), 71 deletions(-)
--git a/boot/bootflow_menu.c b/boot/bootflow_menu.c
index 43125e15832..e3a27f16daa 100644
--- a/boot/bootflow_menu.c
+++ b/boot/bootflow_menu.c
@@ -216,39 +216,8 @@ int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
done = false;
do {
struct expo_action act;
- int ichar, key;
- ret = expo_render(exp);
- if (ret)
- break;
-
- ichar = cli_ch_process(&exp->cch, 0);
- if (!ichar) {
- while (!ichar && !tstc()) {
- schedule();
- mdelay(2);
- ichar = cli_ch_process(&exp->cch, -ETIMEDOUT);
- }
- if (!ichar) {
- ichar = getchar();
- ichar = cli_ch_process(&exp->cch, ichar);
- }
- }
-
- key = 0;
- if (ichar) {
- key = bootmenu_conv_key(ichar);
- if (key == BKEY_NONE)
- key = ichar;
- }
- if (!key)
- continue;
-
- ret = expo_send_key(exp, key);
- if (ret)
- break;
-
- ret = expo_action_get(exp, &act);
+ ret = expo_poll(exp, &act);
if (!ret) {
switch (act.type) {
case EXPOACT_SELECT:
@@ -256,17 +225,15 @@ int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
done = true;
break;
case EXPOACT_QUIT:
- done = true;
- break;
+ return -EPIPE;
default:
break;
}
+ } else if (ret != -EPIPE && ret != -EAGAIN) {
+ LOGR("bmr", ret);
}
} while (!done);
- if (ret)
- return log_msg_ret("end", ret);
-
if (sel_id) {
struct bootflow *bflow;
int i;
diff --git a/boot/cedit.c b/boot/cedit.c
index 50d63c8258d..9baef39a0cd 100644
--- a/boot/cedit.c
+++ b/boot/cedit.c
@@ -166,39 +166,8 @@ int cedit_run(struct expo *exp)
save = false;
do {
struct expo_action act;
- int ichar, key;
- ret = expo_render(exp);
- if (ret)
- break;
-
- ichar = cli_ch_process(&exp->cch, 0);
- if (!ichar) {
- while (!ichar && !tstc()) {
- schedule();
- mdelay(2);
- ichar = cli_ch_process(&exp->cch, -ETIMEDOUT);
- }
- if (!ichar) {
- ichar = getchar();
- ichar = cli_ch_process(&exp->cch, ichar);
- }
- }
-
- key = 0;
- if (ichar) {
- key = bootmenu_conv_key(ichar);
- if (key == BKEY_NONE || key >= BKEY_FIRST_EXTRA)
- key = ichar;
- }
- if (!key)
- continue;
-
- ret = expo_send_key(exp, key);
- if (ret)
- break;
-
- ret = expo_action_get(exp, &act);
+ ret = expo_poll(exp, &act);
if (!ret) {
switch (act.type) {
case EXPOACT_POINT_OBJ:
@@ -233,6 +202,8 @@ int cedit_run(struct expo *exp)
default:
break;
}
+ } else if (ret != -EAGAIN) {
+ LOGR("cep", ret);
}
} while (!done);
diff --git a/boot/expo.c b/boot/expo.c
index 9c042f16fe7..ba052df932c 100644
--- a/boot/expo.c
+++ b/boot/expo.c
@@ -10,8 +10,12 @@
#include <dm.h>
#include <expo.h>
+#include <log.h>
#include <malloc.h>
+#include <menu.h>
#include <video.h>
+#include <watchdog.h>
+#include <linux/delay.h>
#include "scene_internal.h"
int expo_new(const char *name, void *priv, struct expo **expp)
@@ -286,3 +290,37 @@ int expo_iter_scene_objs(struct expo *exp, expo_scene_obj_iterator iter,
return 0;
}
+
+int expo_poll(struct expo *exp, struct expo_action *act)
+{
+ int ichar, key;
+
+ LOGR("ere", expo_render(exp));
+
+ ichar = cli_ch_process(&exp->cch, 0);
+ if (!ichar) {
+ while (!ichar && !tstc()) {
+ schedule();
+ mdelay(2);
+ ichar = cli_ch_process(&exp->cch, -ETIMEDOUT);
+ }
+ if (!ichar) {
+ ichar = getchar();
+ ichar = cli_ch_process(&exp->cch, ichar);
+ }
+ }
+
+ key = 0;
+ if (ichar) {
+ key = bootmenu_conv_key(ichar);
+ if (key == BKEY_NONE || key >= BKEY_FIRST_EXTRA)
+ key = ichar;
+ }
+ if (!key)
+ return -EAGAIN;
+
+ LOGR("epk", expo_send_key(exp, key));
+ LOGR("eag", expo_action_get(exp, act));
+
+ return 0;
+}
diff --git a/cmd/bootflow.c b/cmd/bootflow.c
index 0163129deba..6189ab7fa40 100644
--- a/cmd/bootflow.c
+++ b/cmd/bootflow.c
@@ -110,7 +110,7 @@ __maybe_unused static int bootflow_handle_menu(struct bootstd_priv *std,
ret = bootflow_menu_run(std, text_mode, &bflow);
if (ret) {
- if (ret == -EAGAIN) {
+ if (ret == -EPIPE) {
printf("Nothing chosen\n");
std->cur_bootflow = NULL;
} else {
diff --git a/include/bootflow.h b/include/bootflow.h
index d988bc9355b..ef1d1a75ded 100644
--- a/include/bootflow.h
+++ b/include/bootflow.h
@@ -509,7 +509,7 @@ int bootflow_menu_apply_theme(struct expo *exp, ofnode node);
* @std: Bootstd information
* @text_mode: Uses a text-based menu suitable for a serial port
* @bflowp: Returns chosen bootflow (set to NULL if nothing is chosen)
- * @return 0 if an option was chosen, -EAGAIN if nothing was chosen, -ve on
+ * @return 0 if an option was chosen, -EPIPE if nothing was chosen, -ve on
* error
*/
int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
diff --git a/include/expo.h b/include/expo.h
index b3b9c0b8872..63452bbdd6a 100644
--- a/include/expo.h
+++ b/include/expo.h
@@ -772,4 +772,17 @@ int expo_build(ofnode root, struct expo **expp);
*/
int cb_expo_build(struct expo **expp);
+/**
+ * expo_poll() - render an expo and see if the user takes an action
+ *
+ * Thsi calls expo_render() and then checks for a keypress. If there is one, it
+ * is processed and the resulting action returned, if any
+ *
+ * @exp: Expo to poll
+ * @act: Returns action on success
+ * Return: 0 if an action was obtained, -EAGAIN if not, other error if something
+ * went wrong
+ */
+int expo_poll(struct expo *exp, struct expo_action *act);
+
#endif /*__EXPO_H */
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 15/56] expo: Destroy the cedit expo when done
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (13 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 14/56] expo: Add a function to poll for input Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 16/56] vidconsole: Avoid kerning against an unrelated character Simon Glass
` (41 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Tom Rini
Once 'cedit run' is completed, destroy the expo so that a fresh one is
used for any future editing.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
cmd/cedit.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/cmd/cedit.c b/cmd/cedit.c
index b0eca7b4daf..2e15b063462 100644
--- a/cmd/cedit.c
+++ b/cmd/cedit.c
@@ -285,6 +285,8 @@ static int do_cedit_run(struct cmd_tbl *cmdtp, int flag, int argc,
log_err("Failed (err=%dE)\n", ret);
return CMD_RET_FAILURE;
}
+ expo_destroy(cur_exp);
+ cur_exp = NULL;
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 16/56] vidconsole: Avoid kerning against an unrelated character
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (14 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 15/56] expo: Destroy the cedit expo when done Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 17/56] expo: Create a rendering test for cedit Simon Glass
` (40 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Alexander Graf, Alper Nebi Yasak, Anatolij Gustschin,
Bin Meng, Peter Robinson, Tom Rini
When the cursor position changes, kerning should not be used for the
next character, since it can make the first displayed character shuffle
left or right a bit.
Clear the kern character when setting the position.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
drivers/video/console_truetype.c | 2 ++
drivers/video/vidconsole-uclass.c | 3 +++
2 files changed, 5 insertions(+)
diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c
index 2e3e6f07112..6d2c2c2e177 100644
--- a/drivers/video/console_truetype.c
+++ b/drivers/video/console_truetype.c
@@ -490,10 +490,12 @@ static int console_truetype_backspace(struct udevice *dev)
static int console_truetype_entry_start(struct udevice *dev)
{
+ struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
struct console_tt_priv *priv = dev_get_priv(dev);
/* A new input line has start, so clear our history */
priv->pos_ptr = 0;
+ vc_priv->last_ch = 0;
return 0;
}
diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c
index 6ba62ec348e..f1b2d61bd8f 100644
--- a/drivers/video/vidconsole-uclass.c
+++ b/drivers/video/vidconsole-uclass.c
@@ -127,6 +127,9 @@ void vidconsole_set_cursor_pos(struct udevice *dev, int x, int y)
priv->xcur_frac = VID_TO_POS(x);
priv->xstart_frac = priv->xcur_frac;
priv->ycur = y;
+
+ /* make sure not to kern against the previous character */
+ priv->last_ch = 0;
vidconsole_entry_start(dev);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 17/56] expo: Create a rendering test for cedit
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (15 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 16/56] vidconsole: Avoid kerning against an unrelated character Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 18/56] expo: Move cedit-state fields into expo Simon Glass
` (39 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Mattijs Korpershoek, Tom Rini
Add a test to check that the cedit renders as expected.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
test/boot/cedit.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/test/boot/cedit.c b/test/boot/cedit.c
index 4d1b99bc2ea..df191a09f89 100644
--- a/test/boot/cedit.c
+++ b/test/boot/cedit.c
@@ -5,11 +5,13 @@
*/
#include <cedit.h>
+#include <dm.h>
#include <env.h>
#include <expo.h>
#include <mapmem.h>
#include <dm/ofnode.h>
#include <test/ut.h>
+#include <test/video.h>
#include "bootstd_common.h"
#include <test/cedit-test.h>
#include "../../boot/scene_internal.h"
@@ -220,3 +222,27 @@ static int cedit_cmos(struct unit_test_state *uts)
return 0;
}
BOOTSTD_TEST(cedit_cmos, UTF_CONSOLE);
+
+/* Check the cedit displays correctely */
+static int cedit_render(struct unit_test_state *uts)
+{
+ struct video_priv *vid_priv;
+ extern struct expo *cur_exp;
+ struct udevice *dev;
+ struct scene *scn;
+ struct expo *exp;
+
+ ut_assertok(run_command("cedit load hostfs - cedit.dtb", 0));
+
+ exp = cur_exp;
+ ut_assertok(uclass_first_device_err(UCLASS_VIDEO, &dev));
+ ut_asserteq(ID_SCENE1, cedit_prepare(exp, &vid_priv, &scn));
+ ut_assertok(expo_render(exp));
+ ut_asserteq(4929, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
+ expo_destroy(exp);
+ cur_exp = NULL;
+
+ return 0;
+}
+BOOTSTD_TEST(cedit_render, UTF_DM | UTF_SCAN_FDT);
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 18/56] expo: Move cedit-state fields into expo
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (16 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 17/56] expo: Create a rendering test for cedit Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 19/56] expo: Test some cedit actions Simon Glass
` (38 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Rasmus Villemoes, Stefan Roese, Tom Rini
Move the boolean flags into struct expo so that the state can be
maintained over function calls.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
boot/cedit.c | 17 ++++++++---------
include/expo.h | 4 ++++
2 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/boot/cedit.c b/boot/cedit.c
index 9baef39a0cd..3703538e5dc 100644
--- a/boot/cedit.c
+++ b/boot/cedit.c
@@ -154,7 +154,6 @@ int cedit_run(struct expo *exp)
struct video_priv *vid_priv;
uint scene_id;
struct scene *scn;
- bool done, save;
int ret;
ret = cedit_prepare(exp, &vid_priv, &scn);
@@ -162,8 +161,8 @@ int cedit_run(struct expo *exp)
return log_msg_ret("prep", ret);
scene_id = ret;
- done = false;
- save = false;
+ exp->done = false;
+ exp->save = false;
do {
struct expo_action act;
@@ -179,11 +178,11 @@ int cedit_run(struct expo *exp)
cedit_arange(exp, vid_priv, scene_id);
switch (scn->highlight_id) {
case EXPOID_SAVE:
- done = true;
- save = true;
+ exp->done = true;
+ exp->save = true;
break;
case EXPOID_DISCARD:
- done = true;
+ exp->done = true;
break;
}
break;
@@ -197,7 +196,7 @@ int cedit_run(struct expo *exp)
break;
case EXPOACT_QUIT:
log_debug("quitting\n");
- done = true;
+ exp->done = true;
break;
default:
break;
@@ -205,11 +204,11 @@ int cedit_run(struct expo *exp)
} else if (ret != -EAGAIN) {
LOGR("cep", ret);
}
- } while (!done);
+ } while (!exp->done);
if (ret)
return log_msg_ret("end", ret);
- if (!save)
+ if (!exp->save)
return -EACCES;
return 0;
diff --git a/include/expo.h b/include/expo.h
index 63452bbdd6a..f8d44c0ea20 100644
--- a/include/expo.h
+++ b/include/expo.h
@@ -105,6 +105,8 @@ struct expo_theme {
* @text_mode: true to use text mode for the menu (no vidconsole)
* @popup: true to use popup menus, instead of showing all items
* @priv: Private data for the controller
+ * @done: Indicates that a cedit session is complete and the user has quit
+ * @save: Indicates that cedit data should be saved, rather than discarded
* @theme: Information about fonts styles, etc.
* @scene_head: List of scenes
* @str_head: list of strings
@@ -120,6 +122,8 @@ struct expo {
bool text_mode;
bool popup;
void *priv;
+ bool done;
+ bool save;
struct expo_theme theme;
struct list_head scene_head;
struct list_head str_head;
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 19/56] expo: Test some cedit actions
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (17 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 18/56] expo: Move cedit-state fields into expo Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 20/56] expo: Pass in the video device for cedit_prepare() Simon Glass
` (37 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Mattijs Korpershoek, Rasmus Villemoes, Stefan Roese,
Tom Rini
Refactor the action-processing code into a new cedit_do_action()
function so we can call it from a test. Check moving to a new field and
opening the menu, to ensure that rendering is correct.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
boot/cedit.c | 75 ++++++++++++++++++++++++++---------------------
include/cedit.h | 13 ++++++++
test/boot/cedit.c | 43 +++++++++++++++++++++++++++
3 files changed, 98 insertions(+), 33 deletions(-)
diff --git a/boot/cedit.c b/boot/cedit.c
index 3703538e5dc..bcbbe69fe33 100644
--- a/boot/cedit.c
+++ b/boot/cedit.c
@@ -149,6 +149,47 @@ int cedit_prepare(struct expo *exp, struct video_priv **vid_privp,
return scene_id;
}
+int cedit_do_action(struct expo *exp, struct scene *scn,
+ struct video_priv *vid_priv, struct expo_action *act)
+{
+ switch (act->type) {
+ case EXPOACT_NONE:
+ case EXPOACT_POINT_ITEM:
+ return -EAGAIN;
+ case EXPOACT_POINT_OBJ:
+ scene_set_highlight_id(scn, act->select.id);
+ cedit_arange(exp, vid_priv, scn->id);
+ break;
+ case EXPOACT_OPEN:
+ scene_set_open(scn, act->select.id, true);
+ cedit_arange(exp, vid_priv, scn->id);
+ switch (scn->highlight_id) {
+ case EXPOID_SAVE:
+ exp->done = true;
+ exp->save = true;
+ break;
+ case EXPOID_DISCARD:
+ exp->done = true;
+ break;
+ }
+ break;
+ case EXPOACT_CLOSE:
+ scene_set_open(scn, act->select.id, false);
+ cedit_arange(exp, vid_priv, scn->id);
+ break;
+ case EXPOACT_SELECT:
+ scene_set_open(scn, scn->highlight_id, false);
+ cedit_arange(exp, vid_priv, scn->id);
+ break;
+ case EXPOACT_QUIT:
+ log_debug("quitting\n");
+ exp->done = true;
+ break;
+ }
+
+ return 0;
+}
+
int cedit_run(struct expo *exp)
{
struct video_priv *vid_priv;
@@ -168,39 +209,7 @@ int cedit_run(struct expo *exp)
ret = expo_poll(exp, &act);
if (!ret) {
- switch (act.type) {
- case EXPOACT_POINT_OBJ:
- scene_set_highlight_id(scn, act.select.id);
- cedit_arange(exp, vid_priv, scene_id);
- break;
- case EXPOACT_OPEN:
- scene_set_open(scn, act.select.id, true);
- cedit_arange(exp, vid_priv, scene_id);
- switch (scn->highlight_id) {
- case EXPOID_SAVE:
- exp->done = true;
- exp->save = true;
- break;
- case EXPOID_DISCARD:
- exp->done = true;
- break;
- }
- break;
- case EXPOACT_CLOSE:
- scene_set_open(scn, act.select.id, false);
- cedit_arange(exp, vid_priv, scene_id);
- break;
- case EXPOACT_SELECT:
- scene_set_open(scn, scn->highlight_id, false);
- cedit_arange(exp, vid_priv, scene_id);
- break;
- case EXPOACT_QUIT:
- log_debug("quitting\n");
- exp->done = true;
- break;
- default:
- break;
- }
+ cedit_do_action(exp, scn, vid_priv, &act);
} else if (ret != -EAGAIN) {
LOGR("cep", ret);
}
diff --git a/include/cedit.h b/include/cedit.h
index 856509f0c7f..a9305ceebcb 100644
--- a/include/cedit.h
+++ b/include/cedit.h
@@ -13,6 +13,7 @@
struct abuf;
struct expo;
+struct expo_action;
struct scene;
struct udevice;
struct video_priv;
@@ -62,6 +63,18 @@ int cedit_run(struct expo *exp);
int cedit_prepare(struct expo *exp, struct video_priv **vid_privp,
struct scene **scnp);
+/**
+ * cedit_do_action() - Process an action on a cedit
+ *
+ * @exp: Expo to use
+ * @scn: Current scene
+ * @vid_priv: Private data for the video device
+ * @act: Action to process
+ * Return: 0 on success, -EAGAIN if there was no action taken
+ */
+int cedit_do_action(struct expo *exp, struct scene *scn,
+ struct video_priv *vid_priv, struct expo_action *act);
+
/**
* cedit_write_settings() - Write settings in FDT format
*
diff --git a/test/boot/cedit.c b/test/boot/cedit.c
index df191a09f89..5b3e9b586a6 100644
--- a/test/boot/cedit.c
+++ b/test/boot/cedit.c
@@ -226,8 +226,10 @@ BOOTSTD_TEST(cedit_cmos, UTF_CONSOLE);
/* Check the cedit displays correctely */
static int cedit_render(struct unit_test_state *uts)
{
+ struct scene_obj_menu *menu;
struct video_priv *vid_priv;
extern struct expo *cur_exp;
+ struct expo_action act;
struct udevice *dev;
struct scene *scn;
struct expo *exp;
@@ -237,9 +239,50 @@ static int cedit_render(struct unit_test_state *uts)
exp = cur_exp;
ut_assertok(uclass_first_device_err(UCLASS_VIDEO, &dev));
ut_asserteq(ID_SCENE1, cedit_prepare(exp, &vid_priv, &scn));
+
+ menu = scene_obj_find(scn, ID_POWER_LOSS, SCENEOBJT_MENU);
+ ut_assertnonnull(menu);
+ ut_asserteq(ID_AC_OFF, menu->cur_item_id);
+
ut_assertok(expo_render(exp));
ut_asserteq(4929, video_compress_fb(uts, dev, false));
ut_assertok(video_check_copy_fb(uts, dev));
+
+ /* move to the second menu */
+ act.type = EXPOACT_POINT_OBJ;
+ act.select.id = ID_POWER_LOSS;
+ ut_assertok(cedit_do_action(exp, scn, vid_priv, &act));
+ ut_assertok(expo_render(exp));
+ ut_asserteq(4986, video_compress_fb(uts, dev, false));
+
+ /* open the menu */
+ act.type = EXPOACT_OPEN;
+ act.select.id = ID_POWER_LOSS;
+ ut_assertok(cedit_do_action(exp, scn, vid_priv, &act));
+ ut_assertok(expo_render(exp));
+ ut_asserteq(5393, video_compress_fb(uts, dev, false));
+
+ /* close the menu */
+ act.type = EXPOACT_CLOSE;
+ act.select.id = ID_POWER_LOSS;
+ ut_assertok(cedit_do_action(exp, scn, vid_priv, &act));
+ ut_assertok(expo_render(exp));
+ ut_asserteq(4986, video_compress_fb(uts, dev, false));
+
+ /* open the menu again to check it looks the same */
+ act.type = EXPOACT_OPEN;
+ act.select.id = ID_POWER_LOSS;
+ ut_assertok(cedit_do_action(exp, scn, vid_priv, &act));
+ ut_assertok(expo_render(exp));
+ ut_asserteq(5393, video_compress_fb(uts, dev, false));
+
+ /* close the menu */
+ act.type = EXPOACT_CLOSE;
+ act.select.id = ID_POWER_LOSS;
+ ut_assertok(cedit_do_action(exp, scn, vid_priv, &act));
+ ut_assertok(expo_render(exp));
+ ut_asserteq(4986, video_compress_fb(uts, dev, false));
+
expo_destroy(exp);
cur_exp = NULL;
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 20/56] expo: Pass in the video device for cedit_prepare()
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (18 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 19/56] expo: Test some cedit actions Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 21/56] expo: Test rendering a lineedit Simon Glass
` (36 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Mattijs Korpershoek, Rasmus Villemoes, Stefan Roese,
Tom Rini
At present this function locates it own video device. Pass it in to
provide more flexibility.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Add new patch to pass in the video device for cedit_prepare()
boot/cedit.c | 18 ++++++++++--------
include/cedit.h | 4 ++--
test/boot/cedit.c | 20 ++++++++++++++++----
3 files changed, 28 insertions(+), 14 deletions(-)
diff --git a/boot/cedit.c b/boot/cedit.c
index bcbbe69fe33..3fde6928f90 100644
--- a/boot/cedit.c
+++ b/boot/cedit.c
@@ -100,19 +100,16 @@ int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id)
return 0;
}
-int cedit_prepare(struct expo *exp, struct video_priv **vid_privp,
+int cedit_prepare(struct expo *exp, struct udevice *vid_dev,
struct scene **scnp)
{
+ struct udevice *dev = vid_dev;
struct video_priv *vid_priv;
- struct udevice *dev;
struct scene *scn;
uint scene_id;
int ret;
/* For now we only support a video console */
- ret = uclass_first_device_err(UCLASS_VIDEO, &dev);
- if (ret)
- return log_msg_ret("vid", ret);
ret = expo_set_display(exp, dev);
if (ret)
return log_msg_ret("dis", ret);
@@ -143,7 +140,6 @@ int cedit_prepare(struct expo *exp, struct video_priv **vid_privp,
if (ret)
return log_msg_ret("dim", ret);
- *vid_privp = vid_priv;
*scnp = scn;
return scene_id;
@@ -193,11 +189,17 @@ int cedit_do_action(struct expo *exp, struct scene *scn,
int cedit_run(struct expo *exp)
{
struct video_priv *vid_priv;
- uint scene_id;
+ struct udevice *dev;
struct scene *scn;
+ uint scene_id;
int ret;
- ret = cedit_prepare(exp, &vid_priv, &scn);
+ ret = uclass_first_device_err(UCLASS_VIDEO, &dev);
+ if (ret)
+ return log_msg_ret("vid", ret);
+ vid_priv = dev_get_uclass_priv(dev);
+
+ ret = cedit_prepare(exp, dev, &scn);
if (ret < 0)
return log_msg_ret("prep", ret);
scene_id = ret;
diff --git a/include/cedit.h b/include/cedit.h
index a9305ceebcb..319a61aecb8 100644
--- a/include/cedit.h
+++ b/include/cedit.h
@@ -56,11 +56,11 @@ int cedit_run(struct expo *exp);
* This ensures that all menus have a selected item.
*
* @exp: Expo to use
- * @vid_privp: Set to private data for the video device
+ * @dev: Video device to use
* @scnp: Set to the first scene
* Return: scene ID of first scene if OK, -ve on error
*/
-int cedit_prepare(struct expo *exp, struct video_priv **vid_privp,
+int cedit_prepare(struct expo *exp, struct udevice *vid_dev,
struct scene **scnp);
/**
diff --git a/test/boot/cedit.c b/test/boot/cedit.c
index 5b3e9b586a6..746f60067fd 100644
--- a/test/boot/cedit.c
+++ b/test/boot/cedit.c
@@ -63,6 +63,7 @@ static int cedit_fdt(struct unit_test_state *uts)
struct video_priv *vid_priv;
extern struct expo *cur_exp;
struct scene_obj_menu *menu;
+ struct udevice *dev;
ulong addr = 0x1000;
struct ofprop prop;
struct scene *scn;
@@ -72,9 +73,12 @@ static int cedit_fdt(struct unit_test_state *uts)
void *fdt;
int i;
+ ut_assertok(uclass_first_device_err(UCLASS_VIDEO, &dev));
+ vid_priv = dev_get_uclass_priv(dev);
+
ut_assertok(run_command("cedit load hostfs - cedit.dtb", 0));
- ut_asserteq(ID_SCENE1, cedit_prepare(cur_exp, &vid_priv, &scn));
+ ut_asserteq(ID_SCENE1, cedit_prepare(cur_exp, dev, &scn));
/* get a menu to fiddle with */
menu = scene_obj_find(scn, ID_CPU_SPEED, SCENEOBJT_MENU);
@@ -134,12 +138,16 @@ static int cedit_env(struct unit_test_state *uts)
struct video_priv *vid_priv;
extern struct expo *cur_exp;
struct scene_obj_menu *menu;
+ struct udevice *dev;
struct scene *scn;
char *str;
ut_assertok(run_command("cedit load hostfs - cedit.dtb", 0));
- ut_asserteq(ID_SCENE1, cedit_prepare(cur_exp, &vid_priv, &scn));
+ ut_assertok(uclass_first_device_err(UCLASS_VIDEO, &dev));
+ vid_priv = dev_get_uclass_priv(dev);
+
+ ut_asserteq(ID_SCENE1, cedit_prepare(cur_exp, dev, &scn));
/* get a menu to fiddle with */
menu = scene_obj_find(scn, ID_CPU_SPEED, SCENEOBJT_MENU);
@@ -189,11 +197,14 @@ static int cedit_cmos(struct unit_test_state *uts)
struct scene_obj_menu *menu, *menu2;
struct video_priv *vid_priv;
extern struct expo *cur_exp;
+ struct udevice *dev;
struct scene *scn;
ut_assertok(run_command("cedit load hostfs - cedit.dtb", 0));
- ut_asserteq(ID_SCENE1, cedit_prepare(cur_exp, &vid_priv, &scn));
+ ut_assertok(uclass_first_device_err(UCLASS_VIDEO, &dev));
+ vid_priv = dev_get_uclass_priv(dev);
+ ut_asserteq(ID_SCENE1, cedit_prepare(cur_exp, dev, &scn));
/* get the menus to fiddle with */
menu = scene_obj_find(scn, ID_CPU_SPEED, SCENEOBJT_MENU);
@@ -238,7 +249,8 @@ static int cedit_render(struct unit_test_state *uts)
exp = cur_exp;
ut_assertok(uclass_first_device_err(UCLASS_VIDEO, &dev));
- ut_asserteq(ID_SCENE1, cedit_prepare(exp, &vid_priv, &scn));
+ vid_priv = dev_get_uclass_priv(dev);
+ ut_asserteq(ID_SCENE1, cedit_prepare(exp, dev, &scn));
menu = scene_obj_find(scn, ID_POWER_LOSS, SCENEOBJT_MENU);
ut_assertnonnull(menu);
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 21/56] expo: Test rendering a lineedit
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (19 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 20/56] expo: Pass in the video device for cedit_prepare() Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 22/56] expo: Provide access to the current menu item Simon Glass
` (35 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Mattijs Korpershoek, Tom Rini
Check the rendering output when adding characters to a line-edit object.
Add a separate test to check behaviour when starting with existing text
in the lineedit. The cursor should start at the end.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Add new patch to test rendering a lineedit
test/boot/cedit.c | 113 ++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 110 insertions(+), 3 deletions(-)
diff --git a/test/boot/cedit.c b/test/boot/cedit.c
index 746f60067fd..97ca63b3082 100644
--- a/test/boot/cedit.c
+++ b/test/boot/cedit.c
@@ -234,21 +234,28 @@ static int cedit_cmos(struct unit_test_state *uts)
}
BOOTSTD_TEST(cedit_cmos, UTF_CONSOLE);
-/* Check the cedit displays correctely */
+/* Check the cedit displays correctly */
static int cedit_render(struct unit_test_state *uts)
{
struct scene_obj_menu *menu;
struct video_priv *vid_priv;
extern struct expo *cur_exp;
+ struct expo_action evt;
struct expo_action act;
- struct udevice *dev;
+ struct udevice *dev, *con;
+ struct stdio_dev *sdev;
struct scene *scn;
struct expo *exp;
+ int i;
ut_assertok(run_command("cedit load hostfs - cedit.dtb", 0));
exp = cur_exp;
- ut_assertok(uclass_first_device_err(UCLASS_VIDEO, &dev));
+ sdev = stdio_get_by_name("vidconsole");
+ ut_assertnonnull(sdev);
+ con = sdev->priv;
+
+ dev = dev_get_parent(con);
vid_priv = dev_get_uclass_priv(dev);
ut_asserteq(ID_SCENE1, cedit_prepare(exp, dev, &scn));
@@ -295,9 +302,109 @@ static int cedit_render(struct unit_test_state *uts)
ut_assertok(expo_render(exp));
ut_asserteq(4986, video_compress_fb(uts, dev, false));
+ /* move to the line-edit field */
+ act.type = EXPOACT_POINT_OBJ;
+ act.select.id = ID_MACHINE_NAME;
+ ut_assertok(cedit_do_action(exp, scn, vid_priv, &act));
+ ut_assertok(expo_render(exp));
+ ut_asserteq(4872, video_compress_fb(uts, dev, false));
+
+ /* open it */
+ act.type = EXPOACT_OPEN;
+ act.select.id = ID_MACHINE_NAME;
+ ut_assertok(cedit_do_action(exp, scn, vid_priv, &act));
+ ut_assertok(expo_render(exp));
+ ut_asserteq(4841, video_compress_fb(uts, dev, false));
+
+ /*
+ * Send some keypresses. Note that the console must be enabled so that
+ * the characters actually reach the putc_xy() in console_truetype,
+ * since in scene_textline_send_key(), the lineedit restores the
+ * vidconsole state, outputs the character and then saves the state
+ * again. If the character is never output, then the state won't be
+ * updated and the lineedit will be inconsistent.
+ */
+ ut_unsilence_console(uts);
+ for (i = 'a'; i < 'd'; i++)
+ ut_assertok(scene_send_key(scn, i, &evt));
+ ut_silence_console(uts);
+ ut_assertok(cedit_arange(exp, vid_priv, scn->id));
+ ut_assertok(expo_render(exp));
+ ut_asserteq(5009, video_compress_fb(uts, dev, false));
+
expo_destroy(exp);
cur_exp = NULL;
return 0;
}
BOOTSTD_TEST(cedit_render, UTF_DM | UTF_SCAN_FDT);
+
+/* Check the cedit displays lineedits correctly */
+static int cedit_render_lineedit(struct unit_test_state *uts)
+{
+ struct scene_obj_textline *tline;
+ struct video_priv *vid_priv;
+ extern struct expo *cur_exp;
+ struct expo_action evt;
+ struct expo_action act;
+ struct udevice *dev, *con;
+ struct stdio_dev *sdev;
+ struct scene *scn;
+ struct expo *exp;
+ char *str;
+ int i;
+
+ ut_assertok(run_command("cedit load hostfs - cedit.dtb", 0));
+
+ exp = cur_exp;
+ sdev = stdio_get_by_name("vidconsole");
+ ut_assertnonnull(sdev);
+ con = sdev->priv;
+
+ dev = dev_get_parent(con);
+ vid_priv = dev_get_uclass_priv(dev);
+ ut_asserteq(ID_SCENE1, cedit_prepare(exp, dev, &scn));
+
+ /* set up an initial value for the textline */
+ tline = scene_obj_find(scn, ID_MACHINE_NAME, SCENEOBJT_TEXTLINE);
+ ut_assertnonnull(tline);
+ str = abuf_data(&tline->buf);
+ strcpy(str, "my-machine");
+ ut_asserteq(20, tline->pos);
+
+ ut_assertok(expo_render(exp));
+ ut_asserteq(5336, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
+
+ /* move to the line-edit field */
+ act.type = EXPOACT_POINT_OBJ;
+ act.select.id = ID_MACHINE_NAME;
+ ut_assertok(cedit_do_action(exp, scn, vid_priv, &act));
+ ut_assertok(expo_render(exp));
+ ut_asserteq(5363, video_compress_fb(uts, dev, false));
+
+ /* open it */
+ act.type = EXPOACT_OPEN;
+ act.select.id = ID_MACHINE_NAME;
+ ut_assertok(cedit_do_action(exp, scn, vid_priv, &act));
+ // ut_asserteq(0, tline->pos);
+ ut_assertok(expo_render(exp));
+ ut_asserteq(5283, video_compress_fb(uts, dev, false));
+
+ /* delete some characters */
+ ut_unsilence_console(uts);
+ for (i = 0; i < 3; i++)
+ ut_assertok(scene_send_key(scn, '\b', &evt));
+ ut_silence_console(uts);
+ ut_asserteq_str("my-mach", str);
+
+ ut_assertok(cedit_arange(exp, vid_priv, scn->id));
+ ut_assertok(expo_render(exp));
+ ut_asserteq(5170, video_compress_fb(uts, dev, false));
+
+ expo_destroy(exp);
+ cur_exp = NULL;
+
+ return 0;
+}
+BOOTSTD_TEST(cedit_render_lineedit, UTF_DM | UTF_SCAN_FDT);
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 22/56] expo: Provide access to the current menu item
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (20 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 21/56] expo: Test rendering a lineedit Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 23/56] expo: Adjust how menu items are highlighted Simon Glass
` (34 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Tom Rini
Add functions to allow a caller to find out the current menu item and to
select a different one.
Update the event handling so that an attempt to change the current item
(e.g. by pressing the up-arrow key) is reported to the caller, since
this may be used to cancel an autoboot timeout.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
| 32 +++++++++++++++++++++++++++++---
include/expo.h | 20 ++++++++++++++++++++
test/boot/expo.c | 4 ++++
3 files changed, 53 insertions(+), 3 deletions(-)
--git a/boot/scene_menu.c b/boot/scene_menu.c
index 17150af145d..48905d3e2b6 100644
--- a/boot/scene_menu.c
+++ b/boot/scene_menu.c
@@ -121,12 +121,14 @@ static int update_pointers(struct scene_obj_menu *menu, uint id, bool point)
*
* Sets the currently pointed-to / highlighted menu item
*/
-static void menu_point_to_item(struct scene_obj_menu *menu, uint item_id)
+static int menu_point_to_item(struct scene_obj_menu *menu, uint item_id)
{
if (menu->cur_item_id)
- update_pointers(menu, menu->cur_item_id, false);
+ LOGR("mpi", update_pointers(menu, menu->cur_item_id, false));
menu->cur_item_id = item_id;
- update_pointers(menu, item_id, true);
+ LOGR("mpu", update_pointers(menu, item_id, true));
+
+ return 0;
}
void scene_menu_calc_bbox(struct scene_obj_menu *menu,
@@ -483,6 +485,30 @@ int scene_menu_set_pointer(struct scene *scn, uint id, uint pointer_id)
return 0;
}
+int scene_menu_select_item(struct scene *scn, uint id, uint cur_item_id)
+{
+ struct scene_obj_menu *menu;
+
+ menu = scene_obj_find(scn, id, SCENEOBJT_MENU);
+ if (!menu)
+ return log_msg_ret("menu", -ENOENT);
+
+ LOGR("msi", menu_point_to_item(menu, cur_item_id));
+
+ return 0;
+}
+
+int scene_menu_get_cur_item(struct scene *scn, uint id)
+{
+ struct scene_obj_menu *menu;
+
+ menu = scene_obj_find(scn, id, SCENEOBJT_MENU);
+ if (!menu)
+ return log_msg_ret("menu", -ENOENT);
+
+ return menu->cur_item_id;
+}
+
int scene_menu_display(struct scene_obj_menu *menu)
{
struct scene *scn = menu->obj.scene;
diff --git a/include/expo.h b/include/expo.h
index f8d44c0ea20..a2b093c521d 100644
--- a/include/expo.h
+++ b/include/expo.h
@@ -689,6 +689,26 @@ int scene_menu_set_title(struct scene *scn, uint id, uint title_id);
*/
int scene_menu_set_pointer(struct scene *scn, uint id, uint cur_item_id);
+/**
+ * scene_menu_select_item() - move the pointer/highlight to an item
+ *
+ * @scn: Scene to update
+ * @id: ID of menu object to update
+ * @sel_id: ID of the menuitem to select
+ * Return 0 on success, -ENOENT if there was no such item
+ */
+int scene_menu_select_item(struct scene *scn, uint id, uint sel_id);
+
+/**
+ * scene_menu_get_cur_item() - get the currently pointed-to item
+ *
+ * @scn: Scene to update
+ * @id: ID of menu object to update
+ * Return ID of the current item the menu is pointing to, -ENOENT if @id is not
+ * valid, 0 if no item is pointed to
+ */
+int scene_menu_get_cur_item(struct scene *scn, uint id);
+
/**
* scene_obj_get_hw() - Get width and height of an object in a scene
*
diff --git a/test/boot/expo.c b/test/boot/expo.c
index 1d283a2ac95..616071ead48 100644
--- a/test/boot/expo.c
+++ b/test/boot/expo.c
@@ -588,6 +588,8 @@ static int expo_render_image(struct unit_test_state *uts)
expo_set_scene_id(exp, SCENE1);
ut_assertok(expo_render(exp));
+ ut_asserteq(0, scn->highlight_id);
+
/* move down */
ut_assertok(expo_send_key(exp, BKEY_DOWN));
@@ -595,6 +597,8 @@ static int expo_render_image(struct unit_test_state *uts)
ut_asserteq(EXPOACT_POINT_ITEM, act.type);
ut_asserteq(ITEM2, act.select.id);
+ ut_assertok(scene_menu_select_item(scn, OBJ_MENU, act.select.id));
+ ut_asserteq(ITEM2, scene_menu_get_cur_item(scn, OBJ_MENU));
ut_assertok(expo_render(exp));
/* make sure only the preview for the second item is shown */
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 23/56] expo: Adjust how menu items are highlighted
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (21 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 22/56] expo: Provide access to the current menu item Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 24/56] expo: Test editing a lineedit Simon Glass
` (33 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Quentin Schulz, Rasmus Villemoes, Stefan Roese,
Tom Rini
At present when the user moves to a new menu item, the menu code
handles this immediately. This means it is not possible to use an expo
action to effect the same change.
Update this so that EXPOACT_POINT_ITEM is handled in cedit_do_action().
Expand the test to cover this.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
| 8 ++++++++
boot/cedit.c | 5 ++++-
| 2 --
test/boot/expo.c | 4 ++++
4 files changed, 16 insertions(+), 3 deletions(-)
--git a/boot/bootflow_menu.c b/boot/bootflow_menu.c
index e3a27f16daa..d20d0be4734 100644
--- a/boot/bootflow_menu.c
+++ b/boot/bootflow_menu.c
@@ -180,6 +180,7 @@ int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
{
struct bootflow *sel_bflow;
struct udevice *dev;
+ struct scene *scn;
struct expo *exp;
uint sel_id;
bool done;
@@ -209,6 +210,9 @@ int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
ret = expo_set_scene_id(exp, MAIN);
if (ret)
return log_msg_ret("scn", ret);
+ scn = expo_lookup_scene_id(exp, MAIN);
+ if (!scn)
+ return log_msg_ret("scn", -ENOENT);
if (text_mode)
expo_set_text_mode(exp, text_mode);
@@ -224,6 +228,10 @@ int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
sel_id = act.select.id;
done = true;
break;
+ case EXPOACT_POINT_ITEM:
+ LOGR("bmp", scene_menu_select_item(scn,
+ OBJ_MENU, act.select.id));
+ break;
case EXPOACT_QUIT:
return -EPIPE;
default:
diff --git a/boot/cedit.c b/boot/cedit.c
index 3fde6928f90..eabbf07a8a0 100644
--- a/boot/cedit.c
+++ b/boot/cedit.c
@@ -150,8 +150,11 @@ int cedit_do_action(struct expo *exp, struct scene *scn,
{
switch (act->type) {
case EXPOACT_NONE:
- case EXPOACT_POINT_ITEM:
return -EAGAIN;
+ case EXPOACT_POINT_ITEM:
+ LOGR("cdp", scene_menu_select_item(scn, scn->highlight_id,
+ act->select.id));
+ break;
case EXPOACT_POINT_OBJ:
scene_set_highlight_id(scn, act->select.id);
cedit_arange(exp, vid_priv, scn->id);
--git a/boot/scene_menu.c b/boot/scene_menu.c
index 48905d3e2b6..df14a6c0409 100644
--- a/boot/scene_menu.c
+++ b/boot/scene_menu.c
@@ -399,8 +399,6 @@ int scene_menu_send_key(struct scene *scn, struct scene_obj_menu *menu, int key,
break;
}
- menu_point_to_item(menu, item->id);
-
return 0;
}
diff --git a/test/boot/expo.c b/test/boot/expo.c
index 616071ead48..b32a4596e85 100644
--- a/test/boot/expo.c
+++ b/test/boot/expo.c
@@ -588,6 +588,8 @@ static int expo_render_image(struct unit_test_state *uts)
expo_set_scene_id(exp, SCENE1);
ut_assertok(expo_render(exp));
+ ut_asserteq(0, scn->highlight_id);
+ ut_assertok(scene_arrange(scn));
ut_asserteq(0, scn->highlight_id);
/* move down */
@@ -599,6 +601,7 @@ static int expo_render_image(struct unit_test_state *uts)
ut_asserteq(ITEM2, act.select.id);
ut_assertok(scene_menu_select_item(scn, OBJ_MENU, act.select.id));
ut_asserteq(ITEM2, scene_menu_get_cur_item(scn, OBJ_MENU));
+ ut_assertok(scene_arrange(scn));
ut_assertok(expo_render(exp));
/* make sure only the preview for the second item is shown */
@@ -639,6 +642,7 @@ static int expo_render_image(struct unit_test_state *uts)
ut_asserteq(EXPOACT_POINT_ITEM, act.type);
ut_asserteq(ITEM1, act.select.id);
+ ut_assertok(scene_menu_select_item(scn, OBJ_MENU, act.select.id));
ut_assertok(expo_render(exp));
ut_assert_nextline("U-Boot : Boot Menu");
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 24/56] expo: Test editing a lineedit
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (22 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 23/56] expo: Adjust how menu items are highlighted Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 25/56] expo: Split bootflow_menu_run() into two pieces Simon Glass
` (32 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Mattijs Korpershoek, Tom Rini
Open the lineedit and add a few characters, to check that things look
right.
At present when the user moves to a new menu item, the menu code
handles this immediately. This means it is not possible to use an expo
action to effect the same change.
Update this so that EXPOACT_POINT_ITEM is handled in cedit_do_action().
Expand the test to cover this.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Add new patch to test editing a lineedit
test/boot/cedit.c | 27 ++++++++++++++++++++++++---
1 file changed, 24 insertions(+), 3 deletions(-)
diff --git a/test/boot/cedit.c b/test/boot/cedit.c
index 97ca63b3082..0c34d4b3df0 100644
--- a/test/boot/cedit.c
+++ b/test/boot/cedit.c
@@ -302,19 +302,40 @@ static int cedit_render(struct unit_test_state *uts)
ut_assertok(expo_render(exp));
ut_asserteq(4986, video_compress_fb(uts, dev, false));
+ act.type = EXPOACT_OPEN;
+ act.select.id = ID_POWER_LOSS;
+ ut_assertok(cedit_do_action(exp, scn, vid_priv, &act));
+ ut_assertok(expo_render(exp));
+ ut_asserteq(5393, video_compress_fb(uts, dev, false));
+
+ act.type = EXPOACT_POINT_ITEM;
+ act.select.id = ID_AC_ON;
+ ut_assertok(cedit_do_action(exp, scn, vid_priv, &act));
+ ut_assertok(expo_render(exp));
+ ut_asserteq(5365, video_compress_fb(uts, dev, false));
+
+ /* select it */
+ act.type = EXPOACT_SELECT;
+ act.select.id = ID_AC_ON;
+ ut_assertok(cedit_do_action(exp, scn, vid_priv, &act));
+ ut_assertok(expo_render(exp));
+ ut_asserteq(4980, video_compress_fb(uts, dev, false));
+
+ ut_asserteq(ID_AC_ON, menu->cur_item_id);
+
/* move to the line-edit field */
act.type = EXPOACT_POINT_OBJ;
act.select.id = ID_MACHINE_NAME;
ut_assertok(cedit_do_action(exp, scn, vid_priv, &act));
ut_assertok(expo_render(exp));
- ut_asserteq(4872, video_compress_fb(uts, dev, false));
+ ut_asserteq(4862, video_compress_fb(uts, dev, false));
/* open it */
act.type = EXPOACT_OPEN;
act.select.id = ID_MACHINE_NAME;
ut_assertok(cedit_do_action(exp, scn, vid_priv, &act));
ut_assertok(expo_render(exp));
- ut_asserteq(4841, video_compress_fb(uts, dev, false));
+ ut_asserteq(4851, video_compress_fb(uts, dev, false));
/*
* Send some keypresses. Note that the console must be enabled so that
@@ -330,7 +351,7 @@ static int cedit_render(struct unit_test_state *uts)
ut_silence_console(uts);
ut_assertok(cedit_arange(exp, vid_priv, scn->id));
ut_assertok(expo_render(exp));
- ut_asserteq(5009, video_compress_fb(uts, dev, false));
+ ut_asserteq(4996, video_compress_fb(uts, dev, false));
expo_destroy(exp);
cur_exp = NULL;
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 25/56] expo: Split bootflow_menu_run() into two pieces
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (23 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 24/56] expo: Test editing a lineedit Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 26/56] expo: Split bootflow_menu_new() " Simon Glass
` (31 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Guillaume La Roque, Heinrich Schuchardt,
Igor Opaniuk, Julien Masson, Mattijs Korpershoek, Quentin Schulz,
Tom Rini
Split the starting piece of this function into bootflow_menu_start()
and the polling part into bootflow_menu_poll() so that it is possible
for the caller to be in control of the event loop.
Move the expo_destroy() call into the caller.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
| 86 ++++++++++++++++++++------------------------
cmd/bootflow.c | 34 +++++++++++-------
include/bootflow.h | 33 ++++++++++-------
3 files changed, 81 insertions(+), 72 deletions(-)
--git a/boot/bootflow_menu.c b/boot/bootflow_menu.c
index d20d0be4734..018910c65b8 100644
--- a/boot/bootflow_menu.c
+++ b/boot/bootflow_menu.c
@@ -175,20 +175,13 @@ int bootflow_menu_apply_theme(struct expo *exp, ofnode node)
return 0;
}
-int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
- struct bootflow **bflowp)
+int bootflow_menu_start(struct bootstd_priv *std, bool text_mode,
+ struct expo **expp)
{
- struct bootflow *sel_bflow;
struct udevice *dev;
- struct scene *scn;
struct expo *exp;
- uint sel_id;
- bool done;
int ret;
- sel_bflow = NULL;
- *bflowp = NULL;
-
ret = bootflow_menu_new(&exp);
if (ret)
return log_msg_ret("exp", ret);
@@ -210,56 +203,55 @@ int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
ret = expo_set_scene_id(exp, MAIN);
if (ret)
return log_msg_ret("scn", ret);
- scn = expo_lookup_scene_id(exp, MAIN);
- if (!scn)
- return log_msg_ret("scn", -ENOENT);
if (text_mode)
expo_set_text_mode(exp, text_mode);
- done = false;
- do {
- struct expo_action act;
-
- ret = expo_poll(exp, &act);
- if (!ret) {
- switch (act.type) {
- case EXPOACT_SELECT:
- sel_id = act.select.id;
- done = true;
- break;
- case EXPOACT_POINT_ITEM:
- LOGR("bmp", scene_menu_select_item(scn,
- OBJ_MENU, act.select.id));
- break;
- case EXPOACT_QUIT:
- return -EPIPE;
- default:
- break;
- }
- } else if (ret != -EPIPE && ret != -EAGAIN) {
- LOGR("bmr", ret);
- }
- } while (!done);
+ *expp = exp;
+
+ return 0;
+}
- if (sel_id) {
+int bootflow_menu_poll(struct expo *exp, struct bootflow **bflowp)
+{
+ struct bootflow *sel_bflow;
+ struct expo_action act;
+ int ret;
+
+ sel_bflow = NULL;
+ *bflowp = NULL;
+
+ LOGR("bmp", expo_poll(exp, &act));
+
+ switch (act.type) {
+ case EXPOACT_SELECT: {
struct bootflow *bflow;
int i;
for (ret = bootflow_first_glob(&bflow), i = 0; !ret && i < 36;
ret = bootflow_next_glob(&bflow), i++) {
- if (i == sel_id - ITEM) {
- sel_bflow = bflow;
- break;
+ if (i == act.select.id - ITEM) {
+ *bflowp = bflow;
+ // printf("found %p\n", bflow);
+ return 0;
}
}
+ break;
+ }
+ case EXPOACT_POINT_ITEM: {
+ struct scene *scn = expo_lookup_scene_id(exp, MAIN);
+
+ if (!scn)
+ return log_msg_ret("bms", -ENOENT);
+ LOGR("bmp", scene_menu_select_item(scn, OBJ_MENU,
+ act.select.id));
+ break;
+ }
+ case EXPOACT_QUIT:
+ return -EPIPE;
+ default:
+ break;
}
- expo_destroy(exp);
-
- if (!sel_bflow)
- return -EAGAIN;
- *bflowp = sel_bflow;
-
- return 0;
+ return -EAGAIN;
}
diff --git a/cmd/bootflow.c b/cmd/bootflow.c
index 6189ab7fa40..456f51760f1 100644
--- a/cmd/bootflow.c
+++ b/cmd/bootflow.c
@@ -13,6 +13,8 @@
#include <command.h>
#include <console.h>
#include <dm.h>
+#include <expo.h>
+#include <log.h>
#include <mapmem.h>
/**
@@ -105,24 +107,30 @@ __maybe_unused static int bootflow_handle_menu(struct bootstd_priv *std,
bool text_mode,
struct bootflow **bflowp)
{
+ struct expo *exp;
struct bootflow *bflow;
int ret;
- ret = bootflow_menu_run(std, text_mode, &bflow);
- if (ret) {
- if (ret == -EPIPE) {
- printf("Nothing chosen\n");
- std->cur_bootflow = NULL;
- } else {
- printf("Menu failed (err=%d)\n", ret);
- }
+ LOGR("bhs", bootflow_menu_start(std, text_mode, &exp));
- return ret;
- }
+ do {
+ ret = bootflow_menu_poll(exp, &bflow);
+ } while (ret == -EAGAIN);
- printf("Selected: %s\n", bflow->os_name ? bflow->os_name : bflow->name);
- std->cur_bootflow = bflow;
- *bflowp = bflow;
+ if (ret == -EPIPE) {
+ printf("Nothing chosen\n");
+ std->cur_bootflow = NULL;
+ } else if (ret) {
+ printf("Menu failed (err=%d)\n", ret);
+ } else {
+ printf("Selected: %s\n", bflow->os_name ? bflow->os_name :
+ bflow->name);
+ std->cur_bootflow = bflow;
+ *bflowp = bflow;
+ }
+ expo_destroy(exp);
+ if (ret)
+ return ret;
return 0;
}
diff --git a/include/bootflow.h b/include/bootflow.h
index ef1d1a75ded..72f09304cff 100644
--- a/include/bootflow.h
+++ b/include/bootflow.h
@@ -503,18 +503,6 @@ int bootflow_menu_new(struct expo **expp);
*/
int bootflow_menu_apply_theme(struct expo *exp, ofnode node);
-/**
- * bootflow_menu_run() - Create and run a menu of available bootflows
- *
- * @std: Bootstd information
- * @text_mode: Uses a text-based menu suitable for a serial port
- * @bflowp: Returns chosen bootflow (set to NULL if nothing is chosen)
- * @return 0 if an option was chosen, -EPIPE if nothing was chosen, -ve on
- * error
- */
-int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
- struct bootflow **bflowp);
-
#define BOOTFLOWCL_EMPTY ((void *)1)
/**
@@ -639,4 +627,25 @@ struct bootflow_img *bootflow_img_add(struct bootflow *bflow, const char *fname,
*/
int bootflow_get_seq(const struct bootflow *bflow);
+/**
+ * bootflow_menu_start() - Start up a menu for bootflows
+ *
+ * @std: bootstd information
+ * @text_mode: true to show the menu in text mode, false to use video display
+ * @expp: Returns the expo created, on success
+ * Return: 0 if OK, -ve on error
+ */
+int bootflow_menu_start(struct bootstd_priv *std, bool text_mode,
+ struct expo **expp);
+
+/**
+ * bootflow_menu_poll() - Poll a menu for user action
+ *
+ * @exp: Expo to poll
+ * @bflowp: Returns chosen bootflow (set to NULL if nothing is chosen)
+ * Return 0 if a bootflow was chosen, -EAGAIN if nothing is chosen yet, -EPIPE
+ * if the user quit
+ */
+int bootflow_menu_poll(struct expo *exp, struct bootflow **bflowp);
+
#endif
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 26/56] expo: Split bootflow_menu_new() into two pieces
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (24 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 25/56] expo: Split bootflow_menu_run() into two pieces Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 27/56] expo: Allow adding a single bootflow to a menu Simon Glass
` (30 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Guillaume La Roque, Heinrich Schuchardt,
Igor Opaniuk, Julien Masson, Mattijs Korpershoek, Quentin Schulz,
Tom Rini
Split the iteration piece of this function into bootflow_menu_add_all()
so that it is possible for the caller to be in control of adding items
to the menu.
Move the expo_destroy() call into the caller.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
| 31 +++++++++++++++++++++++--------
include/bootflow.h | 13 +++++++++++++
test/boot/bootflow.c | 1 +
3 files changed, 37 insertions(+), 8 deletions(-)
--git a/boot/bootflow_menu.c b/boot/bootflow_menu.c
index 018910c65b8..9b97156d943 100644
--- a/boot/bootflow_menu.c
+++ b/boot/bootflow_menu.c
@@ -32,14 +32,12 @@ struct menu_priv {
int bootflow_menu_new(struct expo **expp)
{
- struct udevice *last_bootdev;
struct scene_obj_menu *menu;
struct menu_priv *priv;
- struct bootflow *bflow;
struct scene *scn;
struct expo *exp;
void *logo;
- int ret, i;
+ int ret;
priv = calloc(1, sizeof(*priv));
if (!priv)
@@ -74,6 +72,26 @@ int bootflow_menu_new(struct expo **expp)
if (ret < 0)
return log_msg_ret("new", -EINVAL);
+ *expp = exp;
+
+ return 0;
+}
+
+int bootflow_menu_add_all(struct expo *exp)
+{
+ struct menu_priv *priv = exp->priv;
+ struct udevice *last_bootdev;
+ struct bootflow *bflow;
+ struct scene *scn;
+ uint scene_id;
+ int ret, i;
+
+ ret = expo_first_scene_id(exp);
+ if (ret < 0)
+ return log_msg_ret("scn", ret);
+ scene_id = ret;
+ scn = expo_lookup_scene_id(exp, scene_id);
+
last_bootdev = NULL;
for (ret = bootflow_first_glob(&bflow), i = 0; !ret && i < 36;
ret = bootflow_next_glob(&bflow), i++) {
@@ -133,8 +151,6 @@ int bootflow_menu_new(struct expo **expp)
if (ret)
return log_msg_ret("arr", ret);
- *expp = exp;
-
return 0;
}
@@ -182,9 +198,8 @@ int bootflow_menu_start(struct bootstd_priv *std, bool text_mode,
struct expo *exp;
int ret;
- ret = bootflow_menu_new(&exp);
- if (ret)
- return log_msg_ret("exp", ret);
+ LOGR("bmn", bootflow_menu_new(&exp));
+ LOGR("bma", bootflow_menu_add_all(exp));
if (ofnode_valid(std->theme)) {
ret = bootflow_menu_apply_theme(exp, std->theme);
diff --git a/include/bootflow.h b/include/bootflow.h
index 72f09304cff..5f65129ca65 100644
--- a/include/bootflow.h
+++ b/include/bootflow.h
@@ -489,11 +489,24 @@ int bootflow_iter_check_system(const struct bootflow_iter *iter);
/**
* bootflow_menu_new() - Create a new bootflow menu
*
+ * This is initially empty. Call bootflow_menu_add_all() to add all the
+ * bootflows to it.
+ *
* @expp: Returns the expo created
* Returns 0 on success, -ve on error
*/
int bootflow_menu_new(struct expo **expp);
+/**
+ * bootflow_menu_add_all() - Add all bootflows to a menu
+ *
+ * Loops through all bootflows and adds them to the menu
+ *
+ * @exp: Menu to update
+ * Return 0 on success, -ve on error
+ */
+int bootflow_menu_add_all(struct expo *exp);
+
/**
* bootflow_menu_apply_theme() - Apply a theme to a bootmenu
*
diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
index cbb5bcc0cf3..572851761c5 100644
--- a/test/boot/bootflow.c
+++ b/test/boot/bootflow.c
@@ -881,6 +881,7 @@ static int bootflow_menu_theme(struct unit_test_state *uts)
ut_assertok(scan_mmc4_bootdev(uts));
ut_assertok(bootflow_menu_new(&exp));
+ ut_assertok(bootflow_menu_add_all(exp));
node = ofnode_path("/bootstd/theme");
ut_assert(ofnode_valid(node));
ut_assertok(bootflow_menu_apply_theme(exp, node));
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 27/56] expo: Allow adding a single bootflow to a menu
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (25 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 26/56] expo: Split bootflow_menu_new() " Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 28/56] expo: Rename scene_dim to scene_obj_bbox Simon Glass
` (29 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Igor Opaniuk, Julien Masson, Mattijs Korpershoek,
Quentin Schulz, Tom Rini
Refactor bootflow_menu_add_all() to call a new bootflow_menu_add() to
add each of its bootflows.
Move the last_bootdev value into struct menu_priv to make this work.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
| 102 ++++++++++++++++++++++++-------------------
include/bootflow.h | 16 +++++++
2 files changed, 73 insertions(+), 45 deletions(-)
--git a/boot/bootflow_menu.c b/boot/bootflow_menu.c
index 9b97156d943..19cd84e6454 100644
--- a/boot/bootflow_menu.c
+++ b/boot/bootflow_menu.c
@@ -25,9 +25,11 @@
* struct menu_priv - information about the menu
*
* @num_bootflows: Number of bootflows in the menu
+ * @last_bootdev: bootdev of the last bootflow added to the menu, NULL if none
*/
struct menu_priv {
int num_bootflows;
+ struct udevice *last_bootdev;
};
int bootflow_menu_new(struct expo **expp)
@@ -77,14 +79,16 @@ int bootflow_menu_new(struct expo **expp)
return 0;
}
-int bootflow_menu_add_all(struct expo *exp)
+int bootflow_menu_add(struct expo *exp, struct bootflow *bflow, int seq,
+ struct scene **scnp)
{
struct menu_priv *priv = exp->priv;
- struct udevice *last_bootdev;
- struct bootflow *bflow;
+ char str[2], *label, *key;
struct scene *scn;
+ uint preview_id;
uint scene_id;
- int ret, i;
+ bool add_gap;
+ int ret;
ret = expo_first_scene_id(exp);
if (ret < 0)
@@ -92,13 +96,57 @@ int bootflow_menu_add_all(struct expo *exp)
scene_id = ret;
scn = expo_lookup_scene_id(exp, scene_id);
- last_bootdev = NULL;
+ *str = seq < 10 ? '0' + seq : 'A' + seq - 10;
+ str[1] = '\0';
+ key = strdup(str);
+ if (!key)
+ return log_msg_ret("key", -ENOMEM);
+ label = strdup(dev_get_parent(bflow->dev)->name);
+ if (!label) {
+ free(key);
+ return log_msg_ret("nam", -ENOMEM);
+ }
+
+ add_gap = priv->last_bootdev != bflow->dev;
+ priv->last_bootdev = bflow->dev;
+
+ ret = expo_str(exp, "prompt", STR_POINTER, ">");
+ ret |= scene_txt_str(scn, "label", ITEM_LABEL + seq,
+ STR_LABEL + seq, label, NULL);
+ ret |= scene_txt_str(scn, "desc", ITEM_DESC + seq, STR_DESC + seq,
+ bflow->os_name ? bflow->os_name :
+ bflow->name, NULL);
+ ret |= scene_txt_str(scn, "key", ITEM_KEY + seq, STR_KEY + seq, key,
+ NULL);
+ preview_id = 0;
+ if (bflow->logo) {
+ preview_id = ITEM_PREVIEW + seq;
+ ret |= scene_img(scn, "preview", preview_id,
+ bflow->logo, NULL);
+ }
+ ret |= scene_menuitem(scn, OBJ_MENU, "item", ITEM + seq,
+ ITEM_KEY + seq, ITEM_LABEL + seq,
+ ITEM_DESC + seq, preview_id,
+ add_gap ? SCENEMIF_GAP_BEFORE : 0,
+ NULL);
+
+ if (ret < 0)
+ return log_msg_ret("itm", -EINVAL);
+ priv->num_bootflows++;
+ *scnp = scn;
+
+ return 0;
+}
+
+int bootflow_menu_add_all(struct expo *exp)
+{
+ struct bootflow *bflow;
+ struct scene *scn;
+ int ret, i;
+
for (ret = bootflow_first_glob(&bflow), i = 0; !ret && i < 36;
ret = bootflow_next_glob(&bflow), i++) {
struct bootmeth_uc_plat *ucp;
- char str[2], *label, *key;
- uint preview_id;
- bool add_gap;
if (bflow->state != BOOTFLOWST_READY)
continue;
@@ -108,43 +156,7 @@ int bootflow_menu_add_all(struct expo *exp)
if (ucp->flags & BOOTMETHF_GLOBAL)
continue;
- *str = i < 10 ? '0' + i : 'A' + i - 10;
- str[1] = '\0';
- key = strdup(str);
- if (!key)
- return log_msg_ret("key", -ENOMEM);
- label = strdup(dev_get_parent(bflow->dev)->name);
- if (!label) {
- free(key);
- return log_msg_ret("nam", -ENOMEM);
- }
-
- add_gap = last_bootdev != bflow->dev;
- last_bootdev = bflow->dev;
-
- ret = expo_str(exp, "prompt", STR_POINTER, ">");
- ret |= scene_txt_str(scn, "label", ITEM_LABEL + i,
- STR_LABEL + i, label, NULL);
- ret |= scene_txt_str(scn, "desc", ITEM_DESC + i, STR_DESC + i,
- bflow->os_name ? bflow->os_name :
- bflow->name, NULL);
- ret |= scene_txt_str(scn, "key", ITEM_KEY + i, STR_KEY + i, key,
- NULL);
- preview_id = 0;
- if (bflow->logo) {
- preview_id = ITEM_PREVIEW + i;
- ret |= scene_img(scn, "preview", preview_id,
- bflow->logo, NULL);
- }
- ret |= scene_menuitem(scn, OBJ_MENU, "item", ITEM + i,
- ITEM_KEY + i, ITEM_LABEL + i,
- ITEM_DESC + i, preview_id,
- add_gap ? SCENEMIF_GAP_BEFORE : 0,
- NULL);
-
- if (ret < 0)
- return log_msg_ret("itm", -EINVAL);
- priv->num_bootflows++;
+ LOGR("bao", bootflow_menu_add(exp, bflow, i, &scn));
}
ret = scene_arrange(scn);
diff --git a/include/bootflow.h b/include/bootflow.h
index 5f65129ca65..aa46cec4979 100644
--- a/include/bootflow.h
+++ b/include/bootflow.h
@@ -15,6 +15,7 @@
struct bootstd_priv;
struct expo;
+struct scene;
enum {
BOOTFLOW_MAX_USED_DEVS = 16,
@@ -507,6 +508,21 @@ int bootflow_menu_new(struct expo **expp);
*/
int bootflow_menu_add_all(struct expo *exp);
+/**
+ * bootflow_menu_add() - Add a bootflow to a menu
+ *
+ * Adds a new bootflow to the end of a menu. The caller must be careful to pass
+ * seq=0 for the first bootflow added, 1 for the second, etc.
+ *
+ * @exp: Menu to update
+ * @bflow: Bootflow to add
+ * @seq: Sequence number of this bootflow (0 = first)
+ * @scnp: Returns a pointer to the scene
+ * Return 0 on success, -ve on error
+ */
+int bootflow_menu_add(struct expo *exp, struct bootflow *bflow, int seq,
+ struct scene **scnp);
+
/**
* bootflow_menu_apply_theme() - Apply a theme to a bootmenu
*
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 28/56] expo: Rename scene_dim to scene_obj_bbox
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (26 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 27/56] expo: Allow adding a single bootflow to a menu Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 29/56] expo: Rename x and y in struct scene_obj_bbox Simon Glass
` (28 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Tom Rini
At present we assume that each object is a simple box and that it fills
the whole box.
This is quite limiting for text objects, which we may want to centre
within the box. We need a position within the box where drawing starts.
Rename the scene_dim struct to indicate that it is a bounding box.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
boot/scene.c | 36 +++++++++++-----------
| 12 ++++----
boot/scene_textline.c | 22 ++++++-------
include/expo.h | 8 ++---
test/boot/expo.c | 72 +++++++++++++++++++++----------------------
5 files changed, 75 insertions(+), 75 deletions(-)
diff --git a/boot/scene.c b/boot/scene.c
index fb82ffe768c..fbc6f783257 100644
--- a/boot/scene.c
+++ b/boot/scene.c
@@ -211,8 +211,8 @@ int scene_obj_set_pos(struct scene *scn, uint id, int x, int y)
obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
if (!obj)
return log_msg_ret("find", -ENOENT);
- obj->dim.x = x;
- obj->dim.y = y;
+ obj->bbox.x = x;
+ obj->bbox.y = y;
return 0;
}
@@ -224,8 +224,8 @@ int scene_obj_set_size(struct scene *scn, uint id, int w, int h)
obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
if (!obj)
return log_msg_ret("find", -ENOENT);
- obj->dim.w = w;
- obj->dim.h = h;
+ obj->bbox.w = w;
+ obj->bbox.h = h;
return 0;
}
@@ -369,8 +369,8 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode)
struct udevice *cons = text_mode ? NULL : exp->cons;
int x, y, ret;
- x = obj->dim.x;
- y = obj->dim.y;
+ x = obj->bbox.x;
+ y = obj->bbox.y;
switch (obj->type) {
case SCENEOBJT_NONE:
@@ -420,8 +420,8 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode)
if (obj->flags & SCENEOF_POINT) {
vidconsole_push_colour(cons, fore, back, &old);
video_fill_part(dev, x - theme->menu_inset, y,
- x + obj->dim.w,
- y + obj->dim.h,
+ x + obj->bbox.w,
+ y + obj->bbox.h,
vid_priv->colour_bg);
}
vidconsole_set_cursor_pos(cons, x, y);
@@ -766,8 +766,8 @@ int scene_calc_dims(struct scene *scn, bool do_menus)
ret = scene_obj_get_hw(scn, obj->id, &width);
if (ret < 0)
return log_msg_ret("get", ret);
- obj->dim.w = width;
- obj->dim.h = ret;
+ obj->bbox.w = width;
+ obj->bbox.h = ret;
}
break;
}
@@ -916,15 +916,15 @@ int scene_bbox_union(struct scene *scn, uint id, int inset,
if (!obj)
return log_msg_ret("obj", -ENOENT);
if (bbox->valid) {
- bbox->x0 = min(bbox->x0, obj->dim.x - inset);
- bbox->y0 = min(bbox->y0, obj->dim.y);
- bbox->x1 = max(bbox->x1, obj->dim.x + obj->dim.w + inset);
- bbox->y1 = max(bbox->y1, obj->dim.y + obj->dim.h);
+ bbox->x0 = min(bbox->x0, obj->bbox.x - inset);
+ bbox->y0 = min(bbox->y0, obj->bbox.y);
+ bbox->x1 = max(bbox->x1, obj->bbox.x + obj->bbox.w + inset);
+ bbox->y1 = max(bbox->y1, obj->bbox.y + obj->bbox.h);
} else {
- bbox->x0 = obj->dim.x - inset;
- bbox->y0 = obj->dim.y;
- bbox->x1 = obj->dim.x + obj->dim.w + inset;
- bbox->y1 = obj->dim.y + obj->dim.h;
+ bbox->x0 = obj->bbox.x - inset;
+ bbox->y0 = obj->bbox.y;
+ bbox->x1 = obj->bbox.x + obj->bbox.w + inset;
+ bbox->y1 = obj->bbox.y + obj->bbox.h;
bbox->valid = true;
}
--git a/boot/scene_menu.c b/boot/scene_menu.c
index df14a6c0409..f0a060a6356 100644
--- a/boot/scene_menu.c
+++ b/boot/scene_menu.c
@@ -102,7 +102,7 @@ static int update_pointers(struct scene_obj_menu *menu, uint id, bool point)
label = scene_obj_find(scn, item->label_id, SCENEOBJT_NONE);
ret = scene_obj_set_pos(scn, menu->pointer_id,
- menu->obj.dim.x + 200, label->dim.y);
+ menu->obj.bbox.x + 200, label->bbox.y);
if (ret < 0)
return log_msg_ret("ptr", ret);
}
@@ -179,8 +179,8 @@ int scene_menu_calc_dims(struct scene_obj_menu *menu)
}
if (bbox.valid) {
- menu->obj.dim.w = bbox.x1 - bbox.x0;
- menu->obj.dim.h = bbox.y1 - bbox.y0;
+ menu->obj.bbox.w = bbox.x1 - bbox.x0;
+ menu->obj.bbox.h = bbox.y1 - bbox.y0;
}
return 0;
@@ -198,12 +198,12 @@ int scene_menu_arrange(struct scene *scn, struct expo_arrange_info *arr,
int x, y;
int ret;
- x = menu->obj.dim.x;
- y = menu->obj.dim.y;
+ x = menu->obj.bbox.x;
+ y = menu->obj.bbox.y;
if (menu->title_id) {
int width;
- ret = scene_obj_set_pos(scn, menu->title_id, menu->obj.dim.x, y);
+ ret = scene_obj_set_pos(scn, menu->title_id, menu->obj.bbox.x, y);
if (ret < 0)
return log_msg_ret("tit", ret);
diff --git a/boot/scene_textline.c b/boot/scene_textline.c
index 6adef7cc173..4467bc4abcf 100644
--- a/boot/scene_textline.c
+++ b/boot/scene_textline.c
@@ -77,11 +77,11 @@ int scene_textline_calc_dims(struct scene_obj_textline *tline)
return log_msg_ret("nom", ret);
if (bbox.valid) {
- tline->obj.dim.w = bbox.x1 - bbox.x0;
- tline->obj.dim.h = bbox.y1 - bbox.y0;
+ tline->obj.bbox.w = bbox.x1 - bbox.x0;
+ tline->obj.bbox.h = bbox.y1 - bbox.y0;
- scene_obj_set_size(scn, tline->edit_id, tline->obj.dim.w,
- tline->obj.dim.h);
+ scene_obj_set_size(scn, tline->edit_id, tline->obj.bbox.w,
+ tline->obj.bbox.h);
}
return 0;
@@ -95,16 +95,16 @@ int scene_textline_arrange(struct scene *scn, struct expo_arrange_info *arr,
int x, y;
int ret;
- x = tline->obj.dim.x;
- y = tline->obj.dim.y;
+ x = tline->obj.bbox.x;
+ y = tline->obj.bbox.y;
if (tline->label_id) {
- ret = scene_obj_set_pos(scn, tline->label_id, tline->obj.dim.x,
+ ret = scene_obj_set_pos(scn, tline->label_id, tline->obj.bbox.x,
y);
if (ret < 0)
return log_msg_ret("tit", ret);
ret = scene_obj_set_pos(scn, tline->edit_id,
- tline->obj.dim.x + 200, y);
+ tline->obj.bbox.x + 200, y);
if (ret < 0)
return log_msg_ret("tit", ret);
@@ -198,8 +198,8 @@ int scene_textline_render_deps(struct scene *scn,
if (ret)
return log_msg_ret("sav", ret);
- vidconsole_set_cursor_visible(cons, true, txt->obj.dim.x,
- txt->obj.dim.y, scn->cls.num);
+ vidconsole_set_cursor_visible(cons, true, txt->obj.bbox.x,
+ txt->obj.bbox.y, scn->cls.num);
}
return 0;
@@ -220,7 +220,7 @@ int scene_textline_open(struct scene *scn, struct scene_obj_textline *tline)
if (!txt)
return log_msg_ret("cur", -ENOENT);
- vidconsole_set_cursor_pos(cons, txt->obj.dim.x, txt->obj.dim.y);
+ vidconsole_set_cursor_pos(cons, txt->obj.bbox.x, txt->obj.bbox.y);
vidconsole_entry_start(cons);
cli_cread_init(&scn->cls, abuf_data(&tline->buf), tline->max_chars);
scn->cls.insert = true;
diff --git a/include/expo.h b/include/expo.h
index a2b093c521d..42e934e3ff2 100644
--- a/include/expo.h
+++ b/include/expo.h
@@ -192,14 +192,14 @@ enum scene_obj_t {
};
/**
- * struct scene_dim - Dimensions of an object
+ * struct scene_obj_bbox - Dimensions of an object
*
* @x: x position, in pixels from left side
* @y: y position, in pixels from top
* @w: width, in pixels
* @h: height, in pixels
*/
-struct scene_dim {
+struct scene_obj_bbox {
int x;
int y;
int w;
@@ -232,7 +232,7 @@ enum {
* @name: Name of the object (allocated)
* @id: ID number of the object
* @type: Type of this object
- * @dim: Dimensions for this object
+ * @bbox: Dimensions for this object
* @flags: Flags for this object
* @bit_length: Number of bits used for this object in CMOS RAM
* @start_bit: Start bit to use for this object in CMOS RAM
@@ -243,7 +243,7 @@ struct scene_obj {
char *name;
uint id;
enum scene_obj_t type;
- struct scene_dim dim;
+ struct scene_obj_bbox bbox;
u8 flags;
u8 bit_length;
u16 start_bit;
diff --git a/test/boot/expo.c b/test/boot/expo.c
index b32a4596e85..77b956bdf06 100644
--- a/test/boot/expo.c
+++ b/test/boot/expo.c
@@ -270,8 +270,8 @@ static int expo_object_attr(struct unit_test_state *uts)
ut_assert(id > 0);
ut_assertok(scene_obj_set_pos(scn, OBJ_LOGO, 123, 456));
- ut_asserteq(123, img->obj.dim.x);
- ut_asserteq(456, img->obj.dim.y);
+ ut_asserteq(123, img->obj.bbox.x);
+ ut_asserteq(456, img->obj.bbox.y);
ut_asserteq(-ENOENT, scene_obj_set_pos(scn, OBJ_TEXT2, 0, 0));
@@ -360,8 +360,8 @@ static int expo_object_menu(struct unit_test_state *uts)
ut_asserteq(0, menu->pointer_id);
ut_assertok(scene_obj_set_pos(scn, OBJ_MENU, 50, 400));
- ut_asserteq(50, menu->obj.dim.x);
- ut_asserteq(400, menu->obj.dim.y);
+ ut_asserteq(50, menu->obj.bbox.x);
+ ut_asserteq(400, menu->obj.bbox.y);
id = scene_txt_str(scn, "title", OBJ_MENU_TITLE, STR_MENU_TITLE,
"Main Menu", &tit);
@@ -407,24 +407,24 @@ static int expo_object_menu(struct unit_test_state *uts)
ut_asserteq(id, menu->cur_item_id);
/* the title should be at the top */
- ut_asserteq(menu->obj.dim.x, tit->obj.dim.x);
- ut_asserteq(menu->obj.dim.y, tit->obj.dim.y);
+ ut_asserteq(menu->obj.bbox.x, tit->obj.bbox.x);
+ ut_asserteq(menu->obj.bbox.y, tit->obj.bbox.y);
/* the first item should be next */
- ut_asserteq(menu->obj.dim.x, name1->obj.dim.x);
- ut_asserteq(menu->obj.dim.y + 32, name1->obj.dim.y);
+ ut_asserteq(menu->obj.bbox.x, name1->obj.bbox.x);
+ ut_asserteq(menu->obj.bbox.y + 32, name1->obj.bbox.y);
- ut_asserteq(menu->obj.dim.x + 230, key1->obj.dim.x);
- ut_asserteq(menu->obj.dim.y + 32, key1->obj.dim.y);
+ ut_asserteq(menu->obj.bbox.x + 230, key1->obj.bbox.x);
+ ut_asserteq(menu->obj.bbox.y + 32, key1->obj.bbox.y);
- ut_asserteq(menu->obj.dim.x + 200, ptr->obj.dim.x);
- ut_asserteq(menu->obj.dim.y + 32, ptr->obj.dim.y);
+ ut_asserteq(menu->obj.bbox.x + 200, ptr->obj.bbox.x);
+ ut_asserteq(menu->obj.bbox.y + 32, ptr->obj.bbox.y);
- ut_asserteq(menu->obj.dim.x + 280, desc1->obj.dim.x);
- ut_asserteq(menu->obj.dim.y + 32, desc1->obj.dim.y);
+ ut_asserteq(menu->obj.bbox.x + 280, desc1->obj.bbox.x);
+ ut_asserteq(menu->obj.bbox.y + 32, desc1->obj.bbox.y);
- ut_asserteq(-4, prev1->obj.dim.x);
- ut_asserteq(menu->obj.dim.y + 32, prev1->obj.dim.y);
+ ut_asserteq(-4, prev1->obj.bbox.x);
+ ut_asserteq(menu->obj.bbox.y + 32, prev1->obj.bbox.y);
ut_asserteq(true, prev1->obj.flags & SCENEOF_HIDE);
/* check iterating through scene items */
@@ -548,41 +548,41 @@ static int expo_render_image(struct unit_test_state *uts)
/* check dimensions of text */
obj = scene_obj_find(scn, OBJ_TEXT, SCENEOBJT_NONE);
ut_assertnonnull(obj);
- ut_asserteq(400, obj->dim.x);
- ut_asserteq(100, obj->dim.y);
- ut_asserteq(126, obj->dim.w);
- ut_asserteq(40, obj->dim.h);
+ ut_asserteq(400, obj->bbox.x);
+ ut_asserteq(100, obj->bbox.y);
+ ut_asserteq(126, obj->bbox.w);
+ ut_asserteq(40, obj->bbox.h);
/* check dimensions of image */
obj = scene_obj_find(scn, OBJ_LOGO, SCENEOBJT_NONE);
ut_assertnonnull(obj);
- ut_asserteq(50, obj->dim.x);
- ut_asserteq(20, obj->dim.y);
- ut_asserteq(160, obj->dim.w);
- ut_asserteq(160, obj->dim.h);
+ ut_asserteq(50, obj->bbox.x);
+ ut_asserteq(20, obj->bbox.y);
+ ut_asserteq(160, obj->bbox.w);
+ ut_asserteq(160, obj->bbox.h);
/* check dimensions of menu labels - both should be the same width */
obj = scene_obj_find(scn, ITEM1_LABEL, SCENEOBJT_NONE);
ut_assertnonnull(obj);
- ut_asserteq(50, obj->dim.x);
- ut_asserteq(436, obj->dim.y);
- ut_asserteq(29, obj->dim.w);
- ut_asserteq(18, obj->dim.h);
+ ut_asserteq(50, obj->bbox.x);
+ ut_asserteq(436, obj->bbox.y);
+ ut_asserteq(29, obj->bbox.w);
+ ut_asserteq(18, obj->bbox.h);
obj = scene_obj_find(scn, ITEM2_LABEL, SCENEOBJT_NONE);
ut_assertnonnull(obj);
- ut_asserteq(50, obj->dim.x);
- ut_asserteq(454, obj->dim.y);
- ut_asserteq(29, obj->dim.w);
- ut_asserteq(18, obj->dim.h);
+ ut_asserteq(50, obj->bbox.x);
+ ut_asserteq(454, obj->bbox.y);
+ ut_asserteq(29, obj->bbox.w);
+ ut_asserteq(18, obj->bbox.h);
/* check dimensions of menu */
obj = scene_obj_find(scn, OBJ_MENU, SCENEOBJT_NONE);
ut_assertnonnull(obj);
- ut_asserteq(50, obj->dim.x);
- ut_asserteq(400, obj->dim.y);
- ut_asserteq(160, obj->dim.w);
- ut_asserteq(160, obj->dim.h);
+ ut_asserteq(50, obj->bbox.x);
+ ut_asserteq(400, obj->bbox.y);
+ ut_asserteq(160, obj->bbox.w);
+ ut_asserteq(160, obj->bbox.h);
/* render it */
expo_set_scene_id(exp, SCENE1);
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 29/56] expo: Rename x and y in struct scene_obj_bbox
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (27 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 28/56] expo: Rename scene_dim to scene_obj_bbox Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 30/56] expo: Use an abuf to hold strings Simon Glass
` (27 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Tom Rini
These coordinates are the top left values, so rename them to x0 and y0
in preparation for changing the width and height to x1 and y1
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
boot/scene.c | 24 ++++++++++----------
| 8 +++----
boot/scene_textline.c | 16 ++++++-------
include/expo.h | 8 +++----
test/boot/expo.c | 52 +++++++++++++++++++++----------------------
5 files changed, 54 insertions(+), 54 deletions(-)
diff --git a/boot/scene.c b/boot/scene.c
index fbc6f783257..75b1e4faba5 100644
--- a/boot/scene.c
+++ b/boot/scene.c
@@ -211,8 +211,8 @@ int scene_obj_set_pos(struct scene *scn, uint id, int x, int y)
obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
if (!obj)
return log_msg_ret("find", -ENOENT);
- obj->bbox.x = x;
- obj->bbox.y = y;
+ obj->bbox.x0 = x;
+ obj->bbox.y0 = y;
return 0;
}
@@ -369,8 +369,8 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode)
struct udevice *cons = text_mode ? NULL : exp->cons;
int x, y, ret;
- x = obj->bbox.x;
- y = obj->bbox.y;
+ x = obj->bbox.x0;
+ y = obj->bbox.y0;
switch (obj->type) {
case SCENEOBJT_NONE:
@@ -916,15 +916,15 @@ int scene_bbox_union(struct scene *scn, uint id, int inset,
if (!obj)
return log_msg_ret("obj", -ENOENT);
if (bbox->valid) {
- bbox->x0 = min(bbox->x0, obj->bbox.x - inset);
- bbox->y0 = min(bbox->y0, obj->bbox.y);
- bbox->x1 = max(bbox->x1, obj->bbox.x + obj->bbox.w + inset);
- bbox->y1 = max(bbox->y1, obj->bbox.y + obj->bbox.h);
+ bbox->x0 = min(bbox->x0, obj->bbox.x0 - inset);
+ bbox->y0 = min(bbox->y0, obj->bbox.y0);
+ bbox->x1 = max(bbox->x1, obj->bbox.x0 + obj->bbox.w + inset);
+ bbox->y1 = max(bbox->y1, obj->bbox.y0 + obj->bbox.h);
} else {
- bbox->x0 = obj->bbox.x - inset;
- bbox->y0 = obj->bbox.y;
- bbox->x1 = obj->bbox.x + obj->bbox.w + inset;
- bbox->y1 = obj->bbox.y + obj->bbox.h;
+ bbox->x0 = obj->bbox.x0 - inset;
+ bbox->y0 = obj->bbox.y0;
+ bbox->x1 = obj->bbox.x0 + obj->bbox.w + inset;
+ bbox->y1 = obj->bbox.y0 + obj->bbox.h;
bbox->valid = true;
}
--git a/boot/scene_menu.c b/boot/scene_menu.c
index f0a060a6356..00bbf9a3849 100644
--- a/boot/scene_menu.c
+++ b/boot/scene_menu.c
@@ -102,7 +102,7 @@ static int update_pointers(struct scene_obj_menu *menu, uint id, bool point)
label = scene_obj_find(scn, item->label_id, SCENEOBJT_NONE);
ret = scene_obj_set_pos(scn, menu->pointer_id,
- menu->obj.bbox.x + 200, label->bbox.y);
+ menu->obj.bbox.x0 + 200, label->bbox.y0);
if (ret < 0)
return log_msg_ret("ptr", ret);
}
@@ -198,12 +198,12 @@ int scene_menu_arrange(struct scene *scn, struct expo_arrange_info *arr,
int x, y;
int ret;
- x = menu->obj.bbox.x;
- y = menu->obj.bbox.y;
+ x = menu->obj.bbox.x0;
+ y = menu->obj.bbox.y0;
if (menu->title_id) {
int width;
- ret = scene_obj_set_pos(scn, menu->title_id, menu->obj.bbox.x, y);
+ ret = scene_obj_set_pos(scn, menu->title_id, menu->obj.bbox.x0, y);
if (ret < 0)
return log_msg_ret("tit", ret);
diff --git a/boot/scene_textline.c b/boot/scene_textline.c
index 4467bc4abcf..2ffeffeb5f5 100644
--- a/boot/scene_textline.c
+++ b/boot/scene_textline.c
@@ -95,16 +95,16 @@ int scene_textline_arrange(struct scene *scn, struct expo_arrange_info *arr,
int x, y;
int ret;
- x = tline->obj.bbox.x;
- y = tline->obj.bbox.y;
+ x = tline->obj.bbox.x0;
+ y = tline->obj.bbox.y0;
if (tline->label_id) {
- ret = scene_obj_set_pos(scn, tline->label_id, tline->obj.bbox.x,
- y);
+ ret = scene_obj_set_pos(scn, tline->label_id,
+ tline->obj.bbox.x0, y);
if (ret < 0)
return log_msg_ret("tit", ret);
ret = scene_obj_set_pos(scn, tline->edit_id,
- tline->obj.bbox.x + 200, y);
+ tline->obj.bbox.x0 + 200, y);
if (ret < 0)
return log_msg_ret("tit", ret);
@@ -198,8 +198,8 @@ int scene_textline_render_deps(struct scene *scn,
if (ret)
return log_msg_ret("sav", ret);
- vidconsole_set_cursor_visible(cons, true, txt->obj.bbox.x,
- txt->obj.bbox.y, scn->cls.num);
+ vidconsole_set_cursor_visible(cons, true, txt->obj.bbox.x0,
+ txt->obj.bbox.y0, scn->cls.num);
}
return 0;
@@ -220,7 +220,7 @@ int scene_textline_open(struct scene *scn, struct scene_obj_textline *tline)
if (!txt)
return log_msg_ret("cur", -ENOENT);
- vidconsole_set_cursor_pos(cons, txt->obj.bbox.x, txt->obj.bbox.y);
+ vidconsole_set_cursor_pos(cons, txt->obj.bbox.x0, txt->obj.bbox.y0);
vidconsole_entry_start(cons);
cli_cread_init(&scn->cls, abuf_data(&tline->buf), tline->max_chars);
scn->cls.insert = true;
diff --git a/include/expo.h b/include/expo.h
index 42e934e3ff2..84dc77f771e 100644
--- a/include/expo.h
+++ b/include/expo.h
@@ -194,14 +194,14 @@ enum scene_obj_t {
/**
* struct scene_obj_bbox - Dimensions of an object
*
- * @x: x position, in pixels from left side
- * @y: y position, in pixels from top
+ * @x0: x position, in pixels from left side
+ * @y0: y position, in pixels from top
* @w: width, in pixels
* @h: height, in pixels
*/
struct scene_obj_bbox {
- int x;
- int y;
+ int x0;
+ int y0;
int w;
int h;
};
diff --git a/test/boot/expo.c b/test/boot/expo.c
index 77b956bdf06..9c940825278 100644
--- a/test/boot/expo.c
+++ b/test/boot/expo.c
@@ -270,8 +270,8 @@ static int expo_object_attr(struct unit_test_state *uts)
ut_assert(id > 0);
ut_assertok(scene_obj_set_pos(scn, OBJ_LOGO, 123, 456));
- ut_asserteq(123, img->obj.bbox.x);
- ut_asserteq(456, img->obj.bbox.y);
+ ut_asserteq(123, img->obj.bbox.x0);
+ ut_asserteq(456, img->obj.bbox.y0);
ut_asserteq(-ENOENT, scene_obj_set_pos(scn, OBJ_TEXT2, 0, 0));
@@ -360,8 +360,8 @@ static int expo_object_menu(struct unit_test_state *uts)
ut_asserteq(0, menu->pointer_id);
ut_assertok(scene_obj_set_pos(scn, OBJ_MENU, 50, 400));
- ut_asserteq(50, menu->obj.bbox.x);
- ut_asserteq(400, menu->obj.bbox.y);
+ ut_asserteq(50, menu->obj.bbox.x0);
+ ut_asserteq(400, menu->obj.bbox.y0);
id = scene_txt_str(scn, "title", OBJ_MENU_TITLE, STR_MENU_TITLE,
"Main Menu", &tit);
@@ -407,24 +407,24 @@ static int expo_object_menu(struct unit_test_state *uts)
ut_asserteq(id, menu->cur_item_id);
/* the title should be at the top */
- ut_asserteq(menu->obj.bbox.x, tit->obj.bbox.x);
- ut_asserteq(menu->obj.bbox.y, tit->obj.bbox.y);
+ ut_asserteq(menu->obj.bbox.x0, tit->obj.bbox.x0);
+ ut_asserteq(menu->obj.bbox.y0, tit->obj.bbox.y0);
/* the first item should be next */
- ut_asserteq(menu->obj.bbox.x, name1->obj.bbox.x);
- ut_asserteq(menu->obj.bbox.y + 32, name1->obj.bbox.y);
+ ut_asserteq(menu->obj.bbox.x0, name1->obj.bbox.x0);
+ ut_asserteq(menu->obj.bbox.y0 + 32, name1->obj.bbox.y0);
- ut_asserteq(menu->obj.bbox.x + 230, key1->obj.bbox.x);
- ut_asserteq(menu->obj.bbox.y + 32, key1->obj.bbox.y);
+ ut_asserteq(menu->obj.bbox.x0 + 230, key1->obj.bbox.x0);
+ ut_asserteq(menu->obj.bbox.y0 + 32, key1->obj.bbox.y0);
- ut_asserteq(menu->obj.bbox.x + 200, ptr->obj.bbox.x);
- ut_asserteq(menu->obj.bbox.y + 32, ptr->obj.bbox.y);
+ ut_asserteq(menu->obj.bbox.x0 + 200, ptr->obj.bbox.x0);
+ ut_asserteq(menu->obj.bbox.y0 + 32, ptr->obj.bbox.y0);
- ut_asserteq(menu->obj.bbox.x + 280, desc1->obj.bbox.x);
- ut_asserteq(menu->obj.bbox.y + 32, desc1->obj.bbox.y);
+ ut_asserteq(menu->obj.bbox.x0 + 280, desc1->obj.bbox.x0);
+ ut_asserteq(menu->obj.bbox.y0 + 32, desc1->obj.bbox.y0);
- ut_asserteq(-4, prev1->obj.bbox.x);
- ut_asserteq(menu->obj.bbox.y + 32, prev1->obj.bbox.y);
+ ut_asserteq(-4, prev1->obj.bbox.x0);
+ ut_asserteq(menu->obj.bbox.y0 + 32, prev1->obj.bbox.y0);
ut_asserteq(true, prev1->obj.flags & SCENEOF_HIDE);
/* check iterating through scene items */
@@ -548,39 +548,39 @@ static int expo_render_image(struct unit_test_state *uts)
/* check dimensions of text */
obj = scene_obj_find(scn, OBJ_TEXT, SCENEOBJT_NONE);
ut_assertnonnull(obj);
- ut_asserteq(400, obj->bbox.x);
- ut_asserteq(100, obj->bbox.y);
+ ut_asserteq(400, obj->bbox.x0);
+ ut_asserteq(100, obj->bbox.y0);
ut_asserteq(126, obj->bbox.w);
ut_asserteq(40, obj->bbox.h);
/* check dimensions of image */
obj = scene_obj_find(scn, OBJ_LOGO, SCENEOBJT_NONE);
ut_assertnonnull(obj);
- ut_asserteq(50, obj->bbox.x);
- ut_asserteq(20, obj->bbox.y);
+ ut_asserteq(50, obj->bbox.x0);
+ ut_asserteq(20, obj->bbox.y0);
ut_asserteq(160, obj->bbox.w);
ut_asserteq(160, obj->bbox.h);
/* check dimensions of menu labels - both should be the same width */
obj = scene_obj_find(scn, ITEM1_LABEL, SCENEOBJT_NONE);
ut_assertnonnull(obj);
- ut_asserteq(50, obj->bbox.x);
- ut_asserteq(436, obj->bbox.y);
+ ut_asserteq(50, obj->bbox.x0);
+ ut_asserteq(436, obj->bbox.y0);
ut_asserteq(29, obj->bbox.w);
ut_asserteq(18, obj->bbox.h);
obj = scene_obj_find(scn, ITEM2_LABEL, SCENEOBJT_NONE);
ut_assertnonnull(obj);
- ut_asserteq(50, obj->bbox.x);
- ut_asserteq(454, obj->bbox.y);
+ ut_asserteq(50, obj->bbox.x0);
+ ut_asserteq(454, obj->bbox.y0);
ut_asserteq(29, obj->bbox.w);
ut_asserteq(18, obj->bbox.h);
/* check dimensions of menu */
obj = scene_obj_find(scn, OBJ_MENU, SCENEOBJT_NONE);
ut_assertnonnull(obj);
- ut_asserteq(50, obj->bbox.x);
- ut_asserteq(400, obj->bbox.y);
+ ut_asserteq(50, obj->bbox.x0);
+ ut_asserteq(400, obj->bbox.y0);
ut_asserteq(160, obj->bbox.w);
ut_asserteq(160, obj->bbox.h);
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 30/56] expo: Use an abuf to hold strings
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (28 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 29/56] expo: Rename x and y in struct scene_obj_bbox Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 31/56] expo: Separate dimensions from the bounding box Simon Glass
` (26 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Tom Rini
It is more convenient to put strings in an abuf so they can easily be
resized. Adjust the struct accordingly.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
boot/expo.c | 4 ++--
include/expo.h | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/boot/expo.c b/boot/expo.c
index ba052df932c..ee635116abc 100644
--- a/boot/expo.c
+++ b/boot/expo.c
@@ -86,7 +86,7 @@ int expo_str(struct expo *exp, const char *name, uint id, const char *str)
return log_msg_ret("obj", -ENOMEM);
estr->id = resolve_id(exp, id);
- estr->str = str;
+ abuf_init_const(&estr->buf, str, strlen(str) + 1);
list_add_tail(&estr->sibling, &exp->str_head);
return estr->id;
@@ -98,7 +98,7 @@ const char *expo_get_str(struct expo *exp, uint id)
list_for_each_entry(estr, &exp->str_head, sibling) {
if (estr->id == id)
- return estr->str;
+ return estr->buf.data;
}
return NULL;
diff --git a/include/expo.h b/include/expo.h
index 84dc77f771e..b6de0310071 100644
--- a/include/expo.h
+++ b/include/expo.h
@@ -134,12 +134,12 @@ struct expo {
* struct expo_string - a string that can be used in an expo
*
* @id: ID number of the string
- * @str: String
+ * @buf: String (contains nul terminator)
* @sibling: Node to link this object to its siblings
*/
struct expo_string {
uint id;
- const char *str;
+ struct abuf buf;
struct list_head sibling;
};
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 31/56] expo: Separate dimensions from the bounding box
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (29 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 30/56] expo: Use an abuf to hold strings Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 32/56] expo: Make bounding-box calculation more flexible Simon Glass
` (25 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Tom Rini
At present each object has a width and height and the bounding box is
implicit in that.
This is not flexible enough to handle objects which are larger than
their contents might need. For example, when centring a text object we
might want to have it stretch across the whole width of the display even
if the text itself does not need that much space.
Create a new 'dimensions' field and convert the existing width/height
into x1/y1 coordinates.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
boot/scene.c | 31 +++++++++++++++++++++----------
| 7 +++++--
boot/scene_textline.c | 18 ++++++++++++------
include/expo.h | 31 ++++++++++++++++++++++++++-----
test/boot/expo.c | 20 ++++++++++----------
5 files changed, 74 insertions(+), 33 deletions(-)
diff --git a/boot/scene.c b/boot/scene.c
index 75b1e4faba5..ff6712a0db6 100644
--- a/boot/scene.c
+++ b/boot/scene.c
@@ -207,12 +207,17 @@ int scene_txt_set_font(struct scene *scn, uint id, const char *font_name,
int scene_obj_set_pos(struct scene *scn, uint id, int x, int y)
{
struct scene_obj *obj;
+ int w, h;
obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
if (!obj)
return log_msg_ret("find", -ENOENT);
+ w = obj->bbox.x1 - obj->bbox.x0;
+ h = obj->bbox.y1 - obj->bbox.y0;
obj->bbox.x0 = x;
obj->bbox.y0 = y;
+ obj->bbox.x1 = obj->bbox.x0 + w;
+ obj->bbox.y1 = obj->bbox.y0 + h;
return 0;
}
@@ -224,8 +229,9 @@ int scene_obj_set_size(struct scene *scn, uint id, int w, int h)
obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
if (!obj)
return log_msg_ret("find", -ENOENT);
- obj->bbox.w = w;
- obj->bbox.h = h;
+ obj->bbox.x1 = obj->bbox.x0 + w;
+ obj->bbox.y1 = obj->bbox.y0 + h;
+ obj->flags |= SCENEOF_SIZE_VALID;
return 0;
}
@@ -420,8 +426,8 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode)
if (obj->flags & SCENEOF_POINT) {
vidconsole_push_colour(cons, fore, back, &old);
video_fill_part(dev, x - theme->menu_inset, y,
- x + obj->bbox.w,
- y + obj->bbox.h,
+ obj->bbox.x1,
+ obj->bbox.y1,
vid_priv->colour_bg);
}
vidconsole_set_cursor_pos(cons, x, y);
@@ -766,8 +772,13 @@ int scene_calc_dims(struct scene *scn, bool do_menus)
ret = scene_obj_get_hw(scn, obj->id, &width);
if (ret < 0)
return log_msg_ret("get", ret);
- obj->bbox.w = width;
- obj->bbox.h = ret;
+ obj->dims.x = width;
+ obj->dims.y = ret;
+ if (!(obj->flags & SCENEOF_SIZE_VALID)) {
+ obj->bbox.x1 = obj->bbox.x0 + width;
+ obj->bbox.y1 = obj->bbox.y0 + ret;
+ obj->flags |= SCENEOF_SIZE_VALID;
+ }
}
break;
}
@@ -918,13 +929,13 @@ int scene_bbox_union(struct scene *scn, uint id, int inset,
if (bbox->valid) {
bbox->x0 = min(bbox->x0, obj->bbox.x0 - inset);
bbox->y0 = min(bbox->y0, obj->bbox.y0);
- bbox->x1 = max(bbox->x1, obj->bbox.x0 + obj->bbox.w + inset);
- bbox->y1 = max(bbox->y1, obj->bbox.y0 + obj->bbox.h);
+ bbox->x1 = max(bbox->x1, obj->bbox.x1 + inset);
+ bbox->y1 = max(bbox->y1, obj->bbox.y1);
} else {
bbox->x0 = obj->bbox.x0 - inset;
bbox->y0 = obj->bbox.y0;
- bbox->x1 = obj->bbox.x0 + obj->bbox.w + inset;
- bbox->y1 = obj->bbox.y0 + obj->bbox.h;
+ bbox->x1 = obj->bbox.x1 + inset;
+ bbox->y1 = obj->bbox.y1;
bbox->valid = true;
}
--git a/boot/scene_menu.c b/boot/scene_menu.c
index 00bbf9a3849..490fb42995c 100644
--- a/boot/scene_menu.c
+++ b/boot/scene_menu.c
@@ -179,8 +179,8 @@ int scene_menu_calc_dims(struct scene_obj_menu *menu)
}
if (bbox.valid) {
- menu->obj.bbox.w = bbox.x1 - bbox.x0;
- menu->obj.bbox.h = bbox.y1 - bbox.y0;
+ menu->obj.dims.x = bbox.x1 - bbox.x0;
+ menu->obj.dims.y = bbox.y1 - bbox.y0;
}
return 0;
@@ -288,6 +288,9 @@ int scene_menu_arrange(struct scene *scn, struct expo_arrange_info *arr,
if (sel_id)
menu_point_to_item(menu, sel_id);
+ menu->obj.bbox.x1 = menu->obj.bbox.x0 + menu->obj.dims.x;
+ menu->obj.bbox.y1 = menu->obj.bbox.y0 + menu->obj.dims.y;
+ menu->obj.flags |= SCENEOF_SIZE_VALID;
return 0;
}
diff --git a/boot/scene_textline.c b/boot/scene_textline.c
index 2ffeffeb5f5..0bf54b2108b 100644
--- a/boot/scene_textline.c
+++ b/boot/scene_textline.c
@@ -62,7 +62,8 @@ void scene_textline_calc_bbox(struct scene_obj_textline *tline,
int scene_textline_calc_dims(struct scene_obj_textline *tline)
{
- struct scene *scn = tline->obj.scene;
+ struct scene_obj *obj = &tline->obj;
+ struct scene *scn = obj->scene;
struct vidconsole_bbox bbox;
struct scene_obj_txt *txt;
int ret;
@@ -77,11 +78,16 @@ int scene_textline_calc_dims(struct scene_obj_textline *tline)
return log_msg_ret("nom", ret);
if (bbox.valid) {
- tline->obj.bbox.w = bbox.x1 - bbox.x0;
- tline->obj.bbox.h = bbox.y1 - bbox.y0;
-
- scene_obj_set_size(scn, tline->edit_id, tline->obj.bbox.w,
- tline->obj.bbox.h);
+ obj->dims.x = bbox.x1 - bbox.x0;
+ obj->dims.y = bbox.y1 - bbox.y0;
+ if (!(obj->flags & SCENEOF_SIZE_VALID)) {
+ obj->bbox.x1 = obj->bbox.x0 + obj->dims.x;
+ obj->bbox.y1 = obj->bbox.y0 + obj->dims.y;
+ obj->flags |= SCENEOF_SIZE_VALID;
+ }
+ scene_obj_set_size(scn, tline->edit_id,
+ obj->bbox.x1 - obj->bbox.x0,
+ obj->bbox.y1 - obj->bbox.y0);
}
return 0;
diff --git a/include/expo.h b/include/expo.h
index b6de0310071..6f0547a4b38 100644
--- a/include/expo.h
+++ b/include/expo.h
@@ -9,6 +9,7 @@
#include <abuf.h>
#include <dm/ofnode_decl.h>
+#include <linux/bitops.h>
#include <linux/list.h>
struct udevice;
@@ -196,14 +197,29 @@ enum scene_obj_t {
*
* @x0: x position, in pixels from left side
* @y0: y position, in pixels from top
- * @w: width, in pixels
- * @h: height, in pixels
+ * @x1: x position of right size
+ * @y1: y position of bottom
*/
struct scene_obj_bbox {
int x0;
int y0;
- int w;
- int h;
+ int x1;
+ int y1;
+};
+
+/**
+ * struct scene_obj_dims - Dimensions of the object being drawn
+ *
+ * Image and text objects have a dimension which can change depending on what
+ * they contain. For images this stores the size. For text it stores the size as
+ * rendered on the display
+ *
+ * @x: x dimension
+ * @y: y dimension
+ */
+struct scene_obj_dims {
+ int x;
+ int y;
};
/**
@@ -213,11 +229,14 @@ struct scene_obj_bbox {
* @SCENEOF_POINT: object should be highlighted
* @SCENEOF_OPEN: object should be opened (e.g. menu is opened so that an option
* can be selected)
+ * @SCENEOF_SIZE_VALID: object's size (width/height) is valid, so any adjustment
+ * to x0/y0 should maintain the width/height of the object
*/
enum scene_obj_flags_t {
SCENEOF_HIDE = 1 << 0,
SCENEOF_POINT = 1 << 1,
SCENEOF_OPEN = 1 << 2,
+ SCENEOF_SIZE_VALID = BIT(3),
};
enum {
@@ -232,7 +251,8 @@ enum {
* @name: Name of the object (allocated)
* @id: ID number of the object
* @type: Type of this object
- * @bbox: Dimensions for this object
+ * @bbox: Bounding box for this object
+ * @dims: Dimensions of the text/image (may be smaller than bbox)
* @flags: Flags for this object
* @bit_length: Number of bits used for this object in CMOS RAM
* @start_bit: Start bit to use for this object in CMOS RAM
@@ -244,6 +264,7 @@ struct scene_obj {
uint id;
enum scene_obj_t type;
struct scene_obj_bbox bbox;
+ struct scene_obj_dims dims;
u8 flags;
u8 bit_length;
u16 start_bit;
diff --git a/test/boot/expo.c b/test/boot/expo.c
index 9c940825278..94c13e9b71f 100644
--- a/test/boot/expo.c
+++ b/test/boot/expo.c
@@ -550,39 +550,39 @@ static int expo_render_image(struct unit_test_state *uts)
ut_assertnonnull(obj);
ut_asserteq(400, obj->bbox.x0);
ut_asserteq(100, obj->bbox.y0);
- ut_asserteq(126, obj->bbox.w);
- ut_asserteq(40, obj->bbox.h);
+ ut_asserteq(400 + 126, obj->bbox.x1);
+ ut_asserteq(100 + 40, obj->bbox.y1);
/* check dimensions of image */
obj = scene_obj_find(scn, OBJ_LOGO, SCENEOBJT_NONE);
ut_assertnonnull(obj);
ut_asserteq(50, obj->bbox.x0);
ut_asserteq(20, obj->bbox.y0);
- ut_asserteq(160, obj->bbox.w);
- ut_asserteq(160, obj->bbox.h);
+ ut_asserteq(50 + 160, obj->bbox.x1);
+ ut_asserteq(20 + 160, obj->bbox.y1);
/* check dimensions of menu labels - both should be the same width */
obj = scene_obj_find(scn, ITEM1_LABEL, SCENEOBJT_NONE);
ut_assertnonnull(obj);
ut_asserteq(50, obj->bbox.x0);
ut_asserteq(436, obj->bbox.y0);
- ut_asserteq(29, obj->bbox.w);
- ut_asserteq(18, obj->bbox.h);
+ ut_asserteq(50 + 29, obj->bbox.x1);
+ ut_asserteq(436 + 18, obj->bbox.y1);
obj = scene_obj_find(scn, ITEM2_LABEL, SCENEOBJT_NONE);
ut_assertnonnull(obj);
ut_asserteq(50, obj->bbox.x0);
ut_asserteq(454, obj->bbox.y0);
- ut_asserteq(29, obj->bbox.w);
- ut_asserteq(18, obj->bbox.h);
+ ut_asserteq(50 + 29, obj->bbox.x1);
+ ut_asserteq(454 + 18, obj->bbox.y1);
/* check dimensions of menu */
obj = scene_obj_find(scn, OBJ_MENU, SCENEOBJT_NONE);
ut_assertnonnull(obj);
ut_asserteq(50, obj->bbox.x0);
ut_asserteq(400, obj->bbox.y0);
- ut_asserteq(160, obj->bbox.w);
- ut_asserteq(160, obj->bbox.h);
+ ut_asserteq(50 + 160, obj->bbox.x1);
+ ut_asserteq(400 + 160, obj->bbox.y1);
/* render it */
expo_set_scene_id(exp, SCENE1);
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 32/56] expo: Make bounding-box calculation more flexible
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (30 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 31/56] expo: Separate dimensions from the bounding box Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 33/56] expo: Support setting the size and bounds of an object Simon Glass
` (24 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Tom Rini
In some cases it is useful to obtain more than just two bounding boxes
from a menu, e.g. to line up all descriptions vertically.
Use an array to obtain bounding-box information and calculate it
separately for each item.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
boot/scene.c | 61 ++++++++++++++++++++++++--------------
boot/scene_internal.h | 46 ++++++++++++++++++++++++-----
| 69 +++++++++++++++++++++++++++----------------
3 files changed, 121 insertions(+), 55 deletions(-)
diff --git a/boot/scene.c b/boot/scene.c
index ff6712a0db6..6142d2b736d 100644
--- a/boot/scene.c
+++ b/boot/scene.c
@@ -326,9 +326,9 @@ int scene_obj_get_hw(struct scene *scn, uint id, int *widthp)
*/
static void scene_render_background(struct scene_obj *obj, bool box_only)
{
+ struct vidconsole_bbox bbox[SCENEBB_count], *sel;
struct expo *exp = obj->scene->expo;
const struct expo_theme *theme = &exp->theme;
- struct vidconsole_bbox bbox, label_bbox;
struct udevice *dev = exp->display;
struct video_priv *vid_priv;
struct udevice *cons = exp->cons;
@@ -347,17 +347,20 @@ static void scene_render_background(struct scene_obj *obj, bool box_only)
}
/* see if this object wants to render a background */
- if (scene_obj_calc_bbox(obj, &bbox, &label_bbox))
+ if (scene_obj_calc_bbox(obj, bbox))
+ return;
+
+ sel = &bbox[SCENEBB_label];
+ if (!sel->valid)
return;
vidconsole_push_colour(cons, fore, back, &old);
- video_fill_part(dev, label_bbox.x0 - inset, label_bbox.y0 - inset,
- label_bbox.x1 + inset, label_bbox.y1 + inset,
+ video_fill_part(dev, sel->x0 - inset, sel->y0 - inset,
+ sel->x1 + inset, sel->y1 + inset,
vid_priv->colour_fg);
vidconsole_pop_colour(cons, &old);
if (box_only) {
- video_fill_part(dev, label_bbox.x0, label_bbox.y0,
- label_bbox.x1, label_bbox.y1,
+ video_fill_part(dev, sel->x0, sel->y0, sel->x1, sel->y1,
vid_priv->colour_bg);
}
}
@@ -730,8 +733,7 @@ int scene_send_key(struct scene *scn, int key, struct expo_action *event)
return 0;
}
-int scene_obj_calc_bbox(struct scene_obj *obj, struct vidconsole_bbox *bbox,
- struct vidconsole_bbox *label_bbox)
+int scene_obj_calc_bbox(struct scene_obj *obj, struct vidconsole_bbox bbox[])
{
switch (obj->type) {
case SCENEOBJT_NONE:
@@ -741,14 +743,15 @@ int scene_obj_calc_bbox(struct scene_obj *obj, struct vidconsole_bbox *bbox,
case SCENEOBJT_MENU: {
struct scene_obj_menu *menu = (struct scene_obj_menu *)obj;
- scene_menu_calc_bbox(menu, bbox, label_bbox);
+ scene_menu_calc_bbox(menu, bbox);
break;
}
case SCENEOBJT_TEXTLINE: {
struct scene_obj_textline *tline;
tline = (struct scene_obj_textline *)obj;
- scene_textline_calc_bbox(tline, bbox, label_bbox);
+ scene_textline_calc_bbox(tline, &bbox[SCENEBB_all],
+ &bbox[SCENEBB_label]);
break;
}
}
@@ -916,28 +919,42 @@ int scene_iter_objs(struct scene *scn, expo_scene_obj_iterator iter,
return 0;
}
+int scene_bbox_join(const struct vidconsole_bbox *src, int inset,
+ struct vidconsole_bbox *dst)
+{
+ if (dst->valid) {
+ dst->x0 = min(dst->x0, src->x0 - inset);
+ dst->y0 = min(dst->y0, src->y0);
+ dst->x1 = max(dst->x1, src->x1 + inset);
+ dst->y1 = max(dst->y1, src->y1);
+ } else {
+ dst->x0 = src->x0 - inset;
+ dst->y0 = src->y0;
+ dst->x1 = src->x1 + inset;
+ dst->y1 = src->y1;
+ dst->valid = true;
+ }
+
+ return 0;
+}
+
int scene_bbox_union(struct scene *scn, uint id, int inset,
struct vidconsole_bbox *bbox)
{
struct scene_obj *obj;
+ struct vidconsole_bbox local;
if (!id)
return 0;
obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
if (!obj)
return log_msg_ret("obj", -ENOENT);
- if (bbox->valid) {
- bbox->x0 = min(bbox->x0, obj->bbox.x0 - inset);
- bbox->y0 = min(bbox->y0, obj->bbox.y0);
- bbox->x1 = max(bbox->x1, obj->bbox.x1 + inset);
- bbox->y1 = max(bbox->y1, obj->bbox.y1);
- } else {
- bbox->x0 = obj->bbox.x0 - inset;
- bbox->y0 = obj->bbox.y0;
- bbox->x1 = obj->bbox.x1 + inset;
- bbox->y1 = obj->bbox.y1;
- bbox->valid = true;
- }
+ local.x0 = obj->bbox.x0;
+ local.y0 = obj->bbox.y0;
+ local.x1 = obj->bbox.x1;
+ local.y1 = obj->bbox.y1;
+ local.valid = true;
+ scene_bbox_join(&local, inset, bbox);
return 0;
}
diff --git a/boot/scene_internal.h b/boot/scene_internal.h
index ec9008ea593..ac2a36d6e4d 100644
--- a/boot/scene_internal.h
+++ b/boot/scene_internal.h
@@ -13,6 +13,27 @@ struct vidconsole_bbox;
typedef int (*expo_scene_obj_iterator)(struct scene_obj *obj, void *priv);
+/**
+ * enum scene_bbox_t - Parts of an object which can have a bounding box
+ *
+ * Objects can provide any or all of these bounding boxes
+ *
+ * @SCENEBB_label: Menu-item label
+ * @SCENEBB_key: Menu-item key label
+ * @SCENEBB_desc: Menu-item Description
+ * @SCENEBB_curitem: Current item (pointed to)
+ * @SCENEBB_all: All the above objects combined
+ */
+enum scene_bbox_t {
+ SCENEBB_label,
+ SCENEBB_key,
+ SCENEBB_desc,
+ SCENEBB_curitem,
+ SCENEBB_all,
+
+ SCENEBB_count,
+};
+
/**
* expo_lookup_scene_id() - Look up a scene ID
*
@@ -291,6 +312,19 @@ struct scene_menitem *scene_menuitem_find_seq(const struct scene_obj_menu *menu,
struct scene_menitem *scene_menuitem_find_val(const struct scene_obj_menu *menu,
int val);
+/**
+ * scene_bbox_join() - update bouding box with a given src box
+ *
+ * Updates @dst so that it encompasses the bounding box @src
+ *
+ * @src: Input bounding box
+ * @inset: Amount of inset to use for width
+ * @dst: Bounding box to update
+ * Return: 0 if OK, -ve on error
+ */
+int scene_bbox_join(const struct vidconsole_bbox *src, int inset,
+ struct vidconsole_bbox *dst);
+
/**
* scene_bbox_union() - update bouding box with the demensions of an object
*
@@ -319,13 +353,11 @@ int scene_textline_calc_dims(struct scene_obj_textline *tline);
* scene_menu_calc_bbox() - Calculate bounding boxes for the menu
*
* @menu: Menu to process
- * @bbox: Returns bounding box of menu including prompts
- * @label_bbox: Returns bounding box of labels
+ * @bbox: List of bounding box to fill in
* Return: 0 if OK, -ve on error
*/
void scene_menu_calc_bbox(struct scene_obj_menu *menu,
- struct vidconsole_bbox *bbox,
- struct vidconsole_bbox *label_bbox);
+ struct vidconsole_bbox *bbox);
/**
* scene_textline_calc_bbox() - Calculate bounding box for the textline
@@ -343,12 +375,10 @@ void scene_textline_calc_bbox(struct scene_obj_textline *menu,
* scene_obj_calc_bbox() - Calculate bounding boxes for an object
*
* @obj: Object to process
- * @bbox: Returns bounding box of object including prompts
- * @label_bbox: Returns bounding box of labels (active area)
+ * @bbox: Returns bounding boxes for object
* Return: 0 if OK, -ve on error
*/
-int scene_obj_calc_bbox(struct scene_obj *obj, struct vidconsole_bbox *bbox,
- struct vidconsole_bbox *label_bbox);
+int scene_obj_calc_bbox(struct scene_obj *obj, struct vidconsole_bbox *bbox);
/**
* scene_textline_open() - Open a textline object
--git a/boot/scene_menu.c b/boot/scene_menu.c
index 490fb42995c..3df3c6ed1d8 100644
--- a/boot/scene_menu.c
+++ b/boot/scene_menu.c
@@ -132,55 +132,74 @@ static int menu_point_to_item(struct scene_obj_menu *menu, uint item_id)
}
void scene_menu_calc_bbox(struct scene_obj_menu *menu,
- struct vidconsole_bbox *bbox,
- struct vidconsole_bbox *label_bbox)
+ struct vidconsole_bbox *bbox)
{
const struct expo_theme *theme = &menu->obj.scene->expo->theme;
const struct scene_menitem *item;
+ int inset = theme->menu_inset;
+ int i;
- bbox->valid = false;
- scene_bbox_union(menu->obj.scene, menu->title_id, 0, bbox);
+ for (i = 0; i < SCENEBB_count; i++)
+ bbox[i].valid = false;
- label_bbox->valid = false;
+ scene_bbox_union(menu->obj.scene, menu->title_id, 0,
+ &bbox[SCENEBB_all]);
list_for_each_entry(item, &menu->item_head, sibling) {
- scene_bbox_union(menu->obj.scene, item->label_id,
- theme->menu_inset, bbox);
- scene_bbox_union(menu->obj.scene, item->key_id, 0, bbox);
- scene_bbox_union(menu->obj.scene, item->desc_id, 0, bbox);
- scene_bbox_union(menu->obj.scene, item->preview_id, 0, bbox);
-
- /* Get the bounding box of all labels */
- scene_bbox_union(menu->obj.scene, item->label_id,
- theme->menu_inset, label_bbox);
+ struct vidconsole_bbox local;
+
+ local.valid = false;
+ scene_bbox_union(menu->obj.scene, item->label_id, inset,
+ &local);
+ scene_bbox_union(menu->obj.scene, item->key_id, 0, &local);
+ scene_bbox_union(menu->obj.scene, item->desc_id, 0, &local);
+ scene_bbox_union(menu->obj.scene, item->preview_id, 0, &local);
+
+ scene_bbox_join(&local, 0, &bbox[SCENEBB_all]);
+
+ /* Get the bounding box of all individual fields */
+ scene_bbox_union(menu->obj.scene, item->label_id, inset,
+ &bbox[SCENEBB_label]);
+ scene_bbox_union(menu->obj.scene, item->key_id, inset,
+ &bbox[SCENEBB_key]);
+ scene_bbox_union(menu->obj.scene, item->desc_id, inset,
+ &bbox[SCENEBB_desc]);
+
+ if (menu->cur_item_id == item->id)
+ scene_bbox_join(&local, 0, &bbox[SCENEBB_curitem]);
}
/*
- * subtract the final menuitem's gap to keep the insert the same top
- * and bottom
+ * subtract the final menuitem's gap to keep the inset the same top and
+ * bottom
*/
- label_bbox->y1 -= theme->menuitem_gap_y;
+ bbox[SCENEBB_label].y1 -= theme->menuitem_gap_y;
}
int scene_menu_calc_dims(struct scene_obj_menu *menu)
{
- struct vidconsole_bbox bbox, label_bbox;
+ struct vidconsole_bbox bbox[SCENEBB_count], *cur;
const struct scene_menitem *item;
- scene_menu_calc_bbox(menu, &bbox, &label_bbox);
+ scene_menu_calc_bbox(menu, bbox);
/* Make all labels the same size */
- if (label_bbox.valid) {
+ cur = &bbox[SCENEBB_label];
+ if (cur->valid) {
list_for_each_entry(item, &menu->item_head, sibling) {
scene_obj_set_size(menu->obj.scene, item->label_id,
- label_bbox.x1 - label_bbox.x0,
- label_bbox.y1 - label_bbox.y0);
+ cur->x1 - cur->x0,
+ cur->y1 - cur->y0);
}
}
- if (bbox.valid) {
- menu->obj.dims.x = bbox.x1 - bbox.x0;
- menu->obj.dims.y = bbox.y1 - bbox.y0;
+ cur = &bbox[SCENEBB_all];
+ if (cur->valid) {
+ menu->obj.dims.x = cur->x1 - cur->x0;
+ menu->obj.dims.y = cur->y1 - cur->y0;
+
+ menu->obj.bbox.x1 = cur->x1;
+ menu->obj.bbox.y1 = cur->y1;
}
return 0;
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 33/56] expo: Support setting the size and bounds of an object
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (31 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 32/56] expo: Make bounding-box calculation more flexible Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 34/56] expo: Line up all menu objects Simon Glass
` (23 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Tom Rini
Add a function to allow the size of an object to be set independently
of its position.
Also add a function to permit the object's bounding box to be set
independently of its dimensions.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
boot/scene.c | 29 +++++++++++++++++++++++++++++
include/expo.h | 24 ++++++++++++++++++++++++
test/boot/expo.c | 11 +++++++++++
3 files changed, 64 insertions(+)
diff --git a/boot/scene.c b/boot/scene.c
index 6142d2b736d..dd48589f378 100644
--- a/boot/scene.c
+++ b/boot/scene.c
@@ -236,6 +236,35 @@ int scene_obj_set_size(struct scene *scn, uint id, int w, int h)
return 0;
}
+int scene_obj_set_width(struct scene *scn, uint id, int w)
+{
+ struct scene_obj *obj;
+
+ obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
+ if (!obj)
+ return log_msg_ret("find", -ENOENT);
+ obj->bbox.x1 = obj->bbox.x0 + w;
+
+ return 0;
+}
+
+int scene_obj_set_bbox(struct scene *scn, uint id, int x0, int y0, int x1,
+ int y1)
+{
+ struct scene_obj *obj;
+
+ obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
+ if (!obj)
+ return log_msg_ret("find", -ENOENT);
+ obj->bbox.x0 = x0;
+ obj->bbox.y0 = y0;
+ obj->bbox.x1 = x1;
+ obj->bbox.y1 = y1;
+ obj->flags |= SCENEOF_SIZE_VALID;
+
+ return 0;
+}
+
int scene_obj_set_hide(struct scene *scn, uint id, bool hide)
{
int ret;
diff --git a/include/expo.h b/include/expo.h
index 6f0547a4b38..990cb3094ee 100644
--- a/include/expo.h
+++ b/include/expo.h
@@ -673,6 +673,30 @@ int scene_obj_set_pos(struct scene *scn, uint id, int x, int y);
*/
int scene_obj_set_size(struct scene *scn, uint id, int w, int h);
+/**
+ * scene_obj_set_width() - Set the width of an object
+ *
+ * @scn: Scene to update
+ * @id: ID of object to update
+ * @w: width in pixels
+ * Returns: 0 if OK, -ENOENT if @id is invalid
+ */
+int scene_obj_set_width(struct scene *scn, uint id, int w);
+
+/**
+ * scene_obj_set_bbox() - Set the bounding box of an object
+ *
+ * @scn: Scene to update
+ * @id: ID of object to update
+ * @x0: x position, in pixels from left side
+ * @y0: y position, in pixels from top
+ * @x1: ending x position (right side)
+ * @y1: ending y position (botton side)
+ * Returns: 0 if OK, -ENOENT if @id is invalid
+ */
+int scene_obj_set_bbox(struct scene *scn, uint id, int x0, int y0, int x1,
+ int y1);
+
/**
* scene_obj_set_hide() - Set whether an object is hidden
*
diff --git a/test/boot/expo.c b/test/boot/expo.c
index 94c13e9b71f..2a430d3d482 100644
--- a/test/boot/expo.c
+++ b/test/boot/expo.c
@@ -584,6 +584,17 @@ static int expo_render_image(struct unit_test_state *uts)
ut_asserteq(50 + 160, obj->bbox.x1);
ut_asserteq(400 + 160, obj->bbox.y1);
+ scene_obj_set_width(scn, OBJ_MENU, 170);
+ ut_asserteq(50 + 170, obj->bbox.x1);
+ scene_obj_set_bbox(scn, OBJ_MENU, 60, 410, 50 + 160, 400 + 160);
+ ut_asserteq(60, obj->bbox.x0);
+ ut_asserteq(410, obj->bbox.y0);
+ ut_asserteq(50 + 160, obj->bbox.x1);
+ ut_asserteq(400 + 160, obj->bbox.y1);
+
+ /* reset back to normal */
+ scene_obj_set_bbox(scn, OBJ_MENU, 50, 400, 50 + 160, 400 + 160);
+
/* render it */
expo_set_scene_id(exp, SCENE1);
ut_assertok(expo_render(exp));
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 34/56] expo: Line up all menu objects
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (32 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 33/56] expo: Support setting the size and bounds of an object Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 35/56] expo: Create a struct for generic text attributes Simon Glass
` (22 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Tom Rini
At present labels are lined up vertically. Do the same with keys and
descriptions, since it looks nicer.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
| 22 ++++++++++++++--------
test/boot/expo.c | 30 ++++++++++++++++++++++++++++++
2 files changed, 44 insertions(+), 8 deletions(-)
--git a/boot/scene_menu.c b/boot/scene_menu.c
index 3df3c6ed1d8..914f109fa35 100644
--- a/boot/scene_menu.c
+++ b/boot/scene_menu.c
@@ -183,14 +183,20 @@ int scene_menu_calc_dims(struct scene_obj_menu *menu)
scene_menu_calc_bbox(menu, bbox);
- /* Make all labels the same size */
- cur = &bbox[SCENEBB_label];
- if (cur->valid) {
- list_for_each_entry(item, &menu->item_head, sibling) {
- scene_obj_set_size(menu->obj.scene, item->label_id,
- cur->x1 - cur->x0,
- cur->y1 - cur->y0);
- }
+ /* Make all field types the same width */
+ list_for_each_entry(item, &menu->item_head, sibling) {
+ cur = &bbox[SCENEBB_label];
+ if (cur->valid)
+ scene_obj_set_width(menu->obj.scene, item->label_id,
+ cur->x1 - cur->x0);
+ cur = &bbox[SCENEBB_key];
+ if (cur->valid)
+ scene_obj_set_width(menu->obj.scene, item->key_id,
+ cur->x1 - cur->x0);
+ cur = &bbox[SCENEBB_desc];
+ if (cur->valid)
+ scene_obj_set_width(menu->obj.scene, item->desc_id,
+ cur->x1 - cur->x0);
}
cur = &bbox[SCENEBB_all];
diff --git a/test/boot/expo.c b/test/boot/expo.c
index 2a430d3d482..70db33d48b1 100644
--- a/test/boot/expo.c
+++ b/test/boot/expo.c
@@ -576,6 +576,36 @@ static int expo_render_image(struct unit_test_state *uts)
ut_asserteq(50 + 29, obj->bbox.x1);
ut_asserteq(454 + 18, obj->bbox.y1);
+ /* same for the key */
+ obj = scene_obj_find(scn, ITEM1_KEY, SCENEOBJT_NONE);
+ ut_assertnonnull(obj);
+ ut_asserteq(280, obj->bbox.x0);
+ ut_asserteq(436, obj->bbox.y0);
+ ut_asserteq(280 + 9, obj->bbox.x1);
+ ut_asserteq(436 + 18, obj->bbox.y1);
+
+ obj = scene_obj_find(scn, ITEM2_KEY, SCENEOBJT_NONE);
+ ut_assertnonnull(obj);
+ ut_asserteq(280, obj->bbox.x0);
+ ut_asserteq(454, obj->bbox.y0);
+ ut_asserteq(280 + 9, obj->bbox.x1);
+ ut_asserteq(454 + 18, obj->bbox.y1);
+
+ /* and the description */
+ obj = scene_obj_find(scn, ITEM1_DESC, SCENEOBJT_NONE);
+ ut_assertnonnull(obj);
+ ut_asserteq(330, obj->bbox.x0);
+ ut_asserteq(436, obj->bbox.y0);
+ ut_asserteq(330 + 89, obj->bbox.x1);
+ ut_asserteq(436 + 18, obj->bbox.y1);
+
+ obj = scene_obj_find(scn, ITEM2_DESC, SCENEOBJT_NONE);
+ ut_assertnonnull(obj);
+ ut_asserteq(330, obj->bbox.x0);
+ ut_asserteq(454, obj->bbox.y0);
+ ut_asserteq(330 + 89, obj->bbox.x1);
+ ut_asserteq(454 + 18, obj->bbox.y1);
+
/* check dimensions of menu */
obj = scene_obj_find(scn, OBJ_MENU, SCENEOBJT_NONE);
ut_assertnonnull(obj);
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 35/56] expo: Create a struct for generic text attributes
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (33 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 34/56] expo: Line up all menu objects Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 36/56] expo: Move text-rendering into its own function Simon Glass
` (21 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Guillaume La Roque, Heinrich Schuchardt,
Mattijs Korpershoek, Rasmus Villemoes, Stefan Roese, Tom Rini
In preparation for adding more text types, refactor the common fields
into a new structure. This will allow common code to be used.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
boot/cedit.c | 2 +-
boot/scene.c | 63 ++++++++++++++++++++++++++++---------------
| 12 ++++-----
boot/scene_textline.c | 10 +++----
include/expo.h | 21 ++++++++++-----
test/boot/bootflow.c | 2 +-
test/boot/cedit.c | 2 +-
test/boot/expo.c | 15 ++++++-----
8 files changed, 78 insertions(+), 49 deletions(-)
diff --git a/boot/cedit.c b/boot/cedit.c
index eabbf07a8a0..83e50f98c93 100644
--- a/boot/cedit.c
+++ b/boot/cedit.c
@@ -268,7 +268,7 @@ static int get_cur_menuitem_text(const struct scene_obj_menu *menu,
if (!txt)
return log_msg_ret("txt", -ENOENT);
- str = expo_get_str(scn->expo, txt->str_id);
+ str = expo_get_str(scn->expo, txt->gen.str_id);
if (!str)
return log_msg_ret("str", -ENOENT);
*strp = str;
diff --git a/boot/scene.c b/boot/scene.c
index dd48589f378..bf56f4341aa 100644
--- a/boot/scene.c
+++ b/boot/scene.c
@@ -143,6 +143,31 @@ int scene_img(struct scene *scn, const char *name, uint id, char *data,
return img->obj.id;
}
+int scene_txt_generic_init(struct expo *exp, struct scene_txt_generic *gen,
+ const char *name, uint str_id, const char *str)
+{
+ int ret;
+
+ if (str) {
+ ret = expo_str(exp, name, str_id, str);
+ if (ret < 0)
+ return log_msg_ret("str", ret);
+ if (str_id && ret != str_id)
+ return log_msg_ret("id", -EEXIST);
+ str_id = ret;
+ } else {
+ ret = resolve_id(exp, str_id);
+ if (ret < 0)
+ return log_msg_ret("nst", ret);
+ if (str_id && ret != str_id)
+ return log_msg_ret("nid", -EEXIST);
+ }
+
+ gen->str_id = str_id;
+
+ return 0;
+}
+
int scene_txt(struct scene *scn, const char *name, uint id, uint str_id,
struct scene_obj_txt **txtp)
{
@@ -155,8 +180,8 @@ int scene_txt(struct scene *scn, const char *name, uint id, uint str_id,
if (ret < 0)
return log_msg_ret("obj", ret);
- txt->str_id = str_id;
-
+ LOGR("stg", scene_txt_generic_init(scn->expo, &txt->gen, name, str_id,
+ NULL));
if (txtp)
*txtp = txt;
@@ -169,21 +194,14 @@ int scene_txt_str(struct scene *scn, const char *name, uint id, uint str_id,
struct scene_obj_txt *txt;
int ret;
- ret = expo_str(scn->expo, name, str_id, str);
- if (ret < 0)
- return log_msg_ret("str", ret);
- if (str_id && ret != str_id)
- return log_msg_ret("id", -EEXIST);
- str_id = ret;
-
ret = scene_obj_add(scn, name, id, SCENEOBJT_TEXT,
sizeof(struct scene_obj_txt),
(struct scene_obj **)&txt);
if (ret < 0)
return log_msg_ret("obj", ret);
- txt->str_id = str_id;
-
+ LOGR("tsg", scene_txt_generic_init(scn->expo, &txt->gen, name, str_id,
+ str));
if (txtp)
*txtp = txt;
@@ -198,8 +216,8 @@ int scene_txt_set_font(struct scene *scn, uint id, const char *font_name,
txt = scene_obj_find(scn, id, SCENEOBJT_TEXT);
if (!txt)
return log_msg_ret("find", -ENOENT);
- txt->font_name = font_name;
- txt->font_size = font_size;
+ txt->gen.font_name = font_name;
+ txt->gen.font_size = font_size;
return 0;
}
@@ -314,13 +332,13 @@ int scene_obj_get_hw(struct scene *scn, uint id, int *widthp)
return height;
}
case SCENEOBJT_TEXT: {
- struct scene_obj_txt *txt = (struct scene_obj_txt *)obj;
+ struct scene_txt_generic *gen = &((struct scene_obj_txt *)obj)->gen;
struct expo *exp = scn->expo;
struct vidconsole_bbox bbox;
const char *str;
int len, ret;
- str = expo_get_str(exp, txt->str_id);
+ str = expo_get_str(exp, gen->str_id);
if (!str)
return log_msg_ret("str", -ENOENT);
len = strlen(str);
@@ -332,8 +350,8 @@ int scene_obj_get_hw(struct scene *scn, uint id, int *widthp)
return 16;
}
- ret = vidconsole_measure(scn->expo->cons, txt->font_name,
- txt->font_size, str, -1, &bbox, NULL);
+ ret = vidconsole_measure(scn->expo->cons, gen->font_name,
+ gen->font_size, str, -1, &bbox, NULL);
if (ret)
return log_msg_ret("mea", ret);
if (widthp)
@@ -425,22 +443,23 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode)
break;
}
case SCENEOBJT_TEXT: {
- struct scene_obj_txt *txt = (struct scene_obj_txt *)obj;
+ struct scene_txt_generic *gen =
+ &((struct scene_obj_txt *)obj)->gen;
const char *str;
if (!cons)
return -ENOTSUPP;
- if (txt->font_name || txt->font_size) {
+ if (gen->font_name || gen->font_size) {
ret = vidconsole_select_font(cons,
- txt->font_name,
- txt->font_size);
+ gen->font_name,
+ gen->font_size);
} else {
ret = vidconsole_select_font(cons, NULL, 0);
}
if (ret && ret != -ENOSYS)
return log_msg_ret("font", ret);
- str = expo_get_str(exp, txt->str_id);
+ str = expo_get_str(exp, gen->str_id);
if (str) {
struct video_priv *vid_priv;
struct vidconsole_colour old;
--git a/boot/scene_menu.c b/boot/scene_menu.c
index 914f109fa35..b0c241a9ee9 100644
--- a/boot/scene_menu.c
+++ b/boot/scene_menu.c
@@ -352,7 +352,7 @@ static struct scene_menitem *scene_menu_find_key(struct scene *scn,
txt = scene_obj_find(scn, item->key_id, SCENEOBJT_TEXT);
if (txt) {
- str = expo_get_str(scn->expo, txt->str_id);
+ str = expo_get_str(scn->expo, txt->gen.str_id);
if (str && *str == key)
return item;
}
@@ -552,7 +552,7 @@ int scene_menu_display(struct scene_obj_menu *menu)
if (!txt)
return log_msg_ret("txt", -EINVAL);
- str = expo_get_str(exp, txt->str_id);
+ str = expo_get_str(exp, txt->gen.str_id);
printf("%s\n\n", str);
}
@@ -560,7 +560,7 @@ int scene_menu_display(struct scene_obj_menu *menu)
return 0;
pointer = scene_obj_find(scn, menu->pointer_id, SCENEOBJT_TEXT);
- pstr = expo_get_str(scn->expo, pointer->str_id);
+ pstr = expo_get_str(scn->expo, pointer->gen.str_id);
list_for_each_entry(item, &menu->item_head, sibling) {
struct scene_obj_txt *key = NULL, *label = NULL;
@@ -569,15 +569,15 @@ int scene_menu_display(struct scene_obj_menu *menu)
key = scene_obj_find(scn, item->key_id, SCENEOBJT_TEXT);
if (key)
- kstr = expo_get_str(exp, key->str_id);
+ kstr = expo_get_str(exp, key->gen.str_id);
label = scene_obj_find(scn, item->label_id, SCENEOBJT_TEXT);
if (label)
- lstr = expo_get_str(exp, label->str_id);
+ lstr = expo_get_str(exp, label->gen.str_id);
desc = scene_obj_find(scn, item->desc_id, SCENEOBJT_TEXT);
if (desc)
- dstr = expo_get_str(exp, desc->str_id);
+ dstr = expo_get_str(exp, desc->gen.str_id);
printf("%3s %3s %-10s %s\n",
pointer && menu->cur_item_id == item->id ? pstr : "",
diff --git a/boot/scene_textline.c b/boot/scene_textline.c
index 0bf54b2108b..fc9e5e426d0 100644
--- a/boot/scene_textline.c
+++ b/boot/scene_textline.c
@@ -72,8 +72,8 @@ int scene_textline_calc_dims(struct scene_obj_textline *tline)
if (!txt)
return log_msg_ret("dim", -ENOENT);
- ret = vidconsole_nominal(scn->expo->cons, txt->font_name,
- txt->font_size, tline->max_chars, &bbox);
+ ret = vidconsole_nominal(scn->expo->cons, txt->gen.font_name,
+ txt->gen.font_size, tline->max_chars, &bbox);
if (ret)
return log_msg_ret("nom", ret);
@@ -192,10 +192,10 @@ int scene_textline_render_deps(struct scene *scn,
if (!txt)
return log_msg_ret("cur", -ENOENT);
- if (txt->font_name || txt->font_size) {
+ if (txt->gen.font_name || txt->gen.font_size) {
ret = vidconsole_select_font(cons,
- txt->font_name,
- txt->font_size);
+ txt->gen.font_name,
+ txt->gen.font_size);
} else {
ret = vidconsole_select_font(cons, NULL, 0);
}
diff --git a/include/expo.h b/include/expo.h
index 990cb3094ee..32d69f269a7 100644
--- a/include/expo.h
+++ b/include/expo.h
@@ -291,22 +291,31 @@ struct scene_obj_img {
};
/**
- * struct scene_obj_txt - information about a text object in a scene
- *
- * This is a single-line text object
+ * struct scene_txt_generic - Generic information common to text objects
*
- * @obj: Basic object information
* @str_id: ID of the text string to display
* @font_name: Name of font (allocated by caller)
* @font_size: Nominal size of font in pixels
*/
-struct scene_obj_txt {
- struct scene_obj obj;
+struct scene_txt_generic {
uint str_id;
const char *font_name;
uint font_size;
};
+/**
+ * struct scene_obj_txt - information about a text object in a scene
+ *
+ * This is a single-line text object
+ *
+ * @obj: Basic object information
+ * @gen: Generic information common to all objects which show text
+ */
+struct scene_obj_txt {
+ struct scene_obj obj;
+ struct scene_txt_generic gen;
+};
+
/**
* struct scene_obj_menu - information about a menu object in a scene
*
diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
index 572851761c5..72fb0644ee8 100644
--- a/test/boot/bootflow.c
+++ b/test/boot/bootflow.c
@@ -861,7 +861,7 @@ static int check_font(struct unit_test_state *uts, struct scene *scn, uint id,
txt = scene_obj_find(scn, id, SCENEOBJT_TEXT);
ut_assertnonnull(txt);
- ut_asserteq(font_size, txt->font_size);
+ ut_asserteq(font_size, txt->gen.font_size);
return 0;
}
diff --git a/test/boot/cedit.c b/test/boot/cedit.c
index 0c34d4b3df0..dbf781902fb 100644
--- a/test/boot/cedit.c
+++ b/test/boot/cedit.c
@@ -48,7 +48,7 @@ static int cedit_base(struct unit_test_state *uts)
txt = scene_obj_find(scn, menu->title_id, SCENEOBJT_NONE);
ut_assertnonnull(txt);
- ut_asserteq_str("AC Power", expo_get_str(exp, txt->str_id));
+ ut_asserteq_str("AC Power", expo_get_str(exp, txt->gen.str_id));
ut_asserteq(ID_AC_ON, menu->cur_item_id);
diff --git a/test/boot/expo.c b/test/boot/expo.c
index 70db33d48b1..96c5943f394 100644
--- a/test/boot/expo.c
+++ b/test/boot/expo.c
@@ -280,8 +280,8 @@ static int expo_object_attr(struct unit_test_state *uts)
strcpy(name, "font2");
ut_assertok(scene_txt_set_font(scn, OBJ_TEXT, name, 42));
- ut_asserteq_ptr(name, txt->font_name);
- ut_asserteq(42, txt->font_size);
+ ut_asserteq_ptr(name, txt->gen.font_name);
+ ut_asserteq(42, txt->gen.font_size);
ut_asserteq(-ENOENT, scene_txt_set_font(scn, OBJ_TEXT2, name, 42));
@@ -296,7 +296,7 @@ static int expo_object_attr(struct unit_test_state *uts)
node = ofnode_path("/bootstd/theme");
ut_assert(ofnode_valid(node));
ut_assertok(expo_apply_theme(exp, node));
- ut_asserteq(30, txt->font_size);
+ ut_asserteq(30, txt->gen.font_size);
expo_destroy(exp);
@@ -727,7 +727,7 @@ static int expo_test_build(struct unit_test_state *uts)
ut_assertnonnull(scn);
ut_asserteq_str("main", scn->name);
ut_asserteq(ID_SCENE1, scn->id);
- ut_asserteq(ID_DYNAMIC_START + 1, scn->title_id);
+ ut_asserteq(ID_DYNAMIC_START, scn->title_id);
ut_asserteq(0, scn->highlight_id);
/* check the title */
@@ -739,7 +739,8 @@ static int expo_test_build(struct unit_test_state *uts)
ut_asserteq(scn->title_id, obj->id);
ut_asserteq(SCENEOBJT_TEXT, obj->type);
ut_asserteq(0, obj->flags);
- ut_asserteq_str("Test Configuration", expo_get_str(exp, txt->str_id));
+ ut_asserteq_str("Test Configuration",
+ expo_get_str(exp, txt->gen.str_id));
/* check the menu */
menu = scene_obj_find(scn, ID_CPU_SPEED, SCENEOBJT_NONE);
@@ -751,7 +752,7 @@ static int expo_test_build(struct unit_test_state *uts)
ut_asserteq(0, obj->flags);
txt = scene_obj_find(scn, menu->title_id, SCENEOBJT_NONE);
- ut_asserteq_str("CPU speed", expo_get_str(exp, txt->str_id));
+ ut_asserteq_str("CPU speed", expo_get_str(exp, txt->gen.str_id));
ut_asserteq(0, menu->cur_item_id);
ut_asserteq(0, menu->pointer_id);
@@ -768,7 +769,7 @@ static int expo_test_build(struct unit_test_state *uts)
ut_asserteq(0, item->value);
txt = scene_obj_find(scn, item->label_id, SCENEOBJT_NONE);
- ut_asserteq_str("2 GHz", expo_get_str(exp, txt->str_id));
+ ut_asserteq_str("2 GHz", expo_get_str(exp, txt->gen.str_id));
count = list_count_nodes(&menu->item_head);
ut_asserteq(3, count);
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 36/56] expo: Move text-rendering into its own function
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (34 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 35/56] expo: Create a struct for generic text attributes Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 37/56] expo: Tidy up scene_txt_render() Simon Glass
` (20 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Tom Rini
The code to render text is quite long, so put it in its own function.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
boot/scene.c | 95 +++++++++++++++++++++++++++++-----------------------
1 file changed, 53 insertions(+), 42 deletions(-)
diff --git a/boot/scene.c b/boot/scene.c
index bf56f4341aa..1e68c17c386 100644
--- a/boot/scene.c
+++ b/boot/scene.c
@@ -412,6 +412,56 @@ static void scene_render_background(struct scene_obj *obj, bool box_only)
}
}
+static int scene_txt_render(struct expo *exp, struct udevice *dev,
+ struct udevice *cons, struct scene_obj *obj,
+ struct scene_txt_generic *gen, int x, int y,
+ int menu_inset)
+{
+ const char *str;
+ int ret;
+
+ if (!cons)
+ return -ENOTSUPP;
+
+ if (gen->font_name || gen->font_size) {
+ ret = vidconsole_select_font(cons, gen->font_name,
+ gen->font_size);
+ } else {
+ ret = vidconsole_select_font(cons, NULL, 0);
+ }
+ if (ret && ret != -ENOSYS)
+ return log_msg_ret("font", ret);
+ str = expo_get_str(exp, gen->str_id);
+ if (str) {
+ struct video_priv *vid_priv;
+ struct vidconsole_colour old;
+ enum colour_idx fore, back;
+
+ vid_priv = dev_get_uclass_priv(dev);
+ if (vid_priv->white_on_black) {
+ fore = VID_BLACK;
+ back = VID_WHITE;
+ } else {
+ fore = VID_LIGHT_GRAY;
+ back = VID_BLACK;
+ }
+
+ if (obj->flags & SCENEOF_POINT) {
+ vidconsole_push_colour(cons, fore, back, &old);
+ video_fill_part(dev, x - menu_inset, y,
+ obj->bbox.x1,
+ obj->bbox.y1,
+ vid_priv->colour_bg);
+ }
+ vidconsole_set_cursor_pos(cons, x, y);
+ vidconsole_put_string(cons, str);
+ if (obj->flags & SCENEOF_POINT)
+ vidconsole_pop_colour(cons, &old);
+ }
+
+ return 0;
+}
+
/**
* scene_obj_render() - Render an object
*
@@ -443,49 +493,10 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode)
break;
}
case SCENEOBJT_TEXT: {
- struct scene_txt_generic *gen =
- &((struct scene_obj_txt *)obj)->gen;
- const char *str;
+ struct scene_obj_txt *txt = (struct scene_obj_txt *)obj;
- if (!cons)
- return -ENOTSUPP;
-
- if (gen->font_name || gen->font_size) {
- ret = vidconsole_select_font(cons,
- gen->font_name,
- gen->font_size);
- } else {
- ret = vidconsole_select_font(cons, NULL, 0);
- }
- if (ret && ret != -ENOSYS)
- return log_msg_ret("font", ret);
- str = expo_get_str(exp, gen->str_id);
- if (str) {
- struct video_priv *vid_priv;
- struct vidconsole_colour old;
- enum colour_idx fore, back;
-
- vid_priv = dev_get_uclass_priv(dev);
- if (vid_priv->white_on_black) {
- fore = VID_BLACK;
- back = VID_WHITE;
- } else {
- fore = VID_LIGHT_GRAY;
- back = VID_BLACK;
- }
-
- if (obj->flags & SCENEOF_POINT) {
- vidconsole_push_colour(cons, fore, back, &old);
- video_fill_part(dev, x - theme->menu_inset, y,
- obj->bbox.x1,
- obj->bbox.y1,
- vid_priv->colour_bg);
- }
- vidconsole_set_cursor_pos(cons, x, y);
- vidconsole_put_string(cons, str);
- if (obj->flags & SCENEOF_POINT)
- vidconsole_pop_colour(cons, &old);
- }
+ ret = scene_txt_render(exp, dev, cons, obj, &txt->gen, x, y,
+ theme->menu_inset);
break;
}
case SCENEOBJT_MENU: {
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 37/56] expo: Tidy up scene_txt_render()
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (35 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 36/56] expo: Move text-rendering into its own function Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 38/56] expo: Allow strings to be editable Simon Glass
` (19 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Tom Rini
Add an early return if there is no string. Move all declarations to the
top of the function.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
boot/scene.c | 46 ++++++++++++++++++++++------------------------
1 file changed, 22 insertions(+), 24 deletions(-)
diff --git a/boot/scene.c b/boot/scene.c
index 1e68c17c386..8ecfa4f33bb 100644
--- a/boot/scene.c
+++ b/boot/scene.c
@@ -417,6 +417,9 @@ static int scene_txt_render(struct expo *exp, struct udevice *dev,
struct scene_txt_generic *gen, int x, int y,
int menu_inset)
{
+ struct video_priv *vid_priv;
+ struct vidconsole_colour old;
+ enum colour_idx fore, back;
const char *str;
int ret;
@@ -432,32 +435,27 @@ static int scene_txt_render(struct expo *exp, struct udevice *dev,
if (ret && ret != -ENOSYS)
return log_msg_ret("font", ret);
str = expo_get_str(exp, gen->str_id);
- if (str) {
- struct video_priv *vid_priv;
- struct vidconsole_colour old;
- enum colour_idx fore, back;
-
- vid_priv = dev_get_uclass_priv(dev);
- if (vid_priv->white_on_black) {
- fore = VID_BLACK;
- back = VID_WHITE;
- } else {
- fore = VID_LIGHT_GRAY;
- back = VID_BLACK;
- }
+ if (!str)
+ return 0;
- if (obj->flags & SCENEOF_POINT) {
- vidconsole_push_colour(cons, fore, back, &old);
- video_fill_part(dev, x - menu_inset, y,
- obj->bbox.x1,
- obj->bbox.y1,
- vid_priv->colour_bg);
- }
- vidconsole_set_cursor_pos(cons, x, y);
- vidconsole_put_string(cons, str);
- if (obj->flags & SCENEOF_POINT)
- vidconsole_pop_colour(cons, &old);
+ vid_priv = dev_get_uclass_priv(dev);
+ if (vid_priv->white_on_black) {
+ fore = VID_BLACK;
+ back = VID_WHITE;
+ } else {
+ fore = VID_LIGHT_GRAY;
+ back = VID_BLACK;
+ }
+
+ if (obj->flags & SCENEOF_POINT) {
+ vidconsole_push_colour(cons, fore, back, &old);
+ video_fill_part(dev, x - menu_inset, y, obj->bbox.x1,
+ obj->bbox.y1, vid_priv->colour_bg);
}
+ vidconsole_set_cursor_pos(cons, x, y);
+ vidconsole_put_string(cons, str);
+ if (obj->flags & SCENEOF_POINT)
+ vidconsole_pop_colour(cons, &old);
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 38/56] expo: Allow strings to be editable
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (36 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 37/56] expo: Tidy up scene_txt_render() Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 39/56] expo: Check the screen contents after rendering Simon Glass
` (18 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Tom Rini
In some cases dynamic text is needed, e.g. for a menu countdown. Add a
function which handles this, allowing the caller to take control of the
text that is shown on each render.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
boot/expo.c | 21 +++++++++++++++++++++
include/expo.h | 17 +++++++++++++++++
test/boot/expo.c | 11 +++++++++++
3 files changed, 49 insertions(+)
diff --git a/boot/expo.c b/boot/expo.c
index ee635116abc..a0be1404f1c 100644
--- a/boot/expo.c
+++ b/boot/expo.c
@@ -104,6 +104,27 @@ const char *expo_get_str(struct expo *exp, uint id)
return NULL;
}
+int expo_edit_str(struct expo *exp, uint id, struct abuf *orig,
+ struct abuf **copyp)
+{
+ struct expo_string *estr;
+ struct abuf old;
+
+ list_for_each_entry(estr, &exp->str_head, sibling) {
+ if (estr->id == id) {
+ old = estr->buf;
+ if (!abuf_copy(&old, &estr->buf))
+ return -ENOMEM;
+ *copyp = &estr->buf;
+ if (orig)
+ *orig = old;
+ return 0;
+ }
+ }
+
+ return -ENOENT;
+}
+
int expo_set_display(struct expo *exp, struct udevice *dev)
{
struct udevice *cons;
diff --git a/include/expo.h b/include/expo.h
index 32d69f269a7..7c6ab4bf630 100644
--- a/include/expo.h
+++ b/include/expo.h
@@ -469,6 +469,23 @@ int expo_str(struct expo *exp, const char *name, uint id, const char *str);
*/
const char *expo_get_str(struct expo *exp, uint id);
+/**
+ * expo_edit_str() - Make a string writeable
+ *
+ * This allows a string to be updated under the control of the caller. The
+ * buffer must remain valid while the expo is active.
+ *
+ * @exp: Expo to use
+ * @id: String ID to look up
+ * @orig: If non-NULL, returns the original buffer, which can be used by the
+ * caller. It is no-longer used by expo so must be uninited by the caller.
+ * It contains a snapshot of the string contents
+ * @copyp: Returns a pointer to the new, writeable buffer
+ * Return: 0 if OK, -ENOENT if the id was not found, -ENOMEM if out of memory
+ */
+int expo_edit_str(struct expo *exp, uint id, struct abuf *orig,
+ struct abuf **copyp);
+
/**
* expo_set_display() - set the display to use for a expo
*
diff --git a/test/boot/expo.c b/test/boot/expo.c
index 96c5943f394..a50e9f721de 100644
--- a/test/boot/expo.c
+++ b/test/boot/expo.c
@@ -707,6 +707,7 @@ static int expo_test_build(struct unit_test_state *uts)
struct scene_obj_menu *menu;
struct scene_menitem *item;
struct scene_obj_txt *txt;
+ struct abuf orig, *copy;
struct scene_obj *obj;
struct scene *scn;
struct expo *exp;
@@ -774,6 +775,16 @@ static int expo_test_build(struct unit_test_state *uts)
count = list_count_nodes(&menu->item_head);
ut_asserteq(3, count);
+ /* try editing some text */
+ ut_assertok(expo_edit_str(exp, txt->gen.str_id, &orig, ©));
+ ut_asserteq_str("2 GHz", orig.data);
+ ut_asserteq_str("2 GHz", copy->data);
+
+ /* change it and check that things look right */
+ abuf_printf(copy, "atlantic %d", 123);
+ ut_asserteq_str("2 GHz", orig.data);
+ ut_asserteq_str("atlantic 123", copy->data);
+
expo_destroy(exp);
return 0;
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 39/56] expo: Check the screen contents after rendering
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (37 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 38/56] expo: Allow strings to be editable Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 40/56] expo: Support rendering multiple lines of text Simon Glass
` (17 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Tom Rini
Make sure that the screen contents are as expected when a scene has been
rendered.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
test/boot/expo.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/test/boot/expo.c b/test/boot/expo.c
index a50e9f721de..6fb9f810885 100644
--- a/test/boot/expo.c
+++ b/test/boot/expo.c
@@ -11,6 +11,7 @@
#include <video.h>
#include <linux/input.h>
#include <test/ut.h>
+#include <test/video.h>
#include "bootstd_common.h"
#include <test/cedit-test.h>
#include "../../boot/scene_internal.h"
@@ -645,6 +646,9 @@ static int expo_render_image(struct unit_test_state *uts)
ut_assertok(scene_arrange(scn));
ut_assertok(expo_render(exp));
+ ut_asserteq(10314, video_compress_fb(uts, dev, false));
+ ut_assertok(video_check_copy_fb(uts, dev));
+
/* make sure only the preview for the second item is shown */
obj = scene_obj_find(scn, ITEM1_PREVIEW, SCENEOBJT_NONE);
ut_asserteq(true, obj->flags & SCENEOF_HIDE);
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 40/56] expo: Support rendering multiple lines of text
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (38 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 39/56] expo: Check the screen contents after rendering Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 41/56] expo: Support white-on-black in the theme Simon Glass
` (16 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Quentin Schulz, Tom Rini
Use the measurement info to write each line of text separately, thus
respecting word-wrapping and newlines.
Fix up the comment for scene_obj_render() while we are here.
Since a lineedit does not support alignment, add a special case to just
display the text if there is no measurement. This happens assuming the
lineedit is initially empty.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Handle the case of an initially empty string
| 2 ++
boot/scene.c | 26 ++++++++++++++++++++++----
include/expo.h | 4 ++++
test/boot/expo.c | 12 +++++++++++-
4 files changed, 39 insertions(+), 5 deletions(-)
--git a/boot/bootflow_menu.c b/boot/bootflow_menu.c
index 19cd84e6454..cadffcf259a 100644
--- a/boot/bootflow_menu.c
+++ b/boot/bootflow_menu.c
@@ -234,6 +234,8 @@ int bootflow_menu_start(struct bootstd_priv *std, bool text_mode,
if (text_mode)
expo_set_text_mode(exp, text_mode);
+ LOGR("bmd", expo_calc_dims(exp));
+
*expp = exp;
return 0;
diff --git a/boot/scene.c b/boot/scene.c
index 8ecfa4f33bb..f24465ef34f 100644
--- a/boot/scene.c
+++ b/boot/scene.c
@@ -8,6 +8,7 @@
#define LOG_CATEGORY LOGC_EXPO
+#include <alist.h>
#include <dm.h>
#include <expo.h>
#include <malloc.h>
@@ -164,6 +165,7 @@ int scene_txt_generic_init(struct expo *exp, struct scene_txt_generic *gen,
}
gen->str_id = str_id;
+ alist_init_struct(&gen->lines, struct vidconsole_mline);
return 0;
}
@@ -335,8 +337,8 @@ int scene_obj_get_hw(struct scene *scn, uint id, int *widthp)
struct scene_txt_generic *gen = &((struct scene_obj_txt *)obj)->gen;
struct expo *exp = scn->expo;
struct vidconsole_bbox bbox;
+ int len, ret, limit;
const char *str;
- int len, ret;
str = expo_get_str(exp, gen->str_id);
if (!str)
@@ -350,8 +352,12 @@ int scene_obj_get_hw(struct scene *scn, uint id, int *widthp)
return 16;
}
+ limit = obj->flags & SCENEOF_SIZE_VALID ?
+ obj->bbox.x1 - obj->bbox.x0 : -1;
+
ret = vidconsole_measure(scn->expo->cons, gen->font_name,
- gen->font_size, str, -1, &bbox, NULL);
+ gen->font_size, str, limit, &bbox,
+ &gen->lines);
if (ret)
return log_msg_ret("mea", ret);
if (widthp)
@@ -417,6 +423,7 @@ static int scene_txt_render(struct expo *exp, struct udevice *dev,
struct scene_txt_generic *gen, int x, int y,
int menu_inset)
{
+ const struct vidconsole_mline *mline;
struct video_priv *vid_priv;
struct vidconsole_colour old;
enum colour_idx fore, back;
@@ -452,8 +459,16 @@ static int scene_txt_render(struct expo *exp, struct udevice *dev,
video_fill_part(dev, x - menu_inset, y, obj->bbox.x1,
obj->bbox.y1, vid_priv->colour_bg);
}
- vidconsole_set_cursor_pos(cons, x, y);
- vidconsole_put_string(cons, str);
+
+ if (!gen->lines.count) {
+ vidconsole_set_cursor_pos(cons, x, y);
+ vidconsole_put_string(cons, str);
+ }
+ alist_for_each(mline, &gen->lines) {
+ vidconsole_set_cursor_pos(cons, x + mline->bbox.x0,
+ y + mline->bbox.y0);
+ vidconsole_put_stringn(cons, str + mline->start, mline->len);
+ }
if (obj->flags & SCENEOF_POINT)
vidconsole_pop_colour(cons, &old);
@@ -463,6 +478,9 @@ static int scene_txt_render(struct expo *exp, struct udevice *dev,
/**
* scene_obj_render() - Render an object
*
+ * @obj: Object to render
+ * @text_mode: true to use text mode
+ * Return: 0 if OK, -ve on error
*/
static int scene_obj_render(struct scene_obj *obj, bool text_mode)
{
diff --git a/include/expo.h b/include/expo.h
index 7c6ab4bf630..a79aa1da74f 100644
--- a/include/expo.h
+++ b/include/expo.h
@@ -8,6 +8,7 @@
#define __EXPO_H
#include <abuf.h>
+#include <alist.h>
#include <dm/ofnode_decl.h>
#include <linux/bitops.h>
#include <linux/list.h>
@@ -296,11 +297,14 @@ struct scene_obj_img {
* @str_id: ID of the text string to display
* @font_name: Name of font (allocated by caller)
* @font_size: Nominal size of font in pixels
+ * @lines: alist of struct vidconsole_mline with a separate record for each
+ * line of text
*/
struct scene_txt_generic {
uint str_id;
const char *font_name;
uint font_size;
+ struct alist lines;
};
/**
diff --git a/test/boot/expo.c b/test/boot/expo.c
index 6fb9f810885..c9ff5b8dd24 100644
--- a/test/boot/expo.c
+++ b/test/boot/expo.c
@@ -25,6 +25,7 @@ enum {
OBJ_LOGO,
OBJ_TEXT,
OBJ_TEXT2,
+ OBJ_TEXT3,
OBJ_MENU,
OBJ_MENU_TITLE,
@@ -33,6 +34,7 @@ enum {
STR_TEXT,
STR_TEXT2,
+ STR_TEXT3,
STR_MENU_TITLE,
STR_POINTER_TEXT,
@@ -488,6 +490,14 @@ static int expo_render_image(struct unit_test_state *uts)
60));
ut_assertok(scene_obj_set_pos(scn, OBJ_TEXT2, 200, 600));
+ id = scene_txt_str(scn, "text", OBJ_TEXT3, STR_TEXT3,
+ "this is yet\nanother string, with word-wrap",
+ NULL);
+ ut_assert(id > 0);
+ ut_assertok(scene_txt_set_font(scn, OBJ_TEXT3, "nimbus_sans_l_regular",
+ 60));
+ ut_assertok(scene_obj_set_bbox(scn, OBJ_TEXT3, 500, 200, 1000, 700));
+
id = scene_menu(scn, "main", OBJ_MENU, &menu);
ut_assert(id > 0);
@@ -646,7 +656,7 @@ static int expo_render_image(struct unit_test_state *uts)
ut_assertok(scene_arrange(scn));
ut_assertok(expo_render(exp));
- ut_asserteq(10314, video_compress_fb(uts, dev, false));
+ ut_asserteq(14848, video_compress_fb(uts, dev, false));
ut_assertok(video_check_copy_fb(uts, dev));
/* make sure only the preview for the second item is shown */
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 41/56] expo: Support white-on-black in the theme
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (39 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 40/56] expo: Support rendering multiple lines of text Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 42/56] expo: Implement a box Simon Glass
` (15 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Tom Rini
Allow this setting to be controlled from the theme.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
boot/expo.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/boot/expo.c b/boot/expo.c
index a0be1404f1c..4e855f60d84 100644
--- a/boot/expo.c
+++ b/boot/expo.c
@@ -277,6 +277,7 @@ int expo_apply_theme(struct expo *exp, ofnode node)
{
struct scene *scn;
struct expo_theme *theme = &exp->theme;
+ bool white_on_black;
int ret;
log_debug("Applying theme %s\n", ofnode_get_name(node));
@@ -287,6 +288,9 @@ int expo_apply_theme(struct expo *exp, ofnode node)
ofnode_read_u32(node, "menuitem-gap-y", &theme->menuitem_gap_y);
ofnode_read_u32(node, "menu-title-margin-x",
&theme->menu_title_margin_x);
+ white_on_black = ofnode_read_bool(node, "white-on-black");
+ if (exp->display)
+ video_set_white_on_black(exp->display, white_on_black);
list_for_each_entry(scn, &exp->scene_head, sibling) {
ret = scene_apply_theme(scn, theme);
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 42/56] expo: Implement a box
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (40 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 41/56] expo: Support white-on-black in the theme Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 43/56] expo: Support object alignment Simon Glass
` (14 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Rasmus Villemoes, Stefan Roese, Tom Rini
It is useful to be able to draw a box around elements in the menu. Add
support for an unfilled box with a selectable thickness.
Note that there is no support for selecting the colour for any expo
objects yet.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
boot/cedit.c | 5 +++++
boot/scene.c | 40 +++++++++++++++++++++++++++++++++++++++-
doc/develop/expo.rst | 2 ++
include/expo.h | 28 ++++++++++++++++++++++++++++
test/boot/expo.c | 13 +++++++++++--
5 files changed, 85 insertions(+), 3 deletions(-)
diff --git a/boot/cedit.c b/boot/cedit.c
index 83e50f98c93..17b346a9f78 100644
--- a/boot/cedit.c
+++ b/boot/cedit.c
@@ -81,6 +81,7 @@ int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id)
case SCENEOBJT_NONE:
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
+ case SCENEOBJT_BOX:
break;
case SCENEOBJT_MENU:
scene_obj_set_pos(scn, obj->id, 50, y);
@@ -378,6 +379,7 @@ static int h_write_settings(struct scene_obj *obj, void *vpriv)
case SCENEOBJT_NONE:
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
+ case SCENEOBJT_BOX:
break;
case SCENEOBJT_TEXTLINE: {
const struct scene_obj_textline *tline;
@@ -478,6 +480,7 @@ static int h_read_settings(struct scene_obj *obj, void *vpriv)
case SCENEOBJT_NONE:
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
+ case SCENEOBJT_BOX:
break;
case SCENEOBJT_TEXTLINE: {
const struct scene_obj_textline *tline;
@@ -549,6 +552,7 @@ static int h_write_settings_env(struct scene_obj *obj, void *vpriv)
case SCENEOBJT_NONE:
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
+ case SCENEOBJT_BOX:
break;
case SCENEOBJT_MENU:
menu = (struct scene_obj_menu *)obj;
@@ -632,6 +636,7 @@ static int h_read_settings_env(struct scene_obj *obj, void *vpriv)
case SCENEOBJT_NONE:
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
+ case SCENEOBJT_BOX:
break;
case SCENEOBJT_MENU:
menu = (struct scene_obj_menu *)obj;
diff --git a/boot/scene.c b/boot/scene.c
index f24465ef34f..e1d50765f4a 100644
--- a/boot/scene.c
+++ b/boot/scene.c
@@ -210,6 +210,26 @@ int scene_txt_str(struct scene *scn, const char *name, uint id, uint str_id,
return txt->obj.id;
}
+int scene_box(struct scene *scn, const char *name, uint id, uint width,
+ struct scene_obj_box **boxp)
+{
+ struct scene_obj_box *box;
+ int ret;
+
+ ret = scene_obj_add(scn, name, id, SCENEOBJT_BOX,
+ sizeof(struct scene_obj_box),
+ (struct scene_obj **)&box);
+ if (ret < 0)
+ return log_msg_ret("obj", ret);
+
+ box->width = width;
+
+ if (boxp)
+ *boxp = box;
+
+ return box->obj.id;
+}
+
int scene_txt_set_font(struct scene *scn, uint id, const char *font_name,
uint font_size)
{
@@ -322,6 +342,7 @@ int scene_obj_get_hw(struct scene *scn, uint id, int *widthp)
case SCENEOBJT_NONE:
case SCENEOBJT_MENU:
case SCENEOBJT_TEXTLINE:
+ case SCENEOBJT_BOX:
break;
case SCENEOBJT_IMAGE: {
struct scene_obj_img *img = (struct scene_obj_img *)obj;
@@ -489,10 +510,12 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode)
const struct expo_theme *theme = &exp->theme;
struct udevice *dev = exp->display;
struct udevice *cons = text_mode ? NULL : exp->cons;
+ struct video_priv *vid_priv;
int x, y, ret;
- x = obj->bbox.x0;
y = obj->bbox.y0;
+ x = obj->bbox.x0;
+ vid_priv = dev_get_uclass_priv(dev);
switch (obj->type) {
case SCENEOBJT_NONE:
@@ -543,6 +566,13 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode)
if (obj->flags & SCENEOF_OPEN)
scene_render_background(obj, true);
break;
+ case SCENEOBJT_BOX: {
+ struct scene_obj_box *box = (struct scene_obj_box *)obj;
+
+ video_draw_box(dev, obj->bbox.x0, obj->bbox.y0, obj->bbox.x1,
+ obj->bbox.y1, box->width, vid_priv->colour_fg);
+ break;
+ }
}
return 0;
@@ -561,6 +591,7 @@ int scene_calc_arrange(struct scene *scn, struct expo_arrange_info *arr)
case SCENEOBJT_NONE:
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
+ case SCENEOBJT_BOX:
break;
case SCENEOBJT_MENU: {
struct scene_obj_menu *menu;
@@ -606,6 +637,7 @@ int scene_arrange(struct scene *scn)
case SCENEOBJT_NONE:
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
+ case SCENEOBJT_BOX:
break;
case SCENEOBJT_MENU: {
struct scene_obj_menu *menu;
@@ -651,6 +683,7 @@ int scene_render_deps(struct scene *scn, uint id)
case SCENEOBJT_NONE:
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
+ case SCENEOBJT_BOX:
break;
case SCENEOBJT_MENU:
scene_menu_render_deps(scn,
@@ -770,6 +803,7 @@ int scene_send_key(struct scene *scn, int key, struct expo_action *event)
case SCENEOBJT_NONE:
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
+ case SCENEOBJT_BOX:
break;
case SCENEOBJT_MENU: {
struct scene_obj_menu *menu;
@@ -814,6 +848,7 @@ int scene_obj_calc_bbox(struct scene_obj *obj, struct vidconsole_bbox bbox[])
case SCENEOBJT_NONE:
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
+ case SCENEOBJT_BOX:
return -ENOSYS;
case SCENEOBJT_MENU: {
struct scene_obj_menu *menu = (struct scene_obj_menu *)obj;
@@ -843,6 +878,7 @@ int scene_calc_dims(struct scene *scn, bool do_menus)
switch (obj->type) {
case SCENEOBJT_NONE:
case SCENEOBJT_TEXT:
+ case SCENEOBJT_BOX:
case SCENEOBJT_IMAGE: {
int width;
@@ -901,6 +937,7 @@ int scene_apply_theme(struct scene *scn, struct expo_theme *theme)
case SCENEOBJT_NONE:
case SCENEOBJT_IMAGE:
case SCENEOBJT_MENU:
+ case SCENEOBJT_BOX:
case SCENEOBJT_TEXTLINE:
break;
case SCENEOBJT_TEXT:
@@ -943,6 +980,7 @@ static int scene_obj_open(struct scene *scn, struct scene_obj *obj)
case SCENEOBJT_IMAGE:
case SCENEOBJT_MENU:
case SCENEOBJT_TEXT:
+ case SCENEOBJT_BOX:
break;
case SCENEOBJT_TEXTLINE:
ret = scene_textline_open(scn,
diff --git a/doc/develop/expo.rst b/doc/develop/expo.rst
index cc7c36173db..8f63ccbe3ef 100644
--- a/doc/develop/expo.rst
+++ b/doc/develop/expo.rst
@@ -65,6 +65,8 @@ item is highlighted.
A `textline object` contains a label and an editable string.
+A `box object` is a rectangle with a given line width. It is not filled.
+
All components have a name. This is mostly for debugging, so it is easy to see
what object is referred to, although the name is also used for saving values.
Of course the ID numbers can help as well, but they are less easy to
diff --git a/include/expo.h b/include/expo.h
index a79aa1da74f..8833dcceb7e 100644
--- a/include/expo.h
+++ b/include/expo.h
@@ -179,6 +179,7 @@ struct scene {
*
* @SCENEOBJT_NONE: Used to indicate that the type does not matter
* @SCENEOBJT_IMAGE: Image data to render
+ * @SCENEOBJT_BOX: Rectangular box
* @SCENEOBJT_TEXT: Text line to render
* @SCENEOBJT_MENU: Menu containing items the user can select
* @SCENEOBJT_TEXTLINE: Line of text the user can edit
@@ -187,6 +188,7 @@ enum scene_obj_t {
SCENEOBJT_NONE = 0,
SCENEOBJT_IMAGE,
SCENEOBJT_TEXT,
+ SCENEOBJT_BOX,
/* types from here on can be highlighted */
SCENEOBJT_MENU,
@@ -406,6 +408,19 @@ struct scene_obj_textline {
uint pos;
};
+/**
+ * struct scene_obj_box - information about a box in a scene
+ *
+ * A box surrounds a part of the screen with a border
+ *
+ * @obj: Basic object information
+ * @width: Line-width in pixels
+ */
+struct scene_obj_box {
+ struct scene_obj obj;
+ uint width;
+};
+
/**
* struct expo_arrange_info - Information used when arranging a scene
*
@@ -670,6 +685,19 @@ int scene_menu(struct scene *scn, const char *name, uint id,
int scene_textline(struct scene *scn, const char *name, uint id, uint max_chars,
struct scene_obj_textline **tlinep);
+/**
+ * scene_box() - create a box
+ *
+ * @scn: Scene to update
+ * @name: Name to use (this is allocated by this call)
+ * @id: ID to use for the new object (0 to allocate one)
+ * @width: Line-width in pixels
+ * @boxp: If non-NULL, returns the new object
+ * Returns: ID number for the object (typically @id), or -ve on error
+ */
+int scene_box(struct scene *scn, const char *name, uint id, uint width,
+ struct scene_obj_box **boxp);
+
/**
* scene_txt_set_font() - Set the font for an object
*
diff --git a/test/boot/expo.c b/test/boot/expo.c
index c9ff5b8dd24..e4f3ffc01fb 100644
--- a/test/boot/expo.c
+++ b/test/boot/expo.c
@@ -28,6 +28,8 @@ enum {
OBJ_TEXT3,
OBJ_MENU,
OBJ_MENU_TITLE,
+ OBJ_BOX,
+ OBJ_BOX2,
/* strings */
STR_SCENE_TITLE,
@@ -545,6 +547,14 @@ static int expo_render_image(struct unit_test_state *uts)
ut_assertok(scene_obj_set_pos(scn, OBJ_MENU, 50, 400));
+ id = scene_box(scn, "box", OBJ_BOX, 3, NULL);
+ ut_assert(id > 0);
+ ut_assertok(scene_obj_set_bbox(scn, OBJ_BOX, 40, 390, 1000, 510));
+
+ id = scene_box(scn, "box2", OBJ_BOX2, 1, NULL);
+ ut_assert(id > 0);
+ ut_assertok(scene_obj_set_bbox(scn, OBJ_BOX, 500, 200, 1000, 350));
+
scn2 = expo_lookup_scene_id(exp, SCENE1);
ut_asserteq_ptr(scn, scn2);
scn2 = expo_lookup_scene_id(exp, SCENE2);
@@ -655,8 +665,7 @@ static int expo_render_image(struct unit_test_state *uts)
ut_asserteq(ITEM2, scene_menu_get_cur_item(scn, OBJ_MENU));
ut_assertok(scene_arrange(scn));
ut_assertok(expo_render(exp));
-
- ut_asserteq(14848, video_compress_fb(uts, dev, false));
+ ut_asserteq(14883, video_compress_fb(uts, dev, false));
ut_assertok(video_check_copy_fb(uts, dev));
/* make sure only the preview for the second item is shown */
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 43/56] expo: Support object alignment
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (41 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 42/56] expo: Implement a box Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 44/56] expo: Begin implementation of a text editor Simon Glass
` (13 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Tom Rini
Add support for left, right and centred alignment for text, in the
horizontal dimension.
Also support top, bottom and centred in the vertical dimension, for the
text object as a whole.
Alignment is not yet implemented for images. It has no meaning for
menus. A textline object uses a text object internally, so alignment
is supported there.
Provide some documentation to explain how objects are positioned.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
boot/scene.c | 107 +++++++++++++++++++++++++++++++++++++++++--
doc/develop/expo.rst | 31 +++++++++++++
include/expo.h | 63 +++++++++++++++++++++++++
test/boot/expo.c | 23 ++++++++--
4 files changed, 216 insertions(+), 8 deletions(-)
diff --git a/boot/scene.c b/boot/scene.c
index e1d50765f4a..485965e68a8 100644
--- a/boot/scene.c
+++ b/boot/scene.c
@@ -305,6 +305,30 @@ int scene_obj_set_bbox(struct scene *scn, uint id, int x0, int y0, int x1,
return 0;
}
+int scene_obj_set_halign(struct scene *scn, uint id, enum scene_obj_align aln)
+{
+ struct scene_obj *obj;
+
+ obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
+ if (!obj)
+ return log_msg_ret("osh", -ENOENT);
+ obj->horiz = aln;
+
+ return 0;
+}
+
+int scene_obj_set_valign(struct scene *scn, uint id, enum scene_obj_align aln)
+{
+ struct scene_obj *obj;
+
+ obj = scene_obj_find(scn, id, SCENEOBJT_NONE);
+ if (!obj)
+ return log_msg_ret("osv", -ENOENT);
+ obj->vert = aln;
+
+ return 0;
+}
+
int scene_obj_set_hide(struct scene *scn, uint id, bool hide)
{
int ret;
@@ -330,6 +354,44 @@ int scene_obj_flag_clrset(struct scene *scn, uint id, uint clr, uint set)
return 0;
}
+static void handle_alignment(enum scene_obj_align horiz,
+ enum scene_obj_align vert,
+ struct scene_obj_bbox *bbox,
+ struct scene_obj_dims *dims,
+ int xsize, int ysize,
+ struct scene_obj_offset *offset)
+{
+ int width, height;
+
+ width = bbox->x1 - bbox->x0;
+ height = bbox->y1 - bbox->y0;
+
+ switch (horiz) {
+ case SCENEOA_CENTRE:
+ offset->xofs = (width - dims->x) / 2;
+ break;
+ case SCENEOA_RIGHT:
+ offset->xofs = width - dims->x;
+ break;
+ case SCENEOA_LEFT:
+ offset->xofs = 0;
+ break;
+ }
+
+ switch (vert) {
+ case SCENEOA_CENTRE:
+ offset->yofs = (height - dims->y) / 2;
+ break;
+ case SCENEOA_BOTTOM:
+ offset->yofs = height - dims->y;
+ break;
+ case SCENEOA_TOP:
+ default:
+ offset->yofs = 0;
+ break;
+ }
+}
+
int scene_obj_get_hw(struct scene *scn, uint id, int *widthp)
{
struct scene_obj *obj;
@@ -444,10 +506,12 @@ static int scene_txt_render(struct expo *exp, struct udevice *dev,
struct scene_txt_generic *gen, int x, int y,
int menu_inset)
{
- const struct vidconsole_mline *mline;
+ const struct vidconsole_mline *mline, *last;
struct video_priv *vid_priv;
struct vidconsole_colour old;
enum colour_idx fore, back;
+ struct scene_obj_dims dims;
+ struct scene_obj_bbox bbox;
const char *str;
int ret;
@@ -481,13 +545,33 @@ static int scene_txt_render(struct expo *exp, struct udevice *dev,
obj->bbox.y1, vid_priv->colour_bg);
}
- if (!gen->lines.count) {
+ mline = alist_get(&gen->lines, 0, typeof(*mline));
+ last = alist_get(&gen->lines, gen->lines.count - 1, typeof(*mline));
+ if (mline)
+ dims.y = last->bbox.y1 - mline->bbox.y0;
+ bbox.y0 = obj->bbox.y0;
+ bbox.y1 = obj->bbox.y1;
+
+ if (!mline) {
vidconsole_set_cursor_pos(cons, x, y);
vidconsole_put_string(cons, str);
}
+
alist_for_each(mline, &gen->lines) {
- vidconsole_set_cursor_pos(cons, x + mline->bbox.x0,
- y + mline->bbox.y0);
+ struct scene_obj_offset offset;
+
+ bbox.x0 = obj->bbox.x0;
+ bbox.x1 = obj->bbox.x1;
+ dims.x = mline->bbox.x1 - mline->bbox.x0;
+ handle_alignment(obj->horiz, obj->vert, &bbox, &dims,
+ obj->bbox.x1 - obj->bbox.x0,
+ obj->bbox.y1 - obj->bbox.y0, &offset);
+
+ x = obj->bbox.x0 + offset.xofs;
+ y = obj->bbox.y0 + offset.yofs + mline->bbox.y0;
+ if (y > bbox.y1)
+ break; /* clip this line and any following */
+ vidconsole_set_cursor_pos(cons, x, y);
vidconsole_put_stringn(cons, str + mline->start, mline->len);
}
if (obj->flags & SCENEOF_POINT)
@@ -514,7 +598,7 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode)
int x, y, ret;
y = obj->bbox.y0;
- x = obj->bbox.x0;
+ x = obj->bbox.x0 + obj->ofs.xofs;
vid_priv = dev_get_uclass_priv(dev);
switch (obj->type) {
@@ -625,14 +709,27 @@ int scene_calc_arrange(struct scene *scn, struct expo_arrange_info *arr)
int scene_arrange(struct scene *scn)
{
struct expo_arrange_info arr;
+ int xsize = 0, ysize = 0;
struct scene_obj *obj;
+ struct udevice *dev;
int ret;
+ dev = scn->expo->display;
+ if (dev) {
+ struct video_priv *priv = dev_get_uclass_priv(dev);
+
+ xsize = priv->xsize;
+ ysize = priv->ysize;
+ }
+
ret = scene_calc_arrange(scn, &arr);
if (ret < 0)
return log_msg_ret("arr", ret);
list_for_each_entry(obj, &scn->obj_head, sibling) {
+ handle_alignment(obj->horiz, obj->vert, &obj->bbox, &obj->dims,
+ xsize, ysize, &obj->ofs);
+
switch (obj->type) {
case SCENEOBJT_NONE:
case SCENEOBJT_IMAGE:
diff --git a/doc/develop/expo.rst b/doc/develop/expo.rst
index 8f63ccbe3ef..d6fc487e030 100644
--- a/doc/develop/expo.rst
+++ b/doc/develop/expo.rst
@@ -107,6 +107,37 @@ refer to objects which have been created. So a menu item is just a collection
of IDs of text and image objects. When adding a menu item you must create these
objects first, then create the menu item, passing in the relevant IDs.
+Position and alignment
+~~~~~~~~~~~~~~~~~~~~~~
+
+Objects are typically positioned automatically, when scene_arrange() is called.
+However it is possible to position objects manually. The scene_obj_set_pos()
+sets the coordinates of the top left of the object.
+
+All objects have a bounding box. Typically this is calculated by looking at the
+object contents, in `scene_calc_arrange()`. The calculated dimensions of each
+object are stored in the object's `dims` field.
+
+It is possible to adjust the size of an object with `scene_obj_set_size()` or
+even set the bounding box, with `scene_obj_set_bbox()`. The `SCENEOF_SIZE_VALID`
+flag tracks whether the width/height should be maintained when the position
+changes.
+
+If the bounding box is larger than the object needs, the object can be aligned
+to different edges within the box. Objects can be left- or right-aligned,
+or centred. For text objects this applies to each line of text. Normally objects
+are drawn starting at the top of their bounding box, but they can be aligned
+vertically to the bottom, or centred vertically within the box.
+
+Where the width of a text object's bounding box is smaller than the space needed
+to show the next, the text is word-wrapped onto multiple lines, assuming there
+is enough vertical space. Newline characters in the next cause a new line to be
+started. The measurement information is created by the Truetype console driver
+and stored in an alist in `struct scene_txt_generic`.
+
+When the object is drawn the `ofs` field indicates the x and y offset to use,
+from the top left of the bounding box. These values are affected by alignment.
+
Creating an expo
----------------
diff --git a/include/expo.h b/include/expo.h
index 8833dcceb7e..001f7db2553 100644
--- a/include/expo.h
+++ b/include/expo.h
@@ -210,6 +210,19 @@ struct scene_obj_bbox {
int y1;
};
+/**
+ * struct scene_obj_offset - Offsets for drawing the object
+ *
+ * Stores the offset from x0, x1 at which objects are drawn
+ *
+ * @xofs: x offset
+ * @yofs: y offset
+ */
+struct scene_obj_offset {
+ int xofs;
+ int yofs;
+};
+
/**
* struct scene_obj_dims - Dimensions of the object being drawn
*
@@ -225,6 +238,30 @@ struct scene_obj_dims {
int y;
};
+/**
+ * enum scene_obj_halign - Horizontal alignment of objects
+ *
+ * Objects are normally drawn on the left size of their bounding box. This
+ * properly allows aligning on the right or having the object centred.
+ *
+ * @SCENEOA_LEFT: Left of object is aligned with its x coordinate
+ * @SCENEOA_RIGHT: Right of object is aligned with x + w
+ * @SCENEOA_CENTRE: Centre of object is aligned with centre of bounding box
+ * @SCENEOA_TOP: Left of object is aligned with its x coordinate
+ * @SCENEOA_BOTTOM: Right of object is aligned with x + w
+ *
+ * Note: It would be nice to make this a char type but Sphinx riddles:
+ * ./include/expo.h:258: error: Cannot parse enum!
+ * enum scene_obj_align : char {
+ */
+enum scene_obj_align {
+ SCENEOA_LEFT,
+ SCENEOA_RIGHT,
+ SCENEOA_CENTRE,
+ SCENEOA_TOP = SCENEOA_LEFT,
+ SCENEOA_BOTTOM = SCENEOA_RIGHT,
+};
+
/**
* enum scene_obj_flags_t - flags for objects
*
@@ -255,7 +292,10 @@ enum {
* @id: ID number of the object
* @type: Type of this object
* @bbox: Bounding box for this object
+ * @ofs: Offset from x0, y0 where the object is drawn
* @dims: Dimensions of the text/image (may be smaller than bbox)
+ * @horiz: Horizonal alignment
+ * @vert: Vertical alignment
* @flags: Flags for this object
* @bit_length: Number of bits used for this object in CMOS RAM
* @start_bit: Start bit to use for this object in CMOS RAM
@@ -267,7 +307,10 @@ struct scene_obj {
uint id;
enum scene_obj_t type;
struct scene_obj_bbox bbox;
+ struct scene_obj_offset ofs;
struct scene_obj_dims dims;
+ enum scene_obj_align horiz;
+ enum scene_obj_align vert;
u8 flags;
u8 bit_length;
u16 start_bit;
@@ -755,6 +798,26 @@ int scene_obj_set_width(struct scene *scn, uint id, int w);
int scene_obj_set_bbox(struct scene *scn, uint id, int x0, int y0, int x1,
int y1);
+/**
+ * scene_obj_set_halign() - Set the horizontal alignment of an object
+ *
+ * @scn: Scene to update
+ * @id: ID of object to update
+ * @aln: Horizontal alignment to use
+ * Returns: 0 if OK, -ENOENT if @id is invalid
+ */
+int scene_obj_set_halign(struct scene *scn, uint id, enum scene_obj_align aln);
+
+/**
+ * scene_obj_set_valign() - Set the vertical alignment of an object
+ *
+ * @scn: Scene to update
+ * @id: ID of object to update
+ * @aln: Vertical alignment to use
+ * Returns: 0 if OK, -ENOENT if @id is invalid
+ */
+int scene_obj_set_valign(struct scene *scn, uint id, enum scene_obj_align aln);
+
/**
* scene_obj_set_hide() - Set whether an object is hidden
*
diff --git a/test/boot/expo.c b/test/boot/expo.c
index e4f3ffc01fb..b9093b5780b 100644
--- a/test/boot/expo.c
+++ b/test/boot/expo.c
@@ -492,13 +492,14 @@ static int expo_render_image(struct unit_test_state *uts)
60));
ut_assertok(scene_obj_set_pos(scn, OBJ_TEXT2, 200, 600));
+ /* this string is clipped as it extends beyond its bottom bound */
id = scene_txt_str(scn, "text", OBJ_TEXT3, STR_TEXT3,
- "this is yet\nanother string, with word-wrap",
+ "this is yet\nanother string, with word-wrap and it goes on for quite a while",
NULL);
ut_assert(id > 0);
ut_assertok(scene_txt_set_font(scn, OBJ_TEXT3, "nimbus_sans_l_regular",
60));
- ut_assertok(scene_obj_set_bbox(scn, OBJ_TEXT3, 500, 200, 1000, 700));
+ ut_assertok(scene_obj_set_bbox(scn, OBJ_TEXT3, 500, 200, 1000, 350));
id = scene_menu(scn, "main", OBJ_MENU, &menu);
ut_assert(id > 0);
@@ -665,9 +666,25 @@ static int expo_render_image(struct unit_test_state *uts)
ut_asserteq(ITEM2, scene_menu_get_cur_item(scn, OBJ_MENU));
ut_assertok(scene_arrange(scn));
ut_assertok(expo_render(exp));
- ut_asserteq(14883, video_compress_fb(uts, dev, false));
+ ut_asserteq(16304, video_compress_fb(uts, dev, false));
ut_assertok(video_check_copy_fb(uts, dev));
+ /* do some alignment checks */
+ ut_assertok(scene_obj_set_halign(scn, OBJ_TEXT3, SCENEOA_CENTRE));
+ ut_assertok(expo_render(exp));
+ ut_asserteq(16368, video_compress_fb(uts, dev, false));
+ ut_assertok(scene_obj_set_halign(scn, OBJ_TEXT3, SCENEOA_RIGHT));
+ ut_assertok(expo_render(exp));
+ ut_asserteq(16321, video_compress_fb(uts, dev, false));
+
+ ut_assertok(scene_obj_set_halign(scn, OBJ_TEXT3, SCENEOA_LEFT));
+ ut_assertok(scene_obj_set_valign(scn, OBJ_TEXT3, SCENEOA_CENTRE));
+ ut_assertok(expo_render(exp));
+ ut_asserteq(18763, video_compress_fb(uts, dev, false));
+ ut_assertok(scene_obj_set_valign(scn, OBJ_TEXT3, SCENEOA_BOTTOM));
+ ut_assertok(expo_render(exp));
+ ut_asserteq(18714, video_compress_fb(uts, dev, false));
+
/* make sure only the preview for the second item is shown */
obj = scene_obj_find(scn, ITEM1_PREVIEW, SCENEOBJT_NONE);
ut_asserteq(true, obj->flags & SCENEOF_HIDE);
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 44/56] expo: Begin implementation of a text editor
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (42 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 43/56] expo: Support object alignment Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 45/56] expo: Use a simpler name for USB media Simon Glass
` (12 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Heinrich Schuchardt, Julien Masson, Marek Vasut,
Mattijs Korpershoek, Rasmus Villemoes, Stefan Roese, Tom Rini
It is useful to be able to edit text, e.g. to allow the user to edit the
environment or the command-line arguments for the OS.
Add the beginnings of an implementation. Future work is needed to finish
this: keypress handling and scrolling. For now it just displays the
text.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
boot/Makefile | 2 +-
boot/cedit.c | 5 ++++
boot/scene.c | 30 ++++++++++++++++++++--
boot/scene_internal.h | 12 +++++++++
boot/scene_textedit.c | 60 +++++++++++++++++++++++++++++++++++++++++++
doc/develop/expo.rst | 1 +
include/expo.h | 41 +++++++++++++++++++++++++++++
test/boot/expo.c | 16 +++++++++++-
8 files changed, 163 insertions(+), 4 deletions(-)
create mode 100644 boot/scene_textedit.c
diff --git a/boot/Makefile b/boot/Makefile
index 284ade3def0..44b962a04f7 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -59,7 +59,7 @@ obj-$(CONFIG_CMD_ADTIMG) += image-android-dt.o
obj-$(CONFIG_$(PHASE_)LOAD_FIT) += common_fit.o
obj-$(CONFIG_$(PHASE_)EXPO) += expo.o scene.o expo_build.o
-obj-$(CONFIG_$(PHASE_)EXPO) += scene_menu.o scene_textline.o
+obj-$(CONFIG_$(PHASE_)EXPO) += scene_menu.o scene_textline.o scene_textedit.o
ifdef CONFIG_COREBOOT_SYSINFO
obj-$(CONFIG_$(SPL_TPL_)EXPO) += expo_build_cb.o
endif
diff --git a/boot/cedit.c b/boot/cedit.c
index 17b346a9f78..ee08daaa870 100644
--- a/boot/cedit.c
+++ b/boot/cedit.c
@@ -82,6 +82,7 @@ int cedit_arange(struct expo *exp, struct video_priv *vpriv, uint scene_id)
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
case SCENEOBJT_BOX:
+ case SCENEOBJT_TEXTEDIT:
break;
case SCENEOBJT_MENU:
scene_obj_set_pos(scn, obj->id, 50, y);
@@ -380,6 +381,7 @@ static int h_write_settings(struct scene_obj *obj, void *vpriv)
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
case SCENEOBJT_BOX:
+ case SCENEOBJT_TEXTEDIT:
break;
case SCENEOBJT_TEXTLINE: {
const struct scene_obj_textline *tline;
@@ -481,6 +483,7 @@ static int h_read_settings(struct scene_obj *obj, void *vpriv)
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
case SCENEOBJT_BOX:
+ case SCENEOBJT_TEXTEDIT:
break;
case SCENEOBJT_TEXTLINE: {
const struct scene_obj_textline *tline;
@@ -553,6 +556,7 @@ static int h_write_settings_env(struct scene_obj *obj, void *vpriv)
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
case SCENEOBJT_BOX:
+ case SCENEOBJT_TEXTEDIT:
break;
case SCENEOBJT_MENU:
menu = (struct scene_obj_menu *)obj;
@@ -637,6 +641,7 @@ static int h_read_settings_env(struct scene_obj *obj, void *vpriv)
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
case SCENEOBJT_BOX:
+ case SCENEOBJT_TEXTEDIT:
break;
case SCENEOBJT_MENU:
menu = (struct scene_obj_menu *)obj;
diff --git a/boot/scene.c b/boot/scene.c
index 485965e68a8..956c7219142 100644
--- a/boot/scene.c
+++ b/boot/scene.c
@@ -416,13 +416,19 @@ int scene_obj_get_hw(struct scene *scn, uint id, int *widthp)
*widthp = width;
return height;
}
- case SCENEOBJT_TEXT: {
- struct scene_txt_generic *gen = &((struct scene_obj_txt *)obj)->gen;
+ case SCENEOBJT_TEXT:
+ case SCENEOBJT_TEXTEDIT: {
+ struct scene_txt_generic *gen;
struct expo *exp = scn->expo;
struct vidconsole_bbox bbox;
int len, ret, limit;
const char *str;
+ if (obj->type == SCENEOBJT_TEXT)
+ gen = &((struct scene_obj_txt *)obj)->gen;
+ else
+ gen = &((struct scene_obj_txtedit *)obj)->gen;
+
str = expo_get_str(exp, gen->str_id);
if (!str)
return log_msg_ret("str", -ENOENT);
@@ -657,6 +663,13 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode)
obj->bbox.y1, box->width, vid_priv->colour_fg);
break;
}
+ case SCENEOBJT_TEXTEDIT: {
+ struct scene_obj_txtedit *ted = (struct scene_obj_txtedit *)obj;
+
+ ret = scene_txt_render(exp, dev, cons, obj, &ted->gen, x, y,
+ theme->menu_inset);
+ break;
+ }
}
return 0;
@@ -676,6 +689,7 @@ int scene_calc_arrange(struct scene *scn, struct expo_arrange_info *arr)
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
case SCENEOBJT_BOX:
+ case SCENEOBJT_TEXTEDIT:
break;
case SCENEOBJT_MENU: {
struct scene_obj_menu *menu;
@@ -735,6 +749,7 @@ int scene_arrange(struct scene *scn)
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
case SCENEOBJT_BOX:
+ case SCENEOBJT_TEXTEDIT:
break;
case SCENEOBJT_MENU: {
struct scene_obj_menu *menu;
@@ -781,6 +796,7 @@ int scene_render_deps(struct scene *scn, uint id)
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
case SCENEOBJT_BOX:
+ case SCENEOBJT_TEXTEDIT:
break;
case SCENEOBJT_MENU:
scene_menu_render_deps(scn,
@@ -920,6 +936,9 @@ int scene_send_key(struct scene *scn, int key, struct expo_action *event)
return log_msg_ret("key", ret);
break;
}
+ case SCENEOBJT_TEXTEDIT:
+ /* TODO(sjg@chromium.org): Implement this */
+ break;
}
return 0;
}
@@ -946,6 +965,7 @@ int scene_obj_calc_bbox(struct scene_obj *obj, struct vidconsole_bbox bbox[])
case SCENEOBJT_IMAGE:
case SCENEOBJT_TEXT:
case SCENEOBJT_BOX:
+ case SCENEOBJT_TEXTEDIT:
return -ENOSYS;
case SCENEOBJT_MENU: {
struct scene_obj_menu *menu = (struct scene_obj_menu *)obj;
@@ -976,6 +996,7 @@ int scene_calc_dims(struct scene *scn, bool do_menus)
case SCENEOBJT_NONE:
case SCENEOBJT_TEXT:
case SCENEOBJT_BOX:
+ case SCENEOBJT_TEXTEDIT:
case SCENEOBJT_IMAGE: {
int width;
@@ -1037,6 +1058,10 @@ int scene_apply_theme(struct scene *scn, struct expo_theme *theme)
case SCENEOBJT_BOX:
case SCENEOBJT_TEXTLINE:
break;
+ case SCENEOBJT_TEXTEDIT:
+ scene_txted_set_font(scn, obj->id, NULL,
+ theme->font_size);
+ break;
case SCENEOBJT_TEXT:
scene_txt_set_font(scn, obj->id, NULL,
theme->font_size);
@@ -1078,6 +1103,7 @@ static int scene_obj_open(struct scene *scn, struct scene_obj *obj)
case SCENEOBJT_MENU:
case SCENEOBJT_TEXT:
case SCENEOBJT_BOX:
+ case SCENEOBJT_TEXTEDIT:
break;
case SCENEOBJT_TEXTLINE:
ret = scene_textline_open(scn,
diff --git a/boot/scene_internal.h b/boot/scene_internal.h
index ac2a36d6e4d..760cc629b86 100644
--- a/boot/scene_internal.h
+++ b/boot/scene_internal.h
@@ -414,4 +414,16 @@ int scene_textline_close(struct scene *scn, struct scene_obj_textline *tline);
*/
int scene_calc_arrange(struct scene *scn, struct expo_arrange_info *arr);
+/**
+ * scene_txt_generic_init() - Set up the generic part of a text object
+ *
+ * @exp: Expo containing the object
+ * @gen: Generic text info
+ * @name: Object name
+ * @str_id: String ID for the text
+ * @str: Initial text string for the object, or NULL to just use str_id
+ */
+int scene_txt_generic_init(struct expo *exp, struct scene_txt_generic *gen,
+ const char *name, uint str_id, const char *str);
+
#endif /* __SCENE_INTERNAL_H */
diff --git a/boot/scene_textedit.c b/boot/scene_textedit.c
new file mode 100644
index 00000000000..8f4accc4d7c
--- /dev/null
+++ b/boot/scene_textedit.c
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Implementation of a menu in a scene
+ *
+ * Copyright 2025 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#define LOG_CATEGORY LOGC_EXPO
+
+#include <expo.h>
+#include <log.h>
+#include <linux/err.h>
+#include <linux/sizes.h>
+#include "scene_internal.h"
+
+enum {
+ INITIAL_SIZE = SZ_4K,
+};
+
+int scene_texted(struct scene *scn, const char *name, uint id, uint str_id,
+ struct scene_obj_txtedit **teditp)
+{
+ struct scene_obj_txtedit *ted;
+ char *buf;
+ int ret;
+
+ ret = scene_obj_add(scn, name, id, SCENEOBJT_TEXTEDIT,
+ sizeof(struct scene_obj_txtedit),
+ (struct scene_obj **)&ted);
+ if (ret < 0)
+ return log_msg_ret("obj", ret);
+
+ abuf_init(&ted->buf);
+ if (!abuf_realloc(&ted->buf, INITIAL_SIZE))
+ return log_msg_ret("buf", -ENOMEM);
+ buf = abuf_data(&ted->buf);
+ *buf = '\0';
+
+ LOGR("teg", scene_txt_generic_init(scn->expo, &ted->gen, name, str_id,
+ buf));
+ if (teditp)
+ *teditp = ted;
+
+ return ted->obj.id;
+}
+
+int scene_txted_set_font(struct scene *scn, uint id, const char *font_name,
+ uint font_size)
+{
+ struct scene_obj_txtedit *ted;
+
+ ted = scene_obj_find(scn, id, SCENEOBJT_TEXTEDIT);
+ if (!ted)
+ return log_msg_ret("find", -ENOENT);
+ ted->gen.font_name = font_name;
+ ted->gen.font_size = font_size;
+
+ return 0;
+}
diff --git a/doc/develop/expo.rst b/doc/develop/expo.rst
index d6fc487e030..b94340e9a8d 100644
--- a/doc/develop/expo.rst
+++ b/doc/develop/expo.rst
@@ -560,6 +560,7 @@ Future ideas
Some ideas for future work:
- Default menu item and a timeout
+- Complete the text editor
- Image formats other than BMP
- Use of ANSI sequences to control a serial terminal
- Colour selection
diff --git a/include/expo.h b/include/expo.h
index 001f7db2553..16f2f18c4fa 100644
--- a/include/expo.h
+++ b/include/expo.h
@@ -183,12 +183,14 @@ struct scene {
* @SCENEOBJT_TEXT: Text line to render
* @SCENEOBJT_MENU: Menu containing items the user can select
* @SCENEOBJT_TEXTLINE: Line of text the user can edit
+ * @SCENEOBJT_TEXTEDIT: Simple text editor
*/
enum scene_obj_t {
SCENEOBJT_NONE = 0,
SCENEOBJT_IMAGE,
SCENEOBJT_TEXT,
SCENEOBJT_BOX,
+ SCENEOBJT_TEXTEDIT,
/* types from here on can be highlighted */
SCENEOBJT_MENU,
@@ -464,6 +466,21 @@ struct scene_obj_box {
uint width;
};
+/**
+ * struct scene_obj_txtedit - information about a box in a scene
+ *
+ * A text editor which allows users to edit a small text file
+ *
+ * @obj: Basic object information
+ * @gen: Generic information common to all objects which show text
+ * @buf: Text buffer containing current text
+ */
+struct scene_obj_txtedit {
+ struct scene_obj obj;
+ struct scene_txt_generic gen;
+ struct abuf buf;
+};
+
/**
* struct expo_arrange_info - Information used when arranging a scene
*
@@ -741,6 +758,19 @@ int scene_textline(struct scene *scn, const char *name, uint id, uint max_chars,
int scene_box(struct scene *scn, const char *name, uint id, uint width,
struct scene_obj_box **boxp);
+/**
+ * scene_texted() - create a text editor
+ *
+ * @scn: Scene to update
+ * @name: Name to use (this is allocated by this call)
+ * @id: ID to use for the new object (0 to allocate one)
+ * @strid: ID of the string to edit
+ * @teditp: If non-NULL, returns the new object
+ * Returns: ID number for the object (typically @id), or -ve on error
+ */
+int scene_texted(struct scene *scn, const char *name, uint id, uint strid,
+ struct scene_obj_txtedit **teditp);
+
/**
* scene_txt_set_font() - Set the font for an object
*
@@ -752,6 +782,17 @@ int scene_box(struct scene *scn, const char *name, uint id, uint width,
int scene_txt_set_font(struct scene *scn, uint id, const char *font_name,
uint font_size);
+/**
+ * scene_txted_set_font() - Set the font for an object
+ *
+ * @scn: Scene to update
+ * @id: ID of object to update
+ * @font_name: Font name to use (allocated by caller)
+ * @font_size: Font size to use (nominal height in pixels)
+ */
+int scene_txted_set_font(struct scene *scn, uint id, const char *font_name,
+ uint font_size);
+
/**
* scene_obj_set_pos() - Set the postion of an object
*
diff --git a/test/boot/expo.c b/test/boot/expo.c
index b9093b5780b..e624a00c2c0 100644
--- a/test/boot/expo.c
+++ b/test/boot/expo.c
@@ -30,6 +30,7 @@ enum {
OBJ_MENU_TITLE,
OBJ_BOX,
OBJ_BOX2,
+ OBJ_TEXTED,
/* strings */
STR_SCENE_TITLE,
@@ -37,6 +38,7 @@ enum {
STR_TEXT,
STR_TEXT2,
STR_TEXT3,
+ STR_TEXTED,
STR_MENU_TITLE,
STR_POINTER_TEXT,
@@ -462,6 +464,7 @@ static int expo_render_image(struct unit_test_state *uts)
{
struct scene_obj_menu *menu;
struct scene *scn, *scn2;
+ struct abuf orig, *text;
struct expo_action act;
struct scene_obj *obj;
struct udevice *dev;
@@ -556,6 +559,14 @@ static int expo_render_image(struct unit_test_state *uts)
ut_assert(id > 0);
ut_assertok(scene_obj_set_bbox(scn, OBJ_BOX, 500, 200, 1000, 350));
+ id = scene_texted(scn, "editor", OBJ_TEXTED, STR_TEXTED, NULL);
+ ut_assert(id > 0);
+ ut_assertok(scene_obj_set_bbox(scn, OBJ_TEXTED, 100, 200, 400, 650));
+ ut_assertok(expo_edit_str(exp, STR_TEXTED, &orig, &text));
+
+ abuf_printf(text, "This\nis the initial contents of the text editor "
+ "but it is quite likely that more will be added later");
+
scn2 = expo_lookup_scene_id(exp, SCENE1);
ut_asserteq_ptr(scn, scn2);
scn2 = expo_lookup_scene_id(exp, SCENE2);
@@ -666,9 +677,12 @@ static int expo_render_image(struct unit_test_state *uts)
ut_asserteq(ITEM2, scene_menu_get_cur_item(scn, OBJ_MENU));
ut_assertok(scene_arrange(scn));
ut_assertok(expo_render(exp));
- ut_asserteq(16304, video_compress_fb(uts, dev, false));
+ ut_asserteq(19673, video_compress_fb(uts, dev, false));
ut_assertok(video_check_copy_fb(uts, dev));
+ /* hide the text editor since the following tets don't need it */
+ scene_obj_set_hide(scn, OBJ_TEXTED, true);
+
/* do some alignment checks */
ut_assertok(scene_obj_set_halign(scn, OBJ_TEXT3, SCENEOA_CENTRE));
ut_assertok(expo_render(exp));
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 45/56] expo: Use a simpler name for USB media
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (43 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 44/56] expo: Begin implementation of a text editor Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 46/56] expo: Drop the gap between groups of menu items Simon Glass
` (11 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Quentin Schulz, Tom Rini
For USB devices we use the string 'usb_mass_storage' which is a bit
verbose. Use 'USB' instead.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
| 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
--git a/boot/bootflow_menu.c b/boot/bootflow_menu.c
index cadffcf259a..986334e95e2 100644
--- a/boot/bootflow_menu.c
+++ b/boot/bootflow_menu.c
@@ -84,7 +84,9 @@ int bootflow_menu_add(struct expo *exp, struct bootflow *bflow, int seq,
{
struct menu_priv *priv = exp->priv;
char str[2], *label, *key;
+ struct udevice *media;
struct scene *scn;
+ const char *name;
uint preview_id;
uint scene_id;
bool add_gap;
@@ -101,7 +103,14 @@ int bootflow_menu_add(struct expo *exp, struct bootflow *bflow, int seq,
key = strdup(str);
if (!key)
return log_msg_ret("key", -ENOMEM);
- label = strdup(dev_get_parent(bflow->dev)->name);
+
+ media = dev_get_parent(bflow->dev);
+ if (device_get_uclass_id(media) == UCLASS_MASS_STORAGE)
+ name = "usb";
+ else
+ name = media->name;
+ label = strdup(name);
+
if (!label) {
free(key);
return log_msg_ret("nam", -ENOMEM);
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 46/56] expo: Drop the gap between groups of menu items
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (44 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 45/56] expo: Use a simpler name for USB media Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 47/56] expo: Add forward declarations to scene_internal.h Simon Glass
` (10 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Quentin Schulz, Tom Rini
The gap is intended to separate options which are on different bootdevs,
but most of the time there is only one. So drop this gap.
Keep the code around in case it becomes useful to have it in the style,
or based on some other mechanism.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
| 3 +++
1 file changed, 3 insertions(+)
--git a/boot/bootflow_menu.c b/boot/bootflow_menu.c
index 986334e95e2..ace89545fa9 100644
--- a/boot/bootflow_menu.c
+++ b/boot/bootflow_menu.c
@@ -117,6 +117,9 @@ int bootflow_menu_add(struct expo *exp, struct bootflow *bflow, int seq,
}
add_gap = priv->last_bootdev != bflow->dev;
+
+ /* disable this gap for now, since it looks a little ugly */
+ add_gap = false;
priv->last_bootdev = bflow->dev;
ret = expo_str(exp, "prompt", STR_POINTER, ">");
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 47/56] expo: Add forward declarations to scene_internal.h
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (45 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 46/56] expo: Drop the gap between groups of menu items Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 48/56] expo: Support highlighting menu items Simon Glass
` (9 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Tom Rini
Provide some forward declarations for types used in this file, to keep
the LSP happy and avoid errors if the caller happens not to include the
required header.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
boot/scene_internal.h | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/boot/scene_internal.h b/boot/scene_internal.h
index 760cc629b86..95927472875 100644
--- a/boot/scene_internal.h
+++ b/boot/scene_internal.h
@@ -9,8 +9,21 @@
#ifndef __SCENE_INTERNAL_H
#define __SCENE_INTERNAL_H
+#include <linux/types.h>
+
+struct expo;
+struct expo_action;
+struct expo_arrange_info;
+struct expo_theme;
+struct scene_obj;
+struct scene_obj_menu;
+struct scene_obj_textline;
+struct scene_obj_txtedit;
+struct scene_txt_generic;
struct vidconsole_bbox;
+enum scene_obj_t;
+
typedef int (*expo_scene_obj_iterator)(struct scene_obj *obj, void *priv);
/**
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 48/56] expo: Support highlighting menu items
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (46 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 47/56] expo: Add forward declarations to scene_internal.h Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 49/56] expo: Adjust expo_poll() to avoid looping forever Simon Glass
` (8 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Rasmus Villemoes, Stefan Roese, Tom Rini
Expo normally uses a pointer to show the current item. Add support for
highlighting as well, since this makes it easier for the user to see the
current item.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
boot/cedit.c | 1 +
boot/scene.c | 31 +++++++++++++++++++++----------
| 14 +++++++++++---
include/expo.h | 2 ++
test/boot/expo.c | 13 +++++++++++++
5 files changed, 48 insertions(+), 13 deletions(-)
diff --git a/boot/cedit.c b/boot/cedit.c
index ee08daaa870..dbb2750c9f2 100644
--- a/boot/cedit.c
+++ b/boot/cedit.c
@@ -126,6 +126,7 @@ int cedit_prepare(struct expo *exp, struct udevice *vid_dev,
return log_msg_ret("sid", ret);
exp->popup = true;
+ exp->show_highlight = true;
/* This is not supported for now */
if (0)
diff --git a/boot/scene.c b/boot/scene.c
index 956c7219142..15f85c39359 100644
--- a/boot/scene.c
+++ b/boot/scene.c
@@ -465,8 +465,10 @@ int scene_obj_get_hw(struct scene *scn, uint id, int *widthp)
* @obj: Object to render
* @box_only: true to show a box around the object, but keep the normal
* background colour inside
+ * @cur_item: true to render the background only for the current menu item
*/
-static void scene_render_background(struct scene_obj *obj, bool box_only)
+static void scene_render_background(struct scene_obj *obj, bool box_only,
+ bool cur_item)
{
struct vidconsole_bbox bbox[SCENEBB_count], *sel;
struct expo *exp = obj->scene->expo;
@@ -492,7 +494,7 @@ static void scene_render_background(struct scene_obj *obj, bool box_only)
if (scene_obj_calc_bbox(obj, bbox))
return;
- sel = &bbox[SCENEBB_label];
+ sel = cur_item ? &bbox[SCENEBB_curitem] : &bbox[SCENEBB_label];
if (!sel->valid)
return;
@@ -546,9 +548,13 @@ static int scene_txt_render(struct expo *exp, struct udevice *dev,
}
if (obj->flags & SCENEOF_POINT) {
+ int inset;
+
+ inset = exp->popup ? menu_inset : 0;
vidconsole_push_colour(cons, fore, back, &old);
- video_fill_part(dev, x - menu_inset, y, obj->bbox.x1,
- obj->bbox.y1, vid_priv->colour_bg);
+ video_fill_part(dev, x - inset, y,
+ obj->bbox.x1, obj->bbox.y1,
+ vid_priv->colour_bg);
}
mline = alist_get(&gen->lines, 0, typeof(*mline));
@@ -631,13 +637,18 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode)
case SCENEOBJT_MENU: {
struct scene_obj_menu *menu = (struct scene_obj_menu *)obj;
- if (exp->popup && (obj->flags & SCENEOF_OPEN)) {
- if (!cons)
- return -ENOTSUPP;
+ if (exp->popup) {
+ if (obj->flags & SCENEOF_OPEN) {
+ if (!cons)
+ return -ENOTSUPP;
- /* draw a background behind the menu items */
- scene_render_background(obj, false);
+ /* draw a background behind the menu items */
+ scene_render_background(obj, false, false);
+ }
+ } else if (exp->show_highlight) {
+ /* do nothing */
}
+
/*
* With a vidconsole, the text and item pointer are rendered as
* normal objects so we don't need to do anything here. The menu
@@ -654,7 +665,7 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode)
}
case SCENEOBJT_TEXTLINE:
if (obj->flags & SCENEOF_OPEN)
- scene_render_background(obj, true);
+ scene_render_background(obj, true, false);
break;
case SCENEOBJT_BOX: {
struct scene_obj_box *box = (struct scene_obj_box *)obj;
--git a/boot/scene_menu.c b/boot/scene_menu.c
index b0c241a9ee9..206c058c11f 100644
--- a/boot/scene_menu.c
+++ b/boot/scene_menu.c
@@ -87,7 +87,7 @@ struct scene_menitem *scene_menuitem_find_val(const struct scene_obj_menu *menu,
static int update_pointers(struct scene_obj_menu *menu, uint id, bool point)
{
struct scene *scn = menu->obj.scene;
- const bool stack = scn->expo->popup;
+ const bool stack = scn->expo->show_highlight;
const struct scene_menitem *item;
int ret;
@@ -108,9 +108,17 @@ static int update_pointers(struct scene_obj_menu *menu, uint id, bool point)
}
if (stack) {
+ uint id;
+ int val;
+
point &= scn->highlight_id == menu->obj.id;
- scene_obj_flag_clrset(scn, item->label_id, SCENEOF_POINT,
- point ? SCENEOF_POINT : 0);
+ val = point ? SCENEOF_POINT : 0;
+ id = item->desc_id;
+ if (!id)
+ id = item->label_id;
+ if (!id)
+ id = item->key_id;
+ scene_obj_flag_clrset(scn, id, SCENEOF_POINT, val);
}
return 0;
diff --git a/include/expo.h b/include/expo.h
index 16f2f18c4fa..dfecd6ed239 100644
--- a/include/expo.h
+++ b/include/expo.h
@@ -106,6 +106,7 @@ struct expo_theme {
* type set to EXPOACT_NONE if there is no action
* @text_mode: true to use text mode for the menu (no vidconsole)
* @popup: true to use popup menus, instead of showing all items
+ * @show_highlight: show a highlight bar on the selected menu item
* @priv: Private data for the controller
* @done: Indicates that a cedit session is complete and the user has quit
* @save: Indicates that cedit data should be saved, rather than discarded
@@ -123,6 +124,7 @@ struct expo {
struct expo_action action;
bool text_mode;
bool popup;
+ bool show_highlight;
void *priv;
bool done;
bool save;
diff --git a/test/boot/expo.c b/test/boot/expo.c
index e624a00c2c0..ddfb739f9cf 100644
--- a/test/boot/expo.c
+++ b/test/boot/expo.c
@@ -666,6 +666,13 @@ static int expo_render_image(struct unit_test_state *uts)
ut_assertok(scene_arrange(scn));
ut_asserteq(0, scn->highlight_id);
+ scene_set_highlight_id(scn, OBJ_MENU);
+ ut_assertok(scene_arrange(scn));
+ ut_asserteq(OBJ_MENU, scn->highlight_id);
+ ut_assertok(expo_render(exp));
+
+ ut_asserteq(19704, video_compress_fb(uts, dev, false));
+
/* move down */
ut_assertok(expo_send_key(exp, BKEY_DOWN));
@@ -719,6 +726,12 @@ static int expo_render_image(struct unit_test_state *uts)
/* make sure there was no console output */
ut_assert_console_end();
+ /* now try with the highlight */
+ exp->show_highlight = true;
+ ut_assertok(scene_arrange(scn));
+ ut_assertok(expo_render(exp));
+ ut_asserteq(18844, video_compress_fb(uts, dev, false));
+
/* now try in text mode */
expo_set_text_mode(exp, true);
ut_assertok(expo_render(exp));
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 49/56] expo: Adjust expo_poll() to avoid looping forever
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (47 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 48/56] expo: Support highlighting menu items Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 50/56] expo: Drop the render from expo_poll() Simon Glass
` (7 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Tom Rini
If the user does not quickly provide some input, exit so that other
things can be done, such as searching for the next OS.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
boot/expo.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/boot/expo.c b/boot/expo.c
index 4e855f60d84..bf2f1dfc68a 100644
--- a/boot/expo.c
+++ b/boot/expo.c
@@ -324,12 +324,14 @@ int expo_poll(struct expo *exp, struct expo_action *act)
ichar = cli_ch_process(&exp->cch, 0);
if (!ichar) {
- while (!ichar && !tstc()) {
+ int i;
+
+ for (i = 0; i < 10 && !ichar && !tstc(); i++) {
schedule();
mdelay(2);
ichar = cli_ch_process(&exp->cch, -ETIMEDOUT);
}
- if (!ichar) {
+ while (!ichar && tstc()) {
ichar = getchar();
ichar = cli_ch_process(&exp->cch, ichar);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 50/56] expo: Drop the render from expo_poll()
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (48 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 49/56] expo: Adjust expo_poll() to avoid looping forever Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 51/56] expo: Provide a way to position things relative to display Simon Glass
` (6 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Heinrich Schuchardt, Rasmus Villemoes, Stefan Roese,
Tom Rini
Within tests it is useful to be able to control rendering of the expo.
Drop the automatic call to expo_render() within expo_poll() and adjust
its callers to handle this instead.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
boot/cedit.c | 1 +
boot/expo.c | 2 --
cmd/bootflow.c | 1 +
include/expo.h | 9 ++++++---
4 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/boot/cedit.c b/boot/cedit.c
index dbb2750c9f2..63392d97459 100644
--- a/boot/cedit.c
+++ b/boot/cedit.c
@@ -215,6 +215,7 @@ int cedit_run(struct expo *exp)
do {
struct expo_action act;
+ LOGR("cer", expo_render(exp));
ret = expo_poll(exp, &act);
if (!ret) {
cedit_do_action(exp, scn, vid_priv, &act);
diff --git a/boot/expo.c b/boot/expo.c
index bf2f1dfc68a..4f96b5ee973 100644
--- a/boot/expo.c
+++ b/boot/expo.c
@@ -320,8 +320,6 @@ int expo_poll(struct expo *exp, struct expo_action *act)
{
int ichar, key;
- LOGR("ere", expo_render(exp));
-
ichar = cli_ch_process(&exp->cch, 0);
if (!ichar) {
int i;
diff --git a/cmd/bootflow.c b/cmd/bootflow.c
index 456f51760f1..1ccd473b267 100644
--- a/cmd/bootflow.c
+++ b/cmd/bootflow.c
@@ -114,6 +114,7 @@ __maybe_unused static int bootflow_handle_menu(struct bootstd_priv *std,
LOGR("bhs", bootflow_menu_start(std, text_mode, &exp));
do {
+ LOGR("bhr", expo_render(exp));
ret = bootflow_menu_poll(exp, &bflow);
} while (ret == -EAGAIN);
diff --git a/include/expo.h b/include/expo.h
index dfecd6ed239..2addddd5012 100644
--- a/include/expo.h
+++ b/include/expo.h
@@ -1006,10 +1006,13 @@ int expo_build(ofnode root, struct expo **expp);
int cb_expo_build(struct expo **expp);
/**
- * expo_poll() - render an expo and see if the user takes an action
+ * expo_poll() - see if the user takes an action
*
- * Thsi calls expo_render() and then checks for a keypress. If there is one, it
- * is processed and the resulting action returned, if any
+ * This checks for a keypress. If there is one, it is processed and the
+ * resulting action returned, if any.
+ *
+ * Note that expo_render() should normally be called immediately before this
+ * function so that the user can see the latest state.
*
* @exp: Expo to poll
* @act: Returns action on success
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 51/56] expo: Provide a way to position things relative to display
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (49 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 50/56] expo: Drop the render from expo_poll() Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 52/56] expo: Improve the visual appearance of the menu Simon Glass
` (5 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Tom Rini
It is often necessary to centre objects within the display area. Add a
special position value to indicate this.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
boot/scene.c | 5 +++++
include/expo.h | 6 ++++++
2 files changed, 11 insertions(+)
diff --git a/boot/scene.c b/boot/scene.c
index 15f85c39359..a6f264cceca 100644
--- a/boot/scene.c
+++ b/boot/scene.c
@@ -363,6 +363,11 @@ static void handle_alignment(enum scene_obj_align horiz,
{
int width, height;
+ if (bbox->x1 == SCENEOB_DISPLAY_MAX)
+ bbox->x1 = xsize ?: 1280;
+ if (bbox->y1 == SCENEOB_DISPLAY_MAX)
+ bbox->y1 = ysize ?: 1024;
+
width = bbox->x1 - bbox->x0;
height = bbox->y1 - bbox->y0;
diff --git a/include/expo.h b/include/expo.h
index 2addddd5012..4dee479e9a0 100644
--- a/include/expo.h
+++ b/include/expo.h
@@ -242,6 +242,12 @@ struct scene_obj_dims {
int y;
};
+/* special values for dimensions */
+enum {
+ /* width/height of the display */
+ SCENEOB_DISPLAY_MAX = 0x7f000000,
+};
+
/**
* enum scene_obj_halign - Horizontal alignment of objects
*
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 52/56] expo: Improve the visual appearance of the menu
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (50 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 51/56] expo: Provide a way to position things relative to display Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 53/56] expo: Update bootflow_menu_poll() to return a sequence ID Simon Glass
` (4 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Guillaume La Roque, Heinrich Schuchardt,
Mattijs Korpershoek, Quentin Schulz, Tom Rini
The menu is currently quite basic. Make use of some recently added
features in expo, to:
- Show proper prompts
- Highlight the current item
- Centre text
- Use multi-line text instead of two independent lines
- Put a box around the items
Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Only check the text objects used by the bootmenu, for now
boot/bootflow_internal.h | 11 ++++++++--
| 47 +++++++++++++++++++++++++++++++++++-----
test/boot/bootflow.c | 2 +-
3 files changed, 52 insertions(+), 8 deletions(-)
diff --git a/boot/bootflow_internal.h b/boot/bootflow_internal.h
index 38cf02a55b5..4cdb6966a7b 100644
--- a/boot/bootflow_internal.h
+++ b/boot/bootflow_internal.h
@@ -14,7 +14,10 @@ enum {
START,
/* strings */
- STR_PROMPT,
+ STR_PROMPT1A,
+ STR_PROMPT1B,
+ STR_PROMPT2,
+ STR_AUTOBOOT,
STR_MENU_TITLE,
STR_POINTER,
@@ -23,10 +26,14 @@ enum {
/* objects */
OBJ_U_BOOT_LOGO,
+ OBJ_BOX,
OBJ_MENU,
- OBJ_PROMPT,
+ OBJ_PROMPT1A,
+ OBJ_PROMPT1B,
+ OBJ_PROMPT2,
OBJ_MENU_TITLE,
OBJ_POINTER,
+ OBJ_AUTOBOOT,
/* strings for menu items */
STR_LABEL = 100,
--git a/boot/bootflow_menu.c b/boot/bootflow_menu.c
index ace89545fa9..a44c340167c 100644
--- a/boot/bootflow_menu.c
+++ b/boot/bootflow_menu.c
@@ -38,6 +38,7 @@ int bootflow_menu_new(struct expo **expp)
struct menu_priv *priv;
struct scene *scn;
struct expo *exp;
+ bool use_font;
void *logo;
int ret;
@@ -53,27 +54,63 @@ int bootflow_menu_new(struct expo **expp)
if (ret < 0)
return log_msg_ret("scn", ret);
- ret |= scene_txt_str(scn, "prompt", OBJ_PROMPT, STR_PROMPT,
- "UP and DOWN to choose, ENTER to select", NULL);
+ LOGR("bmb", scene_box(scn, "box", OBJ_BOX, 2, NULL));
+ ret |= scene_obj_set_bbox(scn, OBJ_BOX, 30, 90, 1366 - 30, 720);
ret = scene_menu(scn, "main", OBJ_MENU, &menu);
ret |= scene_obj_set_pos(scn, OBJ_MENU, MARGIN_LEFT, 100);
ret |= scene_txt_str(scn, "title", OBJ_MENU_TITLE, STR_MENU_TITLE,
"U-Boot - Boot Menu", NULL);
- ret |= scene_menu_set_title(scn, OBJ_MENU, OBJ_PROMPT);
+ ret |= scene_obj_set_bbox(scn, OBJ_MENU_TITLE, 0, 32,
+ SCENEOB_DISPLAY_MAX, 30);
+ ret |= scene_obj_set_halign(scn, OBJ_MENU_TITLE, SCENEOA_CENTRE);
logo = video_get_u_boot_logo();
if (logo) {
ret |= scene_img(scn, "ulogo", OBJ_U_BOOT_LOGO, logo, NULL);
- ret |= scene_obj_set_pos(scn, OBJ_U_BOOT_LOGO, -4, 4);
+ ret |= scene_obj_set_pos(scn, OBJ_U_BOOT_LOGO, 1165, 100);
}
+ ret |= scene_txt_str(scn, "prompt1a", OBJ_PROMPT1A, STR_PROMPT1A,
+ "Use the \x18 and \x19 keys to select which entry is highlighted.",
+ NULL);
+ ret |= scene_txt_str(scn, "prompt1b", OBJ_PROMPT1B, STR_PROMPT1B,
+ "Use the UP and DOWN keys to select which entry is highlighted.",
+ NULL);
+ ret |= scene_txt_str(scn, "prompt2", OBJ_PROMPT2, STR_PROMPT2,
+ "Press enter to boot the selected OS, 'e' to edit the commands "
+ "before booting or 'c' for a command-line. ESC to return to "
+ "previous menu", NULL);
+ ret |= scene_txt_str(scn, "autoboot", OBJ_AUTOBOOT, STR_AUTOBOOT,
+ "The highlighted entry will be executed automatically in %ds.",
+ NULL);
+ ret |= scene_obj_set_bbox(scn, OBJ_PROMPT1A, 0, 590,
+ SCENEOB_DISPLAY_MAX, 30);
+ ret |= scene_obj_set_bbox(scn, OBJ_PROMPT1B, 0, 620,
+ SCENEOB_DISPLAY_MAX, 30);
+ ret |= scene_obj_set_bbox(scn, OBJ_PROMPT2, 100, 650,
+ 1366 - 100, 700);
+ ret |= scene_obj_set_bbox(scn, OBJ_AUTOBOOT, 0, 720,
+ SCENEOB_DISPLAY_MAX, 750);
+ ret |= scene_obj_set_halign(scn, OBJ_PROMPT1A, SCENEOA_CENTRE);
+ ret |= scene_obj_set_halign(scn, OBJ_PROMPT1B, SCENEOA_CENTRE);
+ ret |= scene_obj_set_halign(scn, OBJ_PROMPT2, SCENEOA_CENTRE);
+ ret |= scene_obj_set_valign(scn, OBJ_PROMPT2, SCENEOA_CENTRE);
+ ret |= scene_obj_set_halign(scn, OBJ_AUTOBOOT, SCENEOA_CENTRE);
+
+ use_font = IS_ENABLED(CONFIG_CONSOLE_TRUETYPE);
+ scene_obj_set_hide(scn, OBJ_PROMPT1A, use_font);
+ scene_obj_set_hide(scn, OBJ_PROMPT1B, !use_font);
+ scene_obj_set_hide(scn, OBJ_AUTOBOOT, use_font);
+
ret |= scene_txt_str(scn, "cur_item", OBJ_POINTER, STR_POINTER, ">",
NULL);
ret |= scene_menu_set_pointer(scn, OBJ_MENU, OBJ_POINTER);
if (ret < 0)
return log_msg_ret("new", -EINVAL);
+ exp->show_highlight = true;
+
*expp = exp;
return 0;
@@ -195,7 +232,7 @@ int bootflow_menu_apply_theme(struct expo *exp, ofnode node)
int i;
log_debug("font size %d\n", font_size);
- scene_txt_set_font(scn, OBJ_PROMPT, NULL, font_size);
+ scene_txt_set_font(scn, OBJ_PROMPT1A, NULL, font_size);
scene_txt_set_font(scn, OBJ_POINTER, NULL, font_size);
for (i = 0; i < priv->num_bootflows; i++) {
ret = scene_txt_set_font(scn, ITEM_DESC + i, NULL,
diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
index 72fb0644ee8..06fd2dbb20a 100644
--- a/test/boot/bootflow.c
+++ b/test/boot/bootflow.c
@@ -895,7 +895,7 @@ static int bootflow_menu_theme(struct unit_test_state *uts)
*
* Check both menu items, since there are two bootflows
*/
- ut_assertok(check_font(uts, scn, OBJ_PROMPT, font_size));
+ ut_assertok(check_font(uts, scn, OBJ_PROMPT1A, font_size));
ut_assertok(check_font(uts, scn, OBJ_POINTER, font_size));
for (i = 0; i < 2; i++) {
ut_assertok(check_font(uts, scn, ITEM_DESC + i, font_size));
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 53/56] expo: Update bootflow_menu_poll() to return a sequence ID
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (51 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 52/56] expo: Improve the visual appearance of the menu Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 54/56] expo: Split setting up the menu from adding items Simon Glass
` (3 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Guillaume La Roque, Heinrich Schuchardt,
Igor Opaniuk, Julien Masson, Mattijs Korpershoek, Quentin Schulz,
Tom Rini
Rather than returning a bootflow, return the index of the bootflow. This
will allow callers to do their own translation to bootflows or some
other data structure.
Also return a special code when the user tries to move the pointer, so
that the caller can cancel the boot-menu timeout, if this is in use.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
| 32 +++++++++++++-------------------
cmd/bootflow.c | 11 +++++++----
include/bootflow.h | 8 ++++----
3 files changed, 24 insertions(+), 27 deletions(-)
--git a/boot/bootflow_menu.c b/boot/bootflow_menu.c
index a44c340167c..7e131de3f6d 100644
--- a/boot/bootflow_menu.c
+++ b/boot/bootflow_menu.c
@@ -290,32 +290,26 @@ int bootflow_menu_start(struct bootstd_priv *std, bool text_mode,
return 0;
}
-int bootflow_menu_poll(struct expo *exp, struct bootflow **bflowp)
+int bootflow_menu_poll(struct expo *exp, int *seqp)
{
struct bootflow *sel_bflow;
struct expo_action act;
- int ret;
+ struct scene *scn;
+ int item;
sel_bflow = NULL;
- *bflowp = NULL;
+
+ scn = expo_lookup_scene_id(exp, exp->scene_id);
+
+ item = scene_menu_get_cur_item(scn, OBJ_MENU);
+ *seqp = item > 0 ? item - ITEM : -1;
LOGR("bmp", expo_poll(exp, &act));
switch (act.type) {
- case EXPOACT_SELECT: {
- struct bootflow *bflow;
- int i;
-
- for (ret = bootflow_first_glob(&bflow), i = 0; !ret && i < 36;
- ret = bootflow_next_glob(&bflow), i++) {
- if (i == act.select.id - ITEM) {
- *bflowp = bflow;
- // printf("found %p\n", bflow);
- return 0;
- }
- }
+ case EXPOACT_SELECT:
+ *seqp = act.select.id - ITEM;
break;
- }
case EXPOACT_POINT_ITEM: {
struct scene *scn = expo_lookup_scene_id(exp, MAIN);
@@ -323,13 +317,13 @@ int bootflow_menu_poll(struct expo *exp, struct bootflow **bflowp)
return log_msg_ret("bms", -ENOENT);
LOGR("bmp", scene_menu_select_item(scn, OBJ_MENU,
act.select.id));
- break;
+ return -ERESTART;
}
case EXPOACT_QUIT:
return -EPIPE;
default:
- break;
+ return -EAGAIN;
}
- return -EAGAIN;
+ return 0;
}
diff --git a/cmd/bootflow.c b/cmd/bootflow.c
index 1ccd473b267..3c367a10c8a 100644
--- a/cmd/bootflow.c
+++ b/cmd/bootflow.c
@@ -109,14 +109,16 @@ __maybe_unused static int bootflow_handle_menu(struct bootstd_priv *std,
{
struct expo *exp;
struct bootflow *bflow;
- int ret;
+ int ret, seq;
LOGR("bhs", bootflow_menu_start(std, text_mode, &exp));
+ ret = -ERESTART;
do {
- LOGR("bhr", expo_render(exp));
- ret = bootflow_menu_poll(exp, &bflow);
- } while (ret == -EAGAIN);
+ if (ret == -ERESTART)
+ LOGR("bhr", expo_render(exp));
+ ret = bootflow_menu_poll(exp, &seq);
+ } while (ret == -EAGAIN || ret == -ERESTART);
if (ret == -EPIPE) {
printf("Nothing chosen\n");
@@ -124,6 +126,7 @@ __maybe_unused static int bootflow_handle_menu(struct bootstd_priv *std,
} else if (ret) {
printf("Menu failed (err=%d)\n", ret);
} else {
+ bflow = alist_getw(&std->bootflows, seq, struct bootflow);
printf("Selected: %s\n", bflow->os_name ? bflow->os_name :
bflow->name);
std->cur_bootflow = bflow;
diff --git a/include/bootflow.h b/include/bootflow.h
index aa46cec4979..8362cbe2e69 100644
--- a/include/bootflow.h
+++ b/include/bootflow.h
@@ -671,10 +671,10 @@ int bootflow_menu_start(struct bootstd_priv *std, bool text_mode,
* bootflow_menu_poll() - Poll a menu for user action
*
* @exp: Expo to poll
- * @bflowp: Returns chosen bootflow (set to NULL if nothing is chosen)
- * Return 0 if a bootflow was chosen, -EAGAIN if nothing is chosen yet, -EPIPE
- * if the user quit
+ * @seqp: Returns the bootflow chosen or currently pointed to (numbered from 0)
+ * Return: 0 if a bootflow was chosen, -EAGAIN if nothing is chosen yet, -EPIPE
+ * if the user quit, -ERESTART if the expo needs refreshing
*/
-int bootflow_menu_poll(struct expo *exp, struct bootflow **bflowp);
+int bootflow_menu_poll(struct expo *exp, int *seqp);
#endif
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 54/56] expo: Split setting up the menu from adding items
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (52 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 53/56] expo: Update bootflow_menu_poll() to return a sequence ID Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 55/56] expo: Set up menu fully in bootflow_menu_start() Simon Glass
` (2 subsequent siblings)
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Igor Opaniuk, Julien Masson, Mattijs Korpershoek,
Quentin Schulz, Tom Rini
Some callers may wish to add items later as they are discovered. Split
the setup code into its own function, to permit this.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
| 24 ++++++++++++++++++++++--
include/bootflow.h | 15 +++++++++++++++
2 files changed, 37 insertions(+), 2 deletions(-)
--git a/boot/bootflow_menu.c b/boot/bootflow_menu.c
index 7e131de3f6d..4fe5d985064 100644
--- a/boot/bootflow_menu.c
+++ b/boot/bootflow_menu.c
@@ -252,7 +252,7 @@ int bootflow_menu_apply_theme(struct expo *exp, ofnode node)
return 0;
}
-int bootflow_menu_start(struct bootstd_priv *std, bool text_mode,
+int bootflow_menu_setup(struct bootstd_priv *std, bool text_mode,
struct expo **expp)
{
struct udevice *dev;
@@ -260,7 +260,6 @@ int bootflow_menu_start(struct bootstd_priv *std, bool text_mode,
int ret;
LOGR("bmn", bootflow_menu_new(&exp));
- LOGR("bma", bootflow_menu_add_all(exp));
if (ofnode_valid(std->theme)) {
ret = bootflow_menu_apply_theme(exp, std->theme);
@@ -283,6 +282,27 @@ int bootflow_menu_start(struct bootstd_priv *std, bool text_mode,
if (text_mode)
expo_set_text_mode(exp, text_mode);
+ *expp = exp;
+
+ return 0;
+}
+
+int bootflow_menu_start(struct bootstd_priv *std, bool text_mode,
+ struct expo **expp)
+{
+ struct expo *exp;
+ int ret;
+
+ LOGR("bmn", bootflow_menu_setup(std, text_mode, &exp));
+
+ LOGR("bma", bootflow_menu_add_all(exp));
+
+ if (ofnode_valid(std->theme)) {
+ ret = expo_apply_theme(exp, std->theme);
+ if (ret)
+ return log_msg_ret("thm", ret);
+ }
+
LOGR("bmd", expo_calc_dims(exp));
*expp = exp;
diff --git a/include/bootflow.h b/include/bootflow.h
index 8362cbe2e69..c0e19feb9cc 100644
--- a/include/bootflow.h
+++ b/include/bootflow.h
@@ -656,9 +656,24 @@ struct bootflow_img *bootflow_img_add(struct bootflow *bflow, const char *fname,
*/
int bootflow_get_seq(const struct bootflow *bflow);
+/**
+ * bootflow_menu_setup() - Set up a menu for bootflows
+ *
+ * Set up the expo, initially empty
+ *
+ * @std: bootstd information
+ * @text_mode: true to show the menu in text mode, false to use video display
+ * @expp: Returns the expo created, on success
+ * Return: 0 if OK, -ve on error
+ */
+int bootflow_menu_setup(struct bootstd_priv *std, bool text_mode,
+ struct expo **expp);
+
/**
* bootflow_menu_start() - Start up a menu for bootflows
*
+ * Set up the expo and add items
+ *
* @std: bootstd information
* @text_mode: true to show the menu in text mode, false to use video display
* @expp: Returns the expo created, on success
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 55/56] expo: Set up menu fully in bootflow_menu_start()
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (53 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 54/56] expo: Split setting up the menu from adding items Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-28 13:06 ` [PATCH v2 56/56] expo: Drop the special theme code for bootflow_menu Simon Glass
2025-03-30 14:47 ` [PATCH v2 00/56] expo: Various features and improvements Tom Rini
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List; +Cc: Simon Glass, Quentin Schulz, Tom Rini
Apply the theme, calculate dimensions, highlight the menu and arrange
the scene correctly, so that everything is ready to go when the expo
is rendered.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
| 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
--git a/boot/bootflow_menu.c b/boot/bootflow_menu.c
index 4fe5d985064..03ea24f4778 100644
--- a/boot/bootflow_menu.c
+++ b/boot/bootflow_menu.c
@@ -208,10 +208,6 @@ int bootflow_menu_add_all(struct expo *exp)
LOGR("bao", bootflow_menu_add(exp, bflow, i, &scn));
}
- ret = scene_arrange(scn);
- if (ret)
- return log_msg_ret("arr", ret);
-
return 0;
}
@@ -290,7 +286,9 @@ int bootflow_menu_setup(struct bootstd_priv *std, bool text_mode,
int bootflow_menu_start(struct bootstd_priv *std, bool text_mode,
struct expo **expp)
{
+ struct scene *scn;
struct expo *exp;
+ uint scene_id;
int ret;
LOGR("bmn", bootflow_menu_setup(std, text_mode, &exp));
@@ -305,6 +303,18 @@ int bootflow_menu_start(struct bootstd_priv *std, bool text_mode,
LOGR("bmd", expo_calc_dims(exp));
+ ret = expo_first_scene_id(exp);
+ if (ret < 0)
+ return log_msg_ret("scn", ret);
+ scene_id = ret;
+ scn = expo_lookup_scene_id(exp, scene_id);
+
+ scene_set_highlight_id(scn, OBJ_MENU);
+
+ ret = scene_arrange(scn);
+ if (ret)
+ return log_msg_ret("arr", ret);
+
*expp = exp;
return 0;
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* [PATCH v2 56/56] expo: Drop the special theme code for bootflow_menu
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (54 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 55/56] expo: Set up menu fully in bootflow_menu_start() Simon Glass
@ 2025-03-28 13:06 ` Simon Glass
2025-03-30 14:47 ` [PATCH v2 00/56] expo: Various features and improvements Tom Rini
56 siblings, 0 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-28 13:06 UTC (permalink / raw)
To: U-Boot Mailing List
Cc: Simon Glass, Guillaume La Roque, Heinrich Schuchardt,
Mattijs Korpershoek, Quentin Schulz, Tom Rini
The expo now has all that is needed to apply a suitable theme, so drop
this unnecessary code. Any further tweaks can be added to the generic
expo code.
Signed-off-by: Simon Glass <sjg@chromium.org>
---
(no changes since v1)
| 43 -------------------------------------------
test/boot/bootflow.c | 6 +++---
2 files changed, 3 insertions(+), 46 deletions(-)
--git a/boot/bootflow_menu.c b/boot/bootflow_menu.c
index 03ea24f4778..6cd378f8d39 100644
--- a/boot/bootflow_menu.c
+++ b/boot/bootflow_menu.c
@@ -211,43 +211,6 @@ int bootflow_menu_add_all(struct expo *exp)
return 0;
}
-int bootflow_menu_apply_theme(struct expo *exp, ofnode node)
-{
- struct menu_priv *priv = exp->priv;
- struct scene *scn;
- u32 font_size;
- int ret;
-
- log_debug("Applying theme %s\n", ofnode_get_name(node));
- scn = expo_lookup_scene_id(exp, MAIN);
- if (!scn)
- return log_msg_ret("scn", -ENOENT);
-
- /* Avoid error-checking optional items */
- if (!ofnode_read_u32(node, "font-size", &font_size)) {
- int i;
-
- log_debug("font size %d\n", font_size);
- scene_txt_set_font(scn, OBJ_PROMPT1A, NULL, font_size);
- scene_txt_set_font(scn, OBJ_POINTER, NULL, font_size);
- for (i = 0; i < priv->num_bootflows; i++) {
- ret = scene_txt_set_font(scn, ITEM_DESC + i, NULL,
- font_size);
- if (ret)
- return log_msg_ret("des", ret);
- scene_txt_set_font(scn, ITEM_KEY + i, NULL, font_size);
- scene_txt_set_font(scn, ITEM_LABEL + i, NULL,
- font_size);
- }
- }
-
- ret = scene_arrange(scn);
- if (ret)
- return log_msg_ret("arr", ret);
-
- return 0;
-}
-
int bootflow_menu_setup(struct bootstd_priv *std, bool text_mode,
struct expo **expp)
{
@@ -257,12 +220,6 @@ int bootflow_menu_setup(struct bootstd_priv *std, bool text_mode,
LOGR("bmn", bootflow_menu_new(&exp));
- if (ofnode_valid(std->theme)) {
- ret = bootflow_menu_apply_theme(exp, std->theme);
- if (ret)
- return log_msg_ret("thm", ret);
- }
-
/* For now we only support a video console */
ret = uclass_first_device_err(UCLASS_VIDEO, &dev);
if (ret)
diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
index 06fd2dbb20a..670e73c265b 100644
--- a/test/boot/bootflow.c
+++ b/test/boot/bootflow.c
@@ -884,7 +884,7 @@ static int bootflow_menu_theme(struct unit_test_state *uts)
ut_assertok(bootflow_menu_add_all(exp));
node = ofnode_path("/bootstd/theme");
ut_assert(ofnode_valid(node));
- ut_assertok(bootflow_menu_apply_theme(exp, node));
+ ut_assertok(expo_apply_theme(exp, node));
scn = expo_lookup_scene_id(exp, MAIN);
ut_assertnonnull(scn);
@@ -895,8 +895,8 @@ static int bootflow_menu_theme(struct unit_test_state *uts)
*
* Check both menu items, since there are two bootflows
*/
- ut_assertok(check_font(uts, scn, OBJ_PROMPT1A, font_size));
- ut_assertok(check_font(uts, scn, OBJ_POINTER, font_size));
+ for (i = OBJ_PROMPT1A; i <= OBJ_AUTOBOOT; i++)
+ ut_assertok(check_font(uts, scn, i, font_size));
for (i = 0; i < 2; i++) {
ut_assertok(check_font(uts, scn, ITEM_DESC + i, font_size));
ut_assertok(check_font(uts, scn, ITEM_KEY + i, font_size));
--
2.43.0
^ permalink raw reply related [flat|nested] 63+ messages in thread* Re: [PATCH v2 00/56] expo: Various features and improvements
2025-03-28 13:05 [PATCH v2 00/56] expo: Various features and improvements Simon Glass
` (55 preceding siblings ...)
2025-03-28 13:06 ` [PATCH v2 56/56] expo: Drop the special theme code for bootflow_menu Simon Glass
@ 2025-03-30 14:47 ` Tom Rini
2025-03-31 1:18 ` Simon Glass
56 siblings, 1 reply; 63+ messages in thread
From: Tom Rini @ 2025-03-30 14:47 UTC (permalink / raw)
To: Simon Glass
Cc: U-Boot Mailing List, Alexander Graf, Alexander Sverdlin,
Alper Nebi Yasak, Anatolij Gustschin, Bin Meng, Caleb Connolly,
Christian Marangi, Devarsh Thakkar, Guillaume La Roque,
Heinrich Schuchardt, Igor Opaniuk, Julien Masson, Kever Yang,
Marek Vasut, Mattijs Korpershoek, Miquel Raynal, Nikhil M Jain,
Peter Robinson, Quentin Schulz, Rasmus Villemoes, Stefan Roese,
Sughosh Ganu
[-- Attachment #1: Type: text/plain, Size: 1162 bytes --]
On Fri, Mar 28, 2025 at 07:05:47AM -0600, Simon Glass wrote:
> This series collects together some new features for expo to make it more
> useful for boot menus:
>
> - measurement and display of multi-line text objects
> - internal alignment for objects (e.g. centred text)
> - editable strings in text fields
> - new 'box' object to draw a rectangle
> - highlighting of menu items, rather than just relying on a pointer
>
> Expo's boot menu is restructured so that it is possible to iterate
> through various bootdevs and update the menu as new ones are found. This
> is more in keeping with how bootstd works.
>
> A new textedit object is added, intended to provide a simple text
> editor. Future work will complete this.
>
> With this series the boot menu has a better layout and appearance.
Did I already say this for v2 and forget? It looks like you forgot,
again, to split the expo stuff out from everything else, which others
might review.
[snip]
> base-commit: 37ef92a972663c6de1b81d24d2ca5cfd664fc6df
> branch: schd2
Of course, not being on top of mainline, no one should spend much time
on this anyhow.
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply [flat|nested] 63+ messages in thread* Re: [PATCH v2 00/56] expo: Various features and improvements
2025-03-30 14:47 ` [PATCH v2 00/56] expo: Various features and improvements Tom Rini
@ 2025-03-31 1:18 ` Simon Glass
2025-03-31 10:06 ` Caleb Connolly
2025-03-31 13:42 ` Tom Rini
0 siblings, 2 replies; 63+ messages in thread
From: Simon Glass @ 2025-03-31 1:18 UTC (permalink / raw)
To: Tom Rini
Cc: U-Boot Mailing List, Alexander Graf, Alexander Sverdlin,
Alper Nebi Yasak, Anatolij Gustschin, Bin Meng, Caleb Connolly,
Christian Marangi, Devarsh Thakkar, Guillaume La Roque,
Heinrich Schuchardt, Igor Opaniuk, Julien Masson, Kever Yang,
Marek Vasut, Mattijs Korpershoek, Miquel Raynal, Nikhil M Jain,
Peter Robinson, Quentin Schulz, Rasmus Villemoes, Stefan Roese,
Sughosh Ganu
Hi Tom,
On Mon, 31 Mar 2025 at 03:47, Tom Rini <trini@konsulko.com> wrote:
>
> On Fri, Mar 28, 2025 at 07:05:47AM -0600, Simon Glass wrote:
>
> > This series collects together some new features for expo to make it more
> > useful for boot menus:
> >
> > - measurement and display of multi-line text objects
> > - internal alignment for objects (e.g. centred text)
> > - editable strings in text fields
> > - new 'box' object to draw a rectangle
> > - highlighting of menu items, rather than just relying on a pointer
> >
> > Expo's boot menu is restructured so that it is possible to iterate
> > through various bootdevs and update the menu as new ones are found. This
> > is more in keeping with how bootstd works.
> >
> > A new textedit object is added, intended to provide a simple text
> > editor. Future work will complete this.
> >
> > With this series the boot menu has a better layout and appearance.
>
> Did I already say this for v2 and forget? It looks like you forgot,
> again, to split the expo stuff out from everything else, which others
> might review.
This series is all expo stuff. Can you please explain your objection
more clearly? I still don't really understand.
>
> [snip]
> > base-commit: 37ef92a972663c6de1b81d24d2ca5cfd664fc6df
> > branch: schd2
>
> Of course, not being on top of mainline, no one should spend much time
> on this anyhow.
As I thought we agreed, it is helpful to review patches so we can keep
the trees in sync so far as possible. I take your point that few will
be interested in expo and there may not be many comments, but sending
it makes it available for review and potentially sending a PR for your
tree at some point.
Regards,
Simon
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [PATCH v2 00/56] expo: Various features and improvements
2025-03-31 1:18 ` Simon Glass
@ 2025-03-31 10:06 ` Caleb Connolly
2025-03-31 13:42 ` Tom Rini
1 sibling, 0 replies; 63+ messages in thread
From: Caleb Connolly @ 2025-03-31 10:06 UTC (permalink / raw)
To: Simon Glass, Tom Rini
Cc: U-Boot Mailing List, Alexander Graf, Alexander Sverdlin,
Alper Nebi Yasak, Anatolij Gustschin, Bin Meng, Christian Marangi,
Devarsh Thakkar, Guillaume La Roque, Heinrich Schuchardt,
Igor Opaniuk, Julien Masson, Kever Yang, Marek Vasut,
Mattijs Korpershoek, Miquel Raynal, Nikhil M Jain, Peter Robinson,
Quentin Schulz, Rasmus Villemoes, Stefan Roese, Sughosh Ganu
On 3/31/25 03:18, Simon Glass wrote:
> Hi Tom,
>
> On Mon, 31 Mar 2025 at 03:47, Tom Rini <trini@konsulko.com> wrote:
>>
>> On Fri, Mar 28, 2025 at 07:05:47AM -0600, Simon Glass wrote:
>>
>>> This series collects together some new features for expo to make it more
>>> useful for boot menus:
>>>
>>> - measurement and display of multi-line text objects
>>> - internal alignment for objects (e.g. centred text)
>>> - editable strings in text fields
>>> - new 'box' object to draw a rectangle
>>> - highlighting of menu items, rather than just relying on a pointer
>>>
>>> Expo's boot menu is restructured so that it is possible to iterate
>>> through various bootdevs and update the menu as new ones are found. This
>>> is more in keeping with how bootstd works.
>>>
>>> A new textedit object is added, intended to provide a simple text
>>> editor. Future work will complete this.
>>>
>>> With this series the boot menu has a better layout and appearance.
>>
>> Did I already say this for v2 and forget? It looks like you forgot,
>> again, to split the expo stuff out from everything else, which others
>> might review.
>
> This series is all expo stuff. Can you please explain your objection
> more clearly? I still don't really understand.
>
>>
>> [snip]
>>> base-commit: 37ef92a972663c6de1b81d24d2ca5cfd664fc6df
>>> branch: schd2
>>
>> Of course, not being on top of mainline, no one should spend much time
>> on this anyhow.
>
> As I thought we agreed, it is helpful to review patches so we can keep
> the trees in sync so far as possible. I take your point that few will
Please at least make it clear which series you send don't apply on
mainline in the cover letter.
> be interested in expo and there may not be many comments, but sending
> it makes it available for review and potentially sending a PR for your
> tree at some point.
>
> Regards,
> Simon
--
Caleb (they/them)
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [PATCH v2 00/56] expo: Various features and improvements
2025-03-31 1:18 ` Simon Glass
2025-03-31 10:06 ` Caleb Connolly
@ 2025-03-31 13:42 ` Tom Rini
2025-04-01 15:43 ` Simon Glass
1 sibling, 1 reply; 63+ messages in thread
From: Tom Rini @ 2025-03-31 13:42 UTC (permalink / raw)
To: Simon Glass
Cc: U-Boot Mailing List, Alexander Graf, Alexander Sverdlin,
Alper Nebi Yasak, Anatolij Gustschin, Bin Meng, Caleb Connolly,
Christian Marangi, Devarsh Thakkar, Guillaume La Roque,
Heinrich Schuchardt, Igor Opaniuk, Julien Masson, Kever Yang,
Marek Vasut, Mattijs Korpershoek, Miquel Raynal, Nikhil M Jain,
Peter Robinson, Quentin Schulz, Rasmus Villemoes, Stefan Roese,
Sughosh Ganu
[-- Attachment #1: Type: text/plain, Size: 2254 bytes --]
On Mon, Mar 31, 2025 at 01:18:25AM +0000, Simon Glass wrote:
> Hi Tom,
>
> On Mon, 31 Mar 2025 at 03:47, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Fri, Mar 28, 2025 at 07:05:47AM -0600, Simon Glass wrote:
> >
> > > This series collects together some new features for expo to make it more
> > > useful for boot menus:
> > >
> > > - measurement and display of multi-line text objects
> > > - internal alignment for objects (e.g. centred text)
> > > - editable strings in text fields
> > > - new 'box' object to draw a rectangle
> > > - highlighting of menu items, rather than just relying on a pointer
> > >
> > > Expo's boot menu is restructured so that it is possible to iterate
> > > through various bootdevs and update the menu as new ones are found. This
> > > is more in keeping with how bootstd works.
> > >
> > > A new textedit object is added, intended to provide a simple text
> > > editor. Future work will complete this.
> > >
> > > With this series the boot menu has a better layout and appearance.
> >
> > Did I already say this for v2 and forget? It looks like you forgot,
> > again, to split the expo stuff out from everything else, which others
> > might review.
>
> This series is all expo stuff. Can you please explain your objection
> more clearly? I still don't really understand.
All of those patches that don't start with "expo:" aren't expo changes,
they're changes to other parts of the codebase.
> > [snip]
> > > base-commit: 37ef92a972663c6de1b81d24d2ca5cfd664fc6df
> > > branch: schd2
> >
> > Of course, not being on top of mainline, no one should spend much time
> > on this anyhow.
>
> As I thought we agreed, it is helpful to review patches so we can keep
> the trees in sync so far as possible. I take your point that few will
> be interested in expo and there may not be many comments, but sending
> it makes it available for review and potentially sending a PR for your
> tree at some point.
Yes, said at some point we should try it. And it's been a failure, so
I'm saying to stop. If it's not based on top of one of the mainline
branches, don't post it. Enough other contributors have expressed their
unhappiness at reviewing non-mainline code.
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [PATCH v2 00/56] expo: Various features and improvements
2025-03-31 13:42 ` Tom Rini
@ 2025-04-01 15:43 ` Simon Glass
2025-04-01 17:13 ` Tom Rini
0 siblings, 1 reply; 63+ messages in thread
From: Simon Glass @ 2025-04-01 15:43 UTC (permalink / raw)
To: Tom Rini
Cc: U-Boot Mailing List, Alexander Graf, Alexander Sverdlin,
Alper Nebi Yasak, Anatolij Gustschin, Bin Meng, Caleb Connolly,
Christian Marangi, Devarsh Thakkar, Guillaume La Roque,
Heinrich Schuchardt, Igor Opaniuk, Julien Masson, Kever Yang,
Marek Vasut, Mattijs Korpershoek, Miquel Raynal, Nikhil M Jain,
Peter Robinson, Quentin Schulz, Rasmus Villemoes, Stefan Roese,
Sughosh Ganu
Hi Tom,
On Tue, 1 Apr 2025 at 02:42, Tom Rini <trini@konsulko.com> wrote:
>
> On Mon, Mar 31, 2025 at 01:18:25AM +0000, Simon Glass wrote:
> > Hi Tom,
> >
> > On Mon, 31 Mar 2025 at 03:47, Tom Rini <trini@konsulko.com> wrote:
> > >
> > > On Fri, Mar 28, 2025 at 07:05:47AM -0600, Simon Glass wrote:
> > >
> > > > This series collects together some new features for expo to make it more
> > > > useful for boot menus:
> > > >
> > > > - measurement and display of multi-line text objects
> > > > - internal alignment for objects (e.g. centred text)
> > > > - editable strings in text fields
> > > > - new 'box' object to draw a rectangle
> > > > - highlighting of menu items, rather than just relying on a pointer
> > > >
> > > > Expo's boot menu is restructured so that it is possible to iterate
> > > > through various bootdevs and update the menu as new ones are found. This
> > > > is more in keeping with how bootstd works.
> > > >
> > > > A new textedit object is added, intended to provide a simple text
> > > > editor. Future work will complete this.
> > > >
> > > > With this series the boot menu has a better layout and appearance.
> > >
> > > Did I already say this for v2 and forget? It looks like you forgot,
> > > again, to split the expo stuff out from everything else, which others
> > > might review.
> >
> > This series is all expo stuff. Can you please explain your objection
> > more clearly? I still don't really understand.
>
> All of those patches that don't start with "expo:" aren't expo changes,
> they're changes to other parts of the codebase.
Oh I see, you are talking about the video patches at the start. Yes I
will send them separately.
>
> > > [snip]
> > > > base-commit: 37ef92a972663c6de1b81d24d2ca5cfd664fc6df
> > > > branch: schd2
> > >
> > > Of course, not being on top of mainline, no one should spend much time
> > > on this anyhow.
> >
> > As I thought we agreed, it is helpful to review patches so we can keep
> > the trees in sync so far as possible. I take your point that few will
> > be interested in expo and there may not be many comments, but sending
> > it makes it available for review and potentially sending a PR for your
> > tree at some point.
>
> Yes, said at some point we should try it. And it's been a failure, so
> I'm saying to stop. If it's not based on top of one of the mainline
> branches, don't post it. Enough other contributors have expressed their
> unhappiness at reviewing non-mainline code.
If you would like me to send patches against your tree, please
consider applying the various series you have rejected.
Regards,
Simon
^ permalink raw reply [flat|nested] 63+ messages in thread
* Re: [PATCH v2 00/56] expo: Various features and improvements
2025-04-01 15:43 ` Simon Glass
@ 2025-04-01 17:13 ` Tom Rini
0 siblings, 0 replies; 63+ messages in thread
From: Tom Rini @ 2025-04-01 17:13 UTC (permalink / raw)
To: Simon Glass
Cc: U-Boot Mailing List, Alexander Graf, Alexander Sverdlin,
Alper Nebi Yasak, Anatolij Gustschin, Bin Meng, Caleb Connolly,
Christian Marangi, Devarsh Thakkar, Guillaume La Roque,
Heinrich Schuchardt, Igor Opaniuk, Julien Masson, Kever Yang,
Marek Vasut, Mattijs Korpershoek, Miquel Raynal, Nikhil M Jain,
Peter Robinson, Quentin Schulz, Rasmus Villemoes, Stefan Roese,
Sughosh Ganu
[-- Attachment #1: Type: text/plain, Size: 2989 bytes --]
On Wed, Apr 02, 2025 at 04:43:22AM +1300, Simon Glass wrote:
> Hi Tom,
>
> On Tue, 1 Apr 2025 at 02:42, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Mon, Mar 31, 2025 at 01:18:25AM +0000, Simon Glass wrote:
> > > Hi Tom,
> > >
> > > On Mon, 31 Mar 2025 at 03:47, Tom Rini <trini@konsulko.com> wrote:
> > > >
> > > > On Fri, Mar 28, 2025 at 07:05:47AM -0600, Simon Glass wrote:
> > > >
> > > > > This series collects together some new features for expo to make it more
> > > > > useful for boot menus:
> > > > >
> > > > > - measurement and display of multi-line text objects
> > > > > - internal alignment for objects (e.g. centred text)
> > > > > - editable strings in text fields
> > > > > - new 'box' object to draw a rectangle
> > > > > - highlighting of menu items, rather than just relying on a pointer
> > > > >
> > > > > Expo's boot menu is restructured so that it is possible to iterate
> > > > > through various bootdevs and update the menu as new ones are found. This
> > > > > is more in keeping with how bootstd works.
> > > > >
> > > > > A new textedit object is added, intended to provide a simple text
> > > > > editor. Future work will complete this.
> > > > >
> > > > > With this series the boot menu has a better layout and appearance.
> > > >
> > > > Did I already say this for v2 and forget? It looks like you forgot,
> > > > again, to split the expo stuff out from everything else, which others
> > > > might review.
> > >
> > > This series is all expo stuff. Can you please explain your objection
> > > more clearly? I still don't really understand.
> >
> > All of those patches that don't start with "expo:" aren't expo changes,
> > they're changes to other parts of the codebase.
>
> Oh I see, you are talking about the video patches at the start. Yes I
> will send them separately.
>
> >
> > > > [snip]
> > > > > base-commit: 37ef92a972663c6de1b81d24d2ca5cfd664fc6df
> > > > > branch: schd2
> > > >
> > > > Of course, not being on top of mainline, no one should spend much time
> > > > on this anyhow.
> > >
> > > As I thought we agreed, it is helpful to review patches so we can keep
> > > the trees in sync so far as possible. I take your point that few will
> > > be interested in expo and there may not be many comments, but sending
> > > it makes it available for review and potentially sending a PR for your
> > > tree at some point.
> >
> > Yes, said at some point we should try it. And it's been a failure, so
> > I'm saying to stop. If it's not based on top of one of the mainline
> > branches, don't post it. Enough other contributors have expressed their
> > unhappiness at reviewing non-mainline code.
>
> If you would like me to send patches against your tree, please
> consider applying the various series you have rejected.
They've been rejected for reasons that have been explained seemingly
countless times. Please drop them, or just move on from the project.
--
Tom
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]
^ permalink raw reply [flat|nested] 63+ messages in thread