From 74fe72d0000b5b103b8079706a9739af733d398f Mon Sep 17 00:00:00 2001 From: Thomas Jarosch Date: Fri, 24 Dec 2010 12:16:16 +0100 Subject: [PATCH] Speed up SDL screen updates The current code calls SDL_FillRectangle() for every pixel, which is very slow. We can speed things up greatly by using SDL_BlitSurface() if the LCD_DEPTH is >= 8 and the pixel format is normal RGB. Also don't call SDL_LockSurface() in the pixel-by-pixel code as it's only needed if we are manipulating pixels directly. --- firmware/target/hosted/sdl/lcd-sdl.c | 35 ++++++++++++++++++++++++++---- firmware/target/hosted/sdl/system-sdl.c | 10 ++++++-- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/firmware/target/hosted/sdl/lcd-sdl.c b/firmware/target/hosted/sdl/lcd-sdl.c index 96b1a04..19db68d 100644 --- a/firmware/target/hosted/sdl/lcd-sdl.c +++ b/firmware/target/hosted/sdl/lcd-sdl.c @@ -32,8 +32,36 @@ void sdl_update_rect(SDL_Surface *surface, int x_start, int y_start, int width, { int x, y; int xmax, ymax; - SDL_Rect dest; - + SDL_Rect src, dest; + +#if LCD_DEPTH >= 8 && LCD_PIXELFORMAT & RGB565 \ + && !(LCD_PIXELFORMAT & RGB565SWAPPED) \ + && !defined(LCD_STRIDEFORMAT) + /* Update complete screen via one blit operation */ + SDL_Surface *lcd = SDL_CreateRGBSurfaceFrom(lcd_framebuffer, LCD_FBWIDTH, LCD_FBHEIGHT, + LCD_DEPTH, LCD_FBWIDTH * (LCD_DEPTH/8), + 0, 0, 0, 0); + + src.x = x_start; + src.y = y_start; + src.w = width; + src.h = height; + + dest.x = x_start * display_zoom; + dest.y = y_start * display_zoom; + dest.w = width * display_zoom; + dest.h = height * display_zoom; + + if (display_zoom == 1) { + SDL_BlitSurface(lcd, &src, surface, &dest); + } else { + /* Note: SDL_SoftStretch is currently marked as DO NOT USE + but there are no real alternatives for efficent zooming. */ + SDL_SoftStretch(lcd, &src, surface, &dest); + } + SDL_FreeSurface(lcd); +#else + /* Very slow pixel-by-pixel drawing */ ymax = y_start + height; xmax = x_start + width; @@ -42,8 +70,6 @@ void sdl_update_rect(SDL_Surface *surface, int x_start, int y_start, int width, if(ymax >= max_y) ymax = max_y; - SDL_LockSurface(surface); - dest.w = display_zoom; dest.h = display_zoom; @@ -69,8 +95,7 @@ void sdl_update_rect(SDL_Surface *surface, int x_start, int y_start, int width, } #endif } - - SDL_UnlockSurface(surface); +#endif } void sdl_gui_update(SDL_Surface *surface, int x_start, int y_start, int width, diff --git a/firmware/target/hosted/sdl/system-sdl.c b/firmware/target/hosted/sdl/system-sdl.c index 6937c37..b900d38 100644 --- a/firmware/target/hosted/sdl/system-sdl.c +++ b/firmware/target/hosted/sdl/system-sdl.c @@ -84,6 +84,7 @@ static int sdl_event_thread(void * param) SDL_Surface *picture_surface = NULL; int width, height; + int depth; /* Try and load the background image. If it fails go without */ if (background) { @@ -115,9 +116,12 @@ static int sdl_event_thread(void * param) height = SIM_LCD_HEIGHT; } } - - - if ((gui_surface = SDL_SetVideoMode(width * display_zoom, height * display_zoom, 24, SDL_HWSURFACE|SDL_DOUBLEBUF)) == NULL) { + + depth = LCD_DEPTH; + if (depth < 8) + depth = 16; + + if ((gui_surface = SDL_SetVideoMode(width * display_zoom, height * display_zoom, depth, SDL_HWSURFACE|SDL_DOUBLEBUF)) == NULL) { panicf("%s", SDL_GetError()); } -- 1.7.2.3