Gtk: Add setting to configure for VRR automatically.

Swaps to ideal config for VRR in fullscreen. Switches sound
input rate and frame rate to exact SNES rate and uses timers for
sync.
This commit is contained in:
BearOso 2023-03-01 16:41:58 -06:00
parent a6560f70b5
commit 1434dce671
18 changed files with 69 additions and 18 deletions

View File

@ -234,6 +234,7 @@ int Snes9xConfig::save_config_file()
outint("NumberOfThreads", num_threads); outint("NumberOfThreads", num_threads);
outstring("HardwareAcceleration", display_driver, "none, opengl, xv, vulkan"); outstring("HardwareAcceleration", display_driver, "none, opengl, xv, vulkan");
outint("SplashBackground", splash_image, "0: Black, 1: Color bars, 2: Pattern, 3: Blue, 4: Default"); outint("SplashBackground", splash_image, "0: Black, 1: Color bars, 2: Pattern, 3: Blue, 4: Default");
outbool("AutoVRR", auto_vrr, "Automatically use the best settings for variable sync in fullscreen mode");
section = "NTSC"; section = "NTSC";
outstring("Hue", std::to_string(ntsc_setup.hue)); outstring("Hue", std::to_string(ntsc_setup.hue));
@ -457,6 +458,7 @@ int Snes9xConfig::load_config_file()
instr("HardwareAcceleration", display_driver); instr("HardwareAcceleration", display_driver);
inbool("BilinearFilter", Settings.BilinearFilter); inbool("BilinearFilter", Settings.BilinearFilter);
inint("SplashBackground", splash_image); inint("SplashBackground", splash_image);
inbool("AutoVRR", auto_vrr);
section = "NTSC"; section = "NTSC";
indouble("Hue", ntsc_setup.hue); indouble("Hue", ntsc_setup.hue);

View File

@ -71,6 +71,7 @@ class Snes9xConfig
int hires_effect; int hires_effect;
bool force_inverted_byte_order; bool force_inverted_byte_order;
int splash_image; int splash_image;
bool auto_vrr;
snes_ntsc_setup_t ntsc_setup; snes_ntsc_setup_t ntsc_setup;
int ntsc_format; int ntsc_format;

View File

@ -751,9 +751,9 @@ void S9xConvertMask(void *src,
bpp); bpp);
} }
void S9xDisplayRefresh(int width, int height) void S9xDisplayRefresh()
{ {
driver->refresh(width, height); driver->refresh();
} }
static void ntsc_filter_init() static void ntsc_filter_init()

View File

@ -88,7 +88,7 @@ void S9xFilter(uint8 *src_buffer,
int &width, int &width,
int &height); int &height);
void apply_filter_scale(int &width, int &height); void apply_filter_scale(int &width, int &height);
void S9xDisplayRefresh(int width, int height); void S9xDisplayRefresh();
void S9xReinitDisplay(); void S9xReinitDisplay();
void S9xDisplayReconfigure(); void S9xDisplayReconfigure();
void S9xQueryDrivers(); void S9xQueryDrivers();

View File

@ -15,7 +15,7 @@ class S9xDisplayDriver
virtual ~S9xDisplayDriver() virtual ~S9xDisplayDriver()
{ {
} }
virtual void refresh(int width, int height) = 0; virtual void refresh() = 0;
virtual int init() = 0; virtual int init() = 0;
virtual void deinit() = 0; virtual void deinit() = 0;
virtual void update(uint16_t *buffer, int width, int height, int stride_in_pixels) = 0; virtual void update(uint16_t *buffer, int width, int height, int stride_in_pixels) = 0;

View File

@ -131,7 +131,7 @@ void S9xGTKDisplayDriver::clear()
window->release_cairo(); window->release_cairo();
} }
void S9xGTKDisplayDriver::refresh(int width, int height) void S9xGTKDisplayDriver::refresh()
{ {
clear(); clear();
} }

View File

@ -14,7 +14,7 @@ class S9xGTKDisplayDriver : public S9xDisplayDriver
{ {
public: public:
S9xGTKDisplayDriver(Snes9xWindow *window, Snes9xConfig *config); S9xGTKDisplayDriver(Snes9xWindow *window, Snes9xConfig *config);
void refresh(int width, int height); void refresh();
int init(); int init();
void deinit(); void deinit();
void update(uint16_t *buffer, int width, int height, int stride_in_pixels); void update(uint16_t *buffer, int width, int height, int stride_in_pixels);

View File

@ -340,7 +340,7 @@ bool S9xOpenGLDisplayDriver::opengl_defaults()
return true; return true;
} }
void S9xOpenGLDisplayDriver::refresh(int width, int height) void S9xOpenGLDisplayDriver::refresh()
{ {
resize(); resize();
} }

View File

@ -31,7 +31,7 @@ class S9xOpenGLDisplayDriver : public S9xDisplayDriver
{ {
public: public:
S9xOpenGLDisplayDriver(Snes9xWindow *window, Snes9xConfig *config); S9xOpenGLDisplayDriver(Snes9xWindow *window, Snes9xConfig *config);
void refresh(int width, int height) override; void refresh() override;
int init() override; int init() override;
void deinit() override; void deinit() override;
void update(uint16_t *buffer, int width, int height, int stride_in_pixels) override; void update(uint16_t *buffer, int width, int height, int stride_in_pixels) override;

View File

@ -26,7 +26,7 @@ S9xVulkanDisplayDriver::~S9xVulkanDisplayDriver()
{ {
} }
void S9xVulkanDisplayDriver::refresh(int width, int height) void S9xVulkanDisplayDriver::refresh()
{ {
if (!context) if (!context)
return; return;

View File

@ -21,7 +21,7 @@ class S9xVulkanDisplayDriver : public S9xDisplayDriver
public: public:
S9xVulkanDisplayDriver(Snes9xWindow *window, Snes9xConfig *config); S9xVulkanDisplayDriver(Snes9xWindow *window, Snes9xConfig *config);
~S9xVulkanDisplayDriver(); ~S9xVulkanDisplayDriver();
void refresh(int width, int height) override; void refresh() override;
int init() override; int init() override;
void deinit() override; void deinit() override;
void update(uint16_t *buffer, int width, int height, int stride_in_pixels) override; void update(uint16_t *buffer, int width, int height, int stride_in_pixels) override;

View File

@ -456,7 +456,7 @@ void S9xXVDisplayDriver::clear()
XSync(display, False); XSync(display, False);
} }
void S9xXVDisplayDriver::refresh(int width, int height) void S9xXVDisplayDriver::refresh()
{ {
clear(); clear();
} }

View File

@ -21,7 +21,7 @@ class S9xXVDisplayDriver : public S9xDisplayDriver
{ {
public: public:
S9xXVDisplayDriver(Snes9xWindow *window, Snes9xConfig *config); S9xXVDisplayDriver(Snes9xWindow *window, Snes9xConfig *config);
void refresh(int width, int height); void refresh();
int init(); int init();
void deinit(); void deinit();
void update(uint16_t *buffer, int width, int height, int stride_in_pixels); void update(uint16_t *buffer, int width, int height, int stride_in_pixels);

View File

@ -283,7 +283,7 @@ void Snes9xPreferences::game_data_browse(std::string folder)
void Snes9xPreferences::input_rate_changed() void Snes9xPreferences::input_rate_changed()
{ {
double value = get_object<Gtk::HScale>("sound_input_rate")->get_value(); double value = get_object<Gtk::HScale>("sound_input_rate")->get_value();
value = value / 32040.0 * 60.09881389744051; value = value / 32040.0 * NTSC_PROGRESSIVE_FRAME_RATE;
get_object<Gtk::Label>("relative_video_rate")->set_label(fmt::format("{:.4f}Hz", value)); get_object<Gtk::Label>("relative_video_rate")->set_label(fmt::format("{:.4f}Hz", value));
} }
@ -464,6 +464,7 @@ void Snes9xPreferences::move_settings_to_dialog()
set_combo ("frameskip_combo", Settings.SkipFrames); set_combo ("frameskip_combo", Settings.SkipFrames);
set_check ("bilinear_filter", Settings.BilinearFilter); set_check ("bilinear_filter", Settings.BilinearFilter);
set_check ("auto_vrr", config->auto_vrr);
set_check ("sync_to_vblank", config->sync_to_vblank); set_check ("sync_to_vblank", config->sync_to_vblank);
set_check ("reduce_input_lag", config->reduce_input_lag); set_check ("reduce_input_lag", config->reduce_input_lag);
@ -568,6 +569,7 @@ void Snes9xPreferences::get_settings_from_dialog()
config->aspect_ratio = get_combo("aspect_ratio"); config->aspect_ratio = get_combo("aspect_ratio");
config->scale_method = get_combo("scale_method_combo"); config->scale_method = get_combo("scale_method_combo");
config->hires_effect = get_combo("hires_effect"); config->hires_effect = get_combo("hires_effect");
config->auto_vrr = get_check("auto_vrr");
config->force_inverted_byte_order = get_check("force_inverted_byte_order"); config->force_inverted_byte_order = get_check("force_inverted_byte_order");
Settings.AutoSaveDelay = get_entry_value("save_sram_after_sec"); Settings.AutoSaveDelay = get_entry_value("save_sram_after_sec");
config->multithreading = get_check("multithreading"); config->multithreading = get_check("multithreading");
@ -697,7 +699,7 @@ void Snes9xPreferences::get_settings_from_dialog()
} }
S9xDisplayReconfigure(); S9xDisplayReconfigure();
S9xDisplayRefresh(top_level->last_width, top_level->last_height); S9xDisplayRefresh();
S9xDeinitUpdate(top_level->last_width, top_level->last_height); S9xDeinitUpdate(top_level->last_width, top_level->last_height);

View File

@ -222,7 +222,7 @@ void S9xNoROMLoaded()
{ {
S9xSoundStop(); S9xSoundStop();
gui_config->rom_loaded = false; gui_config->rom_loaded = false;
S9xDisplayRefresh(-1, -1); S9xDisplayRefresh();
top_level->configure_widgets(); top_level->configure_widgets();
} }

View File

@ -5,6 +5,7 @@
\*****************************************************************************/ \*****************************************************************************/
#include "gtk_compat.h" #include "gtk_compat.h"
#include "gtk_config.h"
#ifdef GDK_WINDOWING_X11 #ifdef GDK_WINDOWING_X11
#include <X11/Xatom.h> #include <X11/Xatom.h>
@ -538,7 +539,7 @@ bool Snes9xWindow::draw(const Cairo::RefPtr<Cairo::Context> &cr)
setup_splash(); setup_splash();
} }
S9xDisplayRefresh(last_width, last_height); S9xDisplayRefresh();
if (!(config->fullscreen)) if (!(config->fullscreen))
{ {
@ -1204,6 +1205,21 @@ void Snes9xWindow::enter_fullscreen_mode()
gdk_display_sync(gdk_display); gdk_display_sync(gdk_display);
window->present(); window->present();
if (config->auto_vrr)
{
autovrr_saved_frameskip = Settings.SkipFrames;
autovrr_saved_sound_input_rate = Settings.SoundInputRate;
autovrr_saved_sync_to_vblank = gui_config->sync_to_vblank;
autovrr_saved_sound_sync = Settings.SoundSync;
Settings.SoundSync = false;
Settings.SkipFrames = THROTTLE_TIMER;
Settings.SoundInputRate = 32040;
S9xUpdateDynamicRate(1, 2);
gui_config->sync_to_vblank = true;
S9xDisplayRefresh();
}
#ifdef GDK_WINDOWING_X11 #ifdef GDK_WINDOWING_X11
if (GDK_IS_X11_WINDOW(window->get_window()->gobj()) && if (GDK_IS_X11_WINDOW(window->get_window()->gobj()) &&
config->default_esc_behavior != ESC_TOGGLE_MENUBAR) config->default_esc_behavior != ESC_TOGGLE_MENUBAR)
@ -1216,6 +1232,7 @@ void Snes9xWindow::enter_fullscreen_mode()
config->fullscreen = 1; config->fullscreen = 1;
config->rom_loaded = rom_loaded; config->rom_loaded = rom_loaded;
/* If we're running a game, disable ui when entering fullscreen */ /* If we're running a game, disable ui when entering fullscreen */
if (!Settings.Paused && config->rom_loaded) if (!Settings.Paused && config->rom_loaded)
config->ui_visible = false; config->ui_visible = false;
@ -1230,6 +1247,16 @@ void Snes9xWindow::leave_fullscreen_mode()
if (!config->fullscreen) if (!config->fullscreen)
return; return;
if (config->auto_vrr)
{
Settings.SkipFrames = autovrr_saved_frameskip;
Settings.SoundInputRate = autovrr_saved_sound_input_rate;
gui_config->sync_to_vblank = autovrr_saved_sync_to_vblank;
Settings.SoundSync = autovrr_saved_sound_sync;
S9xUpdateDynamicRate(1, 2);
S9xDisplayRefresh();
}
GdkDisplay *gdk_display = window->get_display()->gobj(); GdkDisplay *gdk_display = window->get_display()->gobj();
GdkWindow *gdk_window = window->get_window()->gobj(); GdkWindow *gdk_window = window->get_window()->gobj();

View File

@ -89,6 +89,10 @@ class Snes9xWindow : public GtkBuilderWindow
int mouse_region_x, mouse_region_y; int mouse_region_x, mouse_region_y;
int mouse_region_width, mouse_region_height; int mouse_region_width, mouse_region_height;
int nfs_width, nfs_height, nfs_x, nfs_y; int nfs_width, nfs_height, nfs_x, nfs_y;
int autovrr_saved_frameskip;
int autovrr_saved_sound_input_rate;
bool autovrr_saved_sync_to_vblank;
bool autovrr_saved_sound_sync;
int fullscreen_state; int fullscreen_state;
int maximized_state; int maximized_state;
bool focused; bool focused;

View File

@ -3802,6 +3802,21 @@
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">1</property> <property name="position">1</property>
</packing> </packing>
</child>
<child>
<object class="GtkCheckButton" id="auto_vrr">
<property name="label" translatable="yes">Use best settings for FreeSync/G-Sync when fullscreen</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkVBox" id="opengl_frame"> <object class="GtkVBox" id="opengl_frame">
@ -3902,7 +3917,7 @@
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">2</property> <property name="position">3</property>
</packing> </packing>
</child> </child>
<child> <child>
@ -3928,7 +3943,7 @@
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">3</property> <property name="position">4</property>
</packing> </packing>
</child> </child>
</object> </object>