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 "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<RenderUpdateFlag>(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))
{
}

View file

@ -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<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
{
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<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))
{
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;
//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);
}

View file

@ -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);
};

View file

@ -29,7 +29,6 @@
Scene::Scene() : pImpl(new Impl(this))
{
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()
{
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))
{
Paint::pImpl->id = TVG_CLASS_ID_SHAPE;
Paint::pImpl->method(new PaintMethod<Shape::Impl>(pImpl));
}