DPF

DISTRHO Plugin Framework
Log | Files | Refs | Submodules | README | LICENSE

commit bb33ac67bc3713a1fe2dd85104f93e466e04b806
parent 93ce2476d997f524cd2c2e749f7e672905d126b6
Author: falkTX <falktx@falktx.com>
Date:   Sun, 11 Sep 2022 15:38:55 +0100

Implement reusing nanovg context across parent/children widgets

Diffstat:
Mdgl/NanoVG.hpp | 31++++++++++++++++++++-----------
Mdgl/src/NanoVG.cpp | 97++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 111 insertions(+), 17 deletions(-)

diff --git a/dgl/NanoVG.hpp b/dgl/NanoVG.hpp @@ -319,10 +319,9 @@ public: /** Constructor reusing a NanoVG context, used for subwidgets. + Context will not be deleted on class destructor. */ - /* - NanoVG(NanoWidget* groupWidget); - */ + explicit NanoVG(NVGcontext* context); /** Destructor. @@ -917,7 +916,17 @@ public: Constructor for a NanoSubWidget. @see CreateFlags */ - explicit NanoBaseWidget(Widget* parentGroupWidget, int flags = CREATE_ANTIALIAS); + explicit NanoBaseWidget(Widget* parentWidget, int flags = CREATE_ANTIALIAS); + + /** + Constructor for a NanoSubWidget reusing a parent subwidget nanovg context. + */ + explicit NanoBaseWidget(NanoBaseWidget<SubWidget>* parentWidget); + + /** + Constructor for a NanoSubWidget reusing a parent top-level-widget nanovg context. + */ + explicit NanoBaseWidget(NanoBaseWidget<TopLevelWidget>* parentWidget); /** Constructor for a NanoTopLevelWidget. @@ -954,13 +963,7 @@ private: Widget display function. Implemented internally to wrap begin/endFrame() automatically. */ - inline void onDisplay() override - { - // NOTE maybe should use BaseWidget::getWindow().getScaleFactor() as 3rd arg ? - NanoVG::beginFrame(BaseWidget::getWidth(), BaseWidget::getHeight()); - onNanoDisplay(); - NanoVG::endFrame(); - } + void onDisplay() override; // these should not be used void beginFrame(uint,uint) {} @@ -969,6 +972,12 @@ private: void cancelFrame() {} void endFrame() {} + /** @internal */ + const bool fUsingParentContext; + void displayChildren(); + friend class NanoBaseWidget<TopLevelWidget>; + friend class NanoBaseWidget<StandaloneWindow>; + DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NanoBaseWidget) }; diff --git a/dgl/src/NanoVG.cpp b/dgl/src/NanoVG.cpp @@ -327,6 +327,14 @@ NanoVG::NanoVG(int flags) DISTRHO_CUSTOM_SAFE_ASSERT("Failed to create NanoVG context, expect a black screen", fContext != nullptr); } +NanoVG::NanoVG(NVGcontext* const context) + : fContext(context), + fInFrame(false), + fIsSubWidget(true) +{ + DISTRHO_CUSTOM_SAFE_ASSERT("Failed to create NanoVG context, expect a black screen", fContext != nullptr); +} + NanoVG::~NanoVG() { DISTRHO_CUSTOM_SAFE_ASSERT("Destroying NanoVG context with still active frame", ! fInFrame); @@ -1058,16 +1066,72 @@ bool NanoVG::loadSharedResources() #endif // ----------------------------------------------------------------------- + +template <class BaseWidget> +void NanoBaseWidget<BaseWidget>::displayChildren() +{ + std::list<SubWidget*> children(BaseWidget::getChildren()); + + for (std::list<SubWidget*>::iterator it = children.begin(); it != children.end(); ++it) + { + if (NanoSubWidget* const subwidget = dynamic_cast<NanoSubWidget*>(*it)) + { + if (subwidget->fUsingParentContext && subwidget->isVisible()) + subwidget->onDisplay(); + } + } +} + +// ----------------------------------------------------------------------- // NanoSubWidget template <> -NanoBaseWidget<SubWidget>::NanoBaseWidget(Widget* const parent, int flags) - : SubWidget(parent), - NanoVG(flags) +NanoBaseWidget<SubWidget>::NanoBaseWidget(Widget* const parentWidget, int flags) + : SubWidget(parentWidget), + NanoVG(flags), + fUsingParentContext(false) { setNeedsViewportScaling(); } +template <> +NanoBaseWidget<SubWidget>::NanoBaseWidget(NanoSubWidget* const parentWidget) + : SubWidget(parentWidget), + NanoVG(parentWidget->getContext()), + fUsingParentContext(true) +{ + setSkipDrawing(); +} + +template <> +NanoBaseWidget<SubWidget>::NanoBaseWidget(NanoTopLevelWidget* const parentWidget) + : SubWidget(parentWidget), + NanoVG(parentWidget->getContext()), + fUsingParentContext(true) +{ + setSkipDrawing(); +} + +template <> +inline void NanoBaseWidget<SubWidget>::onDisplay() +{ + if (fUsingParentContext) + { + NanoVG::save(); + translate(SubWidget::getAbsoluteX(), SubWidget::getAbsoluteY()); + onNanoDisplay(); + NanoVG::restore(); + displayChildren(); + } + else + { + NanoVG::beginFrame(SubWidget::getWidth(), SubWidget::getHeight()); + onNanoDisplay(); + displayChildren(); + NanoVG::endFrame(); + } +} + template class NanoBaseWidget<SubWidget>; // ----------------------------------------------------------------------- @@ -1076,7 +1140,17 @@ template class NanoBaseWidget<SubWidget>; template <> NanoBaseWidget<TopLevelWidget>::NanoBaseWidget(Window& windowToMapTo, int flags) : TopLevelWidget(windowToMapTo), - NanoVG(flags) {} + NanoVG(flags), + fUsingParentContext(false) {} + +template <> +inline void NanoBaseWidget<TopLevelWidget>::onDisplay() +{ + NanoVG::beginFrame(TopLevelWidget::getWidth(), TopLevelWidget::getHeight()); + onNanoDisplay(); + displayChildren(); + NanoVG::endFrame(); +} template class NanoBaseWidget<TopLevelWidget>; @@ -1086,12 +1160,23 @@ template class NanoBaseWidget<TopLevelWidget>; template <> NanoBaseWidget<StandaloneWindow>::NanoBaseWidget(Application& app, int flags) : StandaloneWindow(app), - NanoVG(flags) {} + NanoVG(flags), + fUsingParentContext(false) {} template <> NanoBaseWidget<StandaloneWindow>::NanoBaseWidget(Application& app, Window& parentWindow, int flags) : StandaloneWindow(app, parentWindow), - NanoVG(flags) {} + NanoVG(flags), + fUsingParentContext(false) {} + +template <> +inline void NanoBaseWidget<StandaloneWindow>::onDisplay() +{ + NanoVG::beginFrame(Window::getWidth(), Window::getHeight()); + onNanoDisplay(); + displayChildren(); + NanoVG::endFrame(); +} template class NanoBaseWidget<StandaloneWindow>;