diff --git a/apps/gui/skin_engine/skin_backdrops.c b/apps/gui/skin_engine/skin_backdrops.c index 12b21ccb50..15b68589a9 100644 --- a/apps/gui/skin_engine/skin_backdrops.c +++ b/apps/gui/skin_engine/skin_backdrops.c @@ -95,6 +95,10 @@ int skin_backdrop_assign(char* backdrop, char *bmpdir, filename[2] = '\0'; /* we check this later to see if we actually have an image to load. != '\0' means display the image */ } + else if (!strcmp(backdrop, BACKDROP_BUFFERNAME)) + { + strcpy(filename, backdrop); + } else { get_image_filename(backdrop, bmpdir, filename, sizeof(filename)); @@ -156,15 +160,20 @@ bool skin_backdrops_preload(void) { backdrops[i].buffer = core_get_data(backdrops[i].buflib_handle); handle_being_loaded = backdrops[i].buflib_handle; - backdrops[i].loaded = - screens[screen].backdrop_load(filename, backdrops[i].buffer); - handle_being_loaded = -1; - if (!backdrops[i].loaded) + if (strcmp(filename, BACKDROP_BUFFERNAME)) { - core_free(backdrops[i].buflib_handle); - backdrops[i].buflib_handle = -1; - retval = false; + backdrops[i].loaded = + screens[screen].backdrop_load(filename, backdrops[i].buffer); + handle_being_loaded = -1; + if (!backdrops[i].loaded) + { + core_free(backdrops[i].buflib_handle); + backdrops[i].buflib_handle = -1; + retval = false; + } } + else + backdrops[i].loaded = true; } else retval = false; @@ -176,10 +185,21 @@ bool skin_backdrops_preload(void) return retval; } +void* skin_backdrop_get_buffer(int backdrop_id) +{ + if (backdrop_id < 0) + return NULL; + return backdrops[backdrop_id].buffer; +} + void skin_backdrop_show(int backdrop_id) { if (backdrop_id < 0) + { + screens[0].backdrop_show(NULL); + current_lcd_backdrop[0] = -1; return; + } enum screen_type screen = backdrops[backdrop_id].screen; if ((backdrops[backdrop_id].loaded == false) || (backdrops[backdrop_id].name[0] == '-' && diff --git a/apps/gui/skin_engine/skin_engine.h b/apps/gui/skin_engine/skin_engine.h index ac839fff2e..625467ea3b 100644 --- a/apps/gui/skin_engine/skin_engine.h +++ b/apps/gui/skin_engine/skin_engine.h @@ -70,6 +70,8 @@ bool skin_backdrops_preload(void); void skin_backdrop_show(int backdrop_id); void skin_backdrop_load_setting(void); void skin_backdrop_unload(int backdrop_id); +#define BACKDROP_BUFFERNAME "#backdrop_buffer#" +void* skin_backdrop_get_buffer(int backdrop_id); /* do the button loop as often as required for the peak meters to update * with a good refresh rate. diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c index 340cbbdb01..0fe8789bcb 100644 --- a/apps/gui/skin_engine/skin_parser.c +++ b/apps/gui/skin_engine/skin_parser.c @@ -1832,6 +1832,7 @@ static int convert_viewport(struct wps_data *data, struct skin_element* element) viewport_set_defaults(&skin_vp->vp, curr_screen); #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) + skin_vp->output_to_backdrop_buffer = false; skin_vp->start_fgcolour = skin_vp->vp.fg_pattern; skin_vp->start_bgcolour = skin_vp->vp.bg_pattern; #endif @@ -2023,6 +2024,11 @@ static int skin_element_callback(struct skin_element* element, void* data) case SKIN_TOKEN_VIEWPORT_TEXTSTYLE: function = parse_viewporttextstyle; break; + case SKIN_TOKEN_VIEWPORT_DRAWONBG: + curr_vp->output_to_backdrop_buffer = true; + backdrop_filename = BACKDROP_BUFFERNAME; + wps_data->use_extra_framebuffer = true; + break; #endif #ifdef HAVE_LCD_COLOR case SKIN_TOKEN_VIEWPORT_GRADIENT_SETUP: diff --git a/apps/gui/skin_engine/skin_render.c b/apps/gui/skin_engine/skin_render.c index 951d34a724..d4ddf99c34 100644 --- a/apps/gui/skin_engine/skin_render.c +++ b/apps/gui/skin_engine/skin_render.c @@ -385,11 +385,22 @@ static void do_tags_in_hidden_conditional(struct skin_element* branch, skin_viewport->hidden_flags |= VP_DRAW_WASHIDDEN; else { + if (skin_viewport->output_to_backdrop_buffer) + { + void *backdrop = skin_backdrop_get_buffer(data->backdrop_id); + gwps->display->set_framebuffer(backdrop); + skin_backdrop_show(-1); + } gwps->display->set_viewport(&skin_viewport->vp); gwps->display->clear_viewport(); gwps->display->scroll_stop(&skin_viewport->vp); gwps->display->set_viewport(&info->skin_vp->vp); skin_viewport->hidden_flags |= VP_DRAW_HIDDEN; + if (skin_viewport->output_to_backdrop_buffer) + { + gwps->display->set_framebuffer(NULL); + skin_backdrop_show(data->backdrop_id); + } } } } @@ -767,6 +778,7 @@ void skin_render(struct gui_wps *gwps, unsigned refresh_mode) data->wps_progress_pat[i] = display->get_locked_pattern(); } #endif + viewport = SKINOFFSETTOPTR(skin_buffer, data->tree); skin_viewport = SKINOFFSETTOPTR(skin_buffer, viewport->data); label = SKINOFFSETTOPTR(skin_buffer, skin_viewport->label); @@ -786,6 +798,16 @@ void skin_render(struct gui_wps *gwps, unsigned refresh_mode) #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1) skin_viewport->vp.fg_pattern = skin_viewport->start_fgcolour; skin_viewport->vp.bg_pattern = skin_viewport->start_bgcolour; + if (skin_viewport->output_to_backdrop_buffer) + { + display->set_framebuffer(skin_backdrop_get_buffer(data->backdrop_id)); + skin_backdrop_show(-1); + } + else + { + display->set_framebuffer(NULL); + skin_backdrop_show(data->backdrop_id); + } #endif #ifdef HAVE_LCD_COLOR skin_viewport->vp.lss_pattern = skin_viewport->start_gradient.start; @@ -822,7 +844,10 @@ void skin_render(struct gui_wps *gwps, unsigned refresh_mode) skin_viewport, vp_refresh_mode); refresh_mode = old_refresh_mode; } - +#ifdef HAVE_LCD_BITMAP + display->set_framebuffer(NULL); + skin_backdrop_show(data->backdrop_id); +#endif /* Restore the default viewport */ display->set_viewport(NULL); display->update(); diff --git a/apps/gui/skin_engine/wps_internals.h b/apps/gui/skin_engine/wps_internals.h index c55c8d2515..1ea5dbf467 100644 --- a/apps/gui/skin_engine/wps_internals.h +++ b/apps/gui/skin_engine/wps_internals.h @@ -44,7 +44,6 @@ #include "statusbar.h" #include "metadata.h" - #define TOKEN_VALUE_ONLY 0x0DEADC0D /* wps_data*/ @@ -166,6 +165,7 @@ struct skin_viewport { OFFSETTYPE(char*) label; int parsed_fontid; #if LCD_DEPTH > 1 + bool output_to_backdrop_buffer; unsigned start_fgcolour; unsigned start_bgcolour; #ifdef HAVE_LCD_COLOR @@ -328,6 +328,7 @@ struct wps_data #endif #ifdef HAVE_BACKDROP_IMAGE int backdrop_id; + bool use_extra_framebuffer; #endif #ifdef HAVE_TOUCHSCREEN diff --git a/apps/screen_access.c b/apps/screen_access.c index 5ab08b7fc5..43000e1360 100644 --- a/apps/screen_access.c +++ b/apps/screen_access.c @@ -261,6 +261,9 @@ struct screen screens[NB_SCREENS] = #endif #ifdef HAVE_BUTTONBAR .has_buttonbar=false, +#endif +#if defined(HAVE_LCD_BITMAP) + .set_framebuffer = (void*)lcd_set_framebuffer, #endif }, #if NB_SCREENS == 2 @@ -356,6 +359,9 @@ struct screen screens[NB_SCREENS] = #endif #ifdef HAVE_BUTTONBAR .has_buttonbar=false, +#endif +#if defined(HAVE_LCD_BITMAP) + .set_framebuffer = (void*)lcd_remote_set_framebuffer, #endif } #endif /* NB_SCREENS == 2 */ diff --git a/apps/screen_access.h b/apps/screen_access.h index a9d1408898..343829b915 100644 --- a/apps/screen_access.h +++ b/apps/screen_access.h @@ -160,6 +160,9 @@ struct screen bool (*backdrop_load)(const char *filename, char* backdrop_buffer); void (*backdrop_show)(char* backdrop_buffer); #endif +#if defined(HAVE_LCD_BITMAP) + void (*set_framebuffer)(void *framebuffer); +#endif }; #if defined(HAVE_LCD_BITMAP) || defined(HAVE_REMOTE_LCD) diff --git a/firmware/drivers/lcd-bitmap-common.c b/firmware/drivers/lcd-bitmap-common.c index f122e336d7..b0be687ed2 100644 --- a/firmware/drivers/lcd-bitmap-common.c +++ b/firmware/drivers/lcd-bitmap-common.c @@ -81,6 +81,14 @@ static void lcd_gradient_rect(int x1, int x2, int y, unsigned h, } #endif +void LCDFN(set_framebuffer)(FBFN(data) *fb) +{ + if (fb) + LCDFN(framebuffer) = fb; + else + LCDFN(framebuffer) = &LCDFN(static_framebuffer)[0][0]; +} + /* * draws the borders of the current viewport **/ diff --git a/firmware/export/lcd-remote.h b/firmware/export/lcd-remote.h index 0f5f7ed6b7..1bb19a5cfa 100644 --- a/firmware/export/lcd-remote.h +++ b/firmware/export/lcd-remote.h @@ -132,6 +132,7 @@ void lcd_remote_init(void); void lcd_remote_write_command(int cmd); void lcd_remote_write_command_ex(int cmd, int data); void lcd_remote_write_data(const fb_remote_data *data, int count); +extern void lcd_remote_set_framebuffer(fb_remote_data *fb); extern void lcd_remote_bitmap_part(const fb_remote_data *src, int src_x, int src_y, int stride, int x, int y, diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h index 052b368d9b..7e0e979821 100644 --- a/firmware/export/lcd.h +++ b/firmware/export/lcd.h @@ -529,6 +529,7 @@ extern void lcd_bitmap_part(const fb_data *src, int src_x, int src_y, int stride, int x, int y, int width, int height); extern void lcd_bitmap(const fb_data *src, int x, int y, int width, int height); +extern void lcd_set_framebuffer(fb_data *fb); extern void lcd_scroll_step(int pixels); diff --git a/lib/skin_parser/tag_table.c b/lib/skin_parser/tag_table.c index 9a183986ce..a44b2ef251 100644 --- a/lib/skin_parser/tag_table.c +++ b/lib/skin_parser/tag_table.c @@ -204,6 +204,7 @@ static const struct tag_info legal_tags[] = { SKIN_TOKEN_VIEWPORT_BGCOLOUR, "Vb" , "s", SKIN_REFRESH_STATIC|NOBREAK }, { SKIN_TOKEN_VIEWPORT_TEXTSTYLE, "Vs" , "S|s", SKIN_REFRESH_STATIC }, { SKIN_TOKEN_VIEWPORT_GRADIENT_SETUP, "Vg" , "SS|s", SKIN_REFRESH_STATIC|NOBREAK }, + { SKIN_TOKEN_VIEWPORT_DRAWONBG, "VB" , "", SKIN_REFRESH_STATIC|NOBREAK }, { SKIN_TOKEN_VIEWPORT_CONDITIONAL, "Vl" , "SIIiii", 0 }, { SKIN_TOKEN_UIVIEWPORT_LOAD, "Vi" , "sIIiii", 0 }, diff --git a/lib/skin_parser/tag_table.h b/lib/skin_parser/tag_table.h index d14d31fcb2..cf0096f28d 100644 --- a/lib/skin_parser/tag_table.h +++ b/lib/skin_parser/tag_table.h @@ -92,7 +92,8 @@ enum skin_token_type { SKIN_TOKEN_VIEWPORT_BGCOLOUR, SKIN_TOKEN_VIEWPORT_TEXTSTYLE, SKIN_TOKEN_VIEWPORT_GRADIENT_SETUP, - + SKIN_TOKEN_VIEWPORT_DRAWONBG, + /* Battery */ SKIN_TOKEN_BATTERY_PERCENT, SKIN_TOKEN_BATTERY_PERCENTBAR, diff --git a/manual/appendix/wps_tags.tex b/manual/appendix/wps_tags.tex index ba4cbd16ee..5890e20e93 100644 --- a/manual/appendix/wps_tags.tex +++ b/manual/appendix/wps_tags.tex @@ -91,6 +91,8 @@ show the information for the next song to be played. \config{\%VI('label')} & Set the Info Viewport to use the viewport called label, as declared with the previous tag.\\ + + \config{\%VB} & Draw this viewport on the backdrop layer. \end{tagmap} \section{Additional Fonts}