[RFC PATCH 5/5] sandbox: video: Use partial updates for SDL display

Alper Nebi Yasak alpernebiyasak at gmail.com
Mon Aug 21 20:13:39 CEST 2023


Now that we have video damage tracking, try to reduce the SDL display
work by copying only the updated regions onto the SDL texture instead of
the entire framebuffer. We still have to do RenderClear and RenderCopy
the whole texture onto the renderer, but that allegedly happens in the
GPU.

Signed-off-by: Alper Nebi Yasak <alpernebiyasak at gmail.com>
---
The second half of copy_to_texture is untested.

 arch/sandbox/cpu/sdl.c         | 25 +++++++++++++++++--------
 arch/sandbox/include/asm/sdl.h |  9 +++++++--
 drivers/video/sandbox_sdl.c    | 16 +++++++++++++++-
 3 files changed, 39 insertions(+), 11 deletions(-)

diff --git a/arch/sandbox/cpu/sdl.c b/arch/sandbox/cpu/sdl.c
index 48fae20b4c2d..3a3221d89066 100644
--- a/arch/sandbox/cpu/sdl.c
+++ b/arch/sandbox/cpu/sdl.c
@@ -192,8 +192,10 @@ int sandbox_sdl_init_display(int width, int height, int log2_bpp,
 	return 0;
 }
 
-static int copy_to_texture(void *lcd_base)
+static int copy_to_texture(void *lcd_base, int xstart, int ystart,
+			   int xend, int yend)
 {
+	struct SDL_Rect rect;
 	char *dest;
 	int pitch, x, y;
 	int src_pitch;
@@ -201,8 +203,15 @@ static int copy_to_texture(void *lcd_base)
 	char *src;
 	int ret;
 
+	rect.x = xstart;
+	rect.y = ystart;
+	rect.w = xend - xstart + 1;
+	rect.h = yend - ystart + 1;
+
 	if (sdl.src_depth == sdl.depth) {
-		SDL_UpdateTexture(sdl.texture, NULL, lcd_base, sdl.pitch);
+		src_pitch = sdl.width * sdl.src_depth / 8;
+		src = lcd_base + src_pitch * rect.y + rect.x * sdl.src_depth / 8;
+		SDL_UpdateTexture(sdl.texture, &rect, src, src_pitch);
 		return 0;
 	}
 
@@ -215,7 +224,7 @@ static int copy_to_texture(void *lcd_base)
 		return -EINVAL;
 	}
 
-	ret = SDL_LockTexture(sdl.texture, NULL, &pixels, &pitch);
+	ret = SDL_LockTexture(sdl.texture, &rect, &pixels, &pitch);
 	if (ret) {
 		printf("SDL lock %d: %s\n", ret, SDL_GetError());
 		return ret;
@@ -223,12 +232,12 @@ static int copy_to_texture(void *lcd_base)
 
 	/* Copy the pixels one by one */
 	src_pitch = sdl.width * sdl.src_depth / 8;
-	for (y = 0; y < sdl.height; y++) {
+	for (y = 0; y < rect.h; y++) {
 		char val;
 
 		dest = pixels + y * pitch;
-		src = lcd_base + src_pitch * y;
-		for (x = 0; x < sdl.width; x++, dest += 4) {
+		src = lcd_base + src_pitch * (ystart + y) + xstart;
+		for (x = 0; x < rect.w; x++, dest += 4) {
 			val = *src++;
 			dest[0] = val;
 			dest[1] = val;
@@ -241,7 +250,7 @@ static int copy_to_texture(void *lcd_base)
 	return 0;
 }
 
-int sandbox_sdl_sync(void *lcd_base)
+int sandbox_sdl_sync(void *lcd_base, int xstart, int ystart, int xend, int yend)
 {
 	struct SDL_Rect rect;
 	int ret;
@@ -253,7 +262,7 @@ int sandbox_sdl_sync(void *lcd_base)
 		return -EAGAIN;
 
 	SDL_RenderClear(sdl.renderer);
-	ret = copy_to_texture(lcd_base);
+	ret = copy_to_texture(lcd_base, xstart, ystart, xend, yend);
 	if (ret) {
 		printf("copy_to_texture: %d: %s\n", ret, SDL_GetError());
 		return -EIO;
diff --git a/arch/sandbox/include/asm/sdl.h b/arch/sandbox/include/asm/sdl.h
index 1ace7d1a1217..c7c73ef3a3e6 100644
--- a/arch/sandbox/include/asm/sdl.h
+++ b/arch/sandbox/include/asm/sdl.h
@@ -41,10 +41,14 @@ int sandbox_sdl_remove_display(void);
  * system resources too much.
  *
  * @lcd_base: Base of frame buffer
+ * @xstart:   X start position of updated region in pixels from the left
+ * @ystart:   Y start position of updated region in pixels from the top
+ * @xend:     X end position of updated region in pixels from the left
+ * @yend:     Y end position of updated region in pixels from the top
  * Return: 0 if screen was updated, -ENODEV is there is no screen.
  *	   -EAGAIN if screen was not updated due to sync rate limit.
  */
-int sandbox_sdl_sync(void *lcd_base);
+int sandbox_sdl_sync(void *lcd_base, int xstart, int ystart, int xend, int yend);
 
 /**
  * sandbox_sdl_scan_keys() - scan for pressed keys
@@ -118,7 +122,8 @@ static inline int sandbox_sdl_remove_display(void)
 	return -ENODEV;
 }
 
-static inline int sandbox_sdl_sync(void *lcd_base)
+static inline int sandbox_sdl_sync(void *lcd_base, int xstart, int ystart,
+				   int xend, int yend)
 {
 	return -ENODEV;
 }
diff --git a/drivers/video/sandbox_sdl.c b/drivers/video/sandbox_sdl.c
index 7dc2787a5d25..eb424072b6fe 100644
--- a/drivers/video/sandbox_sdl.c
+++ b/drivers/video/sandbox_sdl.c
@@ -103,11 +103,25 @@ static int sandbox_sdl_video_sync(struct udevice *dev)
 {
 	struct video_priv *priv = dev_get_uclass_priv(dev);
 	void *fb = priv->fb;
+	int xstart = 0;
+	int ystart = 0;
+	int xend = priv->xsize;
+	int yend = priv->ysize;
 
 	if (IS_ENABLED(CONFIG_VIDEO_COPY))
 		fb = priv->copy_fb;
 
-	return sandbox_sdl_sync(fb);
+	if (IS_ENABLED(CONFIG_VIDEO_DAMAGE)) {
+		if (!priv->damage.xend && !priv->damage.yend)
+			return 0;
+
+		xstart = priv->damage.xstart;
+		ystart = priv->damage.ystart;
+		xend = priv->damage.xend;
+		yend = priv->damage.yend;
+	}
+
+	return sandbox_sdl_sync(fb, xstart, ystart, xend, yend);
 }
 
 static int sandbox_sdl_remove(struct udevice *dev)
-- 
2.40.1



More information about the U-Boot mailing list