diff mbox series

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

Message ID 20230821181339.4135800-6-alpernebiyasak@gmail.com
State Under Review
Delegated to: Anatolij Gustschin
Headers show
Series sandbox: video: Refactor out of uclass, try partial screen updates | expand

Commit Message

Alper Nebi Yasak Aug. 21, 2023, 6:13 p.m. UTC
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@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(-)

Comments

Simon Glass Aug. 21, 2023, 10:10 p.m. UTC | #1
On Mon, 21 Aug 2023 at 12:13, Alper Nebi Yasak <alpernebiyasak@gmail.com> wrote:
>
> 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@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(-)
>

Reviewed-by: Simon Glass <sjg@chromium.org>
diff mbox series

Patch

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)