gfx/gfx_display.c (+46) — Adds #include "../tasks/tasks_internal.h". Adds gfx_display_load_icon(), the single dispatch function. A #if defined(__ANDROID__) sets GFX_DISPLAY_ICON_LOAD_SYNCHRONOUS which routes to gfx_display_reset_icon_texture() (blocking file read + GPU upload in one call, pre-async behavior). All other platforms route to task_push_icon_load() (async task queue).

gfx/gfx_display.h (+20) — Declares gfx_display_load_icon() with doc comment explaining the mechanism, that generation/generation_ptr are async-only, and that callers should use this instead of task_push_icon_load() directly.
gfx/gfx_widgets.c (-4/+5) — Replaces task_push_icon_load() with gfx_display_load_icon() in the widget icon loading loop. Updates comments to be path-neutral ("When loads complete" instead of "When async loads complete").
gfx/widgets/gfx_widget_volume.c (-1/+1) — Replaces task_push_icon_load() with gfx_display_load_icon() for volume indicator icons.
menu/drivers/ozone.c (-6/+6) — Replaces 6 task_push_icon_load() calls with gfx_display_load_icon(): theme textures, horizontal list icons, main textures, sidebar tab textures, entry icons.
menu/drivers/materialui.c (-2/+2) — Replaces 2 task_push_icon_load() calls with gfx_display_load_icon(): playlist icons and main texture list.
menu/drivers/xmb.c (-3/+3) — Replaces 3 task_push_icon_load() calls with gfx_display_load_icon(): horizontal list icons (system + content) and context reset textures.
menu/menu_explore.c (-1/+1) — Replaces task_push_icon_load() with gfx_display_load_icon() for explore view system icons.
menu/menu_contentless_cores.c (-2/+2) — Replaces 2 task_push_icon_load() calls with gfx_display_load_icon(): fallback icon and per-core icons.
tasks/task_file_transfer.c (-9) — Reverts b8c7860: removes the #ifdef __ANDROID__ that forced synchronous NBIO file transfer. Unnecessary since Android no longer enters the async icon path.
tasks/task_image.c (-14) — Reverts b8c7860: removes the two #ifdef __ANDROID__ blocks that forced synchronous image decode loops. Same reason — Android icons load synchronously one layer up, never reaching this code.
Net: 86 insertions, 42 deletions across 11 files. One #if defined(__ANDROID__) in one file controls everything.
This commit is contained in:
U-DESKTOP-SPFP6AQ\twistedtechre committed 2026-04-14 17:18:43 +02:00
1 parent b8c78609ee
commit 5c1e31a81f
11 files changed
+86 -42

No files matched your search

+46
View File
@@ -19,6 +19,7 @@
#include "gfx_display.h"
#include "../configuration.h"
#include "../tasks/tasks_internal.h"
#include "../verbosity.h"
#ifdef HAVE_MIST
@@ -1175,6 +1176,51 @@ bool gfx_display_reset_icon_texture(
return true;
}
/* -----------------------------------------------------------------------
* Platform-adaptive icon/texture loading
*
* Dispatches to either the synchronous (blocking) or asynchronous
* (task-queue) icon loading path depending on the platform.
*
* Platforms that define GFX_DISPLAY_ICON_LOAD_SYNCHRONOUS get the
* pre-async behavior: image_texture_load -> video_driver_texture_load
* in one call, no task queue involvement. This avoids frame-spread
* I/O and GL context contention on platforms where the async path is
* actually slower (e.g. Android behind SAF / fuse storage).
*
* To opt a new platform into the synchronous path, add it to the
* ifdef below.
* ----------------------------------------------------------------------- */
#if defined(__ANDROID__)
#define GFX_DISPLAY_ICON_LOAD_SYNCHRONOUS
#endif
bool gfx_display_load_icon(
const char *fullpath,
bool supports_rgba,
uintptr_t *target_texture,
uint64_t generation,
uint64_t *generation_ptr)
{
#ifdef GFX_DISPLAY_ICON_LOAD_SYNCHRONOUS
/* Synchronous path - identical to pre-async behavior.
* Generation counter is irrelevant: the load completes
* before this function returns, so there is no in-flight
* callback that could write to a freed pointer. */
(void)supports_rgba;
(void)generation;
(void)generation_ptr;
return gfx_display_reset_icon_texture(
fullpath, target_texture,
TEXTURE_FILTER_MIPMAP_LINEAR, NULL, NULL);
#else
return task_push_icon_load(
fullpath, supports_rgba,
target_texture, generation, generation_ptr);
#endif
}
void gfx_display_deinit_white_texture(void)
{
if (gfx_white_texture)
+20
View File
@@ -293,6 +293,26 @@ bool gfx_display_reset_icon_texture(
uintptr_t *item, enum texture_filter_type filter_type,
unsigned *width, unsigned *height);
/* Platform-adaptive icon/texture loading.
*
* On platforms where async task-based image loading is detrimental
* to performance (e.g. Android with SAF I/O overhead), falls back
* to synchronous loading identical to the pre-async behavior.
*
* All menu drivers and gfx_widgets should call this instead of
* task_push_icon_load() directly so that adding a new platform
* to the synchronous path requires changing only one place.
*
* |generation| / |generation_ptr| are only used on the async path
* to guard against stale callbacks; on the synchronous path they
* are ignored (the load completes before the function returns). */
bool gfx_display_load_icon(
const char *fullpath,
bool supports_rgba,
uintptr_t *target_texture,
uint64_t generation,
uint64_t *generation_ptr);
bool gfx_display_reset_textures_list_buffer(
uintptr_t *item,
enum texture_filter_type filter_type,
+5 -4
View File
@@ -2006,11 +2006,12 @@ static void gfx_widgets_context_reset(
widget_icon_load_gen++;
/* Start with no-icons layout — text positions are correct for
* text-only rendering. When async loads complete, the callback
* sets MSG_QUEUE_HAS_ICONS and recomputes icon-dependent layout. */
* text-only rendering. When loads complete (immediately on sync
* platforms, via callback on async), the frame-loop detects
* non-zero textures and recomputes icon-dependent layout. */
p_dispwidget->flags &= ~DISPGFX_WIDGET_FLAG_MSG_QUEUE_HAS_ICONS;
/* Queue async icon loads */
/* Load icons */
for (i = 0; i < MENU_WIDGETS_ICON_LAST; i++)
{
char texpath[PATH_MAX_LENGTH];
@@ -2018,7 +2019,7 @@ static void gfx_widgets_context_reset(
p_dispwidget->monochrome_png_path,
gfx_widgets_icons_names[i],
sizeof(texpath));
task_push_icon_load(texpath, supports_rgba,
gfx_display_load_icon(texpath, supports_rgba,
&p_dispwidget->gfx_widgets_icons_textures[i],
widget_icon_load_gen, &widget_icon_load_gen);
}
+1 -1
View File
@@ -365,7 +365,7 @@ static void gfx_widget_volume_context_reset(bool is_threaded,
char texpath[PATH_MAX_LENGTH];
fill_pathname_join_special(texpath,
menu_png_path, ICONS_NAMES[i], sizeof(texpath));
task_push_icon_load(texpath, supports_rgba,
gfx_display_load_icon(texpath, supports_rgba,
&state->textures[i], volume_icon_load_gen,
&volume_icon_load_gen);
}
+2 -2
View File
@@ -2293,7 +2293,7 @@ static void materialui_context_reset_playlist_icons(
fill_pathname_join_special(texpath,
mui->sysicons_path, image_file,
sizeof(texpath));
task_push_icon_load(texpath, supports_rgba,
gfx_display_load_icon(texpath, supports_rgba,
&mui->textures.playlist.icons[i].image,
mui_icon_load_gen, &mui_icon_load_gen);
}
@@ -2569,7 +2569,7 @@ static void materialui_context_reset_textures(materialui_handle_t *mui)
fill_pathname_join_special(texpath,
mui->icons_path, materialui_texture_path(i),
sizeof(texpath));
task_push_icon_load(texpath, supports_rgba,
gfx_display_load_icon(texpath, supports_rgba,
&mui->textures.list[i], mui_icon_load_gen,
&mui_icon_load_gen);
}
+6 -6
View File
@@ -2951,7 +2951,7 @@ static void ozone_reset_theme_textures(ozone_handle_t *ozone)
fill_pathname_join_special(texpath,
theme_path, OZONE_THEME_TEXTURES_FILES[i],
sizeof(texpath));
task_push_icon_load(texpath, supports_rgba,
gfx_display_load_icon(texpath, supports_rgba,
&theme->textures[i], ozone_ctx_icon_load_gen,
&ozone_ctx_icon_load_gen);
}
@@ -5136,7 +5136,7 @@ static void ozone_context_reset_horizontal_list(ozone_handle_t *ozone)
texturepath, ozone->icons_path, "default.png",
sizeof(texturepath));
task_push_icon_load(texturepath, supports_rgba,
gfx_display_load_icon(texturepath, supports_rgba,
&node->icon, ozone_icon_load_gen,
&ozone_icon_load_gen);
@@ -5149,7 +5149,7 @@ static void ozone_context_reset_horizontal_list(ozone_handle_t *ozone)
fill_pathname_join_delim(texturepath, ozone->icons_path_default,
"content.png", '-', sizeof(texturepath));
task_push_icon_load(texturepath, supports_rgba,
gfx_display_load_icon(texturepath, supports_rgba,
&node->content_icon, ozone_icon_load_gen,
&ozone_icon_load_gen);
@@ -9831,7 +9831,7 @@ static void ozone_context_reset(void *data, bool is_threaded)
fill_pathname_join_special(texpath,
ozone->png_path, OZONE_TEXTURES_FILES[i],
sizeof(texpath));
task_push_icon_load(texpath, supports_rgba,
gfx_display_load_icon(texpath, supports_rgba,
&ozone->textures[i], ozone_ctx_icon_load_gen,
&ozone_ctx_icon_load_gen);
}
@@ -9855,7 +9855,7 @@ static void ozone_context_reset(void *data, bool is_threaded)
sizeof(texpath));
break;
}
task_push_icon_load(texpath, supports_rgba,
gfx_display_load_icon(texpath, supports_rgba,
&ozone->tab_textures[i], ozone_ctx_icon_load_gen,
&ozone_ctx_icon_load_gen);
}
@@ -9870,7 +9870,7 @@ static void ozone_context_reset(void *data, bool is_threaded)
fill_pathname_join_special(texpath,
ozone->icons_path, ozone_entries_icon_texture_path(i),
sizeof(texpath));
task_push_icon_load(texpath, supports_rgba,
gfx_display_load_icon(texpath, supports_rgba,
&ozone->icons_textures[i], ozone_ctx_icon_load_gen,
&ozone_ctx_icon_load_gen);
}
+3 -3
View File
@@ -2988,7 +2988,7 @@ static void xmb_context_reset_horizontal_list(xmb_handle_t *xmb)
strlcpy(texturepath + __len, ".png", sizeof(texturepath) - __len);
}
task_push_icon_load(texturepath, supports_rgba,
gfx_display_load_icon(texturepath, supports_rgba,
&node->icon, xmb_icon_load_gen,
&xmb_icon_load_gen);
@@ -3000,7 +3000,7 @@ static void xmb_context_reset_horizontal_list(xmb_handle_t *xmb)
fill_pathname_join_delim(texturepath, icons_path_default,
FILE_PATH_CONTENT_BASENAME, '-', sizeof(texturepath));
task_push_icon_load(texturepath, supports_rgba,
gfx_display_load_icon(texturepath, supports_rgba,
&node->content_icon, xmb_icon_load_gen,
&xmb_icon_load_gen);
@@ -6674,7 +6674,7 @@ static void xmb_context_reset_textures(
fill_pathname_join_special(texpath,
iconpath, texture_path, sizeof(texpath));
task_push_icon_load(texpath, supports_rgba,
gfx_display_load_icon(texpath, supports_rgba,
&xmb->textures.list[i], xmb_ctx_icon_load_gen,
&xmb_ctx_icon_load_gen);
}
+2 -2
View File
@@ -294,7 +294,7 @@ static void contentless_cores_load_icons(contentless_cores_state_t *state)
CONTENTLESS_CORE_ICON_DEFAULT, sizeof(icon_path));
if (path_is_valid(icon_path))
task_push_icon_load(icon_path, rgba_supported,
gfx_display_load_icon(icon_path, rgba_supported,
&state->icons->fallback, contentless_icon_load_gen,
&contentless_icon_load_gen);
@@ -338,7 +338,7 @@ static void contentless_cores_load_icons(contentless_cores_state_t *state)
RHMAP_SET_STR(state->icons->system,
core_info->core_file_id.str, icon);
task_push_icon_load(icon_path, rgba_supported,
gfx_display_load_icon(icon_path, rgba_supported,
icon, contentless_icon_load_gen,
&contentless_icon_load_gen);
}
+1 -1
View File
@@ -440,7 +440,7 @@ static void explore_load_icons(explore_state_t *state)
if (!path_is_valid(path))
continue;
task_push_icon_load(path, supports_rgba,
gfx_display_load_icon(path, supports_rgba,
&state->icons[i], explore_icon_load_gen,
&explore_icon_load_gen);
}
-9
View File
@@ -53,14 +53,6 @@ static int task_file_transfer_iterate_transfer(nbio_handle_t *nbio)
iters = nbio->pos_increment ? nbio->pos_increment
: NBIO_DEFAULT_POS_INCREMENT;
#ifdef __ANDROID__
/* Android: complete the entire file read in one pass to avoid
* spreading I/O across frames, which causes menu freezes and
* icon glitches when combined with async image decoding. */
(void)iters;
while (!nbio_iterate(nbio->handle));
return -1;
#else
for (i = 0; i < iters; i++)
{
if (nbio_iterate(nbio->handle))
@@ -68,7 +60,6 @@ static int task_file_transfer_iterate_transfer(nbio_handle_t *nbio)
}
return 0;
#endif
}
static int task_file_transfer_iterate_parse(nbio_handle_t *nbio)
-14
View File
@@ -151,16 +151,8 @@ static int task_image_iterate_process_transfer(struct nbio_image_handle *image)
if ((retval = task_image_process(image, &width, &height))
!= IMAGE_PROCESS_NEXT)
break;
#ifndef __ANDROID__
/* On non-Android platforms, budget image processing across
* multiple frames to avoid blocking the UI thread.
* On Android this causes freezes and icon glitches with all
* menu drivers, so we complete the entire decode in one pass. */
}while (cpu_features_get_time_usec() - start_time
< image->frame_duration);
#else
}while (1);
#endif
if (retval == IMAGE_PROCESS_NEXT)
return 0;
@@ -358,14 +350,8 @@ bool task_image_load_handler(retro_task_t *task)
image->status = IMAGE_STATUS_TRANSFER_PARSE;
break;
}
#ifndef __ANDROID__
}while (cpu_features_get_time_usec() - start_time
< image->frame_duration);
#else
/* Android: complete transfer in one pass to avoid
* context contention causing freezes/glitches */
}while (1);
#endif
}
break;
case IMAGE_STATUS_PROCESS_TRANSFER_PARSE: