From 4ad0b79eecfeae6c21037f30aa94254158057d68 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 26 Oct 2023 18:48:28 +0900 Subject: [PATCH] renderer: revise the internal paints structure. Get rid of the polymorphism function table, use the switch directly instead. We profiled, both binary & performance is better than before. Tested on a local machine (single thread): - Lottie: 2ms improved - Binary: -0.5kb --- src/renderer/tvgPaint.cpp | 76 +++++++++++++++++++++++-------- src/renderer/tvgPaint.h | 91 ++++--------------------------------- src/renderer/tvgPicture.cpp | 1 - src/renderer/tvgRender.cpp | 19 +++----- src/renderer/tvgRender.h | 4 +- src/renderer/tvgScene.cpp | 1 - src/renderer/tvgScene.h | 2 +- src/renderer/tvgShape.cpp | 1 - 8 files changed, 75 insertions(+), 120 deletions(-) diff --git a/src/renderer/tvgPaint.cpp b/src/renderer/tvgPaint.cpp index 3a5eb7fc..5af63c6d 100644 --- a/src/renderer/tvgPaint.cpp +++ b/src/renderer/tvgPaint.cpp @@ -22,11 +22,22 @@ #include "tvgMath.h" #include "tvgPaint.h" +#include "tvgShape.h" +#include "tvgPicture.h" +#include "tvgScene.h" /************************************************************************/ /* Internal Class Implementation */ /************************************************************************/ +#define PAINT_METHOD(ret, METHOD) \ + switch (id) { \ + case TVG_CLASS_ID_SHAPE: ret = P((Shape*)paint)->METHOD; break; \ + case TVG_CLASS_ID_SCENE: ret = P((Scene*)paint)->METHOD; break; \ + case TVG_CLASS_ID_PICTURE: ret = P((Picture*)paint)->METHOD; break; \ + default: ret = {}; \ + } + static bool _compFastTrack(Paint* cmpTarget, const RenderTransform* pTransform, RenderTransform* rTransform, RenderRegion& viewport) { @@ -93,9 +104,36 @@ static bool _compFastTrack(Paint* cmpTarget, const RenderTransform* pTransform, } +RenderRegion Paint::Impl::bounds(RenderMethod& renderer) const +{ + RenderRegion ret; + PAINT_METHOD(ret, bounds(renderer)); + return ret; +} + + +bool Paint::Impl::dispose(RenderMethod& renderer) +{ + if (compData) compData->target->pImpl->dispose(renderer); + + bool ret; + PAINT_METHOD(ret, dispose(renderer)); + return ret; +} + + +Iterator* Paint::Impl::iterator() +{ + Iterator* ret; + PAINT_METHOD(ret, iterator()); + return ret; +} + + Paint* Paint::Impl::duplicate() { - auto ret = smethod->duplicate(); + Paint* ret; + PAINT_METHOD(ret, duplicate()); //duplicate Transform if (rTransform) { @@ -165,8 +203,10 @@ bool Paint::Impl::render(RenderMethod& renderer) /* Note: only ClipPath is processed in update() step. Create a composition image. */ if (compData && compData->method != CompositeMethod::ClipPath && !(compData->target->pImpl->ctxFlag & ContextFlag::FastTrack)) { - auto region = smethod->bounds(renderer); - if (MASK_REGION_MERGING(compData->method)) region.add(compData->target->pImpl->smethod->bounds(renderer)); + RenderRegion region; + PAINT_METHOD(region, bounds(renderer)); + + if (MASK_REGION_MERGING(compData->method)) region.add(P(compData->target)->bounds(renderer)); if (region.w == 0 || region.h == 0) return true; cmp = renderer.target(region, COMPOSITE_TO_COLORSPACE(renderer, compData->method)); if (renderer.beginComposite(cmp, CompositeMethod::None, 255)) { @@ -177,7 +217,9 @@ bool Paint::Impl::render(RenderMethod& renderer) if (cmp) renderer.beginComposite(cmp, compData->method, compData->target->pImpl->opacity); renderer.blend(blendMethod); - auto ret = smethod->render(renderer); + + bool ret; + PAINT_METHOD(ret, render(renderer)); if (cmp) renderer.endComposite(cmp); @@ -189,10 +231,7 @@ RenderData Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pT { if (renderFlag & RenderUpdateFlag::Transform) { if (!rTransform) return nullptr; - if (!rTransform->update()) { - delete(rTransform); - rTransform = nullptr; - } + rTransform->update(); } /* 1. Composition Pre Processing */ @@ -239,18 +278,13 @@ RenderData Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pT } /* 2. Main Update */ - RenderData rd = nullptr; auto newFlag = static_cast(pFlag | renderFlag); renderFlag = RenderUpdateFlag::None; opacity = MULTIPLY(opacity, this->opacity); - if (rTransform && pTransform) { - RenderTransform outTransform(pTransform, rTransform); - rd = smethod->update(renderer, &outTransform, clips, opacity, newFlag, clipper); - } else { - auto outTransform = pTransform ? pTransform : rTransform; - rd = smethod->update(renderer, outTransform, clips, opacity, newFlag, clipper); - } + RenderData rd = nullptr; + RenderTransform outTransform(pTransform, rTransform); + PAINT_METHOD(rd, update(renderer, &outTransform, clips, opacity, newFlag, clipper)); /* 3. Composition Post Processing */ if (compFastTrack) renderer.viewport(viewport); @@ -263,9 +297,13 @@ RenderData Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pT bool Paint::Impl::bounds(float* x, float* y, float* w, float* h, bool transformed, bool stroking) { Matrix* m = nullptr; + bool ret; //Case: No transformed, quick return! - if (!transformed || !(m = this->transform())) return smethod->bounds(x, y, w, h, stroking); + if (!transformed || !(m = this->transform())) { + PAINT_METHOD(ret, bounds(x, y, w, h, stroking)); + return ret; + } //Case: Transformed auto tx = 0.0f; @@ -273,7 +311,7 @@ bool Paint::Impl::bounds(float* x, float* y, float* w, float* h, bool transforme auto tw = 0.0f; auto th = 0.0f; - auto ret = smethod->bounds(&tx, &ty, &tw, &th, stroking); + PAINT_METHOD(ret, bounds(&tx, &ty, &tw, &th, stroking)); //Get vertices Point pt[4] = {{tx, ty}, {tx + tw, ty}, {tx + tw, ty + th}, {tx, ty + th}}; @@ -307,7 +345,7 @@ bool Paint::Impl::bounds(float* x, float* y, float* w, float* h, bool transforme /* External Class Implementation */ /************************************************************************/ -Paint :: Paint() : pImpl(new Impl()) +Paint :: Paint() : pImpl(new Impl(this)) { } diff --git a/src/renderer/tvgPaint.h b/src/renderer/tvgPaint.h index 88f8f4ad..ca1818b7 100644 --- a/src/renderer/tvgPaint.h +++ b/src/renderer/tvgPaint.h @@ -38,19 +38,6 @@ namespace tvg virtual void begin() = 0; }; - struct StrategyMethod - { - virtual ~StrategyMethod() {} - - virtual bool dispose(RenderMethod& renderer) = 0; //return true if the deletion is allowed. - virtual void* update(RenderMethod& renderer, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag pFlag, bool clipper) = 0; //Return engine data if it has. - virtual bool render(RenderMethod& renderer) = 0; - virtual bool bounds(float* x, float* y, float* w, float* h, bool stroking) = 0; - virtual RenderRegion bounds(RenderMethod& renderer) const = 0; - virtual Paint* duplicate() = 0; - virtual Iterator* iterator() = 0; - }; - struct Composite { Paint* target; @@ -60,7 +47,7 @@ namespace tvg struct Paint::Impl { - StrategyMethod* smethod = nullptr; + Paint* paint = nullptr; RenderTransform* rTransform = nullptr; Composite* compData = nullptr; BlendMethod blendMethod = BlendMethod::Normal; //uint8_t @@ -70,13 +57,16 @@ namespace tvg uint8_t opacity = 255; uint8_t refCnt = 0; + Impl(Paint* paint) : paint(paint) + { + } + ~Impl() { if (compData) { if (P(compData->target)->unref() == 0) delete(compData->target); free(compData); } - delete(smethod); delete(rTransform); } @@ -92,11 +82,6 @@ namespace tvg return (--refCnt); } - void method(StrategyMethod* method) - { - smethod = method; - } - bool transform(const Matrix& m) { if (!rTransform) { @@ -119,22 +104,6 @@ namespace tvg return nullptr; } - RenderRegion bounds(RenderMethod& renderer) const - { - return smethod->bounds(renderer); - } - - bool dispose(RenderMethod& renderer) - { - if (compData) compData->target->pImpl->dispose(renderer); - return smethod->dispose(renderer); - } - - Iterator* iterator() - { - return smethod->iterator(); - } - bool composite(Paint* source, Paint* target, CompositeMethod method) { //Invalid case @@ -162,6 +131,9 @@ namespace tvg return true; } + RenderRegion bounds(RenderMethod& renderer) const; + bool dispose(RenderMethod& renderer); + Iterator* iterator(); bool rotate(float degree); bool scale(float factor); bool translate(float x, float y); @@ -170,51 +142,6 @@ namespace tvg bool render(RenderMethod& renderer); Paint* duplicate(); }; - - - template - struct PaintMethod : StrategyMethod - { - T* inst = nullptr; - - PaintMethod(T* _inst) : inst(_inst) {} - ~PaintMethod() {} - - bool bounds(float* x, float* y, float* w, float* h, bool stroking) override - { - return inst->bounds(x, y, w, h, stroking); - } - - RenderRegion bounds(RenderMethod& renderer) const override - { - return inst->bounds(renderer); - } - - bool dispose(RenderMethod& renderer) override - { - return inst->dispose(renderer); - } - - RenderData update(RenderMethod& renderer, const RenderTransform* transform, Array& clips, uint8_t opacity, RenderUpdateFlag renderFlag, bool clipper) override - { - return inst->update(renderer, transform, clips, opacity, renderFlag, clipper); - } - - bool render(RenderMethod& renderer) override - { - return inst->render(renderer); - } - - Paint* duplicate() override - { - return inst->duplicate(); - } - - Iterator* iterator() override - { - return inst->iterator(); - } - }; } -#endif //_TVG_PAINT_H_ +#endif //_TVG_PAINT_H_ \ No newline at end of file diff --git a/src/renderer/tvgPicture.cpp b/src/renderer/tvgPicture.cpp index 07877b92..e3827956 100644 --- a/src/renderer/tvgPicture.cpp +++ b/src/renderer/tvgPicture.cpp @@ -62,7 +62,6 @@ RenderUpdateFlag Picture::Impl::load() Picture::Picture() : pImpl(new Impl(this)) { Paint::pImpl->id = TVG_CLASS_ID_PICTURE; - Paint::pImpl->method(new PaintMethod(pImpl)); } diff --git a/src/renderer/tvgRender.cpp b/src/renderer/tvgRender.cpp index 9768b5ed..64d76d35 100644 --- a/src/renderer/tvgRender.cpp +++ b/src/renderer/tvgRender.cpp @@ -39,12 +39,9 @@ void RenderTransform::override(const Matrix& m) } -bool RenderTransform::update() +void RenderTransform::update() { - if (overriding) return true; - - //Init Status - if (mathZero(x) && mathZero(y) && mathZero(degree) && mathEqual(scale, 1)) return false; + if (overriding) return; mathIdentity(&m); @@ -53,17 +50,13 @@ bool RenderTransform::update() if (!mathZero(degree)) mathRotate(&m, degree); mathTranslate(&m, x, y); - - return true; -} - - -RenderTransform::RenderTransform() -{ } RenderTransform::RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs) { - m = mathMultiply(&lhs->m, &rhs->m); + if (lhs && rhs) m = mathMultiply(&lhs->m, &rhs->m); + else if (lhs) m = lhs->m; + else if (rhs) m = rhs->m; + else mathIdentity(&m); } diff --git a/src/renderer/tvgRender.h b/src/renderer/tvgRender.h index 1231089f..cd3f4f3f 100644 --- a/src/renderer/tvgRender.h +++ b/src/renderer/tvgRender.h @@ -123,10 +123,10 @@ struct RenderTransform float scale = 1.0f; //scale factor bool overriding = false; //user transform? - bool update(); + void update(); void override(const Matrix& m); - RenderTransform(); + RenderTransform() {} RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs); }; diff --git a/src/renderer/tvgScene.cpp b/src/renderer/tvgScene.cpp index a4a34608..d33c0f98 100644 --- a/src/renderer/tvgScene.cpp +++ b/src/renderer/tvgScene.cpp @@ -29,7 +29,6 @@ Scene::Scene() : pImpl(new Impl(this)) { Paint::pImpl->id = TVG_CLASS_ID_SCENE; - Paint::pImpl->method(new PaintMethod(pImpl)); } diff --git a/src/renderer/tvgScene.h b/src/renderer/tvgScene.h index 10daa49a..25ceaca6 100644 --- a/src/renderer/tvgScene.h +++ b/src/renderer/tvgScene.h @@ -75,7 +75,7 @@ struct Scene::Impl ~Impl() { for (auto paint : paints) { - if (paint->pImpl->unref() == 0) delete(paint); + if (P(paint)->unref() == 0) delete(paint); } } diff --git a/src/renderer/tvgShape.cpp b/src/renderer/tvgShape.cpp index e64491d6..ebae44c0 100644 --- a/src/renderer/tvgShape.cpp +++ b/src/renderer/tvgShape.cpp @@ -35,7 +35,6 @@ constexpr auto PATH_KAPPA = 0.552284f; Shape :: Shape() : pImpl(new Impl(this)) { Paint::pImpl->id = TVG_CLASS_ID_SHAPE; - Paint::pImpl->method(new PaintMethod(pImpl)); }