mirror of
https://github.com/libretro/RetroArch
synced 2025-02-06 18:40:49 +00:00
Add environment callback to get the rate retro_run is called (#13022)
* Add GET_THROTTLE_STATE environment callback * Add RETRO_THROTTLE_UNBLOCKED to report the case where neither vsync nor audio is limiting the call rate. Also fix reporting of some special cases when the menu is open. * Change throttle state mode to unsigned Use #defines Instead of the untyped C enum to allow easier future additions. * Spelling fixes * Avoid any divide-by-zero
This commit is contained in:
parent
e7f182811a
commit
a3d9201581
@ -1747,6 +1747,12 @@ enum retro_mod
|
||||
* to test whether the callback is supported.
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_GET_THROTTLE_STATE (71 | RETRO_ENVIRONMENT_EXPERIMENTAL)
|
||||
/* struct retro_throttle_state * --
|
||||
* Allows an implementation to get details on the actual rate
|
||||
* the frontend is attempting to call retro_run().
|
||||
*/
|
||||
|
||||
/* VFS functionality */
|
||||
|
||||
/* File paths:
|
||||
@ -3692,6 +3698,43 @@ struct retro_fastforwarding_override
|
||||
bool inhibit_toggle;
|
||||
};
|
||||
|
||||
/* During normal operation. Rate will be equal to the core's internal FPS. */
|
||||
#define RETRO_THROTTLE_NONE 0
|
||||
|
||||
/* While paused or stepping single frames. Rate will be 0. */
|
||||
#define RETRO_THROTTLE_FRAME_STEPPING 1
|
||||
|
||||
/* During fast forwarding.
|
||||
* Rate will be 0 if not specifically limited to a maximum speed. */
|
||||
#define RETRO_THROTTLE_FAST_FORWARD 2
|
||||
|
||||
/* During slow motion. Rate will be less than the core's internal FPS. */
|
||||
#define RETRO_THROTTLE_SLOW_MOTION 3
|
||||
|
||||
/* While rewinding recorded save states. Rate can vary depending on the rewind
|
||||
* speed or be 0 if the frontend is not aiming for a specific rate. */
|
||||
#define RETRO_THROTTLE_REWINDING 4
|
||||
|
||||
/* While vsync is active in the video driver and the target refresh rate is
|
||||
* lower than the core's internal FPS. Rate is the target refresh rate. */
|
||||
#define RETRO_THROTTLE_VSYNC 5
|
||||
|
||||
/* When the frontend does not throttle in any way. Rate will be 0.
|
||||
* An example could be if no vsync or audio output is active. */
|
||||
#define RETRO_THROTTLE_UNBLOCKED 6
|
||||
|
||||
struct retro_throttle_state
|
||||
{
|
||||
/* The current throttling mode. Should be one of the values above. */
|
||||
unsigned mode;
|
||||
|
||||
/* How many times per second the frontend aims to call retro_run.
|
||||
* Depending on the mode, it can be 0 if there is no known fixed rate.
|
||||
* This won't be accurate if the total processing time of the core and
|
||||
* the frontend is longer than what is available for one frame. */
|
||||
float rate;
|
||||
};
|
||||
|
||||
/* Callbacks */
|
||||
|
||||
/* Environment callback. Gives implementations a way of performing
|
||||
|
83
retroarch.c
83
retroarch.c
@ -11843,6 +11843,89 @@ static bool retroarch_environment_cb(unsigned cmd, void *data)
|
||||
break;
|
||||
}
|
||||
|
||||
case RETRO_ENVIRONMENT_GET_THROTTLE_STATE:
|
||||
{
|
||||
struct retro_throttle_state *throttle_state =
|
||||
(struct retro_throttle_state *)data;
|
||||
|
||||
bool menu_opened = false;
|
||||
bool core_paused = runloop_state.paused;
|
||||
bool no_audio = (p_rarch->audio_suspended || !p_rarch->audio_driver_active);
|
||||
float core_fps = (float)p_rarch->video_driver_av_info.timing.fps;
|
||||
|
||||
#ifdef HAVE_REWIND
|
||||
if (p_rarch->rewind_st.frame_is_reversed)
|
||||
{
|
||||
throttle_state->mode = RETRO_THROTTLE_REWINDING;
|
||||
throttle_state->rate = 0.0f;
|
||||
break; /* ignore vsync */
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
menu_opened = menu_state_get_ptr()->alive;
|
||||
if (menu_opened)
|
||||
core_paused = settings->bools.menu_pause_libretro;
|
||||
#endif
|
||||
|
||||
if (core_paused)
|
||||
{
|
||||
throttle_state->mode = RETRO_THROTTLE_FRAME_STEPPING;
|
||||
throttle_state->rate = 0.0f;
|
||||
break; /* ignore vsync */
|
||||
}
|
||||
|
||||
/* Base mode and rate. */
|
||||
throttle_state->mode = RETRO_THROTTLE_NONE;
|
||||
throttle_state->rate = core_fps;
|
||||
|
||||
if (runloop_state.fastmotion)
|
||||
{
|
||||
throttle_state->mode = RETRO_THROTTLE_FAST_FORWARD;
|
||||
throttle_state->rate *= retroarch_get_runloop_fastforward_ratio(
|
||||
settings, &runloop_state.fastmotion_override.current);
|
||||
}
|
||||
else if (runloop_state.slowmotion && !no_audio)
|
||||
{
|
||||
throttle_state->mode = RETRO_THROTTLE_SLOW_MOTION;
|
||||
throttle_state->rate /= (settings->floats.slowmotion_ratio > 0.0f ?
|
||||
settings->floats.slowmotion_ratio : 1.0f);
|
||||
}
|
||||
|
||||
/* VSync overrides the mode if the rate is limited by the display. */
|
||||
if (menu_opened || /* Menu currently always runs with vsync on. */
|
||||
(settings->bools.video_vsync && !runloop_state.force_nonblock
|
||||
&& !input_state_get_ptr()->nonblocking_flag))
|
||||
{
|
||||
float refresh_rate = video_driver_get_refresh_rate();
|
||||
if (refresh_rate == 0.0f)
|
||||
refresh_rate = settings->floats.video_refresh_rate;
|
||||
if (refresh_rate < throttle_state->rate || !throttle_state->rate)
|
||||
{
|
||||
/* Keep the mode as fast forward even if vsync limits it. */
|
||||
if (refresh_rate < core_fps)
|
||||
throttle_state->mode = RETRO_THROTTLE_VSYNC;
|
||||
throttle_state->rate = refresh_rate;
|
||||
}
|
||||
}
|
||||
|
||||
/* Special behavior while audio output is not available. */
|
||||
if (no_audio && throttle_state->mode != RETRO_THROTTLE_FAST_FORWARD
|
||||
&& throttle_state->mode != RETRO_THROTTLE_VSYNC)
|
||||
{
|
||||
/* Keep base if frame limiter matching the core is active. */
|
||||
retro_time_t core_limit = (core_fps ?
|
||||
(retro_time_t)(1000000.0f / core_fps) : (retro_time_t)0);
|
||||
retro_time_t frame_limit = p_rarch->frame_limit_minimum_time;
|
||||
if (abs((int)(core_limit - frame_limit)) > 10)
|
||||
{
|
||||
throttle_state->mode = RETRO_THROTTLE_UNBLOCKED;
|
||||
throttle_state->rate = 0.0f;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case RETRO_ENVIRONMENT_GET_INPUT_BITMASKS:
|
||||
/* Just falldown, the function will return true */
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user