Skip to content

Commit d4e75bb

Browse files
committed
MENU/XMB: extract xmb_refresh_visible_icon_paths helper
xmb_selection_pointer_changed and xmb_populate_dynamic_icons both walked the visible playlist range and called xmb_set_dynamic_icon_content on each entry, behind the same is_playlist + GFX_THUMBNAIL_ICON + title gate. The two copies also had matching per-iter gfx_thumbnail_cancel_pending_requests + pending_icons = ICONS pairs that only needed to run once per call. Factor the shared path_data refresh into a single helper. The two callers still own their own surrounding state management, because they need different cancel strategies: - xmb_populate_dynamic_icons is called on list changes and must wipe the previous list's per-node icon textures before queuing fresh requests. xmb_unload_icon_thumbnail_textures handles the wipe + the cancel + clearing pending_icons. - xmb_selection_pointer_changed is called on cursor moves within an unchanged list and must not wipe (existing textures stay valid), so it just cancels and sets pending_icons on success. No behavioural change. Drops three locals from xmb_selection_pointer_changed (entry_start, entry_end, update_icon_content) and shrinks xmb_populate_dynamic_icons from 39 lines to 12.
1 parent f26e635 commit d4e75bb

1 file changed

Lines changed: 71 additions & 54 deletions

File tree

menu/drivers/xmb.c

Lines changed: 71 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1830,12 +1830,58 @@ static void xmb_update_savestate_thumbnail_image(void *data)
18301830
xmb->thumbnails.savestate.flags |= GFX_THUMB_FLAG_CORE_ASPECT;
18311831
}
18321832

1833+
/* Walk the visible playlist range and refresh each entry's icon-thumbnail
1834+
* path_data. Returns true if the refresh actually ran (gates all satisfied),
1835+
* so the caller can set `pending_icons` to wake the request dispatcher in
1836+
* xmb_render. The caller is responsible for the `gfx_thumbnail_cancel_pending_requests()`
1837+
* call that should precede this work, because the two existing callers have
1838+
* different cancel strategies:
1839+
*
1840+
* - `xmb_populate_dynamic_icons` calls `xmb_unload_icon_thumbnail_textures`
1841+
* first, which already cancels and clears pending_icons as part of a full
1842+
* texture wipe (used when the displayed list changes).
1843+
*
1844+
* - `xmb_selection_pointer_changed` only cancels — it runs when the cursor
1845+
* moves within an unchanged list, so existing per-node textures stay
1846+
* valid and an unload would be wasteful.
1847+
*
1848+
* That asymmetry is the reason this helper deliberately does not cancel on
1849+
* its own. */
1850+
static bool xmb_refresh_visible_icon_paths(xmb_handle_t *xmb)
1851+
{
1852+
unsigned i, end, height, entry_start, entry_end;
1853+
struct menu_state *menu_st = menu_state_get_ptr();
1854+
menu_list_t *menu_list = menu_st->entries.list;
1855+
file_list_t *selection_buf = MENU_LIST_GET_SELECTION(menu_list, 0);
1856+
size_t selection = menu_st->selection_ptr;
1857+
1858+
if (!( xmb->is_playlist
1859+
&& gfx_thumbnail_is_enabled(menu_st->thumbnail_path_data, GFX_THUMBNAIL_ICON)
1860+
&& !string_is_equal(xmb->title_name, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_IMAGES_TAB))
1861+
&& !string_is_equal(xmb->title_name, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MUSIC_TAB))
1862+
&& !string_is_equal(xmb->title_name, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_TAB))))
1863+
return false;
1864+
1865+
end = (unsigned)selection_buf->size;
1866+
video_driver_get_size(NULL, &height);
1867+
xmb_calculate_visible_range(xmb, height, end, (unsigned)selection, &entry_start, &entry_end);
1868+
1869+
for (i = entry_start; i <= entry_end; i++)
1870+
{
1871+
xmb_node_t *node = (xmb_node_t*)selection_buf->list[i].userdata;
1872+
if (!node)
1873+
continue;
1874+
xmb_set_dynamic_icon_content(xmb, NULL, i, &node->thumbnail_icon);
1875+
}
1876+
return true;
1877+
}
1878+
18331879
/* Is called when the pointer position changes
18341880
* within a list/sub-list (vertically) */
18351881
static void xmb_selection_pointer_changed(
18361882
xmb_handle_t *xmb, bool allow_animations)
18371883
{
1838-
unsigned i, end, height, entry_start, entry_end;
1884+
unsigned i, end, height;
18391885
size_t num = 0;
18401886
int threshold = 0;
18411887
struct menu_state *menu_st = menu_state_get_ptr();
@@ -1856,7 +1902,19 @@ static void xmb_selection_pointer_changed(
18561902
menu_st->entries.begin = num;
18571903

18581904
video_driver_get_size(NULL, &height);
1859-
xmb_calculate_visible_range(xmb, height, end, (unsigned)selection, &entry_start, &entry_end);
1905+
1906+
/* Refresh icon-thumbnail path_data for currently visible playlist
1907+
* entries. The helper itself only writes path_data; xmb_render issues
1908+
* the requests once pending_icons is set. Cancelling first provides
1909+
* "storm protection during fast jumps" — any in-flight requests from
1910+
* the previous cursor position stop being relevant the moment the
1911+
* cursor moves. Skipped entirely on non-playlist lists (helper returns
1912+
* false before touching anything). */
1913+
if (xmb_refresh_visible_icon_paths(xmb))
1914+
{
1915+
gfx_thumbnail_cancel_pending_requests();
1916+
xmb->thumbnails.pending_icons = XMB_PENDING_THUMBNAIL_ICONS;
1917+
}
18601918

18611919
for (i = 0; i < end; i++)
18621920
{
@@ -1871,23 +1929,6 @@ static void xmb_selection_pointer_changed(
18711929
iy = xmb_item_y(xmb, i, selection);
18721930
real_iy = iy + xmb->margins_screen_top;
18731931

1874-
if ( xmb->is_playlist
1875-
&& gfx_thumbnail_is_enabled(menu_st->thumbnail_path_data, GFX_THUMBNAIL_ICON)
1876-
&& !string_is_equal(xmb->title_name, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_IMAGES_TAB))
1877-
&& !string_is_equal(xmb->title_name, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MUSIC_TAB))
1878-
&& !string_is_equal(xmb->title_name, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_TAB))
1879-
)
1880-
{
1881-
xmb_icons_t *thumbnail_icon = &node->thumbnail_icon;
1882-
if (i >= entry_start && i <= entry_end)
1883-
{
1884-
/* Playlist updates */
1885-
xmb_set_dynamic_icon_content(xmb, NULL, i, thumbnail_icon);
1886-
gfx_thumbnail_cancel_pending_requests();
1887-
xmb->thumbnails.pending_icons = XMB_PENDING_THUMBNAIL_ICONS;
1888-
}
1889-
}
1890-
18911932
if (i == selection)
18921933
{
18931934
unsigned depth = (unsigned)xmb_list_get_size(xmb, MENU_LIST_PLAIN);
@@ -2704,44 +2745,20 @@ static void xmb_tab_set_selection(void *data)
27042745

27052746
static void xmb_populate_dynamic_icons(xmb_handle_t *xmb)
27062747
{
2707-
unsigned i, entry_start, entry_end, height;
2708-
struct menu_state *menu_st = menu_state_get_ptr();
2709-
menu_list_t *menu_list = menu_st->entries.list;
2710-
file_list_t *selection_buf = MENU_LIST_GET_SELECTION(menu_list, 0);
2711-
unsigned end = (unsigned)selection_buf->size;
2712-
size_t selection = menu_st->selection_ptr;
2713-
2714-
if (gfx_thumbnail_is_enabled(menu_st->thumbnail_path_data, GFX_THUMBNAIL_ICON))
2715-
{
2716-
/* Clear current textures if they are there */
2717-
xmb_unload_icon_thumbnail_textures(xmb);
2718-
2719-
entry_start = 0;
2720-
entry_end = end;
2748+
struct menu_state *menu_st = menu_state_get_ptr();
27212749

2722-
video_driver_get_size(NULL, &height);
2723-
xmb_calculate_visible_range(xmb, height, end, (unsigned)selection, &entry_start, &entry_end);
2724-
if ( xmb->is_playlist
2725-
&& !string_is_equal(xmb->title_name, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_IMAGES_TAB))
2726-
&& !string_is_equal(xmb->title_name, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MUSIC_TAB))
2727-
&& !string_is_equal(xmb->title_name, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_TAB))
2728-
)
2729-
{
2730-
for (i = entry_start; i <= entry_end; i++)
2731-
{
2732-
xmb_icons_t *thumbnail_icon;
2733-
xmb_node_t *node = (xmb_node_t*)selection_buf->list[i].userdata;
2750+
if (!gfx_thumbnail_is_enabled(menu_st->thumbnail_path_data, GFX_THUMBNAIL_ICON))
2751+
return;
27342752

2735-
if (!node)
2736-
continue;
2753+
/* Used when the displayed list changes (new playlist pushed or context
2754+
* reset): the previous list's per-node icon textures are stale, so wipe
2755+
* them before queuing fresh requests. `xmb_unload_icon_thumbnail_textures`
2756+
* handles the cancel and clears `pending_icons` as part of the wipe;
2757+
* the helper below only needs to write fresh path_data. */
2758+
xmb_unload_icon_thumbnail_textures(xmb);
27372759

2738-
thumbnail_icon = &node->thumbnail_icon;
2739-
xmb_set_dynamic_icon_content(xmb, NULL, i, thumbnail_icon);
2740-
gfx_thumbnail_cancel_pending_requests();
2741-
xmb->thumbnails.pending_icons = XMB_PENDING_THUMBNAIL_ICONS;
2742-
}
2743-
}
2744-
}
2760+
if (xmb_refresh_visible_icon_paths(xmb))
2761+
xmb->thumbnails.pending_icons = XMB_PENDING_THUMBNAIL_ICONS;
27452762
}
27462763

27472764
static void xmb_list_switch(xmb_handle_t *xmb)

0 commit comments

Comments
 (0)