mirror of
https://github.com/libretro/RetroArch
synced 2025-03-29 22:20:21 +00:00
Automatic Frame Delay improvements (#14754)
This commit is contained in:
parent
1334bd0408
commit
05c3c0a552
@ -949,10 +949,8 @@ void recording_dump_frame(
|
||||
unsigned height, size_t pitch, bool is_idle)
|
||||
{
|
||||
struct record_video_data ffemu_data;
|
||||
video_driver_state_t
|
||||
*video_st = &video_driver_st;
|
||||
recording_state_t
|
||||
*record_st = recording_state_get_ptr();
|
||||
video_driver_state_t *video_st = &video_driver_st;
|
||||
recording_state_t *record_st = recording_state_get_ptr();
|
||||
|
||||
ffemu_data.data = data;
|
||||
ffemu_data.width = width;
|
||||
@ -1290,7 +1288,6 @@ bool video_display_server_get_flags(gfx_ctx_flags_t *flags)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool video_driver_is_threaded(void)
|
||||
{
|
||||
#ifdef HAVE_THREADS
|
||||
@ -2412,7 +2409,7 @@ bool video_driver_find_driver(
|
||||
RARCH_LOG_OUTPUT("Available %ss are:\n", prefix);
|
||||
for (d = 0; video_drivers[d]; d++)
|
||||
RARCH_LOG_OUTPUT("\t%s\n", video_drivers[d]->ident);
|
||||
RARCH_WARN("Going to default to first %s...\n", prefix);
|
||||
RARCH_WARN("Going to default to first %s..\n", prefix);
|
||||
}
|
||||
|
||||
if (!(video_st->current_video = (video_driver_t*)video_drivers[0]))
|
||||
@ -2687,7 +2684,7 @@ size_t video_driver_get_window_title(char *buf, unsigned len)
|
||||
void video_driver_build_info(video_frame_info_t *video_info)
|
||||
{
|
||||
video_viewport_t *custom_vp = NULL;
|
||||
runloop_state_t *runloop_st = runloop_state_get_ptr();
|
||||
runloop_state_t *runloop_st = runloop_state_get_ptr();
|
||||
settings_t *settings = config_get_ptr();
|
||||
video_driver_state_t *video_st = &video_driver_st;
|
||||
input_driver_state_t *input_st = input_state_get_ptr();
|
||||
@ -2699,7 +2696,7 @@ void video_driver_build_info(video_frame_info_t *video_info)
|
||||
#endif
|
||||
#ifdef HAVE_THREADS
|
||||
bool is_threaded =
|
||||
VIDEO_DRIVER_IS_THREADED_INTERNAL(video_st);
|
||||
VIDEO_DRIVER_IS_THREADED_INTERNAL(video_st);
|
||||
|
||||
VIDEO_DRIVER_THREADED_LOCK(video_st, is_threaded);
|
||||
#endif
|
||||
@ -2710,9 +2707,8 @@ void video_driver_build_info(video_frame_info_t *video_info)
|
||||
video_info->widgets_active = false;
|
||||
#endif
|
||||
#ifdef HAVE_MENU
|
||||
video_info->notifications_hidden =
|
||||
settings->bools.notification_show_when_menu_is_alive && !(menu_st->flags &
|
||||
MENU_ST_FLAG_ALIVE);
|
||||
video_info->notifications_hidden = settings->bools.notification_show_when_menu_is_alive
|
||||
&& !(menu_st->flags & MENU_ST_FLAG_ALIVE);
|
||||
#endif
|
||||
video_info->refresh_rate = settings->floats.video_refresh_rate;
|
||||
video_info->crt_switch_resolution = settings->uints.crt_switch_resolution;
|
||||
@ -2730,11 +2726,12 @@ void video_driver_build_info(video_frame_info_t *video_info)
|
||||
video_info->core_status_msg_show = runloop_st->core_status_msg.set;
|
||||
video_info->aspect_ratio_idx = settings->uints.video_aspect_ratio_idx;
|
||||
video_info->post_filter_record = settings->bools.video_post_filter_record;
|
||||
video_info->input_menu_swap_ok_cancel_buttons = settings->bools.input_menu_swap_ok_cancel_buttons;
|
||||
video_info->input_menu_swap_ok_cancel_buttons
|
||||
= settings->bools.input_menu_swap_ok_cancel_buttons;
|
||||
video_info->max_swapchain_images = settings->uints.video_max_swapchain_images;
|
||||
video_info->windowed_fullscreen = settings->bools.video_windowed_fullscreen;
|
||||
video_info->fullscreen = settings->bools.video_fullscreen
|
||||
|| (video_st->flags & VIDEO_FLAG_FORCE_FULLSCREEN);
|
||||
|| (video_st->flags & VIDEO_FLAG_FORCE_FULLSCREEN);
|
||||
video_info->menu_mouse_enable = settings->bools.menu_mouse_enable;
|
||||
video_info->monitor_index = settings->uints.video_monitor_index;
|
||||
|
||||
@ -2753,12 +2750,9 @@ void video_driver_build_info(video_frame_info_t *video_info)
|
||||
|
||||
#if defined(HAVE_GFX_WIDGETS)
|
||||
video_info->widgets_userdata = p_dispwidget;
|
||||
video_info->widgets_is_paused = video_st->flags &
|
||||
VIDEO_FLAG_WIDGETS_PAUSED;
|
||||
video_info->widgets_is_fast_forwarding = video_st->flags &
|
||||
VIDEO_FLAG_WIDGETS_FAST_FORWARD;
|
||||
video_info->widgets_is_rewinding = video_st->flags &
|
||||
VIDEO_FLAG_WIDGETS_REWINDING;
|
||||
video_info->widgets_is_paused = video_st->flags & VIDEO_FLAG_WIDGETS_PAUSED;
|
||||
video_info->widgets_is_fast_forwarding = video_st->flags & VIDEO_FLAG_WIDGETS_FAST_FORWARD;
|
||||
video_info->widgets_is_rewinding = video_st->flags & VIDEO_FLAG_WIDGETS_REWINDING;
|
||||
#else
|
||||
video_info->widgets_userdata = NULL;
|
||||
video_info->widgets_is_paused = false;
|
||||
@ -2769,21 +2763,18 @@ VIDEO_FLAG_WIDGETS_FAST_FORWARD;
|
||||
video_info->width = video_st->width;
|
||||
video_info->height = video_st->height;
|
||||
|
||||
video_info->use_rgba = video_st->flags &
|
||||
VIDEO_FLAG_USE_RGBA;
|
||||
video_info->use_rgba = video_st->flags & VIDEO_FLAG_USE_RGBA;
|
||||
video_info->hdr_enable = settings->bools.video_hdr_enable;
|
||||
|
||||
video_info->libretro_running = false;
|
||||
video_info->msg_bgcolor_enable =
|
||||
settings->bools.video_msg_bgcolor_enable;
|
||||
video_info->msg_bgcolor_enable = settings->bools.video_msg_bgcolor_enable;
|
||||
|
||||
video_info->fps_update_interval = settings->uints.fps_update_interval;
|
||||
video_info->memory_update_interval = settings->uints.memory_update_interval;
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
video_info->menu_is_alive = menu_st->flags & MENU_ST_FLAG_ALIVE;
|
||||
video_info->menu_screensaver_active = menu_st->flags &
|
||||
MENU_ST_FLAG_SCREENSAVER_ACTIVE;
|
||||
video_info->menu_screensaver_active = menu_st->flags & MENU_ST_FLAG_SCREENSAVER_ACTIVE;
|
||||
video_info->menu_footer_opacity = settings->floats.menu_footer_opacity;
|
||||
video_info->menu_header_opacity = settings->floats.menu_header_opacity;
|
||||
video_info->materialui_color_theme = settings->uints.menu_materialui_color_theme;
|
||||
@ -2793,18 +2784,12 @@ VIDEO_FLAG_WIDGETS_FAST_FORWARD;
|
||||
video_info->xmb_color_theme = settings->uints.menu_xmb_color_theme;
|
||||
video_info->timedate_enable = settings->bools.menu_timedate_enable;
|
||||
video_info->battery_level_enable = settings->bools.menu_battery_level_enable;
|
||||
video_info->xmb_shadows_enable =
|
||||
settings->bools.menu_xmb_shadows_enable;
|
||||
video_info->xmb_alpha_factor =
|
||||
settings->uints.menu_xmb_alpha_factor;
|
||||
video_info->menu_wallpaper_opacity =
|
||||
settings->floats.menu_wallpaper_opacity;
|
||||
video_info->menu_framebuffer_opacity =
|
||||
settings->floats.menu_framebuffer_opacity;
|
||||
video_info->xmb_shadows_enable = settings->bools.menu_xmb_shadows_enable;
|
||||
video_info->xmb_alpha_factor = settings->uints.menu_xmb_alpha_factor;
|
||||
video_info->menu_wallpaper_opacity = settings->floats.menu_wallpaper_opacity;
|
||||
video_info->menu_framebuffer_opacity = settings->floats.menu_framebuffer_opacity;
|
||||
video_info->overlay_behind_menu = settings->bools.input_overlay_behind_menu;
|
||||
|
||||
video_info->libretro_running = runloop_st->current_core.flags &
|
||||
RETRO_CORE_FLAG_GAME_LOADED;
|
||||
video_info->libretro_running = runloop_st->current_core.flags & RETRO_CORE_FLAG_GAME_LOADED;
|
||||
#else
|
||||
video_info->menu_is_alive = false;
|
||||
video_info->menu_screensaver_active = false;
|
||||
@ -2828,14 +2813,12 @@ RETRO_CORE_FLAG_GAME_LOADED;
|
||||
video_info->runloop_is_slowmotion = runloop_st->flags & RUNLOOP_FLAG_SLOWMOTION;
|
||||
video_info->fastforward_frameskip = settings->bools.fastforward_frameskip;
|
||||
|
||||
video_info->input_driver_nonblock_state = input_st ?
|
||||
(input_st->flags & INP_FLAG_NONBLOCKING) : false;
|
||||
video_info->input_driver_grab_mouse_state = (input_st->flags &
|
||||
INP_FLAG_GRAB_MOUSE_STATE);
|
||||
video_info->input_driver_nonblock_state = input_st
|
||||
? (input_st->flags & INP_FLAG_NONBLOCKING) : false;
|
||||
video_info->input_driver_grab_mouse_state = (input_st->flags & INP_FLAG_GRAB_MOUSE_STATE);
|
||||
video_info->disp_userdata = disp_get_ptr();
|
||||
|
||||
video_info->userdata =
|
||||
VIDEO_DRIVER_GET_PTR_INTERNAL(video_st);
|
||||
video_info->userdata = VIDEO_DRIVER_GET_PTR_INTERNAL(video_st);
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
VIDEO_DRIVER_THREADED_UNLOCK(video_st, is_threaded);
|
||||
@ -3139,7 +3122,7 @@ bool video_context_driver_set_flags(gfx_ctx_flags_t *flags)
|
||||
}
|
||||
|
||||
video_st->current_video_context.set_flags(
|
||||
video_st->context_data, flags->flags);
|
||||
video_st->context_data, flags->flags);
|
||||
return true;
|
||||
|
||||
}
|
||||
@ -3461,10 +3444,10 @@ bool video_driver_init_internal(bool *video_is_threaded, bool verbosity_enabled)
|
||||
|
||||
video.width = width;
|
||||
video.height = height;
|
||||
video.fullscreen = settings->bools.video_fullscreen ||
|
||||
(video_st->flags & VIDEO_FLAG_FORCE_FULLSCREEN);
|
||||
video.vsync = settings->bools.video_vsync &&
|
||||
(!(runloop_st->flags & RUNLOOP_FLAG_FORCE_NONBLOCK));
|
||||
video.fullscreen = settings->bools.video_fullscreen
|
||||
|| (video_st->flags & VIDEO_FLAG_FORCE_FULLSCREEN);
|
||||
video.vsync = settings->bools.video_vsync
|
||||
&& (!(runloop_st->flags & RUNLOOP_FLAG_FORCE_NONBLOCK));
|
||||
video.force_aspect = settings->bools.video_force_aspect;
|
||||
video.font_enable = settings->bools.video_font_enable;
|
||||
video.swap_interval = runloop_get_video_swap_interval(
|
||||
@ -3480,13 +3463,12 @@ bool video_driver_init_internal(bool *video_is_threaded, bool verbosity_enabled)
|
||||
video.font_size = settings->floats.video_font_size;
|
||||
video.path_font = settings->paths.path_font;
|
||||
#ifdef HAVE_VIDEO_FILTER
|
||||
video.rgb32 =
|
||||
video_st->state_filter
|
||||
? (video_st->flags & VIDEO_FLAG_STATE_OUT_RGB32)
|
||||
: (video_driver_pix_fmt == RETRO_PIXEL_FORMAT_XRGB8888);
|
||||
video.rgb32 = video_st->state_filter
|
||||
? (video_st->flags & VIDEO_FLAG_STATE_OUT_RGB32)
|
||||
: (video_driver_pix_fmt == RETRO_PIXEL_FORMAT_XRGB8888);
|
||||
#else
|
||||
video.rgb32 =
|
||||
(video_driver_pix_fmt == RETRO_PIXEL_FORMAT_XRGB8888);
|
||||
(video_driver_pix_fmt == RETRO_PIXEL_FORMAT_XRGB8888);
|
||||
#endif
|
||||
video.parent = 0;
|
||||
|
||||
@ -3499,19 +3481,17 @@ bool video_driver_init_internal(bool *video_is_threaded, bool verbosity_enabled)
|
||||
|
||||
tmp = input_state_get_ptr()->current_driver;
|
||||
/* Need to grab the "real" video driver interface on a reinit. */
|
||||
video_driver_find_driver(settings,
|
||||
"video driver", verbosity_enabled);
|
||||
video_driver_find_driver(settings, "video driver", verbosity_enabled);
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
video.is_threaded =
|
||||
VIDEO_DRIVER_IS_THREADED_INTERNAL(video_st);
|
||||
video.is_threaded = VIDEO_DRIVER_IS_THREADED_INTERNAL(video_st);
|
||||
*video_is_threaded = video.is_threaded;
|
||||
|
||||
if (video.is_threaded)
|
||||
{
|
||||
bool ret;
|
||||
/* Can't do hardware rendering with threaded driver currently. */
|
||||
RARCH_LOG("[Video]: Starting threaded video driver ...\n");
|
||||
RARCH_LOG("[Video]: Starting threaded video driver..\n");
|
||||
|
||||
ret = video_init_thread(
|
||||
(const video_driver_t**)&video_st->current_video,
|
||||
@ -3522,7 +3502,7 @@ VIDEO_DRIVER_IS_THREADED_INTERNAL(video_st);
|
||||
video);
|
||||
if (!ret)
|
||||
{
|
||||
RARCH_ERR("[Video]: Cannot open threaded video driver ... Exiting ...\n");
|
||||
RARCH_ERR("[Video]: Cannot open threaded video driver.. Exiting..\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -3535,7 +3515,7 @@ VIDEO_DRIVER_IS_THREADED_INTERNAL(video_st);
|
||||
|
||||
if (!video_st->data)
|
||||
{
|
||||
RARCH_ERR("[Video]: Cannot open video driver ... Exiting ...\n");
|
||||
RARCH_ERR("[Video]: Cannot open video driver.. Exiting..\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3784,15 +3764,15 @@ void video_driver_frame(const void *data, unsigned width,
|
||||
status_text[buf_pos+3] = ' ';
|
||||
status_text[buf_pos+4] = '\0';
|
||||
}
|
||||
buf_pos = strlcat(status_text, msg_hash_to_str(MSG_FRAMES),
|
||||
sizeof(status_text));
|
||||
buf_pos = strlcat(status_text,
|
||||
msg_hash_to_str(MSG_FRAMES),
|
||||
sizeof(status_text));
|
||||
status_text[buf_pos ] = ':';
|
||||
status_text[++buf_pos] = ' ';
|
||||
status_text[++buf_pos] = '\0';
|
||||
buf_pos += snprintf(
|
||||
status_text + buf_pos,
|
||||
sizeof(status_text) - buf_pos,
|
||||
"%" PRIu64, (uint64_t)video_st->frame_count);
|
||||
buf_pos += snprintf(status_text + buf_pos,
|
||||
sizeof(status_text) - buf_pos,
|
||||
"%" PRIu64, (uint64_t)video_st->frame_count);
|
||||
}
|
||||
|
||||
if (video_info.memory_show)
|
||||
@ -4189,43 +4169,52 @@ void video_driver_reinit(int flags)
|
||||
settings_t *settings = config_get_ptr();
|
||||
video_driver_state_t *video_st = &video_driver_st;
|
||||
struct retro_hw_render_callback *hwr =
|
||||
VIDEO_DRIVER_GET_HW_CONTEXT_INTERNAL(video_st);
|
||||
VIDEO_DRIVER_GET_HW_CONTEXT_INTERNAL(video_st);
|
||||
if (hwr->cache_context != false)
|
||||
video_st->flags |= VIDEO_FLAG_CACHE_CONTEXT;
|
||||
video_st->flags |= VIDEO_FLAG_CACHE_CONTEXT;
|
||||
else
|
||||
video_st->flags &= ~VIDEO_FLAG_CACHE_CONTEXT;
|
||||
video_st->flags &= ~VIDEO_FLAG_CACHE_CONTEXT;
|
||||
video_st->flags &= ~VIDEO_FLAG_CACHE_CONTEXT_ACK;
|
||||
video_driver_reinit_context(settings, flags);
|
||||
video_st->flags &= ~VIDEO_FLAG_CACHE_CONTEXT;
|
||||
}
|
||||
|
||||
uint32_t video_driver_get_st_flags(void)
|
||||
{
|
||||
video_driver_state_t *video_st = &video_driver_st;
|
||||
return video_st->flags;
|
||||
}
|
||||
|
||||
#define FRAME_DELAY_AUTO_DEBUG 0
|
||||
void video_frame_delay_auto(video_driver_state_t *video_st, video_frame_delay_auto_t *vfda)
|
||||
{
|
||||
unsigned i = 0;
|
||||
unsigned frame_time = 0;
|
||||
unsigned frame_time_frames = vfda->frame_time_interval;
|
||||
unsigned frame_time_target = 1000000.0f / vfda->refresh_rate;
|
||||
unsigned frame_time_limit_min = frame_time_target * 1.30f;
|
||||
unsigned frame_time_limit_med = frame_time_target * 1.50f;
|
||||
unsigned frame_time_limit_max = frame_time_target * 1.90f;
|
||||
unsigned frame_time_limit_cap = frame_time_target * 3.00f;
|
||||
unsigned frame_time_limit_ign = frame_time_target * 3.50f;
|
||||
retro_time_t frame_time_min = frame_time_target;
|
||||
retro_time_t frame_time_max = frame_time_target;
|
||||
unsigned frame_time_count_pos = 0;
|
||||
unsigned frame_time_count_min = 0;
|
||||
unsigned frame_time_count_med = 0;
|
||||
unsigned frame_time_count_max = 0;
|
||||
unsigned frame_time_count_ign = 0;
|
||||
unsigned frame_time_index =
|
||||
(video_st->frame_time_count &
|
||||
(MEASURE_FRAME_TIME_SAMPLES_COUNT - 1));
|
||||
uint32_t frame_time_average = 0;
|
||||
uint32_t frame_time_delta = 0;
|
||||
uint32_t frame_time_min = 0;
|
||||
uint32_t frame_time_max = 0;
|
||||
uint16_t frame_time_index = (video_st->frame_time_count & (MEASURE_FRAME_TIME_SAMPLES_COUNT - 1));
|
||||
uint16_t frame_time_target = 1000000.0f / vfda->refresh_rate;
|
||||
uint16_t frame_time_limit_mar = frame_time_target * 1.15f;
|
||||
uint16_t frame_time_limit_min = frame_time_target * 1.30f;
|
||||
uint16_t frame_time_limit_med = frame_time_target * 1.50f;
|
||||
uint16_t frame_time_limit_max = frame_time_target * 1.85f;
|
||||
uint16_t frame_time_limit_cap = frame_time_target * 3.00f;
|
||||
uint16_t frame_time_limit_ign = frame_time_target * 3.25f;
|
||||
uint8_t frame_time_frames = vfda->frame_time_interval;
|
||||
uint8_t frame_time_count_pos = 0;
|
||||
uint8_t frame_time_count_min = 0;
|
||||
uint8_t frame_time_count_med = 0;
|
||||
uint8_t frame_time_count_max = 0;
|
||||
uint8_t frame_time_count_ign = 0;
|
||||
uint8_t i = 0;
|
||||
|
||||
/* Initialize min & max to target */
|
||||
frame_time_min = frame_time_max = frame_time_target;
|
||||
|
||||
/* Calculate average frame time */
|
||||
for (i = 1; i < frame_time_frames + 1; i++)
|
||||
{
|
||||
retro_time_t frame_time_i = 0;
|
||||
uint32_t frame_time_i = 0;
|
||||
|
||||
if (i > frame_time_index)
|
||||
continue;
|
||||
@ -4255,25 +4244,26 @@ void video_frame_delay_auto(video_driver_state_t *video_st, video_frame_delay_au
|
||||
frame_time_i = frame_time_limit_cap;
|
||||
}
|
||||
|
||||
frame_time += frame_time_i;
|
||||
frame_time_average += frame_time_i;
|
||||
}
|
||||
|
||||
frame_time /= frame_time_frames;
|
||||
frame_time_average /= frame_time_frames;
|
||||
frame_time_delta = frame_time_max - frame_time_min;
|
||||
|
||||
/* Ignore values when core is doing internal frame skipping */
|
||||
if (frame_time_count_ign > 0)
|
||||
frame_time = 0;
|
||||
frame_time_average = frame_time_target;
|
||||
|
||||
/* Special handlings for different video driver frame timings */
|
||||
if (frame_time < frame_time_limit_med && frame_time > frame_time_target)
|
||||
if ( ( frame_time_average > frame_time_target
|
||||
&& frame_time_average < frame_time_limit_med)
|
||||
|| (frame_time_delta > frame_time_limit_max))
|
||||
{
|
||||
retro_time_t frame_time_frames_half = frame_time_frames / 2;
|
||||
retro_time_t frame_time_delta = frame_time_max - frame_time_min;
|
||||
|
||||
uint8_t frame_time_frames_half = frame_time_frames / 2;
|
||||
/* Ensure outcome on certain conditions */
|
||||
int mode = 0;
|
||||
int8_t mode = 0;
|
||||
|
||||
/* All frames are above the target */
|
||||
/* All interval frames are above the target */
|
||||
if (frame_time_count_pos == frame_time_frames)
|
||||
mode = 1;
|
||||
/* At least half of interval frames are above minimum level */
|
||||
@ -4281,27 +4271,30 @@ void video_frame_delay_auto(video_driver_state_t *video_st, video_frame_delay_au
|
||||
mode = 2;
|
||||
/* D3Dx stripe equalizer */
|
||||
else if (
|
||||
frame_time_count_pos == frame_time_frames_half
|
||||
&& ((
|
||||
( frame_time_count_min > 1
|
||||
|| frame_time_count_med > 0)
|
||||
&& frame_time_delta > (frame_time_target / 3)
|
||||
&& frame_time_delta < (frame_time_target / 2)
|
||||
)
|
||||
|| (frame_time_count_min > 2)
|
||||
)
|
||||
&& frame_time > frame_time_target
|
||||
(frame_time_count_pos == frame_time_frames_half)
|
||||
&& ( frame_time_count_min > 0
|
||||
|| frame_time_count_med > 0)
|
||||
&& (frame_time_delta > frame_time_target / 2.50f)
|
||||
)
|
||||
mode = 3;
|
||||
/* Boost med/max spikes */
|
||||
else if (
|
||||
( frame_time_count_pos >= frame_time_frames_half)
|
||||
&& ( frame_time_count_max > 0
|
||||
|| frame_time_count_med > 1)
|
||||
&& ( frame_time_count_max == frame_time_count_med)
|
||||
&& ( frame_time_delta < frame_time_target)
|
||||
(frame_time_count_pos > frame_time_frames_half)
|
||||
&& ( frame_time_count_med > 1
|
||||
|| frame_time_count_max > 0)
|
||||
&& (frame_time_average > frame_time_limit_mar)
|
||||
&& (frame_time_delta < frame_time_limit_min)
|
||||
)
|
||||
mode = 4;
|
||||
/* Boost min/med spikes */
|
||||
else if (
|
||||
(frame_time_count_pos >= frame_time_frames_half)
|
||||
&& ( frame_time_count_min > 1
|
||||
|| frame_time_count_med > 0)
|
||||
&& (frame_time_count_max == 0)
|
||||
&& (frame_time_average > frame_time_limit_mar)
|
||||
)
|
||||
mode = 5;
|
||||
/* Ignore */
|
||||
else if (
|
||||
(frame_time_delta > frame_time_target)
|
||||
@ -4309,49 +4302,52 @@ void video_frame_delay_auto(video_driver_state_t *video_st, video_frame_delay_au
|
||||
)
|
||||
mode = -1;
|
||||
|
||||
if (mode > 0)
|
||||
if (mode > 0 && frame_time_average < frame_time_limit_med)
|
||||
{
|
||||
#if FRAME_DELAY_AUTO_DEBUG
|
||||
RARCH_LOG("[Video]: Frame delay nudge %d by mode %d.\n", frame_time, mode);
|
||||
RARCH_LOG("[Video]: Frame delay nudge %d by mode %d.\n", frame_time_average, mode);
|
||||
#endif
|
||||
frame_time = frame_time_limit_med;
|
||||
frame_time_average = frame_time_limit_med;
|
||||
}
|
||||
else if (mode < 0)
|
||||
{
|
||||
#if FRAME_DELAY_AUTO_DEBUG
|
||||
RARCH_LOG("[Video]: Frame delay ignore %d.\n", frame_time);
|
||||
RARCH_LOG("[Video]: Frame delay ignore %d.\n", frame_time_average);
|
||||
#endif
|
||||
frame_time = 0;
|
||||
frame_time_average = frame_time_target;
|
||||
}
|
||||
}
|
||||
|
||||
/* Final output decision */
|
||||
if (frame_time > frame_time_limit_min)
|
||||
if (frame_time_average > frame_time_limit_min)
|
||||
{
|
||||
unsigned delay_decrease = 1;
|
||||
uint8_t delay_decrease = 1;
|
||||
|
||||
/* Increase decrease the more frame time is off target */
|
||||
if (frame_time > frame_time_limit_med && video_st->frame_delay_effective > delay_decrease)
|
||||
if ( frame_time_average > frame_time_limit_med
|
||||
&& video_st->frame_delay_effective > delay_decrease)
|
||||
{
|
||||
delay_decrease++;
|
||||
if (frame_time > frame_time_limit_max && video_st->frame_delay_effective > delay_decrease)
|
||||
if ( frame_time_average > frame_time_limit_max
|
||||
&& video_st->frame_delay_effective > delay_decrease)
|
||||
delay_decrease++;
|
||||
}
|
||||
|
||||
vfda->decrease = delay_decrease;
|
||||
vfda->delay_decrease = delay_decrease;
|
||||
}
|
||||
|
||||
vfda->time = frame_time;
|
||||
vfda->target = frame_time_target;
|
||||
vfda->frame_time_average = frame_time_average;
|
||||
vfda->frame_time_target = frame_time_target;
|
||||
|
||||
#if FRAME_DELAY_AUTO_DEBUG
|
||||
if (frame_time_index > frame_time_frames)
|
||||
RARCH_LOG("[Video]: %5d / pos:%d min:%d med:%d max:%d / delta:%5d = %5d %5d %5d %5d %5d %5d %5d %5d\n",
|
||||
frame_time,
|
||||
RARCH_LOG("[Video]: %5d / pos:%d min:%d med:%d max:%d ign:%d / delta:%5d = %5d %5d %5d %5d %5d %5d %5d %5d\n",
|
||||
frame_time_average,
|
||||
frame_time_count_pos,
|
||||
frame_time_count_min,
|
||||
frame_time_count_med,
|
||||
frame_time_count_max,
|
||||
frame_time_count_ign,
|
||||
frame_time_max - frame_time_min,
|
||||
video_st->frame_time_samples[frame_time_index - 1],
|
||||
video_st->frame_time_samples[frame_time_index - 2],
|
||||
@ -4364,9 +4360,3 @@ void video_frame_delay_auto(video_driver_state_t *video_st, video_frame_delay_au
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t video_driver_get_st_flags(void)
|
||||
{
|
||||
video_driver_state_t *video_st = &video_driver_st;
|
||||
return video_st->flags;
|
||||
}
|
||||
|
@ -912,8 +912,6 @@ typedef struct
|
||||
unsigned state_scale;
|
||||
unsigned state_out_bpp;
|
||||
#endif
|
||||
unsigned frame_delay_target;
|
||||
unsigned frame_delay_effective;
|
||||
unsigned frame_cache_width;
|
||||
unsigned frame_cache_height;
|
||||
unsigned width;
|
||||
@ -946,15 +944,19 @@ typedef struct
|
||||
char title_buf[64];
|
||||
char cached_driver_id[32];
|
||||
|
||||
uint8_t frame_delay_target;
|
||||
uint8_t frame_delay_effective;
|
||||
bool frame_delay_pause;
|
||||
|
||||
bool threaded;
|
||||
} video_driver_state_t;
|
||||
|
||||
typedef struct video_frame_delay_auto {
|
||||
float refresh_rate;
|
||||
unsigned frame_time_interval;
|
||||
unsigned decrease;
|
||||
unsigned target;
|
||||
unsigned time;
|
||||
uint16_t frame_time_target;
|
||||
uint16_t frame_time_average;
|
||||
uint8_t frame_time_interval;
|
||||
uint8_t delay_decrease;
|
||||
} video_frame_delay_auto_t;
|
||||
|
||||
extern struct aspect_ratio_elem aspectratio_lut[ASPECT_RATIO_END];
|
||||
|
@ -6969,6 +6969,10 @@ void retroarch_menu_running_finished(bool quit)
|
||||
if (settings && settings->bools.input_overlay_hide_in_menu)
|
||||
input_overlay_init();
|
||||
#endif
|
||||
|
||||
/* Ignore frame delay target temporarily */
|
||||
if (settings->bools.video_frame_delay_auto)
|
||||
video_st->frame_delay_pause = true;
|
||||
}
|
||||
|
||||
bool menu_driver_ctl(enum rarch_menu_ctl_state state, void *data)
|
||||
|
@ -6371,23 +6371,42 @@ static void setting_get_string_representation_video_frame_delay(rarch_setting_t
|
||||
char *s, size_t len)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
video_driver_state_t *video_st = video_state_get_ptr();
|
||||
|
||||
if (!setting)
|
||||
return;
|
||||
|
||||
if (settings && settings->bools.video_frame_delay_auto)
|
||||
{
|
||||
video_driver_state_t *video_st = video_state_get_ptr();
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
file_list_t *menu_stack = MENU_LIST_GET(menu_st->entries.list, 0);
|
||||
const char *label = NULL;
|
||||
|
||||
if (menu_stack && menu_stack->size)
|
||||
label = menu_stack->list[menu_stack->size - 1].label;
|
||||
|
||||
if (*setting->value.target.unsigned_integer == 0)
|
||||
snprintf(s, len, "%s (%u %s)",
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_FRAME_DELAY_AUTOMATIC),
|
||||
video_st->frame_delay_effective,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_FRAME_DELAY_EFFECTIVE));
|
||||
{
|
||||
if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST)))
|
||||
snprintf(s, len, "%s",
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_FRAME_DELAY_AUTOMATIC));
|
||||
else
|
||||
snprintf(s, len, "%s (%u %s)",
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_FRAME_DELAY_AUTOMATIC),
|
||||
video_st->frame_delay_effective,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_FRAME_DELAY_EFFECTIVE));
|
||||
}
|
||||
else
|
||||
snprintf(s, len, "%u (%u %s)",
|
||||
*setting->value.target.unsigned_integer,
|
||||
video_st->frame_delay_effective,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_FRAME_DELAY_EFFECTIVE));
|
||||
{
|
||||
if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_DROPDOWN_BOX_LIST)))
|
||||
snprintf(s, len, "%u",
|
||||
*setting->value.target.unsigned_integer);
|
||||
else
|
||||
snprintf(s, len, "%u (%u %s)",
|
||||
*setting->value.target.unsigned_integer,
|
||||
video_st->frame_delay_effective,
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_FRAME_DELAY_EFFECTIVE));
|
||||
}
|
||||
}
|
||||
else
|
||||
snprintf(s, len, "%u", *setting->value.target.unsigned_integer);
|
||||
|
@ -2000,6 +2000,11 @@ bool command_event(enum event_command cmd, void *data)
|
||||
case CMD_EVENT_REINIT:
|
||||
command_event_reinit(
|
||||
data ? *(const int*)data : DRIVERS_CMD_ALL);
|
||||
|
||||
/* Recalibrate frame delay target */
|
||||
if (settings->bools.video_frame_delay_auto)
|
||||
video_st->frame_delay_target = 0;
|
||||
|
||||
break;
|
||||
case CMD_EVENT_CHEATS_APPLY:
|
||||
#ifdef HAVE_CHEATS
|
||||
|
81
runloop.c
81
runloop.c
@ -2665,9 +2665,15 @@ bool runloop_environment_cb(unsigned cmd, void *data)
|
||||
if (video_fullscreen)
|
||||
video_driver_hide_mouse();
|
||||
|
||||
/* Recalibrate frame delay target */
|
||||
/* Recalibrate frame delay target when video reinits
|
||||
* and pause frame delay when video does not reinit */
|
||||
if (settings->bools.video_frame_delay_auto)
|
||||
video_st->frame_delay_target = 0;
|
||||
{
|
||||
if (no_video_reinit)
|
||||
video_st->frame_delay_pause = true;
|
||||
else
|
||||
video_st->frame_delay_target = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -2874,6 +2880,10 @@ bool runloop_environment_cb(unsigned cmd, void *data)
|
||||
* using core-dependent aspect ratios. */
|
||||
video_driver_set_aspect_ratio();
|
||||
|
||||
/* Ignore frame delay target temporarily */
|
||||
if (settings->bools.video_frame_delay_auto)
|
||||
video_st->frame_delay_pause = true;
|
||||
|
||||
/* TODO: Figure out what to do, if anything, with
|
||||
recording. */
|
||||
}
|
||||
@ -7891,50 +7901,66 @@ int runloop_iterate(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (!(input_st->flags & INP_FLAG_NONBLOCKING))
|
||||
/* Frame delay */
|
||||
if ( !(input_st->flags & INP_FLAG_NONBLOCKING)
|
||||
|| (runloop_st->flags & RUNLOOP_FLAG_FASTMOTION))
|
||||
{
|
||||
bool skip_delay = core_paused
|
||||
|| (runloop_st->flags & RUNLOOP_FLAG_SLOWMOTION)
|
||||
|| (runloop_st->flags & RUNLOOP_FLAG_FASTMOTION);
|
||||
|
||||
if (settings->bools.video_frame_delay_auto)
|
||||
{
|
||||
static bool slowmotion_prev = false;
|
||||
static unsigned skip_frames = 0;
|
||||
float refresh_rate = settings->floats.video_refresh_rate;
|
||||
unsigned video_swap_interval = runloop_get_video_swap_interval(
|
||||
float refresh_rate = settings->floats.video_refresh_rate;
|
||||
uint8_t video_swap_interval = runloop_get_video_swap_interval(
|
||||
settings->uints.video_swap_interval);
|
||||
unsigned video_bfi = settings->uints.video_black_frame_insertion;
|
||||
unsigned frame_time_interval = 8;
|
||||
bool frame_time_update =
|
||||
/* Skip some starting frames for stabilization */
|
||||
uint8_t video_bfi = settings->uints.video_black_frame_insertion;
|
||||
uint8_t frame_time_interval = 8;
|
||||
static uint8_t skip_update = 0;
|
||||
static bool skip_delay_prev = false;
|
||||
bool frame_time_update =
|
||||
/* Skip some initial frames for stabilization */
|
||||
video_st->frame_count > frame_time_interval &&
|
||||
/* Only update when there are enough frames for averaging */
|
||||
video_st->frame_count % frame_time_interval == 0;
|
||||
|
||||
/* A few frames need to get ignored after slowmotion is disabled */
|
||||
if (!(runloop_st->flags & RUNLOOP_FLAG_SLOWMOTION) && slowmotion_prev)
|
||||
skip_frames = frame_time_interval * 2;
|
||||
/* A few frames must be ignored after slow+fastmotion/pause
|
||||
* is disabled or geometry change is triggered */
|
||||
if ( (!skip_delay && skip_delay_prev)
|
||||
|| video_st->frame_delay_pause)
|
||||
{
|
||||
skip_update = frame_time_interval * 4;
|
||||
video_st->frame_delay_pause = false;
|
||||
}
|
||||
|
||||
if (skip_frames)
|
||||
skip_frames--;
|
||||
if (skip_update)
|
||||
skip_update--;
|
||||
|
||||
slowmotion_prev = runloop_st->flags & RUNLOOP_FLAG_SLOWMOTION;
|
||||
/* Always skip when slowmotion is active */
|
||||
if (slowmotion_prev)
|
||||
skip_frames = 1;
|
||||
skip_delay_prev = skip_delay;
|
||||
|
||||
if (skip_frames)
|
||||
/* Always skip when slow+fastmotion/pause is active */
|
||||
if (skip_delay_prev)
|
||||
skip_update = 1;
|
||||
|
||||
if (skip_update)
|
||||
frame_time_update = false;
|
||||
|
||||
/* Black frame insertion + swap interval multiplier */
|
||||
refresh_rate = (refresh_rate / (video_bfi + 1.0f) / video_swap_interval);
|
||||
|
||||
/* Set target moderately as half frame time with 0 delay */
|
||||
/* Set target moderately as half frame time with 0 (Auto) delay */
|
||||
if (video_frame_delay == 0)
|
||||
video_frame_delay = 1 / refresh_rate * 1000 / 2;
|
||||
|
||||
/* Reset new desired delay target */
|
||||
if (video_st->frame_delay_target != video_frame_delay)
|
||||
{
|
||||
frame_time_update = false;
|
||||
video_st->frame_delay_target = video_frame_delay_effective = video_frame_delay;
|
||||
RARCH_LOG("[Video]: Frame delay reset to %d ms.\n", video_frame_delay);
|
||||
}
|
||||
|
||||
/* Decide what should happen to effective delay */
|
||||
if (video_frame_delay_effective > 0 && frame_time_update)
|
||||
{
|
||||
video_frame_delay_auto_t vfda = {0};
|
||||
@ -7942,11 +7968,11 @@ int runloop_iterate(void)
|
||||
vfda.refresh_rate = refresh_rate;
|
||||
|
||||
video_frame_delay_auto(video_st, &vfda);
|
||||
if (vfda.decrease > 0)
|
||||
if (vfda.delay_decrease > 0)
|
||||
{
|
||||
video_frame_delay_effective -= vfda.decrease;
|
||||
RARCH_LOG("[Video]: Frame delay decrease by %d ms to %d ms due to frame time: %d > %d.\n",
|
||||
vfda.decrease, video_frame_delay_effective, vfda.time, vfda.target);
|
||||
video_frame_delay_effective -= vfda.delay_decrease;
|
||||
RARCH_LOG("[Video]: Frame delay decrease by %d ms to %d ms due to frame time average: %d > %d.\n",
|
||||
vfda.delay_decrease, video_frame_delay_effective, vfda.frame_time_average, vfda.frame_time_target);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7955,7 +7981,8 @@ int runloop_iterate(void)
|
||||
|
||||
video_st->frame_delay_effective = video_frame_delay_effective;
|
||||
|
||||
if (video_frame_delay_effective > 0)
|
||||
/* Never apply frame delay when slow+fastmotion/pause is active */
|
||||
if (video_frame_delay_effective > 0 && !skip_delay)
|
||||
retro_sleep(video_frame_delay_effective);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user