|
@@ -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); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|