diff --git a/driver.c b/driver.c index 131146ece7..b419b41bc2 100644 --- a/driver.c +++ b/driver.c @@ -589,22 +589,17 @@ static void compute_audio_buffer_statistics(void) (100.0 * high_water_count) / (samples - 1)); } -static void compute_monitor_fps_statistics(void) +bool driver_monitor_fps_statistics(double *refresh_rate, double *deviation, unsigned *sample_points) { if (g_settings.video.threaded) { RARCH_LOG("Monitor FPS estimation is disabled for threaded video.\n"); - return; + return false; } - if (g_extern.measure_data.frame_time_samples_count < 2 * MEASURE_FRAME_TIME_SAMPLES_COUNT) - { - RARCH_LOG("Does not have enough samples for monitor refresh rate estimation. Requires to run for at least %u frames.\n", - 2 * MEASURE_FRAME_TIME_SAMPLES_COUNT); - return; - } - - unsigned samples = MEASURE_FRAME_TIME_SAMPLES_COUNT; + unsigned samples = min(MEASURE_FRAME_TIME_SAMPLES_COUNT, g_extern.measure_data.frame_time_samples_count); + if (samples < 2) + return false; // Measure statistics on frame time (microsecs), *not* FPS. rarch_time_t accum = 0; @@ -627,11 +622,30 @@ static void compute_monitor_fps_statistics(void) accum_var += diff * diff; } - double stddev = sqrt((double)accum_var / (samples - 1)); - double avg_fps = 1000000.0 / avg; + *deviation = sqrt((double)accum_var / (samples - 1)) / avg; + *refresh_rate = 1000000.0 / avg; + *sample_points = samples; - RARCH_LOG("Average monitor Hz: %.6f Hz. (%.3f %% frame time deviation, based on %u last samples).\n", - avg_fps, 100.0 * stddev / avg, samples); + return true; +} + +static void compute_monitor_fps_statistics(void) +{ + if (g_extern.measure_data.frame_time_samples_count < 2 * MEASURE_FRAME_TIME_SAMPLES_COUNT) + { + RARCH_LOG("Does not have enough samples for monitor refresh rate estimation. Requires to run for at least %u frames.\n", + 2 * MEASURE_FRAME_TIME_SAMPLES_COUNT); + return; + } + + double avg_fps = 0.0; + double stddev = 0.0; + unsigned samples = 0; + if (driver_monitor_fps_statistics(&avg_fps, &stddev, &samples)) + { + RARCH_LOG("Average monitor Hz: %.6f Hz. (%.3f %% frame time deviation, based on %u last samples).\n", + avg_fps, 100.0 * stddev, samples); + } } void uninit_audio(void) diff --git a/driver.h b/driver.h index aa9eb4f90d..2bd3c9c55d 100644 --- a/driver.h +++ b/driver.h @@ -473,6 +473,7 @@ void init_audio(void); void uninit_audio(void); void driver_set_monitor_refresh_rate(float hz); +bool driver_monitor_fps_statistics(double *refresh_rate, double *deviation, unsigned *sample_points); void driver_set_nonblock_state(bool nonblock); // Used by RETRO_ENVIRONMENT_SET_HW_RENDER. diff --git a/frontend/menu/menu_common.h b/frontend/menu/menu_common.h index 78fb443e86..ac748fe7df 100644 --- a/frontend/menu/menu_common.h +++ b/frontend/menu/menu_common.h @@ -118,6 +118,7 @@ typedef enum RGUI_SETTINGS_VIDEO_VSYNC, RGUI_SETTINGS_VIDEO_HARD_SYNC, RGUI_SETTINGS_VIDEO_HARD_SYNC_FRAMES, + RGUI_SETTINGS_VIDEO_REFRESH_RATE_AUTO, RGUI_SETTINGS_VIDEO_OPTIONS_LAST, #ifdef HAVE_SHADER_MANAGER RGUI_SETTINGS_SHADER_OPTIONS, diff --git a/frontend/menu/rgui.c b/frontend/menu/rgui.c index 5125965458..aec4e6d078 100644 --- a/frontend/menu/rgui.c +++ b/frontend/menu/rgui.c @@ -600,6 +600,17 @@ static void render_text(rgui_handle_t *rgui) case RGUI_SETTINGS_VIDEO_HARD_SYNC_FRAMES: snprintf(type_str, sizeof(type_str), "%u", g_settings.video.hard_sync_frames); break; + case RGUI_SETTINGS_VIDEO_REFRESH_RATE_AUTO: + { + double refresh_rate = 0.0; + double deviation = 0.0; + unsigned sample_points = 0; + if (driver_monitor_fps_statistics(&refresh_rate, &deviation, &sample_points)) + snprintf(type_str, sizeof(type_str), "%.3f Hz (%.1f%% dev, %u samples)", refresh_rate, 100.0 * deviation, sample_points); + else + strlcpy(type_str, "N/A", sizeof(type_str)); + break; + } case RGUI_SETTINGS_VIDEO_INTEGER_SCALE: strlcpy(type_str, g_settings.video.scale_integer ? "ON" : "OFF", sizeof(type_str)); break; @@ -1503,6 +1514,7 @@ static void rgui_settings_video_options_populate_entries(rgui_handle_t *rgui) rgui_list_push(rgui->selection_buf, "VSync", RGUI_SETTINGS_VIDEO_VSYNC, 0); rgui_list_push(rgui->selection_buf, "Hard GPU Sync", RGUI_SETTINGS_VIDEO_HARD_SYNC, 0); rgui_list_push(rgui->selection_buf, "Hard GPU Sync Frames", RGUI_SETTINGS_VIDEO_HARD_SYNC_FRAMES, 0); + rgui_list_push(rgui->selection_buf, "Estimated Monitor FPS", RGUI_SETTINGS_VIDEO_REFRESH_RATE_AUTO, 0); } #ifdef HAVE_SHADER_MANAGER @@ -1954,6 +1966,10 @@ static int video_option_toggle_setting(rgui_handle_t *rgui, unsigned setting, rg } break; + case RGUI_SETTINGS_VIDEO_REFRESH_RATE_AUTO: + // TODO: Add support for updating refresh rate from RGUI. + break; + default: break; } diff --git a/settings.c b/settings.c index 60650cfb76..6edfa94231 100644 --- a/settings.c +++ b/settings.c @@ -963,6 +963,10 @@ bool config_save_file(const char *path) config_set_float(conf, "video_aspect_ratio", g_settings.video.aspect_ratio); config_set_bool(conf, "video_scale_integer", g_settings.video.scale_integer); config_set_bool(conf, "video_smooth", g_settings.video.smooth); + + // TODO: Enable when rest of code is set up for this. + //config_set_float(conf, "video_refresh_rate", g_settings.video.refresh_rate); + 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);