diff --git a/include/widget/FramebufferWidget.hpp b/include/widget/FramebufferWidget.hpp index 0166db75..ab0a1215 100644 --- a/include/widget/FramebufferWidget.hpp +++ b/include/widget/FramebufferWidget.hpp @@ -6,9 +6,8 @@ namespace rack { namespace widget { -/** Caches a widget's draw() result to a framebuffer so it is called less frequently. -When `dirty` is true, its children will be re-rendered on the next call to step(). -Events are not passed to the underlying scene. +/** Caches its children's draw() result to a framebuffer image. +When dirty, its children will be re-rendered on the next call to step(). */ struct FramebufferWidget : Widget { struct Internal; diff --git a/include/window.hpp b/include/window.hpp index a78e11b9..45032758 100644 --- a/include/window.hpp +++ b/include/window.hpp @@ -82,7 +82,7 @@ struct Window { void setFullScreen(bool fullScreen); bool isFullScreen(); double getMonitorRefreshRate(); - double getLastFrameTime(); + double getFrameTime(); double getLastFrameDuration(); double getFrameTimeOverdue(); diff --git a/src/app/RackWidget.cpp b/src/app/RackWidget.cpp index d729ca42..3257e08a 100644 --- a/src/app/RackWidget.cpp +++ b/src/app/RackWidget.cpp @@ -73,17 +73,17 @@ struct CableContainer : widget::TransparentWidget { RackWidget::RackWidget() { - railFb = new widget::FramebufferWidget; - railFb->box.size = math::Vec(); - railFb->oversample = 1.0; - // Don't redraw when the world offset of the rail FramebufferWidget changes its fractional value. - railFb->dirtyOnSubpixelChange = false; - { - RackRail* rail = new RackRail; - rail->box.size = math::Vec(); - railFb->addChild(rail); - } - addChild(railFb); + // railFb = new widget::FramebufferWidget; + // railFb->box.size = math::Vec(); + // railFb->oversample = 1.0; + // // Don't redraw when the world offset of the rail FramebufferWidget changes its fractional value. + // railFb->dirtyOnSubpixelChange = false; + // { + // RackRail* rail = new RackRail; + // rail->box.size = math::Vec(); + // railFb->addChild(rail); + // } + // addChild(railFb); moduleContainer = new ModuleContainer; addChild(moduleContainer); @@ -106,16 +106,16 @@ void RackWidget::draw(const DrawArgs& args) { nvgGlobalTint(args.vg, nvgRGBAf(b, b, b, 1)); // Resize and reposition the RackRail to align on the grid. - math::Rect railBox; - railBox.pos = args.clipBox.pos.div(BUS_BOARD_GRID_SIZE).floor().mult(BUS_BOARD_GRID_SIZE); - railBox.size = args.clipBox.size.div(BUS_BOARD_GRID_SIZE).ceil().plus(math::Vec(1, 1)).mult(BUS_BOARD_GRID_SIZE); - if (!railFb->box.size.equals(railBox.size)) { - railFb->dirty = true; - } - railFb->box = railBox; - - RackRail* rail = railFb->getFirstDescendantOfType(); - rail->box.size = railFb->box.size; + // math::Rect railBox; + // railBox.pos = args.clipBox.pos.div(BUS_BOARD_GRID_SIZE).floor().mult(BUS_BOARD_GRID_SIZE); + // railBox.size = args.clipBox.size.div(BUS_BOARD_GRID_SIZE).ceil().plus(math::Vec(1, 1)).mult(BUS_BOARD_GRID_SIZE); + // if (!railFb->box.size.equals(railBox.size)) { + // railFb->dirty = true; + // } + // railFb->box = railBox; + + // RackRail* rail = railFb->getFirstDescendantOfType(); + // rail->box.size = railFb->box.size; Widget::draw(args); } diff --git a/src/app/Scene.cpp b/src/app/Scene.cpp index b303ef54..60b7994f 100644 --- a/src/app/Scene.cpp +++ b/src/app/Scene.cpp @@ -111,7 +111,7 @@ void Scene::step() { // Autosave periodically if (settings::autosaveInterval > 0.0) { - double time = glfwGetTime(); + double time = system::getTime(); if (time - lastAutosaveTime >= settings::autosaveInterval) { lastAutosaveTime = time; APP->patch->saveAutosave(); diff --git a/src/widget/FramebufferWidget.cpp b/src/widget/FramebufferWidget.cpp index 67c83f95..cacf0fa7 100644 --- a/src/widget/FramebufferWidget.cpp +++ b/src/widget/FramebufferWidget.cpp @@ -95,10 +95,6 @@ void FramebufferWidget::draw(const DrawArgs& args) { if (APP->window->getFrameTimeOverdue() > 0.0) return; - // Check that scale has been set by `draw()` yet. - if (scale.isZero()) - return; - // In case we fail drawing the framebuffer, don't try again the next frame, so reset `dirty` here. dirty = false; NVGcontext* vg = APP->window->vg; @@ -134,8 +130,8 @@ void FramebufferWidget::draw(const DrawArgs& args) { } // Create a framebuffer if (internal->fbSize.isFinite() && !internal->fbSize.isZero()) { + // DEBUG("Creating framebuffer of size (%f, %f)", VEC_ARGS(internal->fbSize)); internal->fb = nvgluCreateFramebuffer(vg, internal->fbSize.x, internal->fbSize.y, 0); - // DEBUG("Created framebuffer of size (%f, %f)", VEC_ARGS(internal->fbSize)); } } if (!internal->fb) { @@ -143,7 +139,7 @@ void FramebufferWidget::draw(const DrawArgs& args) { return; } - DEBUG("Drawing to framebuffer of size (%f, %f)", VEC_ARGS(internal->fbSize)); + // DEBUG("Drawing to framebuffer of size (%f, %f)", VEC_ARGS(internal->fbSize)); // Render to framebuffer if (oversample == 1.0) { @@ -156,6 +152,7 @@ void FramebufferWidget::draw(const DrawArgs& args) { NVGLUframebuffer* fb = internal->fb; // If oversampling, create another framebuffer and copy it to actual size. math::Vec oversampledFbSize = internal->fbSize.mult(oversample).ceil(); + // DEBUG("Creating %0.fx oversampled framebuffer of size (%f, %f)", oversample, VEC_ARGS(internal->fbSize)); NVGLUframebuffer* oversampledFb = nvgluCreateFramebuffer(fbVg, oversampledFbSize.x, oversampledFbSize.y, 0); if (!oversampledFb) { @@ -170,9 +167,8 @@ void FramebufferWidget::draw(const DrawArgs& args) { internal->fb = fb; nvgluBindFramebuffer(NULL); - // Use NanoVG for resizing framebuffers + // Use NanoVG for copying oversampled framebuffer to normal framebuffer nvgluBindFramebuffer(internal->fb); - nvgBeginFrame(fbVg, internal->fbBox.size.x, internal->fbBox.size.y, 1.0); // Draw oversampled framebuffer @@ -205,11 +201,7 @@ void FramebufferWidget::draw(const DrawArgs& args) { nvgSave(args.vg); nvgResetTransform(args.vg); - math::Vec scaleRatio = math::Vec(1, 1); - if (!internal->fbScale.isZero() && !scale.equals(internal->fbScale)) { - // Continue to draw with the last framebuffer, but stretch it to rescale. - scaleRatio = scale.div(internal->fbScale); - } + math::Vec scaleRatio = scale.div(internal->fbScale); // DEBUG("%f %f %f %f", scaleRatio.x, scaleRatio.y, offsetF.x, offsetF.y); // DEBUG("%f %f %f %f, %f %f", RECT_ARGS(internal->fbBox), VEC_ARGS(internal->fbSize)); diff --git a/src/widget/event.cpp b/src/widget/event.cpp index 309d54c3..f171023f 100644 --- a/src/widget/event.cpp +++ b/src/widget/event.cpp @@ -2,6 +2,7 @@ #include #include #include +#include namespace rack { @@ -159,7 +160,7 @@ bool EventState::handleButton(math::Vec pos, int button, int action, int mods) { if (action == GLFW_PRESS) { const double doubleClickDuration = 0.3; - double clickTime = glfwGetTime(); + double clickTime = system::getTime(); if (clickedWidget && clickTime - lastClickTime <= doubleClickDuration && lastClickedWidget == clickedWidget) { diff --git a/src/window.cpp b/src/window.cpp index d946842e..94bc83c9 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -81,8 +81,8 @@ struct Window::Internal { bool ignoreNextMouseDelta = false; int frameSwapInterval = -1; double monitorRefreshRate = 0.0; + double frameTime = 0.0; double lastFrameDuration = 0.0; - double lastFrameTime = 0.0; math::Vec lastMousePos; @@ -387,10 +387,10 @@ void Window::run() { void Window::step() { - double frameTime = glfwGetTime(); - internal->lastFrameDuration = frameTime - internal->lastFrameTime; + double lastFrameTime = internal->frameTime; + internal->frameTime = system::getTime(); + internal->lastFrameDuration = internal->frameTime - lastFrameTime; // DEBUG("%.2lf Hz", 1.0 / internal->lastFrameDuration); - internal->lastFrameTime = frameTime; // Make event handlers and step() have a clean NanoVG context nvgReset(vg); @@ -540,7 +540,7 @@ void Window::screenshotModules(const std::string& screenshotsDir, float zoom) { zw->addChild(mw); // HACK: Set the frame time so FramebufferWidgets are never overdue and therefore guaranteed to draw - internal->lastFrameTime = INFINITY; + internal->frameTime = INFINITY; // Draw to framebuffer fbw->step(); @@ -636,8 +636,8 @@ double Window::getMonitorRefreshRate() { } -double Window::getLastFrameTime() { - return internal->lastFrameTime; +double Window::getFrameTime() { + return internal->frameTime; } @@ -648,7 +648,7 @@ double Window::getLastFrameDuration() { double Window::getFrameTimeOverdue() { double desiredFrameDuration = internal->frameSwapInterval / internal->monitorRefreshRate; - double frameDuration = glfwGetTime() - internal->lastFrameTime; + double frameDuration = system::getTime() - internal->frameTime; return frameDuration - desiredFrameDuration; }