[Concept,20/22] video: sandbox: Optimise drawing based on damage

Message ID 20251003165525.440173-21-sjg@u-boot.org
State New
Headers
Series video: Enhancements to support a pointer |

Commit Message

Simon Glass Oct. 3, 2025, 4:55 p.m. UTC
  From: Simon Glass <sjg@chromium.org>

Update sandbox_sdl_sync() to accept an optional damage rectangle and
update only the damaged region. This should reduce the amount of work
performed by the driver when only a small part of the display needs to
be updated.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

 arch/sandbox/cpu/sdl.c | 46 ++++++++++++++++++++++++++++++++++--------
 1 file changed, 38 insertions(+), 8 deletions(-)
  

Patch

diff --git a/arch/sandbox/cpu/sdl.c b/arch/sandbox/cpu/sdl.c
index fa431010b11..f4038c2431a 100644
--- a/arch/sandbox/cpu/sdl.c
+++ b/arch/sandbox/cpu/sdl.c
@@ -6,6 +6,7 @@ 
 #include <errno.h>
 #include <mouse.h>
 #include <unistd.h>
+#include <video_defs.h>
 #include <stdbool.h>
 #include <sysreset.h>
 #include <linux/input.h>
@@ -232,17 +233,46 @@  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, const struct video_bbox *damage)
 {
 	char *dest;
 	int pitch, x, y;
 	int src_pitch;
 	void *pixels;
 	char *src;
+	SDL_Rect rect, *rectp = NULL;
 	int ret;
+	int x0, y0, x1, y1;
+
+	/* Set up damage region if provided */
+	if (damage && damage->x1 > damage->x0 && damage->y1 > damage->y0) {
+		rect.x = damage->x0;
+		rect.y = damage->y0;
+		rect.w = damage->x1 - damage->x0;
+		rect.h = damage->y1 - damage->y0;
+		rectp = &rect;
+		x0 = damage->x0;
+		y0 = damage->y0;
+		x1 = damage->x1;
+		y1 = damage->y1;
+	} else {
+		x0 = 0;
+		y0 = 0;
+		x1 = sdl.width;
+		y1 = sdl.height;
+	}
 
 	if (sdl.src_depth == sdl.depth) {
-		SDL_UpdateTexture(sdl.texture, NULL, lcd_base, sdl.pitch);
+		if (rectp) {
+			/* Update only the damaged region */
+			src_pitch = sdl.width * sdl.src_depth / 8;
+			src = lcd_base + y0 * src_pitch +
+						x0 * sdl.src_depth / 8;
+			SDL_UpdateTexture(sdl.texture, rectp, src, src_pitch);
+		} else {
+			SDL_UpdateTexture(sdl.texture, NULL, lcd_base,
+					  sdl.pitch);
+		}
 		return 0;
 	}
 
@@ -255,7 +285,7 @@  static int copy_to_texture(void *lcd_base)
 		return -EINVAL;
 	}
 
-	ret = SDL_LockTexture(sdl.texture, NULL, &pixels, &pitch);
+	ret = SDL_LockTexture(sdl.texture, rectp, &pixels, &pitch);
 	if (ret) {
 		printf("SDL lock %d: %s\n", ret, SDL_GetError());
 		return ret;
@@ -263,12 +293,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 = y0; y < y1; y++) {
 		char val;
 
-		dest = pixels + y * pitch;
-		src = lcd_base + src_pitch * y;
-		for (x = 0; x < sdl.width; x++, dest += 4) {
+		dest = pixels + (y - y0) * pitch;
+		src = lcd_base + src_pitch * y + x0;
+		for (x = x0; x < x1; x++, dest += 4) {
 			val = *src++;
 			dest[0] = val;
 			dest[1] = val;
@@ -289,7 +319,7 @@  int sandbox_sdl_sync(void *lcd_base)
 	if (!sdl.texture)
 		return 0;
 	SDL_RenderClear(sdl.renderer);
-	ret = copy_to_texture(lcd_base);
+	ret = copy_to_texture(lcd_base, NULL);
 	if (ret) {
 		printf("copy_to_texture: %d: %s\n", ret, SDL_GetError());
 		return -EIO;