common sw_engine: code refactoring & stabilizing.

Apply tvg Array instead of std::vector

Also Fixed to compList in update() to passed by reference, not copying.
Also Fixed Composition Target memory leak

Here is the binary size result:

[libthorvg.so] 1785376 >> 1607416
[text] 121255 >> 118277
[data] 7792 >> 7736
[dec] 129119 >> 126085
This commit is contained in:
Hermet Park 2020-12-09 19:56:59 +09:00 committed by GitHub
parent d13cd37094
commit 1ed611386d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 96 additions and 73 deletions

View file

@ -162,14 +162,14 @@ bool GlRenderer::dispose(void *data)
}
void* GlRenderer::prepare(TVG_UNUSED const Picture& picture, TVG_UNUSED void* data, TVG_UNUSED uint32_t *buffer, TVG_UNUSED const RenderTransform* transform, TVG_UNUSED uint32_t opacity, TVG_UNUSED vector<Composite>& compList, TVG_UNUSED RenderUpdateFlag flags)
void* GlRenderer::prepare(TVG_UNUSED const Picture& picture, TVG_UNUSED void* data, TVG_UNUSED uint32_t *buffer, TVG_UNUSED const RenderTransform* transform, TVG_UNUSED uint32_t opacity, TVG_UNUSED Array<Composite>& compList, TVG_UNUSED RenderUpdateFlag flags)
{
//TODO:
return nullptr;
}
void* GlRenderer::prepare(const Shape& shape, void* data, TVG_UNUSED const RenderTransform* transform, TVG_UNUSED uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flags)
void* GlRenderer::prepare(const Shape& shape, void* data, TVG_UNUSED const RenderTransform* transform, TVG_UNUSED uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flags)
{
//prepare shape data
GlShape* sdata = static_cast<GlShape*>(data);

View file

@ -30,8 +30,8 @@ class GlRenderer : public RenderMethod
public:
Surface surface = {nullptr, 0, 0, 0};
void* prepare(const Shape& shape, void* data, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flags) override;
void* prepare(const Picture& picture, void* data, uint32_t *buffer, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flags) override;
void* prepare(const Shape& shape, void* data, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flags) override;
void* prepare(const Picture& picture, void* data, uint32_t *buffer, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flags) override;
bool dispose(void *data) override;
void* beginComposite(uint32_t x, uint32_t y, uint32_t w, uint32_t h) override;
bool endComposite(void* ctx, uint32_t opacity) override;

View file

@ -43,7 +43,7 @@ struct SwTask : Task
Matrix* transform = nullptr;
SwSurface* surface = nullptr;
RenderUpdateFlag flags = RenderUpdateFlag::None;
vector<Composite> compList;
Array<Composite> compList;
uint32_t opacity;
virtual bool dispose() = 0;
@ -91,7 +91,7 @@ struct SwShapeTask : SwTask
shape outline below stroke could be full covered by stroke drawing.
Thus it turns off antialising in that condition. */
auto antiAlias = (strokeAlpha == 255 && strokeWidth > 2) ? false : true;
if (!shapeGenRle(&shape, sdata, clip, antiAlias, compList.size() > 0 ? true : false)) goto end;
if (!shapeGenRle(&shape, sdata, clip, antiAlias, compList.count > 0 ? true : false)) goto end;
++addStroking;
}
}
@ -121,9 +121,9 @@ struct SwShapeTask : SwTask
}
//Composition
for (auto comp : compList) {
if (comp.method == CompositeMethod::ClipPath) {
auto compShape = &static_cast<SwShapeTask*>(comp.edata)->shape;
for (auto comp = compList.data; comp < (compList.data + compList.count); ++comp) {
if ((*comp).method == CompositeMethod::ClipPath) {
auto compShape = &static_cast<SwShapeTask*>((*comp).edata)->shape;
//Clip shape rle
if (shape.rle) {
if (compShape->rect) rleClipRect(shape.rle, &compShape->bbox);
@ -169,12 +169,12 @@ struct SwImageTask : SwTask
if (!imagePrepare(&image, pdata, tid, clip, transform)) goto end;
//Composition?
if (compList.size() > 0) {
if (compList.count > 0) {
if (!imageGenRle(&image, pdata, clip, false, true)) goto end;
if (image.rle) {
for (auto comp : compList) {
if (comp.method == CompositeMethod::ClipPath) {
auto compShape = &static_cast<SwShapeTask*>(comp.edata)->shape;
for (auto comp = compList.data; comp < (compList.data + compList.count); ++comp) {
if ((*comp).method == CompositeMethod::ClipPath) {
auto compShape = &static_cast<SwShapeTask*>((*comp).edata)->shape;
if (compShape->rect) rleClipRect(image.rle, &compShape->bbox);
else if (compShape->rle) rleClipPath(image.rle, compShape->rle);
}
@ -220,7 +220,7 @@ SwRenderer::~SwRenderer()
bool SwRenderer::clear()
{
for (auto task : tasks) task->done();
for (auto task = tasks.data; task < (tasks.data + tasks.count); ++task) (*task)->done();
tasks.clear();
return true;
@ -411,12 +411,14 @@ bool SwRenderer::dispose(void *data)
}
void SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flags)
void SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flags)
{
if (compList.size() > 0) {
if (compList.count > 0) {
//Guarantee composition targets get ready.
for (auto comp : compList) static_cast<SwShapeTask*>(comp.edata)->done();
task->compList.assign(compList.begin(), compList.end());
for (auto comp = compList.data; comp < (compList.data + compList.count); ++comp) {
static_cast<SwShapeTask*>((*comp).edata)->done();
}
task->compList = compList;
}
if (transform) {
@ -431,12 +433,12 @@ void SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform, u
task->surface = surface;
task->flags = flags;
tasks.push_back(task);
tasks.push(task);
TaskScheduler::request(task);
}
void* SwRenderer::prepare(const Picture& pdata, void* data, uint32_t *pixels, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flags)
void* SwRenderer::prepare(const Picture& pdata, void* data, uint32_t *pixels, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flags)
{
//prepare task
auto task = static_cast<SwImageTask*>(data);
@ -459,7 +461,7 @@ void* SwRenderer::prepare(const Picture& pdata, void* data, uint32_t *pixels, co
}
void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flags)
void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flags)
{
//prepare task
auto task = static_cast<SwShapeTask*>(data);

View file

@ -22,7 +22,6 @@
#ifndef _TVG_SW_RENDERER_H_
#define _TVG_SW_RENDERER_H_
#include <vector>
#include "tvgRender.h"
struct SwSurface;
@ -36,8 +35,8 @@ namespace tvg
class SwRenderer : public RenderMethod
{
public:
void* prepare(const Shape& shape, void* data, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flags) override;
void* prepare(const Picture& picture, void* data, uint32_t *buffer, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flags) override;
void* prepare(const Shape& shape, void* data, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flags) override;
void* prepare(const Picture& picture, void* data, uint32_t *buffer, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flags) override;
void* beginComposite(uint32_t x, uint32_t y, uint32_t w, uint32_t h) override;
bool endComposite(void* ctx, uint32_t opacity) override;
bool dispose(void *data) override;
@ -54,13 +53,13 @@ public:
static bool term();
private:
SwSurface* surface = nullptr;
vector<SwTask*> tasks;
SwSurface* surface = nullptr;
Array<SwTask*> tasks;
SwRenderer(){};
~SwRenderer();
void prepareCommon(SwTask* task, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flags);
void prepareCommon(SwTask* task, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flags);
};
}

View file

@ -621,7 +621,7 @@ SwSpan* _intersectSpansRegion(const SwRleData *clip, const SwRleData *targetRle,
auto clipSpans = clip->spans;
auto clipEnd = clip->spans + clip->size;
while (spanCnt && spans < end ) {
while (spanCnt > 0 && spans < end ) {
if (clipSpans > clipEnd) {
spans = end;
break;

View file

@ -22,6 +22,7 @@
#ifndef _TVG_ARRAY_H_
#define _TVG_ARRAY_H_
#include <memory.h>
namespace tvg
{
@ -42,12 +43,20 @@ struct Array
data[count++] = element;
}
void reserve(uint32_t size)
{
if (size > reserved) {
reserved = size;
data = static_cast<T*>(realloc(data, sizeof(T) * reserved));
}
}
void pop()
{
if (count > 0) --count;
}
void clear()
void reset()
{
if (data) {
free(data);
@ -56,6 +65,18 @@ struct Array
count = reserved = 0;
}
void clear()
{
count = 0;
}
void operator=(const Array& rhs)
{
reserve(rhs.count);
memcpy(data, rhs.data, sizeof(T) * reserved);
count = rhs.count;
}
~Array()
{
if (data) free(data);

View file

@ -22,7 +22,6 @@
#ifndef _TVG_CANVAS_IMPL_H_
#define _TVG_CANVAS_IMPL_H_
#include <vector>
#include "tvgPaint.h"
/************************************************************************/
@ -31,7 +30,7 @@
struct Canvas::Impl
{
vector<Paint*> paints;
Array<Paint*> paints;
RenderMethod* renderer;
Impl(RenderMethod* pRenderer):renderer(pRenderer)
@ -48,7 +47,7 @@ struct Canvas::Impl
{
auto p = paint.release();
if (!p) return Result::MemoryCorruption;
paints.push_back(p);
paints.push(p);
return update(p);
}
@ -62,9 +61,9 @@ struct Canvas::Impl
//free paints
if (free) {
for (auto paint : paints) {
paint->pImpl->dispose(*renderer);
delete(paint);
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
(*paint)->pImpl->dispose(*renderer);
delete(*paint);
}
}
@ -77,15 +76,15 @@ struct Canvas::Impl
{
if (!renderer) return Result::InsufficientCondition;
vector<Composite> compList;
Array<Composite> compList;
//Update single paint node
if (paint) {
paint->pImpl->update(*renderer, nullptr, 255, compList, RenderUpdateFlag::None);
//Update all retained paint nodes
} else {
for (auto paint : paints) {
paint->pImpl->update(*renderer, nullptr, 255, compList, RenderUpdateFlag::None);
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
(*paint)->pImpl->update(*renderer, nullptr, 255, compList, RenderUpdateFlag::None);
}
}
return Result::Success;
@ -97,8 +96,8 @@ struct Canvas::Impl
if (!renderer->preRender()) return Result::InsufficientCondition;
for (auto paint : paints) {
if (!paint->pImpl->render(*renderer)) return Result::InsufficientCondition;
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
if (!(*paint)->pImpl->render(*renderer)) return Result::InsufficientCondition;
}
if (!renderer->postRender()) return Result::InsufficientCondition;

View file

@ -26,6 +26,7 @@
#include <math.h>
#include "tvgRender.h"
namespace tvg
{
struct StrategyMethod
@ -33,7 +34,7 @@ namespace tvg
virtual ~StrategyMethod() {}
virtual bool dispose(RenderMethod& renderer) = 0;
virtual void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, vector<Composite> compList, RenderUpdateFlag pFlag) = 0; //Return engine data if it has.
virtual void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag pFlag) = 0; //Return engine data if it has.
virtual bool render(RenderMethod& renderer) = 0;
virtual bool bounds(float* x, float* y, float* w, float* h) const = 0;
virtual Paint* duplicate() = 0;
@ -51,6 +52,7 @@ namespace tvg
uint8_t opacity = 255;
~Impl() {
if (compTarget) delete(compTarget);
if (smethod) delete(smethod);
if (rTransform) delete(rTransform);
}
@ -129,7 +131,7 @@ namespace tvg
return smethod->dispose(renderer);
}
void* update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t opacity, vector<Composite>& compList, uint32_t pFlag)
void* update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t opacity, Array<Composite>& compList, uint32_t pFlag)
{
if (flag & RenderUpdateFlag::Transform) {
if (!rTransform) return nullptr;
@ -143,7 +145,7 @@ namespace tvg
if (compTarget && compMethod == CompositeMethod::ClipPath) {
compdata = compTarget->pImpl->update(renderer, pTransform, opacity, compList, pFlag);
if (compdata) compList.push_back({compdata, compMethod});
if (compdata) compList.push({compdata, compMethod});
}
void *edata = nullptr;
@ -159,7 +161,7 @@ namespace tvg
edata = smethod->update(renderer, outTransform, opacity, compList, newFlag);
}
if (compdata) compList.pop_back();
if (compdata) compList.pop();
return edata;
}
@ -215,7 +217,7 @@ namespace tvg
return inst->dispose(renderer);
}
void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, vector<Composite> compList, RenderUpdateFlag flag) override
void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flag) override
{
return inst->update(renderer, transform, opacity, compList, flag);
}

View file

@ -110,7 +110,7 @@ struct Picture::Impl
return RenderUpdateFlag::None;
}
void* update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag pFlag)
void* update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag pFlag)
{
uint32_t flag = reload();

View file

@ -22,8 +22,8 @@
#ifndef _TVG_RENDER_H_
#define _TVG_RENDER_H_
#include <vector>
#include "tvgCommon.h"
#include "tvgArray.h"
namespace tvg
{
@ -65,8 +65,8 @@ class RenderMethod
{
public:
virtual ~RenderMethod() {}
virtual void* prepare(const Shape& shape, void* data, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flags) = 0;
virtual void* prepare(const Picture& picture, void* data, uint32_t *buffer, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flags) = 0;
virtual void* prepare(const Shape& shape, void* data, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flags) = 0;
virtual void* prepare(const Picture& picture, void* data, uint32_t *buffer, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flags) = 0;
virtual void* beginComposite(uint32_t x, uint32_t y, uint32_t w, uint32_t h) = 0;
virtual bool endComposite(void* ctx, uint32_t opacity) = 0;
virtual bool dispose(void *data) = 0;

View file

@ -47,7 +47,7 @@ Result Scene::push(unique_ptr<Paint> paint) noexcept
{
auto p = paint.release();
if (!p) return Result::MemoryCorruption;
pImpl->paints.push_back(p);
pImpl->paints.push(p);
return Result::Success;
}

View file

@ -22,7 +22,6 @@
#ifndef _TVG_SCENE_IMPL_H_
#define _TVG_SCENE_IMPL_H_
#include <vector>
#include "tvgPaint.h"
/************************************************************************/
@ -31,21 +30,21 @@
struct Scene::Impl
{
vector<Paint*> paints;
Array<Paint*> paints;
uint32_t opacity;
bool dispose(RenderMethod& renderer)
{
for (auto paint : paints) {
paint->pImpl->dispose(renderer);
delete(paint);
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
(*paint)->pImpl->dispose(renderer);
delete(*paint);
}
paints.clear();
return true;
}
void* update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag flag)
void* update(RenderMethod &renderer, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flag)
{
this->opacity = opacity;
@ -57,8 +56,8 @@ struct Scene::Impl
This is necessary for scene composition */
void* edata = nullptr;
for (auto paint : paints) {
edata = paint->pImpl->update(renderer, transform, opacity, compList, static_cast<uint32_t>(flag));
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
edata = (*paint)->pImpl->update(renderer, transform, opacity, compList, static_cast<uint32_t>(flag));
}
return edata;
@ -77,8 +76,8 @@ struct Scene::Impl
ctx = renderer.beginComposite(0, 0, 0, 0);
}
for (auto paint : paints) {
if (!paint->pImpl->render(renderer)) return false;
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
if (!(*paint)->pImpl->render(renderer)) return false;
}
if (ctx) return renderer.endComposite(ctx, opacity);
@ -88,20 +87,20 @@ struct Scene::Impl
bool bounds(float* px, float* py, float* pw, float* ph)
{
if (paints.size() == 0) return false;
if (paints.count == 0) return false;
auto x1 = FLT_MAX;
auto y1 = FLT_MAX;
auto x2 = 0.0f;
auto y2 = 0.0f;
for (auto paint : paints) {
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
auto x = FLT_MAX;
auto y = FLT_MAX;
auto w = 0.0f;
auto h = 0.0f;
if (!paint->pImpl->bounds(&x, &y, &w, &h)) continue;
if (!(*paint)->pImpl->bounds(&x, &y, &w, &h)) continue;
//Merge regions
if (x < x1) x1 = x;
@ -124,10 +123,10 @@ struct Scene::Impl
if (!ret) return nullptr;
auto dup = ret.get()->pImpl;
dup->paints.reserve(paints.size());
dup->paints.reserve(paints.count);
for (auto paint : paints) {
dup->paints.push_back(paint->duplicate());
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
dup->paints.push((*paint)->duplicate());
}
return ret.release();

View file

@ -223,7 +223,7 @@ struct Shape::Impl
return renderer.render(*shape, edata);
}
void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, vector<Composite>& compList, RenderUpdateFlag pFlag)
void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag pFlag)
{
this->edata = renderer.prepare(*shape, this->edata, transform, opacity, compList, static_cast<RenderUpdateFlag>(pFlag | flag));
flag = RenderUpdateFlag::None;

View file

@ -2196,6 +2196,7 @@ static void _styleInherit(SvgStyleProperty* child, SvgStyleProperty* parent)
if (!((int)child->stroke.flags & (int)SvgStrokeFlags::Dash)) {
if (parent->stroke.dash.array.count > 0) {
child->stroke.dash.array.clear();
child->stroke.dash.array.reserve(parent->stroke.dash.array.count);
for (uint32_t i = 0; i < parent->stroke.dash.array.count; ++i) {
child->stroke.dash.array.push(parent->stroke.dash.array.data[i]);
}
@ -2297,7 +2298,7 @@ static void _freeGradientStyle(SvgStyleGradient* grad)
auto colorStop = grad->stops.data[i];
free(colorStop);
}
grad->stops.clear();
grad->stops.reset();
free(grad);
}
@ -2308,7 +2309,7 @@ static void _freeNodeStyle(SvgStyleProperty* style)
_freeGradientStyle(style->fill.paint.gradient);
delete style->fill.paint.url;
_freeGradientStyle(style->stroke.paint.gradient);
if (style->stroke.dash.array.count > 0) style->stroke.dash.array.clear();
if (style->stroke.dash.array.count > 0) style->stroke.dash.array.reset();
delete style->stroke.paint.url;
free(style);
}
@ -2321,7 +2322,7 @@ static void _freeNode(SvgNode* node)
for (uint32_t i = 0; i < node->child.count; ++i, ++child) {
_freeNode(*child);
}
node->child.clear();
node->child.reset();
delete node->id;
free(node->transform);
@ -2349,7 +2350,7 @@ static void _freeNode(SvgNode* node)
_freeGradientStyle(*gradients);
++gradients;
}
node->node.defs.gradients.clear();
node->node.defs.gradients.reset();
break;
}
default: {
@ -2540,11 +2541,11 @@ bool SvgLoader::close()
_freeGradientStyle(*gradients);
++gradients;
}
loaderData.gradients.clear();
loaderData.gradients.reset();
_freeNode(loaderData.doc);
loaderData.doc = nullptr;
loaderData.stack.clear();
loaderData.stack.reset();
return true;
}