citra_qt: Add option to adjust screen refresh rate
This commit is contained in:
parent
b5d6f645bd
commit
ce115869c9
8 changed files with 138 additions and 20 deletions
|
@ -447,6 +447,7 @@ void Config::ReadCoreValues() {
|
||||||
qt_config->beginGroup(QStringLiteral("Core"));
|
qt_config->beginGroup(QStringLiteral("Core"));
|
||||||
|
|
||||||
ReadGlobalSetting(Settings::values.cpu_clock_percentage);
|
ReadGlobalSetting(Settings::values.cpu_clock_percentage);
|
||||||
|
ReadGlobalSetting(Settings::values.refresh_rate);
|
||||||
|
|
||||||
if (global) {
|
if (global) {
|
||||||
ReadBasicSetting(Settings::values.use_cpu_jit);
|
ReadBasicSetting(Settings::values.use_cpu_jit);
|
||||||
|
@ -963,6 +964,7 @@ void Config::SaveCoreValues() {
|
||||||
qt_config->beginGroup(QStringLiteral("Core"));
|
qt_config->beginGroup(QStringLiteral("Core"));
|
||||||
|
|
||||||
WriteGlobalSetting(Settings::values.cpu_clock_percentage);
|
WriteGlobalSetting(Settings::values.cpu_clock_percentage);
|
||||||
|
WriteGlobalSetting(Settings::values.refresh_rate);
|
||||||
|
|
||||||
if (global) {
|
if (global) {
|
||||||
WriteBasicSetting(Settings::values.use_cpu_jit);
|
WriteBasicSetting(Settings::values.use_cpu_jit);
|
||||||
|
|
|
@ -42,13 +42,21 @@ ConfigureDebug::ConfigureDebug(QWidget* parent)
|
||||||
// Set a minimum width for the label to prevent the slider from changing size.
|
// Set a minimum width for the label to prevent the slider from changing size.
|
||||||
// This scales across DPIs. (This value should be enough for "xxx%")
|
// This scales across DPIs. (This value should be enough for "xxx%")
|
||||||
ui->clock_display_label->setMinimumWidth(40);
|
ui->clock_display_label->setMinimumWidth(40);
|
||||||
|
ui->refresh_display_label->setMinimumWidth(40);
|
||||||
|
|
||||||
connect(ui->slider_clock_speed, &QSlider::valueChanged, this, [&](int value) {
|
connect(ui->slider_clock_speed, &QSlider::valueChanged, this, [&](int value) {
|
||||||
ui->clock_display_label->setText(QStringLiteral("%1%").arg(SliderToSettings(value)));
|
ui->clock_display_label->setText(QStringLiteral("%1%").arg(SliderToSettings(value)));
|
||||||
});
|
});
|
||||||
|
|
||||||
ui->clock_speed_label->setVisible(Settings::IsConfiguringGlobal());
|
connect(ui->slider_refresh_rate, &QSlider::valueChanged, this, [&](int value) {
|
||||||
ui->clock_speed_combo->setVisible(!Settings::IsConfiguringGlobal());
|
ui->refresh_display_label->setText(QStringLiteral("%1Hz").arg(value));
|
||||||
|
});
|
||||||
|
|
||||||
|
const bool is_global = Settings::IsConfiguringGlobal();
|
||||||
|
ui->clock_speed_label->setVisible(is_global);
|
||||||
|
ui->refresh_rate_label->setVisible(is_global);
|
||||||
|
ui->clock_speed_combo->setVisible(!is_global);
|
||||||
|
ui->refresh_rate_combo->setVisible(!is_global);
|
||||||
|
|
||||||
SetupPerGameUI();
|
SetupPerGameUI();
|
||||||
}
|
}
|
||||||
|
@ -73,14 +81,26 @@ void ConfigureDebug::SetConfiguration() {
|
||||||
ui->clock_speed_combo->setCurrentIndex(1);
|
ui->clock_speed_combo->setCurrentIndex(1);
|
||||||
ui->slider_clock_speed->setEnabled(true);
|
ui->slider_clock_speed->setEnabled(true);
|
||||||
}
|
}
|
||||||
|
if (Settings::values.refresh_rate.UsingGlobal()) {
|
||||||
|
ui->refresh_rate_combo->setCurrentIndex(0);
|
||||||
|
ui->slider_refresh_rate->setEnabled(false);
|
||||||
|
} else {
|
||||||
|
ui->refresh_rate_combo->setCurrentIndex(1);
|
||||||
|
ui->slider_refresh_rate->setEnabled(true);
|
||||||
|
}
|
||||||
ConfigurationShared::SetHighlight(ui->clock_speed_widget,
|
ConfigurationShared::SetHighlight(ui->clock_speed_widget,
|
||||||
!Settings::values.cpu_clock_percentage.UsingGlobal());
|
!Settings::values.cpu_clock_percentage.UsingGlobal());
|
||||||
|
ConfigurationShared::SetHighlight(ui->refresh_rate_widget,
|
||||||
|
!Settings::values.refresh_rate.UsingGlobal());
|
||||||
}
|
}
|
||||||
|
|
||||||
ui->slider_clock_speed->setValue(
|
ui->slider_clock_speed->setValue(
|
||||||
SettingsToSlider(Settings::values.cpu_clock_percentage.GetValue()));
|
SettingsToSlider(Settings::values.cpu_clock_percentage.GetValue()));
|
||||||
ui->clock_display_label->setText(
|
ui->clock_display_label->setText(
|
||||||
QStringLiteral("%1%").arg(Settings::values.cpu_clock_percentage.GetValue()));
|
QStringLiteral("%1%").arg(Settings::values.cpu_clock_percentage.GetValue()));
|
||||||
|
ui->slider_refresh_rate->setValue(Settings::values.refresh_rate.GetValue());
|
||||||
|
ui->refresh_display_label->setText(
|
||||||
|
QStringLiteral("%1Hz").arg(Settings::values.refresh_rate.GetValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureDebug::ApplyConfiguration() {
|
void ConfigureDebug::ApplyConfiguration() {
|
||||||
|
@ -98,22 +118,32 @@ void ConfigureDebug::ApplyConfiguration() {
|
||||||
ConfigurationShared::ApplyPerGameSetting(
|
ConfigurationShared::ApplyPerGameSetting(
|
||||||
&Settings::values.cpu_clock_percentage, ui->clock_speed_combo,
|
&Settings::values.cpu_clock_percentage, ui->clock_speed_combo,
|
||||||
[this](s32) { return SliderToSettings(ui->slider_clock_speed->value()); });
|
[this](s32) { return SliderToSettings(ui->slider_clock_speed->value()); });
|
||||||
|
|
||||||
|
ConfigurationShared::ApplyPerGameSetting(
|
||||||
|
&Settings::values.refresh_rate, ui->refresh_rate_combo,
|
||||||
|
[this](s32) { return ui->slider_refresh_rate->value(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureDebug::SetupPerGameUI() {
|
void ConfigureDebug::SetupPerGameUI() {
|
||||||
// Block the global settings if a game is currently running that overrides them
|
// Block the global settings if a game is currently running that overrides them
|
||||||
if (Settings::IsConfiguringGlobal()) {
|
if (Settings::IsConfiguringGlobal()) {
|
||||||
ui->slider_clock_speed->setEnabled(Settings::values.cpu_clock_percentage.UsingGlobal());
|
ui->slider_clock_speed->setEnabled(Settings::values.cpu_clock_percentage.UsingGlobal());
|
||||||
|
ui->slider_refresh_rate->setEnabled(Settings::values.refresh_rate.UsingGlobal());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
connect(ui->refresh_rate_combo, qOverload<int>(&QComboBox::activated), this, [this](int index) {
|
||||||
|
ui->slider_refresh_rate->setEnabled(index == 1);
|
||||||
|
ConfigurationShared::SetHighlight(ui->refresh_rate_widget, index == 1);
|
||||||
|
});
|
||||||
|
|
||||||
connect(ui->clock_speed_combo, qOverload<int>(&QComboBox::activated), this, [this](int index) {
|
connect(ui->clock_speed_combo, qOverload<int>(&QComboBox::activated), this, [this](int index) {
|
||||||
ui->slider_clock_speed->setEnabled(index == 1);
|
ui->slider_clock_speed->setEnabled(index == 1);
|
||||||
ConfigurationShared::SetHighlight(ui->clock_speed_widget, index == 1);
|
ConfigurationShared::SetHighlight(ui->clock_speed_widget, index == 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
ui->groupBox->setVisible(false);
|
ui->gdb_group->setVisible(false);
|
||||||
ui->groupBox_2->setVisible(false);
|
ui->logging_group->setVisible(false);
|
||||||
ui->toggle_cpu_jit->setVisible(false);
|
ui->toggle_cpu_jit->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>523</width>
|
<width>523</width>
|
||||||
<height>447</height>
|
<height>495</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
<item>
|
<item>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupBox">
|
<widget class="QGroupBox" name="gdb_group">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>GDB</string>
|
<string>GDB</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -66,7 +66,7 @@
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupBox_2">
|
<widget class="QGroupBox" name="logging_group">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Logging</string>
|
<string>Logging</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -107,18 +107,15 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupBox_4">
|
<widget class="QGroupBox" name="cpu_group">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>CPU</string>
|
<string>CPU</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
<item row="2" column="0">
|
<item row="4" column="0">
|
||||||
<widget class="QCheckBox" name="toggle_cpu_jit">
|
<widget class="QCheckBox" name="toggle_renderer_debug">
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Enables the use of the ARM JIT compiler for emulating the 3DS CPUs. Don't disable unless for debugging purposes</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Enable CPU JIT</string>
|
<string>Enable debug renderer</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -203,10 +200,81 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QCheckBox" name="toggle_renderer_debug">
|
<widget class="QCheckBox" name="toggle_cpu_jit">
|
||||||
<property name="text">
|
<property name="toolTip">
|
||||||
<string>Enable debug renderer</string>
|
<string><html><head/><body><p>Enables the use of the ARM JIT compiler for emulating the 3DS CPUs. Don't disable unless for debugging purposes</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Enable CPU JIT</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QWidget" name="refresh_rate_widget" native="true">
|
||||||
|
<layout class="QHBoxLayout" name="refresh_rate_widget_2">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="refresh_rate_combo">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Use global refresh rate</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Set refresh rate:</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="refresh_rate_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Refresh rate</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSlider" name="slider_refresh_rate">
|
||||||
|
<property name="minimum">
|
||||||
|
<number>30</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>360</number>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<number>30</number>
|
||||||
|
</property>
|
||||||
|
<property name="pageStep">
|
||||||
|
<number>30</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>60</number>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="refresh_display_label">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
|
@ -51,6 +51,8 @@ void Apply() {
|
||||||
GDBStub::SetServerPort(values.gdbstub_port.GetValue());
|
GDBStub::SetServerPort(values.gdbstub_port.GetValue());
|
||||||
GDBStub::ToggleServer(values.use_gdbstub.GetValue());
|
GDBStub::ToggleServer(values.use_gdbstub.GetValue());
|
||||||
|
|
||||||
|
GPU::SetRefreshRate(values.refresh_rate.GetValue());
|
||||||
|
|
||||||
VideoCore::g_shader_jit_enabled = values.use_shader_jit.GetValue();
|
VideoCore::g_shader_jit_enabled = values.use_shader_jit.GetValue();
|
||||||
VideoCore::g_hw_shader_enabled = values.use_hw_shader.GetValue();
|
VideoCore::g_hw_shader_enabled = values.use_hw_shader.GetValue();
|
||||||
VideoCore::g_separable_shader_enabled = values.separable_shader.GetValue();
|
VideoCore::g_separable_shader_enabled = values.separable_shader.GetValue();
|
||||||
|
@ -112,6 +114,7 @@ void LogSettings() {
|
||||||
LOG_INFO(Config, "Citra Configuration:");
|
LOG_INFO(Config, "Citra Configuration:");
|
||||||
log_setting("Core_UseCpuJit", values.use_cpu_jit.GetValue());
|
log_setting("Core_UseCpuJit", values.use_cpu_jit.GetValue());
|
||||||
log_setting("Core_CPUClockPercentage", values.cpu_clock_percentage.GetValue());
|
log_setting("Core_CPUClockPercentage", values.cpu_clock_percentage.GetValue());
|
||||||
|
log_setting("Core_RefreshRate", values.refresh_rate.GetValue());
|
||||||
log_setting("Renderer_UseGLES", values.use_gles.GetValue());
|
log_setting("Renderer_UseGLES", values.use_gles.GetValue());
|
||||||
log_setting("Renderer_GraphicsAPI", GetGraphicsAPIName(values.graphics_api.GetValue()));
|
log_setting("Renderer_GraphicsAPI", GetGraphicsAPIName(values.graphics_api.GetValue()));
|
||||||
log_setting("Renderer_UseHwShader", values.use_hw_shader.GetValue());
|
log_setting("Renderer_UseHwShader", values.use_hw_shader.GetValue());
|
||||||
|
@ -195,6 +198,7 @@ void RestoreGlobalState(bool is_powered_on) {
|
||||||
|
|
||||||
// Core
|
// Core
|
||||||
values.cpu_clock_percentage.SetGlobal(true);
|
values.cpu_clock_percentage.SetGlobal(true);
|
||||||
|
values.refresh_rate.SetGlobal(true);
|
||||||
values.is_new_3ds.SetGlobal(true);
|
values.is_new_3ds.SetGlobal(true);
|
||||||
|
|
||||||
// Renderer
|
// Renderer
|
||||||
|
|
|
@ -490,6 +490,7 @@ struct Values {
|
||||||
std::unordered_map<std::string, bool> lle_modules;
|
std::unordered_map<std::string, bool> lle_modules;
|
||||||
Setting<bool> use_gdbstub{false, "use_gdbstub"};
|
Setting<bool> use_gdbstub{false, "use_gdbstub"};
|
||||||
Setting<u16> gdbstub_port{24689, "gdbstub_port"};
|
Setting<u16> gdbstub_port{24689, "gdbstub_port"};
|
||||||
|
SwitchableSetting<u32, true> refresh_rate{60, 30, 360, "refresh_rate"};
|
||||||
|
|
||||||
// Miscellaneous
|
// Miscellaneous
|
||||||
Setting<std::string> log_filter{"*:Info", "log_filter"};
|
Setting<std::string> log_filter{"*:Info", "log_filter"};
|
||||||
|
|
|
@ -27,6 +27,11 @@
|
||||||
|
|
||||||
namespace GPU {
|
namespace GPU {
|
||||||
|
|
||||||
|
// Measured on hardware to be 2240568 timer cycles or 4481136 ARM11 cycles
|
||||||
|
u64 frame_ticks = 4481136ull;
|
||||||
|
|
||||||
|
double SCREEN_REFRESH_RATE = BASE_CLOCK_RATE_ARM11 / static_cast<double>(frame_ticks);
|
||||||
|
|
||||||
Regs g_regs;
|
Regs g_regs;
|
||||||
Memory::MemorySystem* g_memory;
|
Memory::MemorySystem* g_memory;
|
||||||
|
|
||||||
|
@ -561,4 +566,9 @@ void Shutdown() {
|
||||||
LOG_DEBUG(HW_GPU, "shutdown OK");
|
LOG_DEBUG(HW_GPU, "shutdown OK");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetRefreshRate(u32 refresh) {
|
||||||
|
frame_ticks = (4481136ull * 60) / refresh;
|
||||||
|
SCREEN_REFRESH_RATE = BASE_CLOCK_RATE_ARM11 / static_cast<double>(frame_ticks);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace GPU
|
} // namespace GPU
|
||||||
|
|
|
@ -21,11 +21,11 @@ class MemorySystem;
|
||||||
namespace GPU {
|
namespace GPU {
|
||||||
|
|
||||||
// Measured on hardware to be 2240568 timer cycles or 4481136 ARM11 cycles
|
// Measured on hardware to be 2240568 timer cycles or 4481136 ARM11 cycles
|
||||||
constexpr u64 frame_ticks = 4481136ull;
|
extern u64 frame_ticks;
|
||||||
|
|
||||||
// Refresh rate defined by ratio of ARM11 frequency to ARM11 ticks per frame
|
// Refresh rate defined by ratio of ARM11 frequency to ARM11 ticks per frame
|
||||||
// (268,111,856) / (4,481,136) = 59.83122493939037Hz
|
// (268,111,856) / (4,481,136) = 59.83122493939037Hz
|
||||||
constexpr double SCREEN_REFRESH_RATE = BASE_CLOCK_RATE_ARM11 / static_cast<double>(frame_ticks);
|
extern double SCREEN_REFRESH_RATE;
|
||||||
|
|
||||||
// Returns index corresponding to the Regs member labeled by field_name
|
// Returns index corresponding to the Regs member labeled by field_name
|
||||||
#define GPU_REG_INDEX(field_name) (offsetof(GPU::Regs, field_name) / sizeof(u32))
|
#define GPU_REG_INDEX(field_name) (offsetof(GPU::Regs, field_name) / sizeof(u32))
|
||||||
|
@ -328,4 +328,7 @@ void Init(Memory::MemorySystem& memory);
|
||||||
/// Shutdown hardware
|
/// Shutdown hardware
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
|
/// Sets the screen refresh rate
|
||||||
|
void SetRefreshRate(u32 refresh);
|
||||||
|
|
||||||
} // namespace GPU
|
} // namespace GPU
|
||||||
|
|
|
@ -115,7 +115,7 @@ PerfStats::Results PerfStats::GetAndResetStats(microseconds current_system_time_
|
||||||
double PerfStats::GetLastFrameTimeScale() const {
|
double PerfStats::GetLastFrameTimeScale() const {
|
||||||
std::lock_guard lock{object_mutex};
|
std::lock_guard lock{object_mutex};
|
||||||
|
|
||||||
constexpr double FRAME_LENGTH = 1.0 / GPU::SCREEN_REFRESH_RATE;
|
const double FRAME_LENGTH = 1.0 / GPU::SCREEN_REFRESH_RATE;
|
||||||
return duration_cast<DoubleSecs>(previous_frame_length).count() / FRAME_LENGTH;
|
return duration_cast<DoubleSecs>(previous_frame_length).count() / FRAME_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue