@@ -67,7 +67,8 @@ extern bool tooltips; | |||
extern bool cpuMeter; | |||
extern bool lockModules; | |||
extern bool squeezeModules; | |||
extern int frameSwapInterval; | |||
/** Maximum screen redraw frequency in Hz, or 0 for unlimited. */ | |||
extern float frameRateLimit; | |||
extern float autosaveInterval; | |||
extern bool skipLoadOnLaunch; | |||
extern std::list<std::string> recentPatchPaths; | |||
@@ -409,13 +409,12 @@ struct ViewButton : MenuButton { | |||
APP->window->setFullScreen(!fullscreen); | |||
})); | |||
double frameRate = APP->window->getMonitorRefreshRate() / settings::frameSwapInterval; | |||
menu->addChild(createSubmenuItem("Frame rate", string::f("%.0f Hz", frameRate), [=](ui::Menu* menu) { | |||
menu->addChild(createSubmenuItem("Frame rate", string::f("%.0f Hz", settings::frameRateLimit), [=](ui::Menu* menu) { | |||
for (int i = 1; i <= 6; i++) { | |||
double frameRate = APP->window->getMonitorRefreshRate() / i; | |||
menu->addChild(createCheckMenuItem(string::f("%.0f Hz", frameRate), "", | |||
[=]() {return settings::frameSwapInterval == i;}, | |||
[=]() {settings::frameSwapInterval = i;} | |||
[=]() {return settings::frameRateLimit == frameRate;}, | |||
[=]() {settings::frameRateLimit = frameRate;} | |||
)); | |||
} | |||
})); | |||
@@ -42,10 +42,10 @@ bool cpuMeter = false; | |||
bool lockModules = false; | |||
bool squeezeModules = true; | |||
#if defined ARCH_MAC | |||
// Most Mac GPUs can't handle rendering the screen every frame, so use ~30 Hz by default. | |||
int frameSwapInterval = 2; | |||
// Most Mac GPUs can't handle rendering the screen every frame, so use 30 Hz by default. | |||
float frameRateLimit = 30.f; | |||
#else | |||
int frameSwapInterval = 1; | |||
float frameRateLimit = 60.f; | |||
#endif | |||
float autosaveInterval = 15.0; | |||
bool skipLoadOnLaunch = false; | |||
@@ -158,7 +158,7 @@ json_t* toJson() { | |||
json_object_set_new(rootJ, "squeezeModules", json_boolean(squeezeModules)); | |||
json_object_set_new(rootJ, "frameSwapInterval", json_integer(frameSwapInterval)); | |||
json_object_set_new(rootJ, "frameRateLimit", json_real(frameRateLimit)); | |||
json_object_set_new(rootJ, "autosaveInterval", json_real(autosaveInterval)); | |||
@@ -347,9 +347,20 @@ void fromJson(json_t* rootJ) { | |||
if (squeezeModulesJ) | |||
squeezeModules = json_boolean_value(squeezeModulesJ); | |||
// Legacy setting in Rack <2.2 | |||
json_t* frameSwapIntervalJ = json_object_get(rootJ, "frameSwapInterval"); | |||
if (frameSwapIntervalJ) | |||
frameSwapInterval = json_integer_value(frameSwapIntervalJ); | |||
if (frameSwapIntervalJ) { | |||
// Assume 60 Hz monitor refresh rate. | |||
int frameSwapInterval = json_integer_value(frameSwapIntervalJ); | |||
if (frameSwapInterval > 0) | |||
frameRateLimit = 60.f / frameSwapInterval; | |||
else | |||
frameRateLimit = 0.f; | |||
} | |||
json_t* frameRateLimitJ = json_object_get(rootJ, "frameRateLimit"); | |||
if (frameRateLimitJ) | |||
frameRateLimit = json_number_value(frameRateLimitJ); | |||
json_t* autosaveIntervalJ = json_object_get(rootJ, "autosaveInterval"); | |||
if (autosaveIntervalJ) | |||
@@ -89,8 +89,8 @@ struct Window::Internal { | |||
int frame = 0; | |||
bool ignoreNextMouseDelta = false; | |||
int frameSwapInterval = -1; | |||
double monitorRefreshRate = 0.0; | |||
int frameSwapInterval = -1; | |||
double frameTime = 0.0; | |||
double lastFrameDuration = 0.0; | |||
@@ -298,7 +298,6 @@ Window::Window() { | |||
glfwSetInputMode(win, GLFW_LOCK_KEY_MODS, 1); | |||
glfwMakeContextCurrent(win); | |||
glfwSwapInterval(1); | |||
const GLFWvidmode* monitorMode = glfwGetVideoMode(glfwGetPrimaryMonitor()); | |||
if (monitorMode->refreshRate > 0) { | |||
internal->monitorRefreshRate = monitorMode->refreshRate; | |||
@@ -433,9 +432,16 @@ void Window::step() { | |||
// In case glfwPollEvents() sets another OpenGL context | |||
glfwMakeContextCurrent(win); | |||
if (settings::frameSwapInterval != internal->frameSwapInterval) { | |||
glfwSwapInterval(settings::frameSwapInterval); | |||
internal->frameSwapInterval = settings::frameSwapInterval; | |||
// Set swap interval | |||
int frameSwapInterval = 0; | |||
if (settings::frameRateLimit > 0.f) { | |||
frameSwapInterval = std::ceil(internal->monitorRefreshRate / settings::frameRateLimit); | |||
} | |||
if (frameSwapInterval != internal->frameSwapInterval) { | |||
glfwSwapInterval(frameSwapInterval); | |||
internal->frameSwapInterval = frameSwapInterval; | |||
} | |||
// Call cursorPosCallback every frame, not just when the mouse moves | |||
@@ -711,7 +717,7 @@ double Window::getLastFrameDuration() { | |||
double Window::getFrameDurationRemaining() { | |||
double frameDurationDesired = internal->frameSwapInterval / internal->monitorRefreshRate; | |||
double frameDurationDesired = 1.f / settings::frameRateLimit; | |||
return frameDurationDesired - (system::getTime() - internal->frameTime); | |||
} | |||