From 0e991651397832c920374bdd243531cdd815e2b3 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Mon, 18 Feb 2019 16:10:31 -0500 Subject: [PATCH] Fix framebuffer incorrect scale when zooming. Reset NanoVG state after drawing framebuffer. --- include/widget/FramebufferWidget.hpp | 5 ----- src/widget/FramebufferWidget.cpp | 22 ++++++++++++++++++---- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/include/widget/FramebufferWidget.hpp b/include/widget/FramebufferWidget.hpp index 76eafd0a..b557272e 100644 --- a/include/widget/FramebufferWidget.hpp +++ b/include/widget/FramebufferWidget.hpp @@ -36,11 +36,6 @@ struct FramebufferWidget : Widget { void draw(const DrawArgs &args) override; virtual void drawFramebuffer(); int getImageHandle(); - - void onZoom(const event::Zoom &e) override { - dirty = true; - Widget::onZoom(e); - } }; diff --git a/src/widget/FramebufferWidget.cpp b/src/widget/FramebufferWidget.cpp index c6fb0744..ffbd4da3 100644 --- a/src/widget/FramebufferWidget.cpp +++ b/src/widget/FramebufferWidget.cpp @@ -1,5 +1,6 @@ #include "widget/FramebufferWidget.hpp" #include "app.hpp" +#include "random.hpp" namespace rack { @@ -18,6 +19,9 @@ FramebufferWidget::~FramebufferWidget() { void FramebufferWidget::step() { Widget::step(); + // if (random::uniform() > 0.01) + // return; + // Render to framebuffer if dirty. // Also check that scale has been set by `draw()` yet. if (dirty && !scale.isZero()) { @@ -77,13 +81,20 @@ void FramebufferWidget::draw(const DrawArgs &args) { float xform[6]; nvgCurrentTransform(args.vg, xform); // Skew and rotate is not supported - assert(math::isNear(xform[1], 0.f)); - assert(math::isNear(xform[2], 0.f)); + if (!math::isNear(xform[1], 0.f) || !math::isNear(xform[2], 0.f)) + return; // Extract scale and offset from world transform scale = math::Vec(xform[0], xform[3]); offset = math::Vec(xform[4], xform[5]); math::Vec offsetI = offset.floor(); + math::Vec scaleRatio = math::Vec(1, 1); + if (!fbScale.isZero() && !scale.isEqual(fbScale)) { + dirty = true; + // Continue to draw but at the wrong scale. In the next frame, the framebuffer will be redrawn. + scaleRatio = scale.div(fbScale); + } + if (!fb) return; @@ -95,11 +106,11 @@ void FramebufferWidget::draw(const DrawArgs &args) { nvgRect(args.vg, offsetI.x + fbBox.pos.x, offsetI.y + fbBox.pos.y, - fbBox.size.x, fbBox.size.y); + fbBox.size.x * scaleRatio.x, fbBox.size.y * scaleRatio.y); NVGpaint paint = nvgImagePattern(args.vg, offsetI.x + fbBox.pos.x, offsetI.y + fbBox.pos.y, - fbBox.size.x, fbBox.size.y, + fbBox.size.x * scaleRatio.x, fbBox.size.y * scaleRatio.y, 0.0, fb->image, 1.0); nvgFillPaint(args.vg, paint); nvgFill(args.vg); @@ -134,6 +145,9 @@ void FramebufferWidget::drawFramebuffer() { // glClearColor(0.0, 1.0, 1.0, 0.5); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); nvgEndFrame(vg); + + // Clean up the NanoVG state so that calls to nvgTextBounds() etc during step() don't use a dirty state. + nvgReset(vg); } int FramebufferWidget::getImageHandle() {