video: Add a function to draw a rectangle

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>
This commit is contained in:
Simon Glass
2025-04-02 06:29:43 +13:00
committed by Tom Rini
parent cb32266d4a
commit f94f1f4b8c
3 changed files with 75 additions and 1 deletions

View File

@@ -26,6 +26,7 @@
#ifdef CONFIG_SANDBOX #ifdef CONFIG_SANDBOX
#include <asm/sdl.h> #include <asm/sdl.h>
#endif #endif
#include "vidconsole_internal.h"
/* /*
* Theory of operation: * Theory of operation:
@@ -216,6 +217,40 @@ int video_fill_part(struct udevice *dev, int xstart, int ystart, int xend,
return 0; 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) int video_reserve_from_bloblist(struct video_handoff *ho)
{ {
if (!ho->fb || ho->size == 0) if (!ho->fb || ho->size == 0)
@@ -481,6 +516,7 @@ int video_sync(struct udevice *vid, bool force)
video_flush_dcache(vid, true); video_flush_dcache(vid, true);
#if defined(CONFIG_VIDEO_SANDBOX_SDL) #if defined(CONFIG_VIDEO_SANDBOX_SDL)
/* to see the copy framebuffer, use priv->copy_fb */
sandbox_sdl_sync(priv->fb); sandbox_sdl_sync(priv->fb);
#endif #endif
priv->last_sync = get_timer(0); priv->last_sync = get_timer(0);

View File

@@ -249,7 +249,7 @@ int video_fill(struct udevice *dev, u32 colour);
/** /**
* video_fill_part() - Erase a region * 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 * @dev: Device to update
* @xstart: X start position in pixels from the left * @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 video_fill_part(struct udevice *dev, int xstart, int ystart, int xend,
int yend, u32 colour); 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 * video_sync() - Sync a device's frame buffer with its hardware
* *

View File

@@ -902,3 +902,24 @@ static int dm_test_video_silence(struct unit_test_state *uts)
return 0; return 0;
} }
DM_TEST(dm_test_video_silence, UTF_SCAN_FDT); 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);