Add optional frame skipping when fast-forwarding (#13550)

This commit is contained in:
Tony 2022-01-26 19:30:33 +02:00 committed by GitHub
parent fa213a724f
commit 84f558db0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 73 additions and 8 deletions

View File

@ -1253,6 +1253,9 @@ static const bool savestate_thumbnail_enable = false;
/* Maximum fast forward ratio. */ /* Maximum fast forward ratio. */
#define DEFAULT_FASTFORWARD_RATIO 0.0 #define DEFAULT_FASTFORWARD_RATIO 0.0
/* Skip frames when fast forwarding. */
#define DEFAULT_FASTFORWARD_FRAMESKIP true
/* Enable runloop for variable refresh rate screens. Force x1 speed while handling fast forward too. */ /* Enable runloop for variable refresh rate screens. Force x1 speed while handling fast forward too. */
#define DEFAULT_VRR_RUNLOOP_ENABLE false #define DEFAULT_VRR_RUNLOOP_ENABLE false

View File

@ -1654,6 +1654,7 @@ static struct config_bool_setting *populate_settings_bool(
SETTING_BOOL("ui_menubar_enable", &settings->bools.ui_menubar_enable, true, DEFAULT_UI_MENUBAR_ENABLE, false); SETTING_BOOL("ui_menubar_enable", &settings->bools.ui_menubar_enable, true, DEFAULT_UI_MENUBAR_ENABLE, false);
SETTING_BOOL("suspend_screensaver_enable", &settings->bools.ui_suspend_screensaver_enable, true, true, false); SETTING_BOOL("suspend_screensaver_enable", &settings->bools.ui_suspend_screensaver_enable, true, true, false);
SETTING_BOOL("rewind_enable", &settings->bools.rewind_enable, true, DEFAULT_REWIND_ENABLE, false); SETTING_BOOL("rewind_enable", &settings->bools.rewind_enable, true, DEFAULT_REWIND_ENABLE, false);
SETTING_BOOL("fastforward_frameskip", &settings->bools.fastforward_frameskip, true, DEFAULT_FASTFORWARD_FRAMESKIP, false);
SETTING_BOOL("vrr_runloop_enable", &settings->bools.vrr_runloop_enable, true, DEFAULT_VRR_RUNLOOP_ENABLE, false); SETTING_BOOL("vrr_runloop_enable", &settings->bools.vrr_runloop_enable, true, DEFAULT_VRR_RUNLOOP_ENABLE, false);
SETTING_BOOL("apply_cheats_after_toggle", &settings->bools.apply_cheats_after_toggle, true, DEFAULT_APPLY_CHEATS_AFTER_TOGGLE, false); SETTING_BOOL("apply_cheats_after_toggle", &settings->bools.apply_cheats_after_toggle, true, DEFAULT_APPLY_CHEATS_AFTER_TOGGLE, false);
SETTING_BOOL("apply_cheats_after_load", &settings->bools.apply_cheats_after_load, true, DEFAULT_APPLY_CHEATS_AFTER_LOAD, false); SETTING_BOOL("apply_cheats_after_load", &settings->bools.apply_cheats_after_load, true, DEFAULT_APPLY_CHEATS_AFTER_LOAD, false);

View File

@ -834,6 +834,7 @@ typedef struct settings
bool history_list_enable; bool history_list_enable;
bool playlist_entry_rename; bool playlist_entry_rename;
bool rewind_enable; bool rewind_enable;
bool fastforward_frameskip;
bool vrr_runloop_enable; bool vrr_runloop_enable;
bool apply_cheats_after_toggle; bool apply_cheats_after_toggle;
bool apply_cheats_after_load; bool apply_cheats_after_load;

View File

@ -3579,6 +3579,7 @@ void video_driver_frame(const void *data, unsigned width,
const enum retro_pixel_format const enum retro_pixel_format
video_driver_pix_fmt = video_st->pix_fmt; video_driver_pix_fmt = video_st->pix_fmt;
bool runloop_idle = runloop_st->idle; bool runloop_idle = runloop_st->idle;
bool render_frame = !runloop_st->fastforward_frameskip_frames_current;
bool video_driver_active = video_st->active; bool video_driver_active = video_st->active;
#if defined(HAVE_GFX_WIDGETS) #if defined(HAVE_GFX_WIDGETS)
bool widgets_active = dispwidget_get_ptr()->active; bool widgets_active = dispwidget_get_ptr()->active;
@ -3617,6 +3618,11 @@ void video_driver_frame(const void *data, unsigned width,
video_driver_build_info(&video_info); video_driver_build_info(&video_info);
render_frame |= video_info.menu_is_alive;
if (!render_frame)
runloop_st->fastforward_frameskip_frames_current--;
/* Get the amount of frames per seconds. */ /* Get the amount of frames per seconds. */
if (video_st->frame_count) if (video_st->frame_count)
{ {
@ -3772,7 +3778,7 @@ void video_driver_frame(const void *data, unsigned width,
pitch, runloop_idle); pitch, runloop_idle);
#ifdef HAVE_VIDEO_FILTER #ifdef HAVE_VIDEO_FILTER
if (data && video_st->state_filter) if (render_frame && data && video_st->state_filter)
{ {
unsigned output_width = 0; unsigned output_width = 0;
unsigned output_height = 0; unsigned output_height = 0;
@ -3834,11 +3840,7 @@ void video_driver_frame(const void *data, unsigned width,
msg_entry.category, msg_entry.category,
msg_entry.prio, msg_entry.prio,
false, false,
#ifdef HAVE_MENU video_info.menu_is_alive
menu_state_get_ptr()->alive
#else
false
#endif
); );
} }
/* ...otherwise, just output message via /* ...otherwise, just output message via
@ -3858,7 +3860,7 @@ void video_driver_frame(const void *data, unsigned width,
} }
} }
if (video_info.statistics_show) if (render_frame && video_info.statistics_show)
{ {
audio_statistics_t audio_stats; audio_statistics_t audio_stats;
double stddev = 0.0; double stddev = 0.0;
@ -3920,13 +3922,17 @@ void video_driver_frame(const void *data, unsigned width,
/* TODO/FIXME - add OSD chat text here */ /* TODO/FIXME - add OSD chat text here */
} }
if (video_st->current_video && video_st->current_video->frame) if (render_frame && video_st->current_video && video_st->current_video->frame)
{
video_st->active = video_st->current_video->frame( video_st->active = video_st->current_video->frame(
video_st->data, data, width, height, video_st->data, data, width, height,
video_st->frame_count, (unsigned)pitch, video_st->frame_count, (unsigned)pitch,
video_info.menu_screensaver_active || video_info.notifications_hidden ? "" : video_driver_msg, video_info.menu_screensaver_active || video_info.notifications_hidden ? "" : video_driver_msg,
&video_info); &video_info);
runloop_st->fastforward_frameskip_frames_current = runloop_st->fastforward_frameskip_frames;
}
video_st->frame_count++; video_st->frame_count++;
/* Display the status text, with a higher priority. */ /* Display the status text, with a higher priority. */

View File

@ -1234,6 +1234,10 @@ MSG_HASH(
MENU_ENUM_LABEL_FASTFORWARD_RATIO, MENU_ENUM_LABEL_FASTFORWARD_RATIO,
"fastforward_ratio" "fastforward_ratio"
) )
MSG_HASH(
MENU_ENUM_LABEL_FASTFORWARD_FRAMESKIP,
"fastforward_frameskip"
)
MSG_HASH( MSG_HASH(
MENU_ENUM_LABEL_FILE_BROWSER_CORE, MENU_ENUM_LABEL_FILE_BROWSER_CORE,
"file_browser_core" "file_browser_core"

View File

@ -3460,6 +3460,14 @@ MSG_HASH(
MENU_ENUM_SUBLABEL_FASTFORWARD_RATIO, MENU_ENUM_SUBLABEL_FASTFORWARD_RATIO,
"The maximum rate at which content will be run when using fast-forward (e.g., 5.0x for 60 fps content = 300 fps cap). If set to 0.0x, fast-forward ratio is unlimited (no FPS cap)." "The maximum rate at which content will be run when using fast-forward (e.g., 5.0x for 60 fps content = 300 fps cap). If set to 0.0x, fast-forward ratio is unlimited (no FPS cap)."
) )
MSG_HASH(
MENU_ENUM_LABEL_VALUE_FASTFORWARD_FRAMESKIP,
"Fast-Forward Frameskip"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_FASTFORWARD_FRAMESKIP,
"Skip frames according to fast-forward rate. This conserves power and allows the use of 3rd party frame limiting."
)
MSG_HASH( MSG_HASH(
MENU_ENUM_LABEL_VALUE_SLOWMOTION_RATIO, MENU_ENUM_LABEL_VALUE_SLOWMOTION_RATIO,
"Slow-Motion Rate" "Slow-Motion Rate"

View File

@ -494,6 +494,7 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_gpu_record, MENU_
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_savestate_auto_index, MENU_ENUM_SUBLABEL_SAVESTATE_AUTO_INDEX) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_savestate_auto_index, MENU_ENUM_SUBLABEL_SAVESTATE_AUTO_INDEX)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_block_sram_overwrite, MENU_ENUM_SUBLABEL_BLOCK_SRAM_OVERWRITE) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_block_sram_overwrite, MENU_ENUM_SUBLABEL_BLOCK_SRAM_OVERWRITE)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_fastforward_ratio, MENU_ENUM_SUBLABEL_FASTFORWARD_RATIO) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_fastforward_ratio, MENU_ENUM_SUBLABEL_FASTFORWARD_RATIO)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_fastforward_frameskip, MENU_ENUM_SUBLABEL_FASTFORWARD_FRAMESKIP)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_vrr_runloop_enable, MENU_ENUM_SUBLABEL_VRR_RUNLOOP_ENABLE) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_vrr_runloop_enable, MENU_ENUM_SUBLABEL_VRR_RUNLOOP_ENABLE)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_slowmotion_ratio, MENU_ENUM_SUBLABEL_SLOWMOTION_RATIO) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_slowmotion_ratio, MENU_ENUM_SUBLABEL_SLOWMOTION_RATIO)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_run_ahead_enabled, MENU_ENUM_SUBLABEL_RUN_AHEAD_ENABLED) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_run_ahead_enabled, MENU_ENUM_SUBLABEL_RUN_AHEAD_ENABLED)
@ -3409,6 +3410,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
case MENU_ENUM_LABEL_FASTFORWARD_RATIO: case MENU_ENUM_LABEL_FASTFORWARD_RATIO:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_fastforward_ratio); BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_fastforward_ratio);
break; break;
case MENU_ENUM_LABEL_FASTFORWARD_FRAMESKIP:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_fastforward_frameskip);
break;
case MENU_ENUM_LABEL_VRR_RUNLOOP_ENABLE: case MENU_ENUM_LABEL_VRR_RUNLOOP_ENABLE:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_vrr_runloop_enable); BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_vrr_runloop_enable);
break; break;

