gui: align display updates, reduce UI glitches

Based on commits ce33902 and 8990d52 (without PictureFlow)
from "Rockpod" fork by Nux Li (https://github.com/nuxcodes/rockpod),
with some adjustments.

Addresses flickering when:
- plugin is opened/closed
- activity changes
- theme is toggled
- QuickScreen is opened

In these cases, skin_render will not immediately update the display
anymore, but instead will wait until the UI viewport is ready to be
drawn as well, so we don't produce unnecessary visual glitches.

Change-Id: I8bed8f06221d3e767a32450f199e69d742bc61cd
This commit is contained in:
Christian Soffke 2026-04-24 19:25:52 +02:00
parent 89d24f3bd4
commit c145d19e85
9 changed files with 59 additions and 7 deletions

View file

@ -281,8 +281,7 @@ bool skinlist_draw(struct screen *display, struct gui_synclist *list)
}
current_column = -1;
current_row = -1;
display->set_viewport(parent);
display->update_viewport();
skin_render_deferred(display, parent);
current_drawing_line = list->selected_item;
return true;
}

View file

@ -446,8 +446,7 @@ void list_draw(struct screen *display, struct gui_synclist *list)
callback_draw_item(&list_info);
}
display->set_viewport(parent);
display->update_viewport();
skin_render_deferred(display, parent);
display->set_viewport(last_vp);
}

View file

@ -242,8 +242,7 @@ static void gui_quickscreen_draw(const struct gui_quickscreen *qs,
(vp_icons->width/2) - 4, vp_icons->height - 8, 7, 8);
}
display->set_viewport(parent);
display->update_viewport();
skin_render_deferred(display, parent);
display->set_viewport(last_vp);
}

View file

@ -51,6 +51,11 @@ void skin_disarm_touchregions(struct gui_wps *gwps);
void skin_update(enum skinnable_screens skin, enum screen_type screen,
unsigned int update_type);
/* Defer updates in skin_render */
void skin_defer_rendering(bool deferred);
/* Render viewport together with deferred updates */
void skin_render_deferred(struct screen *display, struct viewport *vp);
bool skin_has_sbs(struct gui_wps *gwps);

View file

@ -84,6 +84,8 @@ static void skin_render_playlistviewer(struct playlistviewer* viewer,
unsigned long refresh_type);
static char* skin_buffer;
static bool defer_rendering;
static bool dirty;
static inline struct skin_element*
get_child(OFFSETTYPE(struct skin_element**) children, int child)
@ -841,6 +843,27 @@ void skin_render_viewport(struct skin_element* viewport, struct gui_wps *gwps,
wps_display_images(gwps, &skin_viewport->vp);
}
void skin_defer_rendering(bool deferred)
{
defer_rendering = deferred;
}
void skin_render_deferred(struct screen *display, struct viewport *vp)
{
if (dirty)
{
dirty = false;
display->set_viewport(NULL);
display->update();
sb_skin_force_next_update();
}
else
{
display->set_viewport(vp);
display->update_viewport();
}
}
void skin_render(struct gui_wps *gwps, unsigned refresh_mode)
{
const int vp_is_appearing = (VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE);
@ -940,6 +963,9 @@ void skin_render(struct gui_wps *gwps, unsigned refresh_mode)
}
/* Restore the default viewport */
display->set_viewport_ex(NULL, VP_FLAG_VP_SET_CLEAN);
if (defer_rendering)
dirty = true;
else
display->update();
}

View file

@ -154,7 +154,11 @@ static void toggle_theme(enum screen_type screen, bool force)
}
intptr_t force = first_boot?0:1;
skin_defer_rendering(true);
send_event(GUI_EVENT_ACTIONUPDATE, (void*)force);
skin_defer_rendering(false);
if (!first_boot)
sb_skin_force_next_update();
}
else
{

View file

@ -533,7 +533,11 @@ static void gwps_leave_wps(bool theme_enabled)
viewports drawn by the WPS. May need further thought... */
struct wps_data *sbs = skin_get_gwps(CUSTOM_STATUSBAR, i)->data;
if (gwps->data->use_extra_framebuffer && sbs->use_extra_framebuffer)
{
skin_defer_rendering(true);
skin_update(CUSTOM_STATUSBAR, i, SKIN_REFRESH_ALL);
skin_defer_rendering(false);
}
#endif
viewportmanager_theme_undo(i, skin_has_sbs(gwps));
}

View file

@ -65,6 +65,7 @@
#include "list.h"
#include "fixedpoint.h"
#include "open_plugin.h"
#include "statusbar-skinned.h"
#include "debug.h"
@ -1795,8 +1796,14 @@ static void push_current_activity_refresh(enum current_activity screen, bool ref
{
skinlist_set_cfg(i, NULL);
if (refresh)
{
skin_defer_rendering(true);
skin_update(CUSTOM_STATUSBAR, i, SKIN_REFRESH_ALL);
skin_defer_rendering(false);
}
}
if (refresh)
sb_skin_force_next_update();
}
static void pop_current_activity_refresh(bool refresh)
@ -1806,8 +1813,14 @@ static void pop_current_activity_refresh(bool refresh)
{
skinlist_set_cfg(i, NULL);
if (refresh)
{
skin_defer_rendering(true);
skin_update(CUSTOM_STATUSBAR, i, SKIN_REFRESH_ALL);
skin_defer_rendering(false);
}
}
if (refresh)
sb_skin_force_next_update();
}
void push_current_activity(enum current_activity screen)

View file

@ -1022,8 +1022,11 @@ int plugin_load(const char* plugin, const void* parameter)
pop_current_activity_without_refresh();
if (get_current_activity() != ACTIVITY_WPS)
{
skin_defer_rendering(true);
FOR_NB_SCREENS(i)
skin_update(CUSTOM_STATUSBAR, i, SKIN_REFRESH_ALL);
skin_defer_rendering(false);
sb_skin_force_next_update();
}
if (!pfn_tsr_exit)