diff --git a/src/lib/gl_engine/tvgGlRenderer.cpp b/src/lib/gl_engine/tvgGlRenderer.cpp index 54df5d51..5ccb8bb1 100644 --- a/src/lib/gl_engine/tvgGlRenderer.cpp +++ b/src/lib/gl_engine/tvgGlRenderer.cpp @@ -180,7 +180,7 @@ void* GlRenderer::prepare(const Shape& shape, void* data, TVG_UNUSED const Rende } -int GlRenderer::init() +int GlRenderer::init(uint32_t threads) { if (rendererCnt > 0) return false; if (initEngine) return true; diff --git a/src/lib/gl_engine/tvgGlRenderer.h b/src/lib/gl_engine/tvgGlRenderer.h index d7d80f32..f85a91a5 100644 --- a/src/lib/gl_engine/tvgGlRenderer.h +++ b/src/lib/gl_engine/tvgGlRenderer.h @@ -40,7 +40,7 @@ public: bool clear() override; static GlRenderer* gen(); - static int init(); + static int init(TVG_UNUSED uint32_t threads); static int term(); private: diff --git a/src/lib/sw_engine/meson.build b/src/lib/sw_engine/meson.build index 66b1e0d1..5bde72f9 100644 --- a/src/lib/sw_engine/meson.build +++ b/src/lib/sw_engine/meson.build @@ -5,6 +5,7 @@ source_file = [ 'tvgSwRenderer.h', 'tvgSwRaster.cpp', 'tvgSwRenderer.cpp', + 'tvgSwResMgr.cpp', 'tvgSwRle.cpp', 'tvgSwShape.cpp', 'tvgSwStroke.cpp', diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index ce54180d..e7244923 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -266,13 +266,13 @@ bool mathSmallCubic(SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& SwFixed mathMean(SwFixed angle1, SwFixed angle2); void shapeReset(SwShape* shape); -bool shapeGenOutline(SwShape* shape, const Shape* sdata, const Matrix* transform); -bool shapePrepare(SwShape* shape, const Shape* sdata, const SwSize& clip, const Matrix* transform); +bool shapeGenOutline(SwShape* shape, const Shape* sdata, unsigned tid, const Matrix* transform); +bool shapePrepare(SwShape* shape, const Shape* sdata, unsigned tid, const SwSize& clip, const Matrix* transform); bool shapePrepared(SwShape* shape); bool shapeGenRle(SwShape* shape, const Shape* sdata, const SwSize& clip, bool antiAlias, bool hasComposite); -void shapeDelOutline(SwShape* shape); +void shapeDelOutline(SwShape* shape, uint32_t tid); void shapeResetStroke(SwShape* shape, const Shape* sdata, const Matrix* transform); -bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwSize& clip); +bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, unsigned tid, const Matrix* transform, const SwSize& clip); void shapeFree(SwShape* shape); void shapeDelStroke(SwShape* shape); bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, SwSurface* surface, bool ctable); @@ -295,6 +295,11 @@ void rleFree(SwRleData* rle); void rleClipPath(SwRleData *rle, const SwRleData *clip); void rleClipRect(SwRleData *rle, const SwBBox* clip); +bool resMgrInit(uint32_t threads); +bool resMgrTerm(); +bool resMgrClear(); +SwOutline* resMgrRequestOutline(unsigned idx); +void resMgrRetrieveOutline(unsigned idx); bool rasterCompositor(SwSurface* surface); bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id); @@ -302,7 +307,6 @@ bool rasterSolidShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a); bool rasterClear(SwSurface* surface); - static inline void rasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len) { #ifdef THORVG_AVX_VECTOR_SUPPORT diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index efeb0f33..ec9b47c7 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -39,7 +39,7 @@ struct SwTask : Task vector compList; uint32_t opacity; - void run() override + void run(unsigned tid) override { if (opacity == 0) return; //Invisible @@ -64,13 +64,13 @@ struct SwTask : Task bool renderShape = (alpha > 0 || sdata->fill()); if (renderShape || strokeAlpha) { shapeReset(&shape); - if (!shapePrepare(&shape, sdata, clip, transform)) return; + if (!shapePrepare(&shape, sdata, tid, clip, transform)) goto end; if (renderShape) { /* We assume that if stroke width is bigger than 2, shape outline below stroke could be full covered by stroke drawing. Thus it turns off antialising in that condition. */ auto antiAlias = (strokeAlpha > 0 && strokeWidth > 2) ? false : true; - if (!shapeGenRle(&shape, sdata, clip, antiAlias, compList.size() > 0 ? true : false)) return; + if (!shapeGenRle(&shape, sdata, clip, antiAlias, compList.size() > 0 ? true : false)) goto end; } } } @@ -81,7 +81,7 @@ struct SwTask : Task if (fill) { auto ctable = (flags & RenderUpdateFlag::Gradient) ? true : false; if (ctable) shapeResetFill(&shape); - if (!shapeGenFillColors(&shape, fill, transform, surface, ctable)) return; + if (!shapeGenFillColors(&shape, fill, transform, surface, ctable)) goto end; } else { shapeDelFill(&shape); } @@ -90,7 +90,7 @@ struct SwTask : Task if (flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) { if (strokeAlpha > 0) { shapeResetStroke(&shape, sdata, transform); - if (!shapeGenStrokeRle(&shape, sdata, transform, clip)) return; + if (!shapeGenStrokeRle(&shape, sdata, tid, transform, clip)) goto end; } else { shapeDelStroke(&shape); } @@ -109,7 +109,8 @@ struct SwTask : Task else if (shape.strokeRle && compShape->rle) rleClipPath(shape.strokeRle, compShape->rle); } } - shapeDelOutline(&shape); + end: + shapeDelOutline(&shape, tid); } }; @@ -117,7 +118,7 @@ static void _termEngine() { if (rendererCnt > 0) return; - //TODO: Clean up global resources + resMgrTerm(); } @@ -141,7 +142,7 @@ bool SwRenderer::clear() for (auto task : tasks) task->get(); tasks.clear(); - return true; + return resMgrClear(); } @@ -173,7 +174,6 @@ bool SwRenderer::preRender() bool SwRenderer::postRender() { tasks.clear(); - return true; } @@ -255,12 +255,12 @@ void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* } -bool SwRenderer::init() +bool SwRenderer::init(uint32_t threads) { if (rendererCnt > 0) return false; if (initEngine) return true; - //TODO: + if (!resMgrInit(threads)) return false; initEngine = true; @@ -283,4 +283,4 @@ SwRenderer* SwRenderer::gen() { ++rendererCnt; return new SwRenderer(); -} +} \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwRenderer.h b/src/lib/sw_engine/tvgSwRenderer.h index 9453ec31..06b2f0f4 100644 --- a/src/lib/sw_engine/tvgSwRenderer.h +++ b/src/lib/sw_engine/tvgSwRenderer.h @@ -43,7 +43,7 @@ public: bool render(const Shape& shape, void *data) override; static SwRenderer* gen(); - static bool init(); + static bool init(uint32_t threads); static bool term(); private: diff --git a/src/lib/sw_engine/tvgSwResMgr.cpp b/src/lib/sw_engine/tvgSwResMgr.cpp new file mode 100644 index 00000000..3a33e9f1 --- /dev/null +++ b/src/lib/sw_engine/tvgSwResMgr.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include +#include "tvgSwCommon.h" + + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +static unsigned threadsCnt = 1; +static vector sharedOutline; + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +SwOutline* resMgrRequestOutline(unsigned idx) +{ + return &sharedOutline[idx]; +} + + +void resMgrRetrieveOutline(unsigned idx) +{ + sharedOutline[idx].cntrsCnt = 0; + sharedOutline[idx].ptsCnt = 0; +} + + +bool resMgrInit(unsigned threads) +{ + sharedOutline.reserve(threads); + sharedOutline.resize(threads); + threadsCnt = threads; + + for (auto& outline : sharedOutline) { + outline.cntrs = nullptr; + outline.pts = nullptr; + outline.types = nullptr; + outline.cntrsCnt = outline.reservedCntrsCnt = 0; + outline.ptsCnt = outline.reservedPtsCnt = 0; + } + + return true; +} + + +bool resMgrClear() +{ + for (auto& outline : sharedOutline) { + if (outline.cntrs) { + free(outline.cntrs); + outline.cntrs = nullptr; + } + if (outline.pts) { + free(outline.pts); + outline.pts = nullptr; + } + if (outline.types) { + free(outline.types); + outline.types = nullptr; + } + outline.cntrsCnt = outline.reservedCntrsCnt = 0; + outline.ptsCnt = outline.reservedPtsCnt = 0; + } + return true; +} + + +bool resMgrTerm() +{ + return resMgrClear(); +} \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwShape.cpp b/src/lib/sw_engine/tvgSwShape.cpp index 5694da9f..9fde7500 100644 --- a/src/lib/sw_engine/tvgSwShape.cpp +++ b/src/lib/sw_engine/tvgSwShape.cpp @@ -443,9 +443,9 @@ bool _fastTrack(const SwOutline* outline) /* External Class Implementation */ /************************************************************************/ -bool shapePrepare(SwShape* shape, const Shape* sdata, const SwSize& clip, const Matrix* transform) +bool shapePrepare(SwShape* shape, const Shape* sdata, unsigned tid, const SwSize& clip, const Matrix* transform) { - if (!shapeGenOutline(shape, sdata, transform)) return false; + if (!shapeGenOutline(shape, sdata, tid, transform)) return false; if (!_updateBBox(shape->outline, shape->bbox)) return false; @@ -476,17 +476,15 @@ bool shapeGenRle(SwShape* shape, TVG_UNUSED const Shape* sdata, const SwSize& cl } -void shapeDelOutline(SwShape* shape) +void shapeDelOutline(SwShape* shape, uint32_t tid) { - auto outline = shape->outline; - _delOutline(outline); + resMgrRetrieveOutline(tid); shape->outline = nullptr; } void shapeReset(SwShape* shape) { - shapeDelOutline(shape); rleFree(shape->rle); shape->rle = nullptr; shape->rect = false; @@ -494,7 +492,7 @@ void shapeReset(SwShape* shape) } -bool shapeGenOutline(SwShape* shape, const Shape* sdata, const Matrix* transform) +bool shapeGenOutline(SwShape* shape, const Shape* sdata, unsigned tid, const Matrix* transform) { const PathCommand* cmds = nullptr; auto cmdCnt = sdata->pathCommands(&cmds); @@ -534,8 +532,8 @@ bool shapeGenOutline(SwShape* shape, const Shape* sdata, const Matrix* transform ++outlinePtsCnt; //for close ++outlineCntrsCnt; //for end + shape->outline = resMgrRequestOutline(tid); auto outline = shape->outline; - if (!outline) outline = static_cast(calloc(1, sizeof(SwOutline))); outline->opened = true; _growOutlinePoint(*outline, outlinePtsCnt); @@ -583,7 +581,6 @@ bool shapeGenOutline(SwShape* shape, const Shape* sdata, const Matrix* transform void shapeFree(SwShape* shape) { - shapeDelOutline(shape); rleFree(shape->rle); shapeDelFill(shape); @@ -617,7 +614,7 @@ void shapeResetStroke(SwShape* shape, const Shape* sdata, const Matrix* transfor } -bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwSize& clip) +bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, unsigned tid, const Matrix* transform, const SwSize& clip) { SwOutline* shapeOutline = nullptr; SwOutline* strokeOutline = nullptr; @@ -632,7 +629,7 @@ bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transfo //Normal Style stroke } else { if (!shape->outline) { - if (!shapeGenOutline(shape, sdata, transform)) return false; + if (!shapeGenOutline(shape, sdata, tid, transform)) return false; } shapeOutline = shape->outline; } diff --git a/src/lib/tvgInitializer.cpp b/src/lib/tvgInitializer.cpp index bc0a65fb..a32cb5df 100644 --- a/src/lib/tvgInitializer.cpp +++ b/src/lib/tvgInitializer.cpp @@ -49,12 +49,12 @@ Result Initializer::init(CanvasEngine engine, uint32_t threads) noexcept if (static_cast(engine) & static_cast(CanvasEngine::Sw)) { #ifdef THORVG_SW_RASTER_SUPPORT - if (!SwRenderer::init()) return Result::InsufficientCondition; + if (!SwRenderer::init(threads)) return Result::InsufficientCondition; nonSupport = false; #endif } else if (static_cast(engine) & static_cast(CanvasEngine::Gl)) { #ifdef THORVG_GL_RASTER_SUPPORT - if (!GlRenderer::init()) return Result::InsufficientCondition; + if (!GlRenderer::init(threads)) return Result::InsufficientCondition; nonSupport = false; #endif } else { diff --git a/src/lib/tvgTaskScheduler.cpp b/src/lib/tvgTaskScheduler.cpp index d4c21f17..2ad4ca60 100644 --- a/src/lib/tvgTaskScheduler.cpp +++ b/src/lib/tvgTaskScheduler.cpp @@ -133,7 +133,7 @@ public: } if (!success && !taskQueues[i].pop(&task)) break; - (*task)(); + (*task)(i); } } @@ -149,7 +149,7 @@ public: taskQueues[i % threadCnt].push(task); //Sync } else { - task->run(); + task->run(0); } } }; diff --git a/src/lib/tvgTaskScheduler.h b/src/lib/tvgTaskScheduler.h index d94a3189..1db434a9 100644 --- a/src/lib/tvgTaskScheduler.h +++ b/src/lib/tvgTaskScheduler.h @@ -50,12 +50,12 @@ public: } protected: - virtual void run() = 0; + virtual void run(unsigned tid) = 0; private: - void operator()() + void operator()(unsigned tid) { - run(); + run(tid); sender.set_value(); } diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index 27a6b916..9aeca5c4 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -2431,7 +2431,7 @@ SvgLoader::~SvgLoader() } -void SvgLoader::run() +void SvgLoader::run(unsigned tid) { if (!simpleXmlParse(content, size, true, _svgLoaderParser, &(loaderData))) return; diff --git a/src/loaders/svg/tvgSvgLoader.h b/src/loaders/svg/tvgSvgLoader.h index cd04d7d2..11f8f4ed 100644 --- a/src/loaders/svg/tvgSvgLoader.h +++ b/src/loaders/svg/tvgSvgLoader.h @@ -44,7 +44,7 @@ public: bool header(); bool read() override; bool close() override; - void run() override; + void run(unsigned tid) override; unique_ptr data() override; };