| @@ -91,8 +91,8 @@ struct Window::Internal { | |||||
| bool ignoreNextMouseDelta = false; | bool ignoreNextMouseDelta = false; | ||||
| double monitorRefreshRate = 0.0; | double monitorRefreshRate = 0.0; | ||||
| int frameSwapInterval = -1; | int frameSwapInterval = -1; | ||||
| double frameTime = 0.0; | |||||
| double lastFrameDuration = 0.0; | |||||
| double frameTime = NAN; | |||||
| double lastFrameDuration = NAN; | |||||
| math::Vec lastMousePos; | math::Vec lastMousePos; | ||||
| @@ -298,6 +298,7 @@ Window::Window() { | |||||
| glfwSetInputMode(win, GLFW_LOCK_KEY_MODS, 1); | glfwSetInputMode(win, GLFW_LOCK_KEY_MODS, 1); | ||||
| glfwMakeContextCurrent(win); | glfwMakeContextCurrent(win); | ||||
| glfwSwapInterval(0); | |||||
| 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; | ||||
| @@ -412,11 +413,11 @@ void Window::run() { | |||||
| void Window::step() { | void Window::step() { | ||||
| double frameTime = system::getTime(); | double frameTime = system::getTime(); | ||||
| double lastFrameTime = internal->frameTime; | |||||
| if (std::isfinite(internal->frameTime)) { | |||||
| internal->lastFrameDuration = frameTime - internal->frameTime; | |||||
| } | |||||
| internal->frameTime = frameTime; | internal->frameTime = frameTime; | ||||
| internal->lastFrameDuration = frameTime - lastFrameTime; | |||||
| internal->fbCount = 0; | internal->fbCount = 0; | ||||
| // DEBUG("%.2lf Hz", 1.0 / internal->lastFrameDuration); | |||||
| // double t1 = 0.0, t2 = 0.0, t3 = 0.0, t4 = 0.0, t5 = 0.0; | // double t1 = 0.0, t2 = 0.0, t3 = 0.0, t4 = 0.0, t5 = 0.0; | ||||
| // Make event handlers and step() have a clean NanoVG context | // Make event handlers and step() have a clean NanoVG context | ||||
| @@ -433,17 +434,6 @@ void Window::step() { | |||||
| // In case glfwPollEvents() sets another OpenGL context | // In case glfwPollEvents() sets another OpenGL context | ||||
| glfwMakeContextCurrent(win); | glfwMakeContextCurrent(win); | ||||
| // 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 | ||||
| { | { | ||||
| double xpos, ypos; | double xpos, ypos; | ||||
| @@ -514,25 +504,26 @@ void Window::step() { | |||||
| glClearColor(0.0, 0.0, 0.0, 1.0); | glClearColor(0.0, 0.0, 0.0, 1.0); | ||||
| glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); | ||||
| nvgEndFrame(vg); | nvgEndFrame(vg); | ||||
| // t4 = system::getTime(); | |||||
| } | } | ||||
| // t4 = system::getTime(); | |||||
| } | } | ||||
| glfwSwapBuffers(win); | glfwSwapBuffers(win); | ||||
| // On some platforms, glfwSwapBuffers() doesn't wait on monitor refresh, so we have to sleep as a fallback. | |||||
| double frameDurationRemaining = getFrameDurationRemaining(); | |||||
| if (frameDurationRemaining > 0.0) { | |||||
| std::this_thread::sleep_for(std::chrono::duration<double>(frameDurationRemaining)); | |||||
| // Limit frame rate | |||||
| if (settings::frameRateLimit > 0) { | |||||
| double remaining = getFrameDurationRemaining(); | |||||
| if (remaining > 0.0) { | |||||
| system::sleep(remaining); | |||||
| } | |||||
| } | } | ||||
| // t5 = system::getTime(); | // t5 = system::getTime(); | ||||
| // DEBUG("pre-step %6.1f step %6.1f draw %6.1f nvgEndFrame %6.1f glfwSwapBuffers %6.1f total %6.1f", | // DEBUG("pre-step %6.1f step %6.1f draw %6.1f nvgEndFrame %6.1f glfwSwapBuffers %6.1f total %6.1f", | ||||
| // (t1 - frameTime) * 1e3f, | // (t1 - frameTime) * 1e3f, | ||||
| // (t2 - t1) * 1e3f, | // (t2 - t1) * 1e3f, | ||||
| // (t3 - t2) * 1e3f, | // (t3 - t2) * 1e3f, | ||||
| // (t4 - t2) * 1e3f, | |||||
| // (t4 - t3) * 1e3f, | |||||
| // (t5 - t4) * 1e3f, | // (t5 - t4) * 1e3f, | ||||
| // (t5 - frameTime) * 1e3f | // (t5 - frameTime) * 1e3f | ||||
| // ); | // ); | ||||
| @@ -717,8 +708,8 @@ double Window::getLastFrameDuration() { | |||||
| double Window::getFrameDurationRemaining() { | double Window::getFrameDurationRemaining() { | ||||
| double frameDurationDesired = 1.f / settings::frameRateLimit; | |||||
| return frameDurationDesired - (system::getTime() - internal->frameTime); | |||||
| double frameDuration = 1.f / settings::frameRateLimit; | |||||
| return frameDuration - (system::getTime() - internal->frameTime); | |||||
| } | } | ||||