From ac421ec19b2d101a466fa1f08c35e3c0135afde5 Mon Sep 17 00:00:00 2001 From: Mike Robinson Date: Thu, 28 Aug 2014 19:54:42 +0100 Subject: [PATCH] Implement frame delay option Sets how many milliseconds to delay after VSync before running the core. --- config.def.h | 4 ++++ frontend/menu/backend/menu_common_backend.c | 2 ++ general.h | 1 + retroarch.c | 3 +++ retroarch.cfg | 5 +++++ settings.c | 6 ++++++ settings_data.c | 14 ++++++++++++++ 7 files changed, 35 insertions(+) diff --git a/config.def.h b/config.def.h index 27258af4fb..d9b432e6b4 100644 --- a/config.def.h +++ b/config.def.h @@ -310,6 +310,10 @@ static const bool hard_sync = false; // 2: Etc ... static const unsigned hard_sync_frames = 0; +// Sets how many milliseconds to delay after VSync before running the core. +// Can reduce latency at cost of performance. +static const unsigned frame_delay = 0; + // Inserts a black frame inbetween frames. // Useful for 120 Hz monitors who want to play 60 Hz material with eliminated ghosting. video_refresh_rate should still be configured as if it is a 60 Hz monitor (divide refresh rate by 2). static bool black_frame_insertion = false; diff --git a/frontend/menu/backend/menu_common_backend.c b/frontend/menu/backend/menu_common_backend.c index 9c01affe75..80696b8874 100644 --- a/frontend/menu/backend/menu_common_backend.c +++ b/frontend/menu/backend/menu_common_backend.c @@ -210,6 +210,8 @@ static void menu_common_entries_init(menu_handle_t *menu, unsigned menu_type) 0, 0, setting_data); file_list_push(menu->selection_buf, "", "video_hard_sync_frames", 0, 0, setting_data); + file_list_push(menu->selection_buf, "", "video_frame_delay", + 0, 0, setting_data); if ((current_setting = (rarch_setting_t*)setting_data_find_setting(setting_data, "video_black_frame_insertion"))) file_list_push(menu->selection_buf, "", "video_black_frame_insertion", 0, 0, setting_data); diff --git a/general.h b/general.h index 14f11fa2b2..f661a68997 100644 --- a/general.h +++ b/general.h @@ -209,6 +209,7 @@ struct settings bool black_frame_insertion; unsigned swap_interval; unsigned hard_sync_frames; + unsigned frame_delay; #ifdef GEKKO unsigned viwidth; #endif diff --git a/retroarch.c b/retroarch.c index 9d012e10a9..230a947373 100644 --- a/retroarch.c +++ b/retroarch.c @@ -3443,6 +3443,9 @@ bool rarch_main_iterate(void) g_settings.input.analog_dpad_mode[i]); } + if ((g_settings.video.frame_delay > 0) && !driver.nonblock_state) + rarch_sleep(g_settings.video.frame_delay); + update_frame_time(); pretro_run(); limit_frame_time(); diff --git a/retroarch.cfg b/retroarch.cfg index 30103fbbd6..f3bc2657a8 100644 --- a/retroarch.cfg +++ b/retroarch.cfg @@ -127,6 +127,11 @@ # Maximum is 3. # video_hard_sync_frames = 0 +# Sets how many milliseconds to delay after VSync before running the core. +# Can reduce latency at cost of performance. +# Maximum is 15. +# video_frame_delay = 0 + # Inserts a black frame inbetween frames. # Useful for 120 Hz monitors who want to play 60 Hz material with eliminated ghosting. # video_refresh_rate should still be configured as if it is a 60 Hz monitor (divide refresh rate by 2). diff --git a/settings.c b/settings.c index e6a4bcb145..c6e176b7cf 100644 --- a/settings.c +++ b/settings.c @@ -287,6 +287,7 @@ void config_set_defaults(void) g_settings.video.vsync = vsync; g_settings.video.hard_sync = hard_sync; g_settings.video.hard_sync_frames = hard_sync_frames; + g_settings.video.frame_delay = frame_delay; g_settings.video.black_frame_insertion = black_frame_insertion; g_settings.video.swap_interval = swap_interval; g_settings.video.threaded = video_threaded; @@ -814,6 +815,10 @@ bool config_load_file(const char *path, bool set_defaults) if (g_settings.video.hard_sync_frames > 3) g_settings.video.hard_sync_frames = 3; + CONFIG_GET_INT(video.frame_delay, "video_frame_delay"); + if (g_settings.video.frame_delay > 15) + g_settings.video.frame_delay = 15; + CONFIG_GET_BOOL(video.black_frame_insertion, "video_black_frame_insertion"); CONFIG_GET_INT(video.swap_interval, "video_swap_interval"); g_settings.video.swap_interval = max(g_settings.video.swap_interval, 1); @@ -1356,6 +1361,7 @@ bool config_save_file(const char *path) config_set_bool(conf, "video_vsync", g_settings.video.vsync); config_set_bool(conf, "video_hard_sync", g_settings.video.hard_sync); config_set_int(conf, "video_hard_sync_frames", g_settings.video.hard_sync_frames); + config_set_int(conf, "video_frame_delay", g_settings.video.frame_delay); config_set_bool(conf, "video_black_frame_insertion", g_settings.video.black_frame_insertion); config_set_bool(conf, "video_disable_composition", g_settings.video.disable_composition); config_set_bool(conf, "pause_nonactive", g_settings.pause_nonactive); diff --git a/settings_data.c b/settings_data.c index 5a7dabc3df..5571bcc74c 100644 --- a/settings_data.c +++ b/settings_data.c @@ -863,6 +863,15 @@ void setting_data_get_description(const void *data, char *msg, " 0: Syncs to GPU immediately.\n" " 1: Syncs to previous frame.\n" " 2: Etc ..."); + else if (!strcmp(setting->name, "video_frame_delay")) + snprintf(msg, sizeof_msg, + " -- Sets how many milliseconds to delay \n" + "after VSync before running the core.\n" + " \n" + "Can reduce latency at cost of \n" + "performance." + " \n" + "Maximum is 15.\n"); else if (!strcmp(setting->name, "audio_rate_control_delta")) snprintf(msg, sizeof_msg, " -- Audio rate control.\n" @@ -1153,6 +1162,8 @@ static void general_read_handler(const void *data) *setting->value.boolean = g_settings.video.hard_sync; else if (!strcmp(setting->name, "video_hard_sync_frames")) *setting->value.unsigned_integer = g_settings.video.hard_sync_frames; + else if (!strcmp(setting->name, "video_frame_delay")) + *setting->value.unsigned_integer = g_settings.video.frame_delay; else if (!strcmp(setting->name, "video_scale_integer")) *setting->value.boolean = g_settings.video.scale_integer; else if (!strcmp(setting->name, "video_fullscreen")) @@ -1496,6 +1507,8 @@ static void general_write_handler(const void *data) g_settings.video.hard_sync = *setting->value.boolean; else if (!strcmp(setting->name, "video_hard_sync_frames")) g_settings.video.hard_sync_frames = *setting->value.unsigned_integer; + else if (!strcmp(setting->name, "video_frame_delay")) + g_settings.video.frame_delay = *setting->value.unsigned_integer; else if (!strcmp(setting->name, "video_scale_integer")) g_settings.video.scale_integer = *setting->value.boolean; else if (!strcmp(setting->name, "video_fullscreen")) @@ -2019,6 +2032,7 @@ rarch_setting_t *setting_data_get_list(void) CONFIG_UINT(g_settings.video.swap_interval, "video_swap_interval", "VSync Swap Interval", swap_interval, GROUP_NAME, SUBGROUP_NAME, general_write_handler, general_read_handler) WITH_RANGE(1, 4, 1, true, true) CONFIG_BOOL(g_settings.video.hard_sync, "video_hard_sync", "Hard GPU Sync", hard_sync, "OFF", "ON", GROUP_NAME, SUBGROUP_NAME, general_write_handler, general_read_handler) CONFIG_UINT(g_settings.video.hard_sync_frames, "video_hard_sync_frames", "Hard GPU Sync Frames", hard_sync_frames, GROUP_NAME, SUBGROUP_NAME, general_write_handler, general_read_handler) WITH_RANGE(0, 3, 1, true, true) + CONFIG_UINT(g_settings.video.frame_delay, "video_frame_delay", "Frame Delay", frame_delay, GROUP_NAME, SUBGROUP_NAME, general_write_handler, general_read_handler) WITH_RANGE(0, 15, 1, true, true) #if !defined(RARCH_MOBILE) CONFIG_BOOL(g_settings.video.black_frame_insertion, "video_black_frame_insertion", "Black Frame Insertion", black_frame_insertion, "OFF", "ON", GROUP_NAME, SUBGROUP_NAME, general_write_handler, general_read_handler) #endif