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
This commit is contained in:
Hermet Park 2023-10-26 18:48:28 +09:00
parent fe259d0414
commit 4ad0b79eec
8 changed files with 75 additions and 120 deletions

View file

@ -22,11 +22,22 @@
#include "tvgMath.h" #include "tvgMath.h"
#include "tvgPaint.h" #include "tvgPaint.h"
#include "tvgShape.h"
#include "tvgPicture.h"
#include "tvgScene.h"
/************************************************************************/ /************************************************************************/
/* Internal Class Implementation */ /* 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) 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() Paint* Paint::Impl::duplicate()
{ {
auto ret = smethod->duplicate(); Paint* ret;
PAINT_METHOD(ret, duplicate());
//duplicate Transform //duplicate Transform
if (rTransform) { if (rTransform) {
@ -165,8 +203,10 @@ bool Paint::Impl::render(RenderMethod& renderer)
/* Note: only ClipPath is processed in update() step. /* Note: only ClipPath is processed in update() step.
Create a composition image. */ Create a composition image. */
if (compData && compData->method != CompositeMethod::ClipPath && !(compData->target->pImpl->ctxFlag & ContextFlag::FastTrack)) { if (compData && compData->method != CompositeMethod::ClipPath && !(compData->target->pImpl->ctxFlag & ContextFlag::FastTrack)) {
auto region = smethod->bounds(renderer); RenderRegion region;
if (MASK_REGION_MERGING(compData->method)) region.add(compData->target->pImpl->smethod->bounds(renderer)); 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; if (region.w == 0 || region.h == 0) return true;
cmp = renderer.target(region, COMPOSITE_TO_COLORSPACE(renderer, compData->method)); cmp = renderer.target(region, COMPOSITE_TO_COLORSPACE(renderer, compData->method));
if (renderer.beginComposite(cmp, CompositeMethod::None, 255)) { 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); if (cmp) renderer.beginComposite(cmp, compData->method, compData->target->pImpl->opacity);
renderer.blend(blendMethod); renderer.blend(blendMethod);
auto ret = smethod->render(renderer);
bool ret;
PAINT_METHOD(ret, render(renderer));
if (cmp) renderer.endComposite(cmp); if (cmp) renderer.endComposite(cmp);
@ -189,10 +231,7 @@ RenderData Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pT
{ {
if (renderFlag & RenderUpdateFlag::Transform) { if (renderFlag & RenderUpdateFlag::Transform) {
if (!rTransform) return nullptr; if (!rTransform) return nullptr;
if (!rTransform->update()) { rTransform->update();
delete(rTransform);
rTransform = nullptr;
}
} }
/* 1. Composition Pre Processing */ /* 1. Composition Pre Processing */
@ -239,18 +278,13 @@ RenderData Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pT
} }
/* 2. Main Update */ /* 2. Main Update */
RenderData rd = nullptr;
auto newFlag = static_cast<RenderUpdateFlag>(pFlag | renderFlag); auto newFlag = static_cast<RenderUpdateFlag>(pFlag | renderFlag);
renderFlag = RenderUpdateFlag::None; renderFlag = RenderUpdateFlag::None;
opacity = MULTIPLY(opacity, this->opacity); opacity = MULTIPLY(opacity, this->opacity);
if (rTransform && pTransform) { RenderData rd = nullptr;
RenderTransform outTransform(pTransform, rTransform); RenderTransform outTransform(pTransform, rTransform);
rd = smethod->update(renderer, &outTransform, clips, opacity, newFlag, clipper); PAINT_METHOD(rd, update(renderer, &outTransform, clips, opacity, newFlag, clipper));
} else {
auto outTransform = pTransform ? pTransform : rTransform;
rd = smethod->update(renderer, outTransform, clips, opacity, newFlag, clipper);
}
/* 3. Composition Post Processing */ /* 3. Composition Post Processing */
if (compFastTrack) renderer.viewport(viewport); 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) bool Paint::Impl::bounds(float* x, float* y, float* w, float* h, bool transformed, bool stroking)
{ {
Matrix* m = nullptr; Matrix* m = nullptr;
bool ret;
//Case: No transformed, quick return! //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 //Case: Transformed
auto tx = 0.0f; 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 tw = 0.0f;
auto th = 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 //Get vertices
Point pt[4] = {{tx, ty}, {tx + tw, ty}, {tx + tw, ty + th}, {tx, ty + th}}; 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 */ /* External Class Implementation */
/************************************************************************/ /************************************************************************/
Paint :: Paint() : pImpl(new Impl()) Paint :: Paint() : pImpl(new Impl(this))
{ {
} }

View file

@ -38,19 +38,6 @@ namespace tvg
virtual void begin() = 0; 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<RenderData>& 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 struct Composite
{ {
Paint* target; Paint* target;
@ -60,7 +47,7 @@ namespace tvg
struct Paint::Impl struct Paint::Impl
{ {
StrategyMethod* smethod = nullptr; Paint* paint = nullptr;
RenderTransform* rTransform = nullptr; RenderTransform* rTransform = nullptr;
Composite* compData = nullptr; Composite* compData = nullptr;
BlendMethod blendMethod = BlendMethod::Normal; //uint8_t BlendMethod blendMethod = BlendMethod::Normal; //uint8_t
@ -70,13 +57,16 @@ namespace tvg
uint8_t opacity = 255; uint8_t opacity = 255;
uint8_t refCnt = 0; uint8_t refCnt = 0;
Impl(Paint* paint) : paint(paint)
{
}
~Impl() ~Impl()
{ {
if (compData) { if (compData) {
if (P(compData->target)->unref() == 0) delete(compData->target); if (P(compData->target)->unref() == 0) delete(compData->target);
free(compData); free(compData);
} }
delete(smethod);
delete(rTransform); delete(rTransform);
} }
@ -92,11 +82,6 @@ namespace tvg
return (--refCnt); return (--refCnt);
} }
void method(StrategyMethod* method)
{
smethod = method;
}
bool transform(const Matrix& m) bool transform(const Matrix& m)
{ {
if (!rTransform) { if (!rTransform) {
@ -119,22 +104,6 @@ namespace tvg
return nullptr; 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) bool composite(Paint* source, Paint* target, CompositeMethod method)
{ {
//Invalid case //Invalid case
@ -162,6 +131,9 @@ namespace tvg
return true; return true;
} }
RenderRegion bounds(RenderMethod& renderer) const;
bool dispose(RenderMethod& renderer);
Iterator* iterator();
bool rotate(float degree); bool rotate(float degree);
bool scale(float factor); bool scale(float factor);
bool translate(float x, float y); bool translate(float x, float y);
@ -170,51 +142,6 @@ namespace tvg
bool render(RenderMethod& renderer); bool render(RenderMethod& renderer);
Paint* duplicate(); Paint* duplicate();
}; };
template<class T>
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<RenderData>& 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_

View file

@ -62,7 +62,6 @@ RenderUpdateFlag Picture::Impl::load()
Picture::Picture() : pImpl(new Impl(this)) Picture::Picture() : pImpl(new Impl(this))
{ {
Paint::pImpl->id = TVG_CLASS_ID_PICTURE; Paint::pImpl->id = TVG_CLASS_ID_PICTURE;
Paint::pImpl->method(new PaintMethod<Picture::Impl>(pImpl));
} }

View file

@ -39,12 +39,9 @@ void RenderTransform::override(const Matrix& m)
} }
bool RenderTransform::update() void RenderTransform::update()
{ {
if (overriding) return true; if (overriding) return;
//Init Status
if (mathZero(x) && mathZero(y) && mathZero(degree) && mathEqual(scale, 1)) return false;
mathIdentity(&m); mathIdentity(&m);
@ -53,17 +50,13 @@ bool RenderTransform::update()
if (!mathZero(degree)) mathRotate(&m, degree); if (!mathZero(degree)) mathRotate(&m, degree);
mathTranslate(&m, x, y); mathTranslate(&m, x, y);
return true;
}
RenderTransform::RenderTransform()
{
} }
RenderTransform::RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs) 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);
} }

View file

@ -123,10 +123,10 @@ struct RenderTransform
float scale = 1.0f; //scale factor float scale = 1.0f; //scale factor
bool overriding = false; //user transform? bool overriding = false; //user transform?
bool update(); void update();
void override(const Matrix& m); void override(const Matrix& m);
RenderTransform(); RenderTransform() {}
RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs); RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs);
}; };

View file

@ -29,7 +29,6 @@
Scene::Scene() : pImpl(new Impl(this)) Scene::Scene() : pImpl(new Impl(this))
{ {
Paint::pImpl->id = TVG_CLASS_ID_SCENE; Paint::pImpl->id = TVG_CLASS_ID_SCENE;
Paint::pImpl->method(new PaintMethod<Scene::Impl>(pImpl));
} }

View file

@ -75,7 +75,7 @@ struct Scene::Impl
~Impl() ~Impl()
{ {
for (auto paint : paints) { for (auto paint : paints) {
if (paint->pImpl->unref() == 0) delete(paint); if (P(paint)->unref() == 0) delete(paint);
} }
} }

View file

@ -35,7 +35,6 @@ constexpr auto PATH_KAPPA = 0.552284f;
Shape :: Shape() : pImpl(new Impl(this)) Shape :: Shape() : pImpl(new Impl(this))
{ {
Paint::pImpl->id = TVG_CLASS_ID_SHAPE; Paint::pImpl->id = TVG_CLASS_ID_SHAPE;
Paint::pImpl->method(new PaintMethod<Shape::Impl>(pImpl));
} }