View File

@ -9393,6 +9393,7 @@ unsigned menu_displaylist_build_list(
#endif #endif
{MENU_ENUM_LABEL_FRAME_TIME_COUNTER_SETTINGS, PARSE_ACTION}, {MENU_ENUM_LABEL_FRAME_TIME_COUNTER_SETTINGS, PARSE_ACTION},
{MENU_ENUM_LABEL_FASTFORWARD_RATIO, PARSE_ONLY_FLOAT}, {MENU_ENUM_LABEL_FASTFORWARD_RATIO, PARSE_ONLY_FLOAT},
{MENU_ENUM_LABEL_FASTFORWARD_FRAMESKIP, PARSE_ONLY_BOOL },
{MENU_ENUM_LABEL_SLOWMOTION_RATIO, PARSE_ONLY_FLOAT}, {MENU_ENUM_LABEL_SLOWMOTION_RATIO, PARSE_ONLY_FLOAT},
{MENU_ENUM_LABEL_VRR_RUNLOOP_ENABLE, PARSE_ONLY_BOOL }, {MENU_ENUM_LABEL_VRR_RUNLOOP_ENABLE, PARSE_ONLY_BOOL },
{MENU_ENUM_LABEL_MENU_THROTTLE_FRAMERATE, PARSE_ONLY_BOOL }, {MENU_ENUM_LABEL_MENU_THROTTLE_FRAMERATE, PARSE_ONLY_BOOL },

View File

@ -13950,6 +13950,22 @@ static bool setting_append_list(
MENU_SETTINGS_LIST_CURRENT_ADD_CMD(list, list_info, CMD_EVENT_SET_FRAME_LIMIT); MENU_SETTINGS_LIST_CURRENT_ADD_CMD(list, list_info, CMD_EVENT_SET_FRAME_LIMIT);
menu_settings_list_current_add_range(list, list_info, 0, 10, 1.0, true, true); menu_settings_list_current_add_range(list, list_info, 0, 10, 1.0, true, true);
CONFIG_BOOL(
list, list_info,
&settings->bools.fastforward_frameskip,
MENU_ENUM_LABEL_FASTFORWARD_FRAMESKIP,
MENU_ENUM_LABEL_VALUE_FASTFORWARD_FRAMESKIP,
DEFAULT_FASTFORWARD_FRAMESKIP,
MENU_ENUM_LABEL_VALUE_OFF,
MENU_ENUM_LABEL_VALUE_ON,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler,
SD_FLAG_NONE
);
CONFIG_BOOL( CONFIG_BOOL(
list, list_info, list, list_info,
&settings->bools.vrr_runloop_enable, &settings->bools.vrr_runloop_enable,

View File

@ -1993,6 +1993,7 @@ enum msg_hash_enums
MENU_LABEL(OVERLAY_CENTER_Y), MENU_LABEL(OVERLAY_CENTER_Y),
MENU_LABEL(FASTFORWARD_RATIO), MENU_LABEL(FASTFORWARD_RATIO),
MENU_LABEL(FASTFORWARD_FRAMESKIP),
MENU_LABEL(VRR_RUNLOOP_ENABLE), MENU_LABEL(VRR_RUNLOOP_ENABLE),
MENU_LABEL(REWIND_ENABLE), MENU_LABEL(REWIND_ENABLE),
MENU_LABEL(CHEAT_APPLY_AFTER_TOGGLE), MENU_LABEL(CHEAT_APPLY_AFTER_TOGGLE),

View File

@ -4910,6 +4910,22 @@ static bool core_unload_game(void)
return true; return true;
} }
static void runloop_apply_fastmotion_frameskip(runloop_state_t *runloop_st, settings_t *settings)
{
unsigned frames = 0;
if (runloop_st->fastmotion && settings->bools.fastforward_frameskip)
{
frames = (unsigned)settings->floats.fastforward_ratio;
/* Pick refresh rate as unlimited throttle rate */
frames = (!frames) ? (unsigned)roundf(settings->floats.video_refresh_rate) : frames;
/* Decrease one to represent skipped frames */
frames--;
}
runloop_st->fastforward_frameskip_frames_current = runloop_st->fastforward_frameskip_frames = frames;
}
static void runloop_apply_fastmotion_override(runloop_state_t *runloop_st, settings_t *settings) static void runloop_apply_fastmotion_override(runloop_state_t *runloop_st, settings_t *settings)
{ {
video_driver_state_t *video_st = video_state_get_ptr(); video_driver_state_t *video_st = video_state_get_ptr();
@ -4947,6 +4963,7 @@ static void runloop_apply_fastmotion_override(runloop_state_t *runloop_st, setti
if (!runloop_st->fastmotion) if (!runloop_st->fastmotion)
runloop_st->fastforward_after_frames = 1; runloop_st->fastforward_after_frames = 1;
runloop_apply_fastmotion_frameskip(runloop_st, settings);
driver_set_nonblock_state(); driver_set_nonblock_state();
/* Reset frame time counter when toggling /* Reset frame time counter when toggling
@ -7063,6 +7080,7 @@ static enum runloop_state_enum runloop_check_state(
runloop_st->fastmotion = true; runloop_st->fastmotion = true;
} }
runloop_apply_fastmotion_frameskip(runloop_st, settings);
driver_set_nonblock_state(); driver_set_nonblock_state();
/* Reset frame time counter when toggling /* Reset frame time counter when toggling

View File

@ -216,6 +216,8 @@ struct runloop
unsigned max_frames; unsigned max_frames;
unsigned audio_latency; unsigned audio_latency;
unsigned fastforward_after_frames; unsigned fastforward_after_frames;
unsigned fastforward_frameskip_frames;
unsigned fastforward_frameskip_frames_current;
unsigned perf_ptr_libretro; unsigned perf_ptr_libretro;
unsigned subsystem_current_count; unsigned subsystem_current_count;
unsigned entry_state_slot; unsigned entry_state_slot;