From: Simon Glass <sjg@chromium.org> Add a test that verifies the sandbox SDL driver receives the correct damage rectangle in its sync() method. The test: - Clears the display and verifies full-screen damage is passed to sync() - Writes text at a specific position and verifies smaller damage region - Draws a box and verifies the damage matches the box dimensions The damage rectangle is recorded in sandbox_sdl_plat.last_sync_damage and can be retrieved using sandbox_sdl_get_sync_damage() for testing purposes. Co-developed-by: Claude <noreply@anthropic.com> Signed-off-by: Simon Glass <sjg@chromium.org> --- drivers/video/sandbox_sdl.c | 23 +++++++-- include/dm/test.h | 15 ++++++ test/dm/video.c | 96 +++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 3 deletions(-) diff --git a/drivers/video/sandbox_sdl.c b/drivers/video/sandbox_sdl.c index 67b4b6c7911..fc5843a2822 100644 --- a/drivers/video/sandbox_sdl.c +++ b/drivers/video/sandbox_sdl.c @@ -129,22 +129,39 @@ static int sandbox_sdl_bind(struct udevice *dev) static int sandbox_sdl_video_sync(struct udevice *vid, uint flags) { - struct video_priv *priv = dev_get_uclass_priv(vid); + struct sandbox_sdl_plat *plat = dev_get_plat(vid); + struct video_priv *uc_priv = dev_get_uclass_priv(vid); const struct video_bbox *damage = NULL; if (!(flags & VIDSYNC_FLUSH)) return 0; if (IS_ENABLED(CONFIG_VIDEO_DAMAGE)) - damage = &priv->damage; + damage = &uc_priv->damage; - return sandbox_sdl_sync(priv->fb, damage); + /* Record the damage box for testing */ + if (damage) + plat->last_sync_damage = *damage; + else + memset(&plat->last_sync_damage, '\0', + sizeof(plat->last_sync_damage)); + + return sandbox_sdl_sync(uc_priv->fb, damage); } static const struct video_ops sandbox_sdl_ops = { .sync = sandbox_sdl_video_sync, }; +int sandbox_sdl_get_sync_damage(struct udevice *dev, struct video_bbox *damage) +{ + struct sandbox_sdl_plat *plat = dev_get_plat(dev); + + *damage = plat->last_sync_damage; + + return 0; +} + static const struct udevice_id sandbox_sdl_ids[] = { { .compatible = "sandbox,lcd-sdl" }, { } diff --git a/include/dm/test.h b/include/dm/test.h index 4aabb4603b9..10fd63e759f 100644 --- a/include/dm/test.h +++ b/include/dm/test.h @@ -7,6 +7,7 @@ #define __DM_TEST_H #include <linux/types.h> +#include <video_defs.h> struct udevice; @@ -157,6 +158,7 @@ extern struct unit_test_state global_dm_test_state; * 2=upside down, 3=90 degree counterclockwise) * @vidconsole_drv_name: Name of video console driver (set by tests) * @font_size: Console font size to select (set by tests) + * @last_sync_damage: Last damage rectangle passed to sync() method (for testing) */ struct sandbox_sdl_plat { int xres; @@ -165,6 +167,7 @@ struct sandbox_sdl_plat { int rot; const char *vidconsole_drv_name; int font_size; + struct video_bbox last_sync_damage; }; /** @@ -232,4 +235,16 @@ void dm_leak_check_start(struct unit_test_state *uts); * @dms: Overall test state */int dm_leak_check_end(struct unit_test_state *uts); +/** + * sandbox_sdl_get_sync_damage() - Get the last damage rect passed to sync() + * + * This is used for testing to verify that the correct damage rectangle was + * passed to the driver's sync() method. + * + * @dev: Video device + * @damage: Returns the last damage rectangle + * Return: 0 if OK, -ve on error + */ +int sandbox_sdl_get_sync_damage(struct udevice *dev, struct video_bbox *damage); + #endif diff --git a/test/dm/video.c b/test/dm/video.c index 080297d8350..5a5d8053856 100644 --- a/test/dm/video.c +++ b/test/dm/video.c @@ -1372,3 +1372,99 @@ static int dm_test_video_manual_sync(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_video_manual_sync, UTF_SCAN_PDATA | UTF_SCAN_FDT); + +/* Test that sync() receives the correct damage rectangle */ +static int dm_test_video_sync_damage(struct unit_test_state *uts) +{ + struct video_bbox damage; + struct udevice *dev, *con; + struct video_priv *priv; + + if (!IS_ENABLED(CONFIG_VIDEO_DAMAGE)) + return -EAGAIN; + + ut_assertok(select_vidconsole(uts, "vidconsole0")); + 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)); + priv = dev_get_uclass_priv(dev); + + /* Use manual sync to prevent interference with the test */ + video_set_manual_sync(true); + + /* Clear the display - this creates a full-screen damage and syncs */ + video_clear(dev); + ut_assertok(video_manual_sync(dev, VIDSYNC_FLUSH | VIDSYNC_COPY)); + ut_asserteq(46, video_compress_fb(uts, dev, false)); + + /* Get the damage rectangle that was passed to sync() */ + ut_assertok(sandbox_sdl_get_sync_damage(dev, &damage)); + + /* Should be the full screen */ + ut_assert(video_bbox_valid(&damage)); + ut_asserteq(0, damage.x0); + ut_asserteq(0, damage.y0); + ut_asserteq(priv->xsize, damage.x1); + ut_asserteq(priv->ysize, damage.y1); + + /* Sync again with no changes - should have empty damage */ + ut_assertok(video_manual_sync(dev, VIDSYNC_FLUSH | VIDSYNC_COPY)); + ut_assertok(sandbox_sdl_get_sync_damage(dev, &damage)); + ut_assert(!video_bbox_valid(&damage)); + + /* Check that priv->damage is still reset to empty */ + ut_assert(!video_bbox_valid(&priv->damage)); + + /* Write a small piece of text at a specific position */ + vidconsole_putc_xy(con, VID_TO_POS(400), 67, 'T'); + + /* Check priv->damage before sync - should have text damage */ + ut_assert(video_bbox_valid(&priv->damage)); + ut_asserteq(400, priv->damage.x0); + ut_asserteq(67, priv->damage.y0); + ut_asserteq(400 + 8, priv->damage.x1); /* 8x16 font */ + ut_asserteq(67 + 16, priv->damage.y1); + + ut_assertok(video_manual_sync(dev, VIDSYNC_FLUSH | VIDSYNC_COPY)); + + /* Get the damage rectangle that was passed to sync() */ + ut_assertok(sandbox_sdl_get_sync_damage(dev, &damage)); + + /* The damage should cover just the character */ + ut_assert(video_bbox_valid(&damage)); + ut_asserteq(400, damage.x0); + ut_asserteq(67, damage.y0); + ut_asserteq(400 + 8, damage.x1); + ut_asserteq(67 + 16, damage.y1); + + /* Check priv->damage after sync - should be reset to empty */ + ut_assert(!video_bbox_valid(&priv->damage)); + + /* Draw a filled box at a different position */ + ut_assertok(video_draw_box(dev, 200, 300, 250, 340, 1, 0xffffff, true)); + + /* Check priv->damage before sync - should have box damage */ + ut_assert(video_bbox_valid(&priv->damage)); + ut_asserteq(200, priv->damage.x0); + ut_asserteq(300, priv->damage.y0); + ut_asserteq(250, priv->damage.x1); + ut_asserteq(340, priv->damage.y1); + + ut_assertok(video_manual_sync(dev, VIDSYNC_FLUSH | VIDSYNC_COPY)); + + /* Get the damage rectangle for the box */ + ut_assertok(sandbox_sdl_get_sync_damage(dev, &damage)); + + /* The damage should cover the box area */ + ut_assert(video_bbox_valid(&damage)); + ut_asserteq(200, damage.x0); + ut_asserteq(300, damage.y0); + ut_asserteq(250, damage.x1); + ut_asserteq(340, damage.y1); + + /* Check priv->damage after sync - should be reset to inverted/empty */ + ut_assert(!video_bbox_valid(&priv->damage)); + + return 0; +} +DM_TEST(dm_test_video_sync_damage, UTF_SCAN_PDATA | UTF_SCAN_FDT); -- 2.43.0