| @@ -67,7 +67,8 @@ extern bool tooltips; | |||||
| extern bool cpuMeter; | extern bool cpuMeter; | ||||
| extern bool lockModules; | extern bool lockModules; | ||||
| extern bool squeezeModules; | extern bool squeezeModules; | ||||
| extern int frameSwapInterval; | |||||
| /** Maximum screen redraw frequency in Hz, or 0 for unlimited. */ | |||||
| extern float frameRateLimit; | |||||
| extern float autosaveInterval; | extern float autosaveInterval; | ||||
| extern bool skipLoadOnLaunch; | extern bool skipLoadOnLaunch; | ||||
| extern std::list<std::string> recentPatchPaths; | extern std::list<std::string> recentPatchPaths; | ||||
| @@ -409,13 +409,12 @@ struct ViewButton : MenuButton { | |||||
| APP->window->setFullScreen(!fullscreen); | 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++) { | for (int i = 1; i <= 6; i++) { | ||||
| double frameRate = APP->window->getMonitorRefreshRate() / i; | double frameRate = APP->window->getMonitorRefreshRate() / i; | ||||
| menu->addChild(createCheckMenuItem(string::f("%.0f Hz", frameRate), "", | 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 lockModules = false; | ||||
| bool squeezeModules = true; | bool squeezeModules = true; | ||||
| #if defined ARCH_MAC | #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 | #else | ||||
| int frameSwapInterval = 1; | |||||
| float frameRateLimit = 60.f; | |||||
| #endif | #endif | ||||
| float autosaveInterval = 15.0; | float autosaveInterval = 15.0; | ||||
| bool skipLoadOnLaunch = false; | bool skipLoadOnLaunch = false; | ||||
| @@ -158,7 +158,7 @@ json_t* toJson() { | |||||
| json_object_set_new(rootJ, "squeezeModules", json_boolean(squeezeModules)); | 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)); | json_object_set_new(rootJ, "autosaveInterval", json_real(autosaveInterval)); | ||||
| @@ -347,9 +347,20 @@ void fromJson(json_t* rootJ) { | |||||
| if (squeezeModulesJ) | if (squeezeModulesJ) | ||||
| squeezeModules = json_boolean_value(squeezeModulesJ); | squeezeModules = json_boolean_value(squeezeModulesJ); | ||||
| // Legacy setting in Rack <2.2 | |||||
| json_t* frameSwapIntervalJ = json_object_get(rootJ, "frameSwapInterval"); | 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"); | json_t* autosaveIntervalJ = json_object_get(rootJ, "autosaveInterval"); | ||||
| if (autosaveIntervalJ) | if (autosaveIntervalJ) | ||||
| @@ -89,8 +89,8 @@ struct Window::Internal { | |||||
| int frame = 0; | int frame = 0; | ||||
| bool ignoreNextMouseDelta = false; | bool ignoreNextMouseDelta = false; | ||||
| int frameSwapInterval = -1; | |||||
| double monitorRefreshRate = 0.0; | double monitorRefreshRate = 0.0; | ||||
| int frameSwapInterval = -1; | |||||
| double frameTime = 0.0; | double frameTime = 0.0; | ||||
| double lastFrameDuration = 0.0; | double lastFrameDuration = 0.0; | ||||
| @@ -298,7 +298,6 @@ Window::Window() { | |||||
| glfwSetInputMode(win, GLFW_LOCK_KEY_MODS, 1); | glfwSetInputMode(win, GLFW_LOCK_KEY_MODS, 1); | ||||
| glfwMakeContextCurrent(win); | glfwMakeContextCurrent(win); | ||||
| glfwSwapInterval(1); | |||||
| const GLFWvidmode* monitorMode = glfwGetVideoMode(glfwGetPrimaryMonitor()); | const GLFWvidmode* monitorMode = glfwGetVideoMode(glfwGetPrimaryMonitor()); | ||||
| if (monitorMode->refreshRate > 0) { | if (monitorMode->refreshRate > 0) { | ||||
| internal->monitorRefreshRate = monitorMode->refreshRate; | internal->monitorRefreshRate = monitorMode->refreshRate; | ||||
| @@ -433,9 +432,16 @@ void Window::step() { | |||||
| // In case glfwPollEvents() sets another OpenGL context | // In case glfwPollEvents() sets another OpenGL context | ||||
| glfwMakeContextCurrent(win); | 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 | // Call cursorPosCallback every frame, not just when the mouse moves | ||||
| @@ -711,7 +717,7 @@ double Window::getLastFrameDuration() { | |||||
| double Window::getFrameDurationRemaining() { | double Window::getFrameDurationRemaining() { | ||||
| double frameDurationDesired = internal->frameSwapInterval / internal->monitorRefreshRate; | |||||
| double frameDurationDesired = 1.f / settings::frameRateLimit; | |||||
| return frameDurationDesired - (system::getTime() - internal->frameTime); | return frameDurationDesired - (system::getTime() - internal->frameTime); | ||||
| } | } | ||||