Skip to content

Commit 4e75fde

Browse files
committed
MENU/XMB: render blank-less while icon thumbnails are loading
Complement to the prior deferral commit, addressing the user-visible "stuttery" feel of playlist icon-thumbnail loading. xmb_render caps synchronous icon loads at 2 per frame to avoid frame-time spikes on slow storage (SD card, Android SAF, spinning rust). That cap itself is fine and is retained here. The problem is what the dispatcher did to entries past the budget: it set node->icon_hide = true, and the per-entry draw at line 5534 gated the entire icon block (including any default-fallback texture) on !node->icon_hide. So on a playlist with N > 2 visible entries, each frame drew 2 newly-loaded icons and left the rest as empty slots until their turn arrived. On a 30-visible-entry playlist that's 15 frames (~250 ms) of icons rippling in against blanks — which reads as the "stutter" in the original complaint. This branch was introduced alongside the per-frame cap itself in 2073b8a "XMB: Icon thumbnail improvements" (Feb 2025). Before that, the dispatcher loaded every visible icon in one frame, and no icon_hide mechanism existed — budget-exceeded entries just kept whatever icon they already had (default fallback on first frame). That pre-regression behaviour is what this commit restores. Removes node->icon_hide entirely (struct field, init in xmb_alloc_node, guard in xmb_draw_item, both assignments in xmb_render). Entries past the per-frame budget still get skipped — pending_icons is re-raised so we resume next frame — but they render their existing default icon instead of rendering as nothing. The paint now fills in rather than pops in. The 2-per-frame cap is retained, so slow-storage frame-time protection is unchanged. The render dispatcher comment is updated to clarify that only synchronous loads count toward the budget; async requests via gfx_thumbnail_request_stream run on a worker thread and land via task callback, so they do not contribute to this frame's work and are correctly uncounted.
1 parent 910c8d0 commit 4e75fde

1 file changed

Lines changed: 12 additions & 7 deletions

File tree

menu/drivers/xmb.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,6 @@ typedef struct
302302
float zoom;
303303
float x;
304304
float y;
305-
bool icon_hide;
306305
} xmb_node_t;
307306

308307
enum xmb_drag_mode
@@ -646,7 +645,6 @@ static xmb_node_t *xmb_alloc_node(void)
646645
node->thumbnail_icon.icon.texture = 0;
647646
node->fullpath = NULL;
648647
node->console_name = NULL;
649-
node->icon_hide = false;
650648

651649
return node;
652650
}
@@ -5536,7 +5534,6 @@ static int xmb_draw_item(
55365534
gfx_display_set_alpha(color, MIN(node->alpha * xmb->alpha_list, xmb->alpha));
55375535

55385536
if ( (!xmb->assets_missing)
5539-
&& (!node->icon_hide)
55405537
&& (color[3] != 0)
55415538
&& ( (entry.flags & MENU_ENTRY_FLAG_CHECKED)
55425539
|| !( entry_type >= MENU_SETTING_DROPDOWN_ITEM
@@ -7375,8 +7372,12 @@ static void xmb_render(void *data,
73757372
/* Handle any pending icon thumbnail load requests */
73767373
if (xmb->thumbnails.pending_icons != XMB_PENDING_THUMBNAIL_NONE)
73777374
{
7378-
/* Limit image loading per frame to prevent slowdowns,
7379-
* and hide the usual icon while pending */
7375+
/* Limit synchronous image loading per frame to prevent
7376+
* frame-time spikes on slow storage (SD card, Android SAF
7377+
* behind fuse, etc.). Async requests via
7378+
* gfx_thumbnail_request_stream are not counted — they run on
7379+
* a worker thread and land via task callback on subsequent
7380+
* frames, so they do not contribute to this frame's work. */
73807381
uint8_t max_per_frame = 2;
73817382
uint8_t cur_per_frame = 0;
73827383

@@ -7396,17 +7397,21 @@ static void xmb_render(void *data,
73967397

73977398
thumbnail_icon = &node->thumbnail_icon;
73987399

7400+
/* Budget exceeded: skip this entry this frame, keep
7401+
* pending_icons raised so we resume next frame. The entry
7402+
* continues to render its existing icon (default fallback
7403+
* if nothing has been loaded yet) rather than rendering as
7404+
* blank, so the user sees a steady draw with icons filling
7405+
* in progressively, not a wave of empty slots. */
73997406
if (cur_per_frame >= max_per_frame)
74007407
{
7401-
node->icon_hide = true;
74027408
xmb->thumbnails.pending_icons = XMB_PENDING_THUMBNAIL_ICONS;
74037409
continue;
74047410
}
74057411

74067412
if ( thumbnail_icon->icon.status == GFX_THUMBNAIL_STATUS_UNKNOWN
74077413
&& *thumbnail_icon->thumbnail_path_data.icon_path)
74087414
{
7409-
node->icon_hide = false;
74107415
if (!xmb_load_dynamic_icon(
74117416
thumbnail_icon->thumbnail_path_data.icon_path,
74127417
&thumbnail_icon->icon))

0 commit comments

Comments
 (0)