diff options
author | Christian Soffke <christian.soffke@gmail.com> | 2024-12-22 22:55:27 +0100 |
---|---|---|
committer | Christian Soffke <christian.soffke@gmail.com> | 2024-12-25 08:34:40 -0500 |
commit | 400452180d0bbf649119b80c4c93b7b6347848c1 (patch) | |
tree | 190f3ace38b1307ca0ec62da764125bd1683496a | |
parent | 7aaa722a5da170dc40eaa6e2df2aa79f892f1d9d (diff) | |
download | rockbox-400452180d.tar.gz rockbox-400452180d.zip |
sdl: Keep texture around, upload LCD-parts only
No need to create a new texture for every
rendered frame, unless the scaling method
has been adjusted.
We also don't need to upload the (unchanged)
player interface to GPU memory repeatedly.
+ Remove unused lcd_display_redraw &
having_new_lcd variables
Change-Id: I5bff6aa2d54347a3f2c3afba8d8d7eb9e39f77f7
-rw-r--r-- | firmware/SOURCES | 1 | ||||
-rw-r--r-- | firmware/drivers/button_queue.c | 4 | ||||
-rw-r--r-- | firmware/target/hosted/sdl/button-sdl.c | 6 | ||||
-rw-r--r-- | firmware/target/hosted/sdl/lcd-sdl.c | 110 | ||||
-rw-r--r-- | firmware/target/hosted/sdl/lcd-sdl.h | 9 | ||||
-rw-r--r-- | firmware/target/hosted/sdl/system-sdl.c | 71 | ||||
-rw-r--r-- | firmware/target/hosted/sdl/window-sdl.c | 223 | ||||
-rw-r--r-- | firmware/target/hosted/sdl/window-sdl.h | 41 |
8 files changed, 279 insertions, 186 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES index 42dc5fb82f..7a373f46cd 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -74,6 +74,7 @@ target/hosted/sdl/lcd-bitmap.c target/hosted/sdl/lcd-remote-bitmap.c #endif target/hosted/sdl/lcd-sdl.c +target/hosted/sdl/window-sdl.c target/hosted/sdl/system-sdl.c #ifdef HAVE_SDL_THREADS target/hosted/sdl/filesystem-sdl.c diff --git a/firmware/drivers/button_queue.c b/firmware/drivers/button_queue.c index f539b88b75..48e0179001 100644 --- a/firmware/drivers/button_queue.c +++ b/firmware/drivers/button_queue.c @@ -24,7 +24,7 @@ #include "button.h" #ifdef HAVE_SDL #include "button-sdl.h" -#include "lcd-sdl.h" +#include "window-sdl.h" #endif static struct event_queue button_queue SHAREDBSS_ATTR; @@ -119,7 +119,7 @@ static inline void button_queue_wait(struct queue_event *evp, int timeout) #else queue_wait_w_tmo(&button_queue, evp, timeout); #ifdef HAVE_SDL - sdl_update_window(); /* Window may have been resized */ + sdl_window_adjust(); /* Window may have been resized */ #endif #endif } diff --git a/firmware/target/hosted/sdl/button-sdl.c b/firmware/target/hosted/sdl/button-sdl.c index 9c46279a15..6f0d468d01 100644 --- a/firmware/target/hosted/sdl/button-sdl.c +++ b/firmware/target/hosted/sdl/button-sdl.c @@ -31,7 +31,7 @@ #include "backlight.h" #include "system.h" #include "button-sdl.h" -#include "lcd-sdl.h" +#include "window-sdl.h" #include "sim_tasks.h" #include "buttonmap.h" #include "debug.h" @@ -243,7 +243,7 @@ static bool event_handler(SDL_Event *event) sdl_app_has_input_focus = 0; else if(event->window.event == SDL_WINDOWEVENT_RESIZED) { - sdl_window_needs_update(); + sdl_window_adjustment_needed(false); #if !defined (__APPLE__) && !defined(__WIN32) static unsigned long last_tick; if (TIME_AFTER(current_tick, last_tick + HZ/20) && !button_queue_full()) @@ -370,7 +370,7 @@ static void button_event(int key, bool pressed) strcmp(SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY) ?: "best", "best") ? "best": "nearest"); - sdl_window_needs_update(); + sdl_window_adjustment_needed(!display_zoom); #if !defined(__WIN32) && !defined (__APPLE__) button_queue_post(SDLK_UNKNOWN, 0); /* update window on main thread */ #endif diff --git a/firmware/target/hosted/sdl/lcd-sdl.c b/firmware/target/hosted/sdl/lcd-sdl.c index 596d3ec1f0..c340dff798 100644 --- a/firmware/target/hosted/sdl/lcd-sdl.c +++ b/firmware/target/hosted/sdl/lcd-sdl.c @@ -23,105 +23,7 @@ #include "lcd-sdl.h" #include "sim-ui-defines.h" #include "system.h" /* for MIN() and MAX() */ -#include "misc.h" - -double display_zoom = 1; -static bool window_needs_update; - -void sdl_get_window_dimensions(int *w, int *h) -{ - if (background) - { - *w = UI_WIDTH; - *h = UI_HEIGHT; - } - else - { -#ifdef HAVE_REMOTE_LCD - if (showremote) - { - *w = SIM_LCD_WIDTH > SIM_REMOTE_WIDTH ? SIM_LCD_WIDTH : SIM_REMOTE_WIDTH; - *h = SIM_LCD_HEIGHT + SIM_REMOTE_HEIGHT; - } - else -#endif - { - *w = SIM_LCD_WIDTH; - *h = SIM_LCD_HEIGHT; - } - } -} - -static inline void sdl_render(void) -{ - SDL_Texture *sdlTexture = SDL_CreateTextureFromSurface(sdlRenderer, gui_surface); - SDL_RenderClear(sdlRenderer); - SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL); - SDL_RenderPresent(sdlRenderer); - SDL_DestroyTexture(sdlTexture); -} - - -#define SNAP_MARGIN 50 -int sdl_update_window(void) -{ - int w, h; - - if (!window_needs_update) - return false; - window_needs_update = false; - - sdl_get_window_dimensions(&w, &h); - - if (!(SDL_GetWindowFlags(window) & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_FULLSCREEN))) - { - if (display_zoom) - { - SDL_SetWindowSize(window, display_zoom * w, display_zoom * h); - } -#if defined(__APPLE__) || defined(__WIN32) - else /* Constrain aspect ratio on Windows and MacOS */ - { - - float aspect_ratio = (float) h / w; - int original_height = h; - int original_width = w; - - SDL_GetWindowSize(window, &w, &h); - if (w != original_width || h != original_height) - { - if (abs(original_width - w) < SNAP_MARGIN) - { - w = original_width; - h = original_height; - } - else - h = w * aspect_ratio; - - SDL_SetWindowSize(window, w, h); - } - } -#endif - } - display_zoom = 0; - sdl_render(); - return true; -} - -void sdl_window_needs_update(void) -{ - window_needs_update = true; - - /* For MacOS and Windows, we're on a main or - display thread already, and can immediately - update the window. - On Linux, we have to defer the update, until - it is handled by the main thread later. */ -#if defined (__APPLE__) || defined(__WIN32) - sdl_update_window(); -#endif -} - +#include "window-sdl.h" void sdl_update_rect(SDL_Surface *surface, int x_start, int y_start, int width, int height, int max_x, int max_y, @@ -201,12 +103,14 @@ void sdl_gui_update(SDL_Surface *surface, int x_start, int y_start, int width, uint8_t alpha; if (SDL_GetSurfaceAlphaMod(surface,&alpha) == 0 && alpha < 255) - SDL_FillRect(gui_surface, &dest, 0); /* alpha needs a black background */ + SDL_FillRect(sim_lcd_surface, NULL, 0); /* alpha needs a black background */ - SDL_BlitSurface(surface, &src, gui_surface, &dest); + SDL_BlitSurface(surface, &src, sim_lcd_surface, NULL); + SDL_UpdateTexture(gui_texture, &dest, + sim_lcd_surface->pixels, sim_lcd_surface->pitch); - if (!sdl_update_window()) /* already calls sdl_render itself */ - sdl_render(); + if (!sdl_window_adjust()) /* already calls sdl_window_render itself */ + sdl_window_render(); } /* set a range of bitmap indices to a gradient from startcolour to endcolour */ diff --git a/firmware/target/hosted/sdl/lcd-sdl.h b/firmware/target/hosted/sdl/lcd-sdl.h index 17fa6e192e..fd1a0b9513 100644 --- a/firmware/target/hosted/sdl/lcd-sdl.h +++ b/firmware/target/hosted/sdl/lcd-sdl.h @@ -25,15 +25,6 @@ #include "lcd.h" #include "SDL.h" -/* Default display zoom level */ -extern SDL_Surface *gui_surface; -extern SDL_Renderer *sdlRenderer; -extern SDL_Window *window; - -void sdl_get_window_dimensions(int *w, int *h); -int sdl_update_window(void); -void sdl_window_needs_update(void); - void sdl_update_rect(SDL_Surface *surface, int x_start, int y_start, int width, int height, int max_x, int max_y, unsigned long (*getpixel)(int, int)); diff --git a/firmware/target/hosted/sdl/system-sdl.c b/firmware/target/hosted/sdl/system-sdl.c index b90f59f216..5d3622dd80 100644 --- a/firmware/target/hosted/sdl/system-sdl.c +++ b/firmware/target/hosted/sdl/system-sdl.c @@ -32,7 +32,7 @@ #include "thread-sdl.h" #include "system-sdl.h" #include "sim-ui-defines.h" -#include "lcd-sdl.h" +#include "window-sdl.h" #include "lcd-bitmap.h" #ifdef HAVE_REMOTE_LCD #include "lcd-remote-bitmap.h" @@ -44,15 +44,10 @@ #include <glib.h> #include <glib-object.h> #include "maemo-thread.h" - #endif #define SIMULATOR_DEFAULT_ROOT "simdisk" -SDL_Surface *gui_surface; -SDL_Window *window; -SDL_Renderer *sdlRenderer; - bool background = true; /* use backgrounds by default */ #ifdef HAVE_REMOTE_LCD bool showremote = true; /* include remote by default */ @@ -61,8 +56,6 @@ bool mapping = false; const char *audiodev = NULL; bool debug_buttons = false; -bool lcd_display_redraw = true; /* Used for player simulator */ -char having_new_lcd = true; /* Used for player simulator */ bool sim_alarm_wakeup = false; const char *sim_root_dir = SIMULATOR_DEFAULT_ROOT; @@ -75,59 +68,6 @@ bool debug_audio = false; bool debug_wps = false; int wps_verbose_level = 3; -static void sdl_window_setup(void) -{ - SDL_Surface *picture_surface = NULL; - int width, height; - int depth; - Uint32 flags = 0; - - /* Try and load the background image. If it fails go without */ - if (background) { - picture_surface = SDL_LoadBMP("UI256.bmp"); - if (picture_surface == NULL) { - background = false; - DEBUGF("warn: %s\n", SDL_GetError()); - } - } - - sdl_get_window_dimensions(&width, &height); - depth = LCD_DEPTH; - if (depth < 8) - depth = 16; - -#if (CONFIG_PLATFORM & (PLATFORM_MAEMO|PLATFORM_PANDORA)) - /* Fullscreen mode for maemo app */ - flags |= SDL_WINDOW_FULLSCREEN; -#endif - - if (display_zoom == 1) - flags |= SDL_WINDOW_RESIZABLE; - - flags |= SDL_WINDOW_ALLOW_HIGHDPI; - - if ((window = SDL_CreateWindow(UI_TITLE, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, - width * display_zoom, height * display_zoom , flags)) == NULL) - panicf("%s", SDL_GetError()); - if ((sdlRenderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC)) == NULL) - panicf("%s", SDL_GetError()); - - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, display_zoom == 1 ? "best" : "nearest"); - display_zoom = 0; /* keeps track of user requesting a scale level change */ - SDL_RenderSetLogicalSize(sdlRenderer, width, height); - - if ((gui_surface = SDL_CreateRGBSurface(0, width, height, depth, - 0, 0, 0, 0)) == NULL) - panicf("%s", SDL_GetError()); - - /* If we have a background, blit it over to the display surface */ - if (background && picture_surface) - { - SDL_BlitSurface(picture_surface, NULL, gui_surface, NULL); - SDL_FreeSurface(picture_surface); - } -} - #ifndef __APPLE__ /* MacOS requires events to be handled on main thread */ /* * This thread will read the buttons in an interrupt like fashion, and @@ -173,8 +113,7 @@ static int sdl_event_thread(void * param) /* let system_init proceed */ SDL_SemPost((SDL_sem *)param); - /* - * finally enter the button loop */ + /* finally enter the button loop */ gui_message_loop(); #if (CONFIG_PLATFORM & PLATFORM_MAEMO5) @@ -354,11 +293,6 @@ void sys_handle_argv(int argc, char *argv[]) printf("Disabling remote image.\n"); } #endif - else if (!strcmp("--old_lcd", argv[x])) - { - having_new_lcd = false; - printf("Using old LCD layout.\n"); - } else if (!strcmp("--zoom", argv[x])) { x++; @@ -413,7 +347,6 @@ void sys_handle_argv(int argc, char *argv[]) #ifdef HAVE_REMOTE_LCD printf(" --noremote \t Disable the remote image (will disable backgrounds)\n"); #endif - printf(" --old_lcd \t [Player] simulate old playermodel (ROM version<4.51)\n"); printf(" --zoom [VAL]\t Window zoom (will disable backgrounds)\n"); printf(" --alarm \t Simulate a wake-up on alarm\n"); printf(" --root [DIR]\t Set root directory\n"); diff --git a/firmware/target/hosted/sdl/window-sdl.c b/firmware/target/hosted/sdl/window-sdl.c new file mode 100644 index 0000000000..731e13067c --- /dev/null +++ b/firmware/target/hosted/sdl/window-sdl.c @@ -0,0 +1,223 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include <SDL.h> +#include "sim-ui-defines.h" +#include "window-sdl.h" +#include "lcd-sdl.h" +#include "misc.h" +#include "panic.h" + +extern SDL_Surface *lcd_surface; +#ifdef HAVE_REMOTE_LCD +extern SDL_Surface *remote_surface; +#endif + +SDL_Texture *gui_texture; +SDL_Surface *sim_lcd_surface; + +static SDL_Window *window; +static SDL_Renderer *sdlRenderer; +static SDL_Surface *picture_surface; + +static bool new_gui_texture_needed = true; +static bool window_adjustment_needed; +double display_zoom = 1; + +static void get_window_dimensions(int *w, int *h) +{ + if (background) + { + *w = UI_WIDTH; + *h = UI_HEIGHT; + } + else + { +#ifdef HAVE_REMOTE_LCD + if (showremote) + { + *w = SIM_LCD_WIDTH > SIM_REMOTE_WIDTH ? SIM_LCD_WIDTH : SIM_REMOTE_WIDTH; + *h = SIM_LCD_HEIGHT + SIM_REMOTE_HEIGHT; + } + else +#endif + { + *w = SIM_LCD_WIDTH; + *h = SIM_LCD_HEIGHT; + } + } +} + +#define SNAP_MARGIN 50 +static void restore_aspect_ratio(int w, int h) +{ + float aspect_ratio = (float) h / w; + int original_height = h; + int original_width = w; + + if ((SDL_GetWindowFlags(window) & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_FULLSCREEN)) + || display_zoom) + return; + + SDL_GetWindowSize(window, &w, &h); + if (w != original_width || h != original_height) + { + if (abs(original_width - w) < SNAP_MARGIN) + { + w = original_width; + h = original_height; + } + else + h = w * aspect_ratio; + + SDL_SetWindowSize(window, w, h); + } +} + +static void rebuild_gui_texture(void) +{ + SDL_Surface *gui_surface; + int w, h, depth = LCD_DEPTH < 8 ? 16 : LCD_DEPTH; + + get_window_dimensions(&w, &h); + SDL_RenderSetLogicalSize(sdlRenderer, w, h); + if ((gui_texture = SDL_CreateTexture(sdlRenderer, SDL_MasksToPixelFormatEnum(depth, + 0, 0, 0, 0), SDL_TEXTUREACCESS_STATIC, w, h)) == NULL) + panicf("%s", SDL_GetError()); + + if (SDL_GetWindowFlags(window) & SDL_WINDOW_RESIZABLE) + restore_aspect_ratio(w, h); + + if (background && picture_surface && + (gui_surface = SDL_ConvertSurface(picture_surface, sim_lcd_surface->format, 0))) + { + SDL_UpdateTexture(gui_texture, NULL, gui_surface->pixels, gui_surface->pitch); + SDL_FreeSurface(gui_surface); + } + + sdl_gui_update(lcd_surface, 0, 0, SIM_LCD_WIDTH, SIM_LCD_HEIGHT, + SIM_LCD_WIDTH, SIM_LCD_HEIGHT, + background ? UI_LCD_POSX : 0, background? UI_LCD_POSY : 0); + +#ifdef HAVE_REMOTE_LCD + sdl_gui_update(remote_surface, 0, 0, LCD_REMOTE_WIDTH, LCD_REMOTE_HEIGHT, + LCD_REMOTE_WIDTH, LCD_REMOTE_HEIGHT, + background ? UI_REMOTE_POSX : 0, + background? UI_REMOTE_POSY : LCD_HEIGHT); +#endif +} + +void sdl_window_render(void) +{ + if (new_gui_texture_needed) + { + new_gui_texture_needed = false; + if (gui_texture) + SDL_DestroyTexture(gui_texture); + rebuild_gui_texture(); + } + else + { + SDL_RenderClear(sdlRenderer); + SDL_RenderCopy(sdlRenderer, gui_texture, NULL, NULL); + SDL_RenderPresent(sdlRenderer); + } +} + +bool sdl_window_adjust(void) +{ + int w, h; + + if (!window_adjustment_needed) + return false; + window_adjustment_needed = false; + + get_window_dimensions(&w, &h); + + if (!(SDL_GetWindowFlags(window) & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_FULLSCREEN)) + && display_zoom) + { + SDL_SetWindowSize(window, display_zoom * w, display_zoom * h); + } +#if defined(__APPLE__) || defined(__WIN32) + restore_aspect_ratio(w, h); +#endif + display_zoom = 0; + sdl_window_render(); + return true; +} + +void sdl_window_adjustment_needed(bool destroy_texture) +{ + window_adjustment_needed = true; + new_gui_texture_needed = destroy_texture; + + /* For MacOS and Windows, we're on a main or + display thread already, and can immediately + adjust the window. + On Linux, we have to defer the update, until + it is handled by the main thread later. */ +#if defined (__APPLE__) || defined(__WIN32) + sdl_window_adjust(); +#endif +} + +void sdl_window_setup(void) +{ + int width, height; + int depth = LCD_DEPTH < 8 ? 16 : LCD_DEPTH; + Uint32 flags = SDL_WINDOW_ALLOW_HIGHDPI; + +#if (CONFIG_PLATFORM & (PLATFORM_MAEMO|PLATFORM_PANDORA)) + /* Fullscreen mode for maemo app */ + flags |= SDL_WINDOW_FULLSCREEN; +#else + if (display_zoom == 1) + flags |= SDL_WINDOW_RESIZABLE; +#endif + + if (!(picture_surface = SDL_LoadBMP("UI256.bmp"))) + background = false; + + get_window_dimensions(&width, &height); + + if ((window = SDL_CreateWindow(UI_TITLE, SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, width * display_zoom, + height * display_zoom , flags)) == NULL) + panicf("%s", SDL_GetError()); + if ((sdlRenderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC)) == NULL) + panicf("%s", SDL_GetError()); + + /* Surface for LCD content only. Needs to fit largest LCD */ + if ((sim_lcd_surface = SDL_CreateRGBSurface(0, +#ifdef HAVE_REMOTE_LCD + SIM_LCD_WIDTH > SIM_REMOTE_WIDTH ? + SIM_LCD_WIDTH : SIM_REMOTE_WIDTH, + SIM_LCD_HEIGHT > SIM_REMOTE_HEIGHT ? + SIM_LCD_HEIGHT : SIM_REMOTE_HEIGHT, +#else + SIM_LCD_WIDTH, SIM_LCD_HEIGHT, +#endif + depth, 0, 0, 0, 0)) == NULL) + panicf("%s", SDL_GetError()); + + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, display_zoom == 1 ? "best" : "nearest"); + display_zoom = 0; /* reset to 0 unless/until user requests a scale level change */ +} diff --git a/firmware/target/hosted/sdl/window-sdl.h b/firmware/target/hosted/sdl/window-sdl.h new file mode 100644 index 0000000000..9b2dc6b14d --- /dev/null +++ b/firmware/target/hosted/sdl/window-sdl.h @@ -0,0 +1,41 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef __WINDOWSDL_H__ +#define __WINDOWSDL_H__ + +#include "SDL.h" + +extern SDL_Texture *gui_texture; /* Window content, including background */ +extern SDL_Surface *sim_lcd_surface; /* LCD content */ + +/* Renders GUI texture. Sets up new texture, if necessary */ +void sdl_window_render(void); + +/* Updates size, aspect ratio, and re-renders window content */ +bool sdl_window_adjust(void); + +/* Needs to be called when window size, scale quality, or background should change */ +void sdl_window_adjustment_needed(bool destroy_texture); + +/* Creates window, renderer, and LCD surface when app launches */ +void sdl_window_setup(void); + +#endif /* #ifndef __WINDOWSDL_H__ */ |