(Ozone/XMB) Prevent unnecessary thumbnail requests when scrolling through playlists

This commit is contained in:
jdgleaver 2022-05-19 16:40:21 +01:00
parent 30685c6e60
commit f2dca12a22
4 changed files with 433 additions and 106 deletions

View File

@ -247,19 +247,15 @@ void gfx_thumbnail_request(
gfx_thumbnail_path_data_t *path_data, enum gfx_thumbnail_id thumbnail_id, gfx_thumbnail_path_data_t *path_data, enum gfx_thumbnail_id thumbnail_id,
playlist_t *playlist, size_t idx, gfx_thumbnail_t *thumbnail, playlist_t *playlist, size_t idx, gfx_thumbnail_t *thumbnail,
unsigned gfx_thumbnail_upscale_threshold, unsigned gfx_thumbnail_upscale_threshold,
bool network_on_demand_thumbnails bool network_on_demand_thumbnails)
)
{ {
const char *thumbnail_path = NULL; const char *thumbnail_path = NULL;
bool has_thumbnail = false; bool has_thumbnail = false;
gfx_thumbnail_state_t *p_gfx_thumb = NULL; gfx_thumbnail_state_t *p_gfx_thumb = &gfx_thumb_st;
p_gfx_thumb = NULL;
if (!path_data || !thumbnail) if (!path_data || !thumbnail)
return; return;
p_gfx_thumb = &gfx_thumb_st;
/* Reset thumbnail, then set 'missing' status by default /* Reset thumbnail, then set 'missing' status by default
* (saves a number of checks later) */ * (saves a number of checks later) */
gfx_thumbnail_reset(thumbnail); gfx_thumbnail_reset(thumbnail);
@ -354,8 +350,7 @@ end:
* once the image load is complete */ * once the image load is complete */
void gfx_thumbnail_request_file( void gfx_thumbnail_request_file(
const char *file_path, gfx_thumbnail_t *thumbnail, const char *file_path, gfx_thumbnail_t *thumbnail,
unsigned gfx_thumbnail_upscale_threshold unsigned gfx_thumbnail_upscale_threshold)
)
{ {
gfx_thumbnail_state_t *p_gfx_thumb = &gfx_thumb_st; gfx_thumbnail_state_t *p_gfx_thumb = &gfx_thumb_st;
gfx_thumbnail_tag_t *thumbnail_tag = NULL; gfx_thumbnail_tag_t *thumbnail_tag = NULL;
@ -424,6 +419,174 @@ void gfx_thumbnail_reset(gfx_thumbnail_t *thumbnail)
/* Stream processing */ /* Stream processing */
/* Requests loading of the specified thumbnail via
* the stream interface
* - Must be called on each frame for the duration
* that specified thumbnail is on-screen
* - Actual load request is deferred by currently
* set stream delay
* - Function becomes a no-op once load request is
* made
* - Thumbnails loaded via this function must be
* deleted manually via gfx_thumbnail_reset()
* when they move off-screen
* NOTE 1: Must be called *after* gfx_thumbnail_set_system()
* and gfx_thumbnail_set_content*()
* NOTE 2: 'playlist' and 'idx' are only required here for
* on-demand thumbnail download support
* (an annoyance...)
* NOTE 3: This function is intended for use in situations
* where each menu entry has a *single* thumbnail.
* If each entry has two thumbnails, use
* gfx_thumbnail_request_streams() for improved
* performance */
void gfx_thumbnail_request_stream(
gfx_thumbnail_path_data_t *path_data,
gfx_animation_t *p_anim,
enum gfx_thumbnail_id thumbnail_id,
playlist_t *playlist, size_t idx,
gfx_thumbnail_t *thumbnail,
unsigned gfx_thumbnail_upscale_threshold,
bool network_on_demand_thumbnails)
{
gfx_thumbnail_state_t *p_gfx_thumb = &gfx_thumb_st;
/* Only process request if current status
* is GFX_THUMBNAIL_STATUS_UNKNOWN */
if (!thumbnail ||
(thumbnail->status != GFX_THUMBNAIL_STATUS_UNKNOWN))
return;
/* Check if stream delay timer has elapsed */
thumbnail->delay_timer += p_anim->delta_time;
if (thumbnail->delay_timer > p_gfx_thumb->stream_delay)
{
/* Sanity check */
if (!path_data)
{
/* No path information
* > Reset thumbnail and set missing status
* to prevent repeated load attempts */
gfx_thumbnail_reset(thumbnail);
thumbnail->status = GFX_THUMBNAIL_STATUS_MISSING;
thumbnail->alpha = 1.0f;
return;
}
/* Request image load */
gfx_thumbnail_request(
path_data, thumbnail_id, playlist, idx, thumbnail,
gfx_thumbnail_upscale_threshold,
network_on_demand_thumbnails);
}
}
/* Requests loading of the specified thumbnails via
* the stream interface
* - Must be called on each frame for the duration
* that specified thumbnails are on-screen
* - Actual load request is deferred by currently
* set stream delay
* - Function becomes a no-op once load request is
* made
* - Thumbnails loaded via this function must be
* deleted manually via gfx_thumbnail_reset()
* when they move off-screen
* NOTE 1: Must be called *after* gfx_thumbnail_set_system()
* and gfx_thumbnail_set_content*()
* NOTE 2: 'playlist' and 'idx' are only required here for
* on-demand thumbnail download support
* (an annoyance...)
* NOTE 3: This function is intended for use in situations
* where each menu entry has *two* thumbnails.
* If each entry only has a single thumbnail, use
* gfx_thumbnail_request_stream() for improved
* performance */
void gfx_thumbnail_request_streams(
gfx_thumbnail_path_data_t *path_data,
gfx_animation_t *p_anim,
playlist_t *playlist, size_t idx,
gfx_thumbnail_t *right_thumbnail,
gfx_thumbnail_t *left_thumbnail,
unsigned gfx_thumbnail_upscale_threshold,
bool network_on_demand_thumbnails)
{
bool process_right = false;
bool process_left = false;
if (!right_thumbnail || !left_thumbnail)
return;
/* Only process request if current status
* is GFX_THUMBNAIL_STATUS_UNKNOWN */
process_right = (right_thumbnail->status == GFX_THUMBNAIL_STATUS_UNKNOWN);
process_left = (left_thumbnail->status == GFX_THUMBNAIL_STATUS_UNKNOWN);
if (process_right || process_left)
{
/* Check if stream delay timer has elapsed */
gfx_thumbnail_state_t *p_gfx_thumb = &gfx_thumb_st;
float delta_time = p_anim->delta_time;
bool request_right = false;
bool request_left = false;
if (process_right)
{
right_thumbnail->delay_timer += delta_time;
request_right =
(right_thumbnail->delay_timer > p_gfx_thumb->stream_delay);
}
if (process_left)
{
left_thumbnail->delay_timer += delta_time;
request_left =
(left_thumbnail->delay_timer > p_gfx_thumb->stream_delay);
}
/* Check if one or more thumbnails should be requested */
if (request_right || request_left)
{
/* Sanity check */
if (!path_data)
{
/* No path information
* > Reset thumbnail and set missing status
* to prevent repeated load attempts */
if (request_right)
{
gfx_thumbnail_reset(right_thumbnail);
right_thumbnail->status = GFX_THUMBNAIL_STATUS_MISSING;
right_thumbnail->alpha = 1.0f;
}
if (request_left)
{
gfx_thumbnail_reset(left_thumbnail);
left_thumbnail->status = GFX_THUMBNAIL_STATUS_MISSING;
left_thumbnail->alpha = 1.0f;
}
return;
}
/* Request image load */
if (request_right)
gfx_thumbnail_request(
path_data, GFX_THUMBNAIL_RIGHT, playlist, idx, right_thumbnail,
gfx_thumbnail_upscale_threshold,
network_on_demand_thumbnails);
if (request_left)
gfx_thumbnail_request(
path_data, GFX_THUMBNAIL_LEFT, playlist, idx, left_thumbnail,
gfx_thumbnail_upscale_threshold,
network_on_demand_thumbnails);
}
}
}
/* Handles streaming of the specified thumbnail as it moves /* Handles streaming of the specified thumbnail as it moves
* on/off screen * on/off screen
* - Must be called each frame for every on-screen entry * - Must be called each frame for every on-screen entry
@ -440,13 +603,11 @@ void gfx_thumbnail_process_stream(
gfx_thumbnail_path_data_t *path_data, gfx_thumbnail_path_data_t *path_data,
gfx_animation_t *p_anim, gfx_animation_t *p_anim,
enum gfx_thumbnail_id thumbnail_id, enum gfx_thumbnail_id thumbnail_id,
playlist_t *playlist, playlist_t *playlist, size_t idx,
size_t idx,
gfx_thumbnail_t *thumbnail, gfx_thumbnail_t *thumbnail,
bool on_screen, bool on_screen,
unsigned gfx_thumbnail_upscale_threshold, unsigned gfx_thumbnail_upscale_threshold,
bool network_on_demand_thumbnails bool network_on_demand_thumbnails)
)
{ {
if (!thumbnail) if (!thumbnail)
return; return;
@ -482,8 +643,7 @@ void gfx_thumbnail_process_stream(
gfx_thumbnail_request( gfx_thumbnail_request(
path_data, thumbnail_id, playlist, idx, thumbnail, path_data, thumbnail_id, playlist, idx, thumbnail,
gfx_thumbnail_upscale_threshold, gfx_thumbnail_upscale_threshold,
network_on_demand_thumbnails network_on_demand_thumbnails);
);
} }
} }
} }
@ -521,8 +681,7 @@ void gfx_thumbnail_process_streams(
gfx_thumbnail_t *left_thumbnail, gfx_thumbnail_t *left_thumbnail,
bool on_screen, bool on_screen,
unsigned gfx_thumbnail_upscale_threshold, unsigned gfx_thumbnail_upscale_threshold,
bool network_on_demand_thumbnails bool network_on_demand_thumbnails)
)
{ {
if (!right_thumbnail || !left_thumbnail) if (!right_thumbnail || !left_thumbnail)
return; return;

View File

@ -171,8 +171,7 @@ void gfx_thumbnail_request(
gfx_thumbnail_path_data_t *path_data, enum gfx_thumbnail_id thumbnail_id, gfx_thumbnail_path_data_t *path_data, enum gfx_thumbnail_id thumbnail_id,
playlist_t *playlist, size_t idx, gfx_thumbnail_t *thumbnail, playlist_t *playlist, size_t idx, gfx_thumbnail_t *thumbnail,
unsigned gfx_thumbnail_upscale_threshold, unsigned gfx_thumbnail_upscale_threshold,
bool network_on_demand_thumbnails bool network_on_demand_thumbnails);
);
/* Requests loading of a specific thumbnail image file /* Requests loading of a specific thumbnail image file
* (may be used, for example, to load savestate images) * (may be used, for example, to load savestate images)
@ -192,6 +191,66 @@ void gfx_thumbnail_reset(gfx_thumbnail_t *thumbnail);
/* Stream processing */ /* Stream processing */
/* Requests loading of the specified thumbnail via
* the stream interface
* - Must be called on each frame for the duration
* that specified thumbnail is on-screen
* - Actual load request is deferred by currently
* set stream delay
* - Function becomes a no-op once load request is
* made
* - Thumbnails loaded via this function must be
* deleted manually via gfx_thumbnail_reset()
* when they move off-screen
* NOTE 1: Must be called *after* gfx_thumbnail_set_system()
* and gfx_thumbnail_set_content*()
* NOTE 2: 'playlist' and 'idx' are only required here for
* on-demand thumbnail download support
* (an annoyance...)
* NOTE 3: This function is intended for use in situations
* where each menu entry has a *single* thumbnail.
* If each entry has two thumbnails, use
* gfx_thumbnail_request_streams() for improved
* performance */
void gfx_thumbnail_request_stream(
gfx_thumbnail_path_data_t *path_data,
gfx_animation_t *p_anim,
enum gfx_thumbnail_id thumbnail_id,
playlist_t *playlist, size_t idx,
gfx_thumbnail_t *thumbnail,
unsigned gfx_thumbnail_upscale_threshold,
bool network_on_demand_thumbnails);
/* Requests loading of the specified thumbnails via
* the stream interface
* - Must be called on each frame for the duration
* that specified thumbnails are on-screen
* - Actual load request is deferred by currently
* set stream delay
* - Function becomes a no-op once load request is
* made
* - Thumbnails loaded via this function must be
* deleted manually via gfx_thumbnail_reset()
* when they move off-screen
* NOTE 1: Must be called *after* gfx_thumbnail_set_system()
* and gfx_thumbnail_set_content*()
* NOTE 2: 'playlist' and 'idx' are only required here for
* on-demand thumbnail download support
* (an annoyance...)
* NOTE 3: This function is intended for use in situations
* where each menu entry has *two* thumbnails.
* If each entry only has a single thumbnail, use
* gfx_thumbnail_request_stream() for improved
* performance */
void gfx_thumbnail_request_streams(
gfx_thumbnail_path_data_t *path_data,
gfx_animation_t *p_anim,
playlist_t *playlist, size_t idx,
gfx_thumbnail_t *right_thumbnail,
gfx_thumbnail_t *left_thumbnail,
unsigned gfx_thumbnail_upscale_threshold,
bool network_on_demand_thumbnails);
/* Handles streaming of the specified thumbnail as it moves /* Handles streaming of the specified thumbnail as it moves
* on/off screen * on/off screen
* - Must be called each frame for every on-screen entry * - Must be called each frame for every on-screen entry
@ -208,13 +267,11 @@ void gfx_thumbnail_process_stream(
gfx_thumbnail_path_data_t *path_data, gfx_thumbnail_path_data_t *path_data,
gfx_animation_t *p_anim, gfx_animation_t *p_anim,
enum gfx_thumbnail_id thumbnail_id, enum gfx_thumbnail_id thumbnail_id,
playlist_t *playlist, playlist_t *playlist, size_t idx,
size_t idx,
gfx_thumbnail_t *thumbnail, gfx_thumbnail_t *thumbnail,
bool on_screen, bool on_screen,
unsigned gfx_thumbnail_upscale_threshold, unsigned gfx_thumbnail_upscale_threshold,
bool network_on_demand_thumbnails bool network_on_demand_thumbnails);
);
/* Handles streaming of the specified thumbnails as they move /* Handles streaming of the specified thumbnails as they move
* on/off screen * on/off screen
@ -236,8 +293,7 @@ void gfx_thumbnail_process_streams(
gfx_thumbnail_t *left_thumbnail, gfx_thumbnail_t *left_thumbnail,
bool on_screen, bool on_screen,
unsigned gfx_thumbnail_upscale_threshold, unsigned gfx_thumbnail_upscale_threshold,
bool network_on_demand_thumbnails bool network_on_demand_thumbnails);
);
/* Thumbnail rendering */ /* Thumbnail rendering */

View File

@ -63,6 +63,8 @@
#define ANIMATION_CURSOR_DURATION 133 #define ANIMATION_CURSOR_DURATION 133
#define ANIMATION_CURSOR_PULSE 500 #define ANIMATION_CURSOR_PULSE 500
#define OZONE_THUMBNAIL_STREAM_DELAY 166.66667f
#define FONT_SIZE_FOOTER 18 #define FONT_SIZE_FOOTER 18
#define FONT_SIZE_TITLE 36 #define FONT_SIZE_TITLE 36
#define FONT_SIZE_TIME 22 #define FONT_SIZE_TIME 22
@ -317,6 +319,14 @@ enum
OZONE_ENTRIES_ICONS_TEXTURE_LAST OZONE_ENTRIES_ICONS_TEXTURE_LAST
}; };
enum ozone_pending_thumbnail_type
{
OZONE_PENDING_THUMBNAIL_NONE = 0,
OZONE_PENDING_THUMBNAIL_RIGHT,
OZONE_PENDING_THUMBNAIL_LEFT,
OZONE_PENDING_THUMBNAIL_BOTH
};
/* This structure holds all objects + metadata /* This structure holds all objects + metadata
* corresponding to a particular font */ * corresponding to a particular font */
typedef struct typedef struct
@ -432,6 +442,8 @@ struct ozone_handle
{ {
gfx_thumbnail_t right; /* uintptr_t alignment */ gfx_thumbnail_t right; /* uintptr_t alignment */
gfx_thumbnail_t left; /* uintptr_t alignment */ gfx_thumbnail_t left; /* uintptr_t alignment */
float stream_delay;
enum ozone_pending_thumbnail_type pending;
} thumbnails; } thumbnails;
uintptr_t textures[OZONE_THEME_TEXTURE_LAST]; uintptr_t textures[OZONE_THEME_TEXTURE_LAST];
uintptr_t icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_LAST]; uintptr_t icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_LAST];
@ -3378,6 +3390,11 @@ static void ozone_entries_update_thumbnail_bar(
} }
ozone->pending_hide_thumbnail_bar = false; ozone->pending_hide_thumbnail_bar = false;
/* Want thumbnails to load instantly when thumbnail
* sidebar first opens */
ozone->thumbnails.stream_delay = 0.0f;
gfx_thumbnail_set_stream_delay(ozone->thumbnails.stream_delay);
} }
/* Hide it */ /* Hide it */
else else
@ -3989,6 +4006,11 @@ static void ozone_refresh_sidebars(
{ {
ozone->animations.thumbnail_bar_position = ozone->dimensions.thumbnail_bar_width; ozone->animations.thumbnail_bar_position = ozone->dimensions.thumbnail_bar_width;
ozone->show_thumbnail_bar = true; ozone->show_thumbnail_bar = true;
/* Want thumbnails to load instantly when thumbnail
* sidebar first opens */
ozone->thumbnails.stream_delay = 0.0f;
gfx_thumbnail_set_stream_delay(ozone->thumbnails.stream_delay);
} }
else else
{ {
@ -6818,6 +6840,17 @@ static enum menu_action ozone_parse_menu_entry_action(
size_t selection; size_t selection;
size_t selection_total; size_t selection_total;
/* We have to override the thumbnail stream
* delay when opening the thumbnail sidebar;
* ensure that the proper value is restored
* whenever the user performs regular navigation */
if ((action != MENU_ACTION_NOOP) &&
(ozone->thumbnails.stream_delay != OZONE_THUMBNAIL_STREAM_DELAY))
{
ozone->thumbnails.stream_delay = OZONE_THUMBNAIL_STREAM_DELAY;
gfx_thumbnail_set_stream_delay(ozone->thumbnails.stream_delay);
}
/* If fullscreen thumbnail view is active, any /* If fullscreen thumbnail view is active, any
* valid menu action will disable it... */ * valid menu action will disable it... */
if (ozone->show_fullscreen_thumbnails) if (ozone->show_fullscreen_thumbnails)
@ -7225,7 +7258,9 @@ static void *ozone_init(void **userdata, bool video_is_threaded)
ozone->animations.left_thumbnail_alpha = 1.0f; ozone->animations.left_thumbnail_alpha = 1.0f;
ozone->force_metadata_display = false; ozone->force_metadata_display = false;
gfx_thumbnail_set_stream_delay(-1.0f); ozone->thumbnails.pending = OZONE_PENDING_THUMBNAIL_NONE;
ozone->thumbnails.stream_delay = OZONE_THUMBNAIL_STREAM_DELAY;
gfx_thumbnail_set_stream_delay(ozone->thumbnails.stream_delay);
gfx_thumbnail_set_fade_duration(-1.0f); gfx_thumbnail_set_fade_duration(-1.0f);
gfx_thumbnail_set_fade_missing(false); gfx_thumbnail_set_fade_missing(false);
@ -7408,46 +7443,28 @@ static void ozone_free(void *data)
static void ozone_update_thumbnail_image(void *data) static void ozone_update_thumbnail_image(void *data)
{ {
ozone_handle_t *ozone = (ozone_handle_t*)data; ozone_handle_t *ozone = (ozone_handle_t*)data;
size_t selection = menu_navigation_get_selection();
settings_t *settings = config_get_ptr();
playlist_t *playlist = playlist_get_cached();
unsigned gfx_thumbnail_upscale_threshold = settings->uints.gfx_thumbnail_upscale_threshold;
bool network_on_demand_thumbnails = settings->bools.network_on_demand_thumbnails;
if (!ozone) if (!ozone)
return; return;
ozone->thumbnails.pending = OZONE_PENDING_THUMBNAIL_NONE;
gfx_thumbnail_cancel_pending_requests(); gfx_thumbnail_cancel_pending_requests();
gfx_thumbnail_reset(&ozone->thumbnails.right);
gfx_thumbnail_request(
ozone->thumbnail_path_data,
GFX_THUMBNAIL_RIGHT,
playlist,
selection,
&ozone->thumbnails.right,
gfx_thumbnail_upscale_threshold,
network_on_demand_thumbnails
);
/* Image (and video/music) content requires special
* treatment... */
if (ozone->selection_core_is_viewer)
{
/* Left thumbnail is simply reset */
gfx_thumbnail_reset(&ozone->thumbnails.left); gfx_thumbnail_reset(&ozone->thumbnails.left);
}
else /* Right thumbnail */
{ if (gfx_thumbnail_is_enabled(ozone->thumbnail_path_data,
/* Left thumbnail */ GFX_THUMBNAIL_RIGHT))
gfx_thumbnail_request( ozone->thumbnails.pending = OZONE_PENDING_THUMBNAIL_RIGHT;
ozone->thumbnail_path_data,
GFX_THUMBNAIL_LEFT, /* Left thumbnail
playlist, * > Disabled for image (and video/music) content */
selection, if (!ozone->selection_core_is_viewer &&
&ozone->thumbnails.left, gfx_thumbnail_is_enabled(ozone->thumbnail_path_data,
gfx_thumbnail_upscale_threshold, GFX_THUMBNAIL_LEFT))
network_on_demand_thumbnails); ozone->thumbnails.pending =
} (ozone->thumbnails.pending == OZONE_PENDING_THUMBNAIL_RIGHT) ?
OZONE_PENDING_THUMBNAIL_BOTH : OZONE_PENDING_THUMBNAIL_LEFT;
} }
static void ozone_refresh_thumbnail_image(void *data, unsigned i) static void ozone_refresh_thumbnail_image(void *data, unsigned i)
@ -7847,6 +7864,7 @@ static void ozone_unload_thumbnail_textures(void *data)
if (!ozone) if (!ozone)
return; return;
ozone->thumbnails.pending = OZONE_PENDING_THUMBNAIL_NONE;
gfx_thumbnail_cancel_pending_requests(); gfx_thumbnail_cancel_pending_requests();
gfx_thumbnail_reset(&ozone->thumbnails.right); gfx_thumbnail_reset(&ozone->thumbnails.right);
gfx_thumbnail_reset(&ozone->thumbnails.left); gfx_thumbnail_reset(&ozone->thumbnails.left);
@ -8646,6 +8664,59 @@ static void ozone_render(void *data,
} }
} }
/* Handle any pending thumbnail load requests */
if (ozone->show_thumbnail_bar &&
(ozone->thumbnails.pending != OZONE_PENDING_THUMBNAIL_NONE))
{
size_t selection = menu_navigation_get_selection();
playlist_t *playlist = playlist_get_cached();
unsigned gfx_thumbnail_upscale_threshold = settings->uints.gfx_thumbnail_upscale_threshold;
bool network_on_demand_thumbnails = settings->bools.network_on_demand_thumbnails;
switch (ozone->thumbnails.pending)
{
case OZONE_PENDING_THUMBNAIL_BOTH:
gfx_thumbnail_request_streams(
ozone->thumbnail_path_data,
p_anim,
playlist, selection,
&ozone->thumbnails.right,
&ozone->thumbnails.left,
gfx_thumbnail_upscale_threshold,
network_on_demand_thumbnails);
if ((ozone->thumbnails.right.status != GFX_THUMBNAIL_STATUS_UNKNOWN) &&
(ozone->thumbnails.left.status != GFX_THUMBNAIL_STATUS_UNKNOWN))
ozone->thumbnails.pending = OZONE_PENDING_THUMBNAIL_NONE;
break;
case OZONE_PENDING_THUMBNAIL_RIGHT:
gfx_thumbnail_request_stream(
ozone->thumbnail_path_data,
p_anim,
GFX_THUMBNAIL_RIGHT,
playlist, selection,
&ozone->thumbnails.right,
gfx_thumbnail_upscale_threshold,
network_on_demand_thumbnails);
if (ozone->thumbnails.right.status != GFX_THUMBNAIL_STATUS_UNKNOWN)
ozone->thumbnails.pending = OZONE_PENDING_THUMBNAIL_NONE;
break;
case OZONE_PENDING_THUMBNAIL_LEFT:
gfx_thumbnail_request_stream(
ozone->thumbnail_path_data,
p_anim,
GFX_THUMBNAIL_LEFT,
playlist, selection,
&ozone->thumbnails.left,
gfx_thumbnail_upscale_threshold,
network_on_demand_thumbnails);
if (ozone->thumbnails.left.status != GFX_THUMBNAIL_STATUS_UNKNOWN)
ozone->thumbnails.pending = OZONE_PENDING_THUMBNAIL_NONE;
break;
default:
break;
}
}
menu_entries_ctl(MENU_ENTRIES_CTL_START_GET, &i); menu_entries_ctl(MENU_ENTRIES_CTL_START_GET, &i);
if (i >= entries_end) if (i >= entries_end)

View File

@ -72,6 +72,8 @@
#define XMB_DELAY 166.66667f #define XMB_DELAY 166.66667f
#endif #endif
#define XMB_THUMBNAIL_STREAM_DELAY 166.66667f
/* Specifies minimum period (in usec) between /* Specifies minimum period (in usec) between
* tab switch events when input repeat is * tab switch events when input repeat is
* active (i.e. when navigating between top level * active (i.e. when navigating between top level
@ -255,6 +257,14 @@ enum
XMB_SYSTEM_TAB_MAX_LENGTH XMB_SYSTEM_TAB_MAX_LENGTH
}; };
enum xmb_pending_thumbnail_type
{
XMB_PENDING_THUMBNAIL_NONE = 0,
XMB_PENDING_THUMBNAIL_RIGHT,
XMB_PENDING_THUMBNAIL_LEFT,
XMB_PENDING_THUMBNAIL_BOTH
};
/* NOTE: If you change this you HAVE to update /* NOTE: If you change this you HAVE to update
* xmb_alloc_node() and xmb_copy_node() */ * xmb_alloc_node() and xmb_copy_node() */
typedef struct typedef struct
@ -317,6 +327,7 @@ typedef struct xmb_handle
gfx_thumbnail_t right; gfx_thumbnail_t right;
gfx_thumbnail_t left; gfx_thumbnail_t left;
gfx_thumbnail_t savestate; gfx_thumbnail_t savestate;
enum xmb_pending_thumbnail_type pending;
} thumbnails; } thumbnails;
struct struct
@ -1213,70 +1224,44 @@ static void xmb_update_savestate_thumbnail_path(void *data, unsigned i)
static void xmb_update_thumbnail_image(void *data) static void xmb_update_thumbnail_image(void *data)
{ {
const char *core_name = NULL;
xmb_handle_t *xmb = (xmb_handle_t*)data; xmb_handle_t *xmb = (xmb_handle_t*)data;
size_t selection = menu_navigation_get_selection(); const char *core_name = NULL;
playlist_t *playlist = playlist_get_cached();
settings_t *settings = config_get_ptr();
unsigned thumbnail_upscale_threshold = settings->uints.gfx_thumbnail_upscale_threshold;
bool network_on_demand_thumbnails = settings->bools.network_on_demand_thumbnails;
if (!xmb) if (!xmb)
return; return;
xmb->thumbnails.pending = XMB_PENDING_THUMBNAIL_NONE;
gfx_thumbnail_cancel_pending_requests(); gfx_thumbnail_cancel_pending_requests();
/* imageviewer content requires special treatment... */
gfx_thumbnail_get_core_name(xmb->thumbnail_path_data, &core_name);
if (string_is_equal(core_name, "imageviewer"))
{
gfx_thumbnail_reset(&xmb->thumbnails.right); gfx_thumbnail_reset(&xmb->thumbnails.right);
gfx_thumbnail_reset(&xmb->thumbnails.left); gfx_thumbnail_reset(&xmb->thumbnails.left);
/* imageviewer content requires special treatment... */
gfx_thumbnail_get_core_name(xmb->thumbnail_path_data, &core_name);
if (string_is_equal(core_name, "imageviewer"))
{
/* Right thumbnail */ /* Right thumbnail */
if (gfx_thumbnail_is_enabled(xmb->thumbnail_path_data, if (gfx_thumbnail_is_enabled(xmb->thumbnail_path_data,
GFX_THUMBNAIL_RIGHT)) GFX_THUMBNAIL_RIGHT))
gfx_thumbnail_request( xmb->thumbnails.pending = XMB_PENDING_THUMBNAIL_RIGHT;
xmb->thumbnail_path_data,
GFX_THUMBNAIL_RIGHT,
playlist,
selection,
&xmb->thumbnails.right,
thumbnail_upscale_threshold,
network_on_demand_thumbnails);
/* Left thumbnail */ /* Left thumbnail */
else if (gfx_thumbnail_is_enabled(xmb->thumbnail_path_data, else if (gfx_thumbnail_is_enabled(xmb->thumbnail_path_data,
GFX_THUMBNAIL_LEFT)) GFX_THUMBNAIL_LEFT))
gfx_thumbnail_request( xmb->thumbnails.pending = XMB_PENDING_THUMBNAIL_LEFT;
xmb->thumbnail_path_data,
GFX_THUMBNAIL_LEFT,
playlist,
selection,
&xmb->thumbnails.left,
thumbnail_upscale_threshold,
network_on_demand_thumbnails);
} }
else else
{ {
/* Right thumbnail */ /* Right thumbnail */
gfx_thumbnail_request( if (gfx_thumbnail_is_enabled(xmb->thumbnail_path_data,
xmb->thumbnail_path_data, GFX_THUMBNAIL_RIGHT))
GFX_THUMBNAIL_RIGHT, xmb->thumbnails.pending = XMB_PENDING_THUMBNAIL_RIGHT;
playlist,
selection,
&xmb->thumbnails.right,
thumbnail_upscale_threshold,
network_on_demand_thumbnails);
/* Left thumbnail */ /* Left thumbnail */
gfx_thumbnail_request( if (gfx_thumbnail_is_enabled(xmb->thumbnail_path_data,
xmb->thumbnail_path_data, GFX_THUMBNAIL_LEFT))
GFX_THUMBNAIL_LEFT, xmb->thumbnails.pending =
playlist, (xmb->thumbnails.pending == XMB_PENDING_THUMBNAIL_RIGHT) ?
selection, XMB_PENDING_THUMBNAIL_BOTH : XMB_PENDING_THUMBNAIL_LEFT;
&xmb->thumbnails.left,
thumbnail_upscale_threshold,
network_on_demand_thumbnails);
} }
} }
@ -1338,6 +1323,7 @@ static void xmb_unload_thumbnail_textures(void *data)
if (!xmb) if (!xmb)
return; return;
xmb->thumbnails.pending = XMB_PENDING_THUMBNAIL_NONE;
gfx_thumbnail_cancel_pending_requests(); gfx_thumbnail_cancel_pending_requests();
gfx_thumbnail_reset(&xmb->thumbnails.right); gfx_thumbnail_reset(&xmb->thumbnails.right);
gfx_thumbnail_reset(&xmb->thumbnails.left); gfx_thumbnail_reset(&xmb->thumbnails.left);
@ -1577,6 +1563,7 @@ static void xmb_selection_pointer_changed(
* content + right/left thumbnails * content + right/left thumbnails
* (otherwise last loaded thumbnail will * (otherwise last loaded thumbnail will
* persist, and be shown on the wrong entry) */ * persist, and be shown on the wrong entry) */
xmb->thumbnails.pending = XMB_PENDING_THUMBNAIL_NONE;
gfx_thumbnail_set_content(xmb->thumbnail_path_data, NULL); gfx_thumbnail_set_content(xmb->thumbnail_path_data, NULL);
gfx_thumbnail_cancel_pending_requests(); gfx_thumbnail_cancel_pending_requests();
gfx_thumbnail_reset(&xmb->thumbnails.right); gfx_thumbnail_reset(&xmb->thumbnails.right);
@ -2563,6 +2550,7 @@ static void xmb_populate_entries(void *data,
* file list is populated... */ * file list is populated... */
if (xmb->is_file_list) if (xmb->is_file_list)
{ {
xmb->thumbnails.pending = XMB_PENDING_THUMBNAIL_NONE;
gfx_thumbnail_set_content(xmb->thumbnail_path_data, NULL); gfx_thumbnail_set_content(xmb->thumbnail_path_data, NULL);
gfx_thumbnail_cancel_pending_requests(); gfx_thumbnail_cancel_pending_requests();
gfx_thumbnail_reset(&xmb->thumbnails.right); gfx_thumbnail_reset(&xmb->thumbnails.right);
@ -4286,6 +4274,58 @@ static void xmb_render(void *data,
} }
} }
/* Handle any pending thumbnail load requests */
if (xmb->thumbnails.pending != XMB_PENDING_THUMBNAIL_NONE)
{
size_t selection = menu_navigation_get_selection();
playlist_t *playlist = playlist_get_cached();
unsigned gfx_thumbnail_upscale_threshold = settings->uints.gfx_thumbnail_upscale_threshold;
bool network_on_demand_thumbnails = settings->bools.network_on_demand_thumbnails;
switch (xmb->thumbnails.pending)
{
case XMB_PENDING_THUMBNAIL_BOTH:
gfx_thumbnail_request_streams(
xmb->thumbnail_path_data,
p_anim,
playlist, selection,
&xmb->thumbnails.right,
&xmb->thumbnails.left,
gfx_thumbnail_upscale_threshold,
network_on_demand_thumbnails);
if ((xmb->thumbnails.right.status != GFX_THUMBNAIL_STATUS_UNKNOWN) &&
(xmb->thumbnails.left.status != GFX_THUMBNAIL_STATUS_UNKNOWN))
xmb->thumbnails.pending = XMB_PENDING_THUMBNAIL_NONE;
break;
case XMB_PENDING_THUMBNAIL_RIGHT:
gfx_thumbnail_request_stream(
xmb->thumbnail_path_data,
p_anim,
GFX_THUMBNAIL_RIGHT,
playlist, selection,
&xmb->thumbnails.right,
gfx_thumbnail_upscale_threshold,
network_on_demand_thumbnails);
if (xmb->thumbnails.right.status != GFX_THUMBNAIL_STATUS_UNKNOWN)
xmb->thumbnails.pending = XMB_PENDING_THUMBNAIL_NONE;
break;
case XMB_PENDING_THUMBNAIL_LEFT:
gfx_thumbnail_request_stream(
xmb->thumbnail_path_data,
p_anim,
GFX_THUMBNAIL_LEFT,
playlist, selection,
&xmb->thumbnails.left,
gfx_thumbnail_upscale_threshold,
network_on_demand_thumbnails);
if (xmb->thumbnails.left.status != GFX_THUMBNAIL_STATUS_UNKNOWN)
xmb->thumbnails.pending = XMB_PENDING_THUMBNAIL_NONE;
break;
default:
break;
}
}
menu_entries_ctl(MENU_ENTRIES_CTL_START_GET, &i); menu_entries_ctl(MENU_ENTRIES_CTL_START_GET, &i);
if (i >= end) if (i >= end)
@ -6008,7 +6048,8 @@ static void *xmb_init(void **userdata, bool video_is_threaded)
xmb->fullscreen_thumbnail_selection = 0; xmb->fullscreen_thumbnail_selection = 0;
xmb->fullscreen_thumbnail_label[0] = '\0'; xmb->fullscreen_thumbnail_label[0] = '\0';
gfx_thumbnail_set_stream_delay(-1.0f); xmb->thumbnails.pending = XMB_PENDING_THUMBNAIL_NONE;
gfx_thumbnail_set_stream_delay(XMB_THUMBNAIL_STREAM_DELAY);
gfx_thumbnail_set_fade_duration(-1.0f); gfx_thumbnail_set_fade_duration(-1.0f);
gfx_thumbnail_set_fade_missing(false); gfx_thumbnail_set_fade_missing(false);