diff --git a/gfx/video_driver.c b/gfx/video_driver.c index bf19a6bdc9..e77b309ec1 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -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; -} diff --git a/gfx/video_driver.h b/gfx/video_driver.h index 60e35a0639..d58a706379 100644 --- a/gfx/video_driver.h +++ b/gfx/video_driver.h @@ -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]; diff --git a/menu/menu_driver.c b/menu/menu_driver.c index ccfb312d0a..e926654046 100644 --- a/menu/menu_driver.c +++ b/menu/menu_driver.c @@ -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) diff --git a/menu/menu_setting.c b/menu/menu_setting.c index 69c2f09f8e..717124fc3a 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -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); diff --git a/retroarch.c b/retroarch.c index 5ad4880c69..a51039eeca 100644 --- a/retroarch.c +++ b/retroarch.c @@ -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 diff --git a/runloop.c b/runloop.c index 0f0ee5094c..daf6437cc9 100644 --- a/runloop.c +++ b/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); }