}
-int GlRenderer::init()
+int GlRenderer::init(uint32_t threads)
{
if (rendererCnt > 0) return false;
if (initEngine) return true;
bool clear() override;
static GlRenderer* gen();
- static int init();
+ static int init(TVG_UNUSED uint32_t threads);
static int term();
private:
'tvgSwRenderer.h',
'tvgSwRaster.cpp',
'tvgSwRenderer.cpp',
+ 'tvgSwResMgr.cpp',
'tvgSwRle.cpp',
'tvgSwShape.cpp',
'tvgSwStroke.cpp',
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);
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);
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
vector<Composite> compList;
uint32_t opacity;
- void run() override
+ void run(unsigned tid) override
{
if (opacity == 0) return; //Invisible
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;
}
}
}
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);
}
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);
}
else if (shape.strokeRle && compShape->rle) rleClipPath(shape.strokeRle, compShape->rle);
}
}
- shapeDelOutline(&shape);
+ end:
+ shapeDelOutline(&shape, tid);
}
};
{
if (rendererCnt > 0) return;
- //TODO: Clean up global resources
+ resMgrTerm();
}
for (auto task : tasks) task->get();
tasks.clear();
- return true;
+ return resMgrClear();
}
bool SwRenderer::postRender()
{
tasks.clear();
-
return true;
}
}
-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;
{
++rendererCnt;
return new SwRenderer();
-}
+}
\ No newline at end of file
bool render(const Shape& shape, void *data) override;
static SwRenderer* gen();
- static bool init();
+ static bool init(uint32_t threads);
static bool term();
private:
--- /dev/null
+/*
+ * 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 <vector>
+#include "tvgSwCommon.h"
+
+
+/************************************************************************/
+/* Internal Class Implementation */
+/************************************************************************/
+
+static unsigned threadsCnt = 1;
+static vector<SwOutline> 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
/* 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;
}
-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;
}
-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);
++outlinePtsCnt; //for close
++outlineCntrsCnt; //for end
+ shape->outline = resMgrRequestOutline(tid);
auto outline = shape->outline;
- if (!outline) outline = static_cast<SwOutline*>(calloc(1, sizeof(SwOutline)));
outline->opened = true;
_growOutlinePoint(*outline, outlinePtsCnt);
void shapeFree(SwShape* shape)
{
- shapeDelOutline(shape);
rleFree(shape->rle);
shapeDelFill(shape);
}
-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;
//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;
}
if (static_cast<uint32_t>(engine) & static_cast<uint32_t>(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<uint32_t>(engine) & static_cast<uint32_t>(CanvasEngine::Gl)) {
#ifdef THORVG_GL_RASTER_SUPPORT
- if (!GlRenderer::init()) return Result::InsufficientCondition;
+ if (!GlRenderer::init(threads)) return Result::InsufficientCondition;
nonSupport = false;
#endif
} else {
}
if (!success && !taskQueues[i].pop(&task)) break;
- (*task)();
+ (*task)(i);
}
}
taskQueues[i % threadCnt].push(task);
//Sync
} else {
- task->run();
+ task->run(0);
}
}
};
}
protected:
- virtual void run() = 0;
+ virtual void run(unsigned tid) = 0;
private:
- void operator()()
+ void operator()(unsigned tid)
{
- run();
+ run(tid);
sender.set_value();
}
}
-void SvgLoader::run()
+void SvgLoader::run(unsigned tid)
{
if (!simpleXmlParse(content, size, true, _svgLoaderParser, &(loaderData))) return;
bool header();
bool read() override;
bool close() override;
- void run() override;
+ void run(unsigned tid) override;
unique_ptr<Scene> data() override;
};