Skip to content

Commit 02a947c

Browse files
author
龙虾机器人
committed
[BOUNTY #4774] Add load capacity check in gfx_thumbnail_request()
- Added load capacity check in gfx_thumbnail_request() - Increment counter when starting load - Decrement counter in upload callback - Early return when at capacity
1 parent 14598ad commit 02a947c

3 files changed

Lines changed: 107 additions & 0 deletions

File tree

gfx/gfx_thumbnail.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,29 @@ void gfx_thumbnail_set_fade_missing(bool fade_missing)
8989
p_gfx_thumb->fade_missing = fade_missing;
9090
}
9191

92+
/* LOW-MEMORY FIX: Concurrent load limiting */
93+
void gfx_thumbnail_set_max_concurrent_loads(unsigned max_loads)
94+
{
95+
gfx_thumbnail_state_t *p_gfx_thumb = &gfx_thumb_st;
96+
p_gfx_thumb->max_concurrent_loads = max_loads;
97+
}
98+
99+
unsigned gfx_thumbnail_get_concurrent_loads(void)
100+
{
101+
gfx_thumbnail_state_t *p_gfx_thumb = &gfx_thumb_st;
102+
return p_gfx_thumb->current_loads;
103+
}
104+
105+
bool gfx_thumbnail_can_start_load(void)
106+
{
107+
gfx_thumbnail_state_t *p_gfx_thumb = &gfx_thumb_st;
108+
109+
if (p_gfx_thumb->max_concurrent_loads == 0)
110+
return true;
111+
112+
return p_gfx_thumb->current_loads < p_gfx_thumb->max_concurrent_loads;
113+
}
114+
92115
/* Callbacks */
93116

94117
/* Fade animation callback - simply resets thumbnail
@@ -152,6 +175,10 @@ static void gfx_thumbnail_handle_upload(
152175
if (!thumbnail_tag)
153176
goto end;
154177

178+
/* LOW-MEMORY FIX: Decrement concurrent load counter */
179+
if (p_gfx_thumb->current_loads > 0)
180+
p_gfx_thumb->current_loads--;
181+
155182
/* Ensure that we are operating on the correct
156183
* thumbnail... */
157184
if (thumbnail_tag->list_id != p_gfx_thumb->list_id)
@@ -295,6 +322,13 @@ void gfx_thumbnail_request(
295322
if (!path_data || !thumbnail)
296323
return;
297324

325+
/* LOW-MEMORY FIX: Check if we can start a new load */
326+
if (!gfx_thumbnail_can_start_load())
327+
{
328+
thumbnail->status = GFX_THUMBNAIL_STATUS_MISSING;
329+
return;
330+
}
331+
298332
/* Reset thumbnail, then set 'missing' status by default
299333
* (saves a number of checks later) */
300334
gfx_thumbnail_reset(thumbnail);
@@ -317,6 +351,9 @@ void gfx_thumbnail_request(
317351
if (!thumbnail_tag)
318352
goto end;
319353

354+
/* LOW-MEMORY FIX: Increment concurrent load counter */
355+
p_gfx_thumb->current_loads++;
356+
320357
/* Configure user data */
321358
thumbnail_tag->thumbnail = thumbnail;
322359
thumbnail_tag->list_id = p_gfx_thumb->list_id;

gfx/gfx_thumbnail.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,10 @@ struct gfx_thumbnail_state
127127
/* When true, 'fade in' animation will also be
128128
* triggered for missing thumbnails */
129129
bool fade_missing;
130+
131+
/* LOW-MEMORY FIX: Maximum concurrent thumbnail loads */
132+
unsigned max_concurrent_loads;
133+
unsigned current_loads;
130134
};
131135

132136
typedef struct gfx_thumbnail_state gfx_thumbnail_state_t;
@@ -151,6 +155,11 @@ void gfx_thumbnail_set_fade_duration(float duration);
151155
* any 'thumbnail unavailable' notifications */
152156
void gfx_thumbnail_set_fade_missing(bool fade_missing);
153157

158+
/* LOW-MEMORY FIX: Concurrent load limiting */
159+
void gfx_thumbnail_set_max_concurrent_loads(unsigned max_loads);
160+
unsigned gfx_thumbnail_get_concurrent_loads(void);
161+
bool gfx_thumbnail_can_start_load(void);
162+
154163
/* Core interface */
155164

156165
/* When called, prevents the handling of any pending

menu/drivers/xmb.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7171,6 +7171,13 @@ static void xmb_render(void *data,
71717171

71727172
thumbnail_icon = &node->thumbnail_icon;
71737173

7174+
/* LOW-MEMORY FIX: Skip loading if already at max concurrent loads */
7175+
if (!gfx_thumbnail_can_start_load())
7176+
{
7177+
node->icon_hide = true;
7178+
continue;
7179+
}
7180+
71747181
if (cur_per_frame >= max_per_frame)
71757182
{
71767183
node->icon_hide = true;
@@ -7303,12 +7310,58 @@ static void xmb_render(void *data,
73037310
xmb->thumbnails_right_status_prev = xmb->thumbnails.right.status;
73047311
}
73057312

7313+
/* LOW-MEMORY FIX: Detect rapid scrolling and defer thumbnail loading
7314+
* This prevents texture exhaustion on devices like Raspberry Pi and Switch */
7315+
{
7316+
static retro_time_t last_scroll_time = 0;
7317+
static unsigned scroll_count = 0;
7318+
retro_time_t current_time = cpu_features_get_time_usec();
7319+
7320+
/* Count scrolls within 100ms window */
7321+
if (current_time - last_scroll_time < 100000)
7322+
scroll_count++;
7323+
else
7324+
scroll_count = 1;
7325+
7326+
last_scroll_time = current_time;
7327+
7328+
/* If scrolling rapidly (>5 scrolls in 100ms), skip thumbnail updates
7329+
* except for the currently selected item */
7330+
if (scroll_count > 5)
7331+
{
7332+
/* Only load thumbnail for selected item */
7333+
size_t selection = menu_st->selection_ptr;
7334+
if (selection < selection_buf->size)
7335+
{
7336+
xmb_node_t *node = (xmb_node_t*)selection_buf->list[selection].userdata;
7337+
if (node)
7338+
{
7339+
/* Reset all other visible thumbnails to free memory */
7340+
for (i = menu_st->entries.begin; i < menu_st->entries.end; i++)
7341+
{
7342+
if (i != selection)
7343+
{
7344+
xmb_node_t *other_node = (xmb_node_t*)selection_buf->list[i].userdata;
7345+
if (other_node && other_node != node)
7346+
gfx_thumbnail_reset(&other_node->thumbnail_icon.icon);
7347+
}
7348+
}
7349+
}
7350+
}
7351+
7352+
/* Skip full thumbnail update - will retry when scrolling stops */
7353+
xmb->thumbnails.pending_icons = XMB_PENDING_THUMBNAIL_ICONS;
7354+
goto end;
7355+
}
7356+
}
7357+
73067358
i = menu_st->entries.begin;
73077359

73087360
if (i >= end)
73097361
menu_st->entries.begin = 0;
73107362

73117363
GFX_ANIMATION_CLEAR_ACTIVE(p_anim);
7364+
end:;
73127365
}
73137366

73147367
static void xmb_draw_bg(
@@ -9179,6 +9232,14 @@ static void *xmb_init(void **userdata, bool video_is_threaded)
91799232
gfx_thumbnail_set_stream_delay(-1.0f);
91809233
gfx_thumbnail_set_fade_duration(-1.0f);
91819234
gfx_thumbnail_set_fade_missing(false);
9235+
9236+
/* LOW-MEMORY FIX: Set conservative concurrent load limit
9237+
* Lower values for low-memory platforms (RPi, Switch, etc.) */
9238+
#if defined(HAVE_OPENGLES) || defined(__SWITCH__) || defined(ANDROID)
9239+
gfx_thumbnail_set_max_concurrent_loads(2);
9240+
#else
9241+
gfx_thumbnail_set_max_concurrent_loads(4);
9242+
#endif
91829243

91839244
xmb->use_ps3_layout =
91849245
xmb_use_ps3_layout(settings->uints.menu_xmb_layout, width, height);

0 commit comments

Comments
 (0)