diff --git a/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml b/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml
index 06894d9576..5bac374fb5 100644
--- a/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml
+++ b/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml
@@ -347,6 +347,10 @@ Flickable {
text: "Real-Time"
refreshRatePreset: 2 // RefreshRateProfile::REALTIME
}
+ ListElement {
+ text: "Custom"
+ refreshRatePreset: 3 // RefreshRateProfile::CUSTOM
+ }
}
HifiControlsUit.ComboBox {
@@ -362,13 +366,7 @@ Flickable {
currentIndex: -1
function refreshRefreshRateDropdownDisplay() {
- if (Performance.getRefreshRateProfile() === 0) {
- refreshRateDropdown.currentIndex = 0;
- } else if (Performance.getRefreshRateProfile() === 1) {
- refreshRateDropdown.currentIndex = 1;
- } else {
- refreshRateDropdown.currentIndex = 2;
- }
+ refreshRateDropdown.currentIndex = Performance.getRefreshRateProfile();
}
Component.onCompleted: {
@@ -382,6 +380,180 @@ Flickable {
}
}
+ ColumnLayout {
+ width: parent.width
+ Layout.topMargin: 32
+ visible: refreshRateDropdown.currentIndex == 3
+
+ RowLayout {
+ Layout.margins: 8
+
+ HifiControlsUit.SpinBox {
+ id: refreshRateCustomFocusActive
+ decimals: 0
+ width: 160
+ height: 32
+ suffix: " FPS"
+ label: "Focus Active"
+ realFrom: 1
+ realTo: 1000
+ realStepSize: 15
+ realValue: 60
+ colorScheme: hifi.colorSchemes.dark
+ property var loaded: false
+
+ Component.onCompleted: {
+ realValue = Performance.getCustomRefreshRate(0)
+ loaded = true
+ }
+
+ onRealValueChanged: {
+ if (loaded) {
+ Performance.setCustomRefreshRate(0, realValue)
+ }
+ }
+ }
+
+ HifiControlsUit.SpinBox {
+ id: refreshRateCustomFocusInactive
+ decimals: 0
+ width: 160
+ height: 32
+ suffix: " FPS"
+ label: "Focus Inactive"
+ realFrom: 1
+ realTo: 1000
+ realStepSize: 15
+ realValue: 60
+ colorScheme: hifi.colorSchemes.dark
+ property var loaded: false
+
+ Component.onCompleted: {
+ realValue = Performance.getCustomRefreshRate(1)
+ loaded = true
+ }
+
+ onRealValueChanged: {
+ if (loaded) {
+ Performance.setCustomRefreshRate(1, realValue)
+ }
+ }
+ }
+ }
+
+ RowLayout {
+ Layout.margins: 8
+
+ HifiControlsUit.SpinBox {
+ id: refreshRateCustomUnfocus
+ decimals: 0
+ width: 160
+ height: 32
+ suffix: " FPS"
+ label: "Unfocus"
+ realFrom: 1
+ realTo: 1000
+ realStepSize: 15
+ realValue: 60
+ colorScheme: hifi.colorSchemes.dark
+ property var loaded: false
+
+ Component.onCompleted: {
+ realValue = Performance.getCustomRefreshRate(2)
+ loaded = true
+ }
+
+ onRealValueChanged: {
+ if (loaded) {
+ Performance.setCustomRefreshRate(2, realValue);
+ }
+ }
+ }
+
+ HifiControlsUit.SpinBox {
+ id: refreshRateCustomMinimized
+ decimals: 0
+ width: 160
+ height: 32
+ suffix: " FPS"
+ label: "Minimized"
+ realFrom: 1
+ realTo: 1000
+ realStepSize: 1
+ realValue: 60
+ colorScheme: hifi.colorSchemes.dark
+ property var loaded: false
+
+ Component.onCompleted: {
+ realValue = Performance.getCustomRefreshRate(3)
+ loaded = true
+ }
+
+ onRealValueChanged: {
+ if (loaded) {
+ Performance.setCustomRefreshRate(3, realValue)
+ }
+ }
+ }
+ }
+
+ RowLayout {
+ Layout.margins: 8
+
+ HifiControlsUit.SpinBox {
+ id: refreshRateCustomStartup
+ decimals: 0
+ width: 160
+ height: 32
+ suffix: " FPS"
+ label: "Startup"
+ realFrom: 1
+ realTo: 1000
+ realStepSize: 15
+ realValue: 60
+ colorScheme: hifi.colorSchemes.dark
+ property var loaded: false
+
+ Component.onCompleted: {
+ realValue = Performance.getCustomRefreshRate(4)
+ loaded = true
+ }
+
+ onRealValueChanged: {
+ if (loaded) {
+ Performance.setCustomRefreshRate(4, realValue)
+ }
+ }
+ }
+
+ HifiControlsUit.SpinBox {
+ id: refreshRateCustomShutdown
+ decimals: 0
+ width: 160
+ height: 32
+ suffix: " FPS"
+ label: "Shutdown"
+ realFrom: 1
+ realTo: 1000
+ realStepSize: 15
+ realValue: 60
+ colorScheme: hifi.colorSchemes.dark
+ property var loaded: false
+
+ Component.onCompleted: {
+ realValue = Performance.getCustomRefreshRate(5)
+ loaded = true
+ }
+
+ onRealValueChanged: {
+ if (loaded) {
+ Performance.setCustomRefreshRate(5, realValue)
+ }
+ }
+ }
+ }
+ }
+
Item {
Layout.preferredWidth: parent.width
Layout.preferredHeight: 35
diff --git a/interface/src/RefreshRateManager.cpp b/interface/src/RefreshRateManager.cpp
index 09428da5ea..9ba446750b 100644
--- a/interface/src/RefreshRateManager.cpp
+++ b/interface/src/RefreshRateManager.cpp
@@ -48,12 +48,13 @@ static const int VR_TARGET_RATE = 90;
*
"Custom" | Custom refresh rate for full control over the refresh rate in all states.
*
*
* @typedef {string} RefreshRateProfileName
*/
static const std::array REFRESH_RATE_PROFILE_TO_STRING =
- { { "Eco", "Interactive", "Realtime" } };
+ { { "Eco", "Interactive", "Realtime", "Custom" } };
/*@jsdoc
* Interface states that affect the refresh rate.
@@ -94,7 +95,8 @@ static const std::array UX_MODE
static const std::map REFRESH_RATE_PROFILE_FROM_STRING =
{ { "Eco", RefreshRateManager::RefreshRateProfile::ECO },
{ "Interactive", RefreshRateManager::RefreshRateProfile::INTERACTIVE },
- { "Realtime", RefreshRateManager::RefreshRateProfile::REALTIME } };
+ { "Realtime", RefreshRateManager::RefreshRateProfile::REALTIME },
+ { "Custom", RefreshRateManager::RefreshRateProfile::CUSTOM } };
// Porfile regimes are:
@@ -107,10 +109,12 @@ static const std::array
{ { 30, 20, 10, 2, 30, 30 } };
static const std::array REALTIME_PROFILE =
- { { 60, 60, 60, 2, 30, 30} };
+ { { 60, 60, 60, 2, 30, 30 } };
-static const std::array, RefreshRateManager::RefreshRateProfile::PROFILE_NUM> REFRESH_RATE_PROFILES =
- { { ECO_PROFILE, INTERACTIVE_PROFILE, REALTIME_PROFILE } };
+static const std::array CUSTOM_PROFILE = REALTIME_PROFILE; // derived from settings and modified by scripts below
+
+static std::array, RefreshRateManager::RefreshRateProfile::PROFILE_NUM> REFRESH_RATE_PROFILES =
+ { { ECO_PROFILE, INTERACTIVE_PROFILE, REALTIME_PROFILE, CUSTOM_PROFILE } };
static const int INACTIVE_TIMER_LIMIT = 3000;
@@ -134,6 +138,10 @@ std::string RefreshRateManager::uxModeToString(RefreshRateManager::RefreshRateMa
RefreshRateManager::RefreshRateManager() {
_refreshRateProfile = (RefreshRateManager::RefreshRateProfile) _refreshRateProfileSetting.get();
+ for (size_t i = 0; i < _customRefreshRateSettings.size(); i++) {
+ REFRESH_RATE_PROFILES[CUSTOM][i] = _customRefreshRateSettings[i].get();
+ }
+
_inactiveTimer->setInterval(INACTIVE_TIMER_LIMIT);
_inactiveTimer->setSingleShot(true);
QObject::connect(_inactiveTimer.get(), &QTimer::timeout, [&] {
@@ -168,6 +176,25 @@ void RefreshRateManager::setRefreshRateProfile(RefreshRateManager::RefreshRatePr
}
}
+int RefreshRateManager::getCustomRefreshRate(RefreshRateRegime regime) {
+ if (isValidRefreshRateRegime(regime)) {
+ return REFRESH_RATE_PROFILES[RefreshRateProfile::CUSTOM][regime];
+ }
+
+ return 0;
+}
+
+void RefreshRateManager::setCustomRefreshRate(RefreshRateRegime regime, int value) {
+ value = std::max(value, 1);
+ if (isValidRefreshRateRegime(regime)) {
+ _refreshRateProfileSettingLock.withWriteLock([&] {
+ REFRESH_RATE_PROFILES[RefreshRateProfile::CUSTOM][regime] = value;
+ _customRefreshRateSettings[regime].set(value);
+ });
+ updateRefreshRateController();
+ }
+}
+
RefreshRateManager::RefreshRateProfile RefreshRateManager::getRefreshRateProfile() const {
RefreshRateManager::RefreshRateProfile profile = RefreshRateManager::RefreshRateProfile::REALTIME;
@@ -191,7 +218,6 @@ void RefreshRateManager::setRefreshRateRegime(RefreshRateManager::RefreshRateReg
_refreshRateRegime = refreshRateRegime;
updateRefreshRateController();
}
-
}
void RefreshRateManager::setUXMode(RefreshRateManager::UXMode uxMode) {
diff --git a/interface/src/RefreshRateManager.h b/interface/src/RefreshRateManager.h
index 4b91f0c45e..6b94a94a4a 100644
--- a/interface/src/RefreshRateManager.h
+++ b/interface/src/RefreshRateManager.h
@@ -32,10 +32,11 @@ public:
ECO = 0,
INTERACTIVE,
REALTIME,
+ CUSTOM,
PROFILE_NUM
};
Q_ENUM(RefreshRateProfile)
- static bool isValidRefreshRateProfile(RefreshRateProfile value) { return (value >= RefreshRateProfile::ECO && value <= RefreshRateProfile::REALTIME); }
+ static bool isValidRefreshRateProfile(RefreshRateProfile value) { return (value >= 0 && value < RefreshRateProfile::PROFILE_NUM); }
/*@jsdoc
* Interface states that affect the refresh rate.
@@ -106,6 +107,9 @@ public:
// query the refresh rate target at the specified combination
int queryRefreshRateTarget(RefreshRateProfile profile, RefreshRateRegime regime, UXMode uxMode) const;
+ int getCustomRefreshRate(RefreshRateRegime regime);
+ void setCustomRefreshRate(RefreshRateRegime regime, int value);
+
void resetInactiveTimer();
void toggleInactive();
@@ -121,7 +125,15 @@ private:
UXMode _uxMode { UXMode::DESKTOP };
mutable ReadWriteLockable _refreshRateProfileSettingLock;
- Setting::Handle _refreshRateProfileSetting { "refreshRateProfile", RefreshRateProfile::INTERACTIVE };
+ Setting::Handle _refreshRateProfileSetting{ "refreshRateProfile", RefreshRateProfile::INTERACTIVE };
+ std::array, REGIME_NUM> _customRefreshRateSettings { {
+ { "customRefreshRateFocusActive", 60 },
+ { "customRefreshRateFocusInactive", 60 },
+ { "customRefreshRateUnfocus", 60 },
+ { "customRefreshRateMinimized", 2 },
+ { "customRefreshRateStartup", 30 },
+ { "customRefreshRateShutdown", 30 }
+ } };
std::function _refreshRateOperator { nullptr };
diff --git a/interface/src/scripting/PerformanceScriptingInterface.cpp b/interface/src/scripting/PerformanceScriptingInterface.cpp
index 9f3534b3e8..f619729eff 100644
--- a/interface/src/scripting/PerformanceScriptingInterface.cpp
+++ b/interface/src/scripting/PerformanceScriptingInterface.cpp
@@ -56,12 +56,22 @@ void PerformanceScriptingInterface::setRefreshRateProfile(RefreshRateProfile ref
emit settingsChanged();
}
+void PerformanceScriptingInterface::setCustomRefreshRate(RefreshRateManager::RefreshRateRegime refreshRateRegime, int value)
+{
+ qApp->getRefreshRateManager().setCustomRefreshRate(refreshRateRegime, value);
+ emit settingsChanged();
+}
+
+int PerformanceScriptingInterface::getCustomRefreshRate(RefreshRateManager::RefreshRateRegime refreshRateRegime) const {
+ return qApp->getRefreshRateManager().getCustomRefreshRate(refreshRateRegime);
+}
+
PerformanceScriptingInterface::RefreshRateProfile PerformanceScriptingInterface::getRefreshRateProfile() const {
return (PerformanceScriptingInterface::RefreshRateProfile)qApp->getRefreshRateManager().getRefreshRateProfile();
}
QStringList PerformanceScriptingInterface::getRefreshRateProfileNames() const {
- static const QStringList refreshRateProfileNames = { "ECO", "INTERACTIVE", "REALTIME" };
+ static const QStringList refreshRateProfileNames = { "ECO", "INTERACTIVE", "REALTIME", "CUSTOM" };
return refreshRateProfileNames;
}
diff --git a/interface/src/scripting/PerformanceScriptingInterface.h b/interface/src/scripting/PerformanceScriptingInterface.h
index 86350c8a1f..05e2c1d7bc 100644
--- a/interface/src/scripting/PerformanceScriptingInterface.h
+++ b/interface/src/scripting/PerformanceScriptingInterface.h
@@ -127,6 +127,22 @@ public slots:
*/
void setRefreshRateProfile(RefreshRateProfile refreshRateProfile);
+ /*@jsdoc
+ * Sets a custom refresh rate.
+ * @function Performance.setCustomRefreshRate
+ * @param {RefreshRateRegime} refreshRateRegime - The refresh rate regime
+ * @param {int} value - The value for the regime
+ */
+ void setCustomRefreshRate(RefreshRateManager::RefreshRateRegime refreshRateRegime, int value);
+
+ /*@jsdoc
+ * Gets the value for a specific RefreshRateRegime.
+ * @function Performance.getCustomRefreshRate
+ * @param {RefreshRateRegime} - The regime to get the value from
+ * @returns {int} - The value from the specified regime
+ */
+ int getCustomRefreshRate(RefreshRateManager::RefreshRateRegime regime) const;
+
/*@jsdoc
* Gets the current refresh rate profile in use.
* @function Performance.getRefreshRateProfile
diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp
index 8597cb5717..ce5a588776 100644
--- a/interface/src/ui/PreferencesDialog.cpp
+++ b/interface/src/ui/PreferencesDialog.cpp
@@ -100,7 +100,8 @@ void setupPreferences() {
QStringList refreshRateProfiles
{ QString::fromStdString(RefreshRateManager::refreshRateProfileToString(RefreshRateManager::RefreshRateProfile::ECO)),
QString::fromStdString(RefreshRateManager::refreshRateProfileToString(RefreshRateManager::RefreshRateProfile::INTERACTIVE)),
- QString::fromStdString(RefreshRateManager::refreshRateProfileToString(RefreshRateManager::RefreshRateProfile::REALTIME)) };
+ QString::fromStdString(RefreshRateManager::refreshRateProfileToString(RefreshRateManager::RefreshRateProfile::REALTIME)),
+ QString::fromStdString(RefreshRateManager::refreshRateProfileToString(RefreshRateManager::RefreshRateProfile::CUSTOM)) };
preference->setItems(refreshRateProfiles);
preferences->addPreference(preference);
|