mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 13:43:43 +00:00
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:
parent
fe259d0414
commit
4ad0b79eec
8 changed files with 75 additions and 120 deletions
|
@ -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))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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_
|
|
@ -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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue