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 "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))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -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_
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue