};
/**
+ * @brief Enumeration specifying the methods of Memory Pool behavior policy.
+ *
+ * @BETA_API
+ */
+ enum MempoolPolicy
+ {
+ Default = 0, ///< Default behavior that ThorVG is designed to.
+ Shareable, ///< Memory Pool is shared among the SwCanvases.
+ Individual ///< Allocate designated memory pool that is only used by current instance.
+ };
+
+ /**
* @brief Sets the target buffer for the rasterization.
*
* The buffer of a desirable size should be allocated and owned by the caller.
Result target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, Colorspace cs) noexcept;
/**
+ * @brief Set sw engine memory pool behavior policy.
+ *
+ * Basically ThorVG draws a lot of shapes, it allocates/deallocates a few chunk of memory
+ * while processing rendering. It internally uses one shared memory pool
+ * which can be reused among the canvases in order to avoid memory overhead.
+ *
+ * Thus ThorVG suggests memory pool policy to satisfy user demands,
+ * if it needs to guarantee the thread-safety of the internal data access.
+ *
+ * @param[in] policy Use the shared cache memory. The default value is @c true
+ *
+ * @retval Result::Success When succeed.
+ * @retval Result::InsufficientCondition If the canvas has any paints.
+ * @retval Result::NonSupport In case the software engine is not supported.
+ *
+ * @note When @c policy is set as @c MempoolPolicy::Individual, current instance of canvas uses its own individual
+ * memory data that is not shared with others. This is necessary when the canvas is accessed on a worker-thread.
+ *
+ * @warning It's not allowed after pushing any paints.
+ *
+ * @BETA_API
+ */
+ Result mempool(MempoolPolicy policy) noexcept;
+
+ /**
* @brief Creates a new SwCanvas object.
* @return A new SwCanvas object when succeed, otherwise @c nullptr
*/
bool valid;
};
+struct SwMpool
+{
+ SwOutline* outline = nullptr;
+ SwOutline* strokeOutline = nullptr;
+ unsigned allocSize = 0;
+};
+
static inline SwCoord TO_SWCOORD(float val)
{
return SwCoord(val * 64);
bool mathUpdateOutlineBBox(const SwOutline* outline, const SwBBox& clipRegion, SwBBox& renderRegion);
void shapeReset(SwShape* shape);
-bool shapeGenOutline(SwShape* shape, const Shape* sdata, unsigned tid, const Matrix* transform);
-bool shapePrepare(SwShape* shape, const Shape* sdata, unsigned tid, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion);
+bool shapePrepare(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid);
bool shapePrepared(const SwShape* shape);
bool shapeGenRle(SwShape* shape, const Shape* sdata, bool antiAlias, bool hasComposite);
-void shapeDelOutline(SwShape* shape, uint32_t tid);
+void shapeDelOutline(SwShape* shape, SwMpool* mpool, uint32_t tid);
void shapeResetStroke(SwShape* shape, const Shape* sdata, const Matrix* transform);
-bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, unsigned tid, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion);
+bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid);
void shapeFree(SwShape* shape);
void shapeDelStroke(SwShape* shape);
bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, SwSurface* surface, uint32_t opacity, bool ctable);
void strokeReset(SwStroke* stroke, const Shape* shape, const Matrix* transform);
bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline);
-SwOutline* strokeExportOutline(SwStroke* stroke, unsigned tid);
+SwOutline* strokeExportOutline(SwStroke* stroke, SwMpool* mpool, unsigned tid);
void strokeFree(SwStroke* stroke);
-bool imagePrepare(SwImage* image, const Picture* pdata, unsigned tid, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion);
+bool imagePrepare(SwImage* image, const Picture* pdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid);
bool imagePrepared(const SwImage* image);
bool imageGenRle(SwImage* image, TVG_UNUSED const Picture* pdata, const SwBBox& renderRegion, bool antiAlias);
-void imageDelOutline(SwImage* image, uint32_t tid);
+void imageDelOutline(SwImage* image, SwMpool* mpool, uint32_t tid);
void imageReset(SwImage* image);
-bool imageGenOutline(SwImage* image, const Picture* pdata, unsigned tid, const Matrix* transform);
void imageFree(SwImage* image);
bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, SwSurface* surface, uint32_t opacity, bool ctable);
void rleClipRect(SwRleData *rle, const SwBBox* clip);
void rleAlphaMask(SwRleData *rle, const SwRleData *clip);
-bool mpoolInit(uint32_t threads);
-bool mpoolTerm();
-bool mpoolClear();
-SwOutline* mpoolReqOutline(unsigned idx);
-void mpoolRetOutline(unsigned idx);
-SwOutline* mpoolReqStrokeOutline(unsigned idx);
-void mpoolRetStrokeOutline(unsigned idx);
+SwMpool* mpoolInit(uint32_t threads);
+bool mpoolTerm(SwMpool* mpool);
+bool mpoolClear(SwMpool* mpool);
+SwOutline* mpoolReqOutline(SwMpool* mpool, unsigned idx);
+void mpoolRetOutline(SwMpool* mpool, unsigned idx);
+SwOutline* mpoolReqStrokeOutline(SwMpool* mpool, unsigned idx);
+void mpoolRetStrokeOutline(SwMpool* mpool, unsigned idx);
bool rasterCompositor(SwSurface* surface);
bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id);
/* Internal Class Implementation */
/************************************************************************/
+static bool _genOutline(SwImage* image, const Picture* pdata, const Matrix* transform, SwMpool* mpool, unsigned tid)
+{
+ float w, h;
+ pdata->viewbox(nullptr, nullptr, &w, &h);
+ if (w == 0 || h == 0) return false;
+
+ image->outline = mpoolReqOutline(mpool, tid);
+ auto outline = image->outline;
+
+ outline->reservedPtsCnt = 5;
+ outline->pts = static_cast<SwPoint*>(realloc(outline->pts, outline->reservedPtsCnt * sizeof(SwPoint)));
+ outline->types = static_cast<uint8_t*>(realloc(outline->types, outline->reservedPtsCnt * sizeof(uint8_t)));
+
+ outline->reservedCntrsCnt = 1;
+ outline->cntrs = static_cast<uint32_t*>(realloc(outline->cntrs, outline->reservedCntrsCnt * sizeof(uint32_t)));
+
+ Point to[4] = {{0 ,0}, {w, 0}, {w, h}, {0, h}};
+ for (int i = 0; i < 4; i++) {
+ outline->pts[outline->ptsCnt] = mathTransform(&to[i], transform);
+ outline->types[outline->ptsCnt] = SW_CURVE_TYPE_POINT;
+ ++outline->ptsCnt;
+ }
+
+ outline->pts[outline->ptsCnt] = outline->pts[0];
+ outline->types[outline->ptsCnt] = SW_CURVE_TYPE_POINT;
+ ++outline->ptsCnt;
+
+ outline->cntrs[outline->cntrsCnt] = outline->ptsCnt - 1;
+ ++outline->cntrsCnt;
+
+ outline->opened = false;
+
+ image->outline = outline;
+ image->w = w;
+ image->h = h;
+
+ return true;
+}
/************************************************************************/
/************************************************************************/
-bool imagePrepare(SwImage* image, const Picture* pdata, unsigned tid, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion)
+bool imagePrepare(SwImage* image, const Picture* pdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid)
{
- if (!imageGenOutline(image, pdata, tid, transform)) return false;
+ if (!_genOutline(image, pdata, transform, mpool, tid)) return false;
return mathUpdateOutlineBBox(image->outline, clipRegion, renderRegion);
}
}
-void imageDelOutline(SwImage* image, uint32_t tid)
+void imageDelOutline(SwImage* image, SwMpool* mpool, uint32_t tid)
{
- mpoolRetOutline(tid);
+ mpoolRetOutline(mpool, tid);
image->outline = nullptr;
}
}
-bool imageGenOutline(SwImage* image, const Picture* pdata, unsigned tid, const Matrix* transform)
-{
- float w, h;
- pdata->viewbox(nullptr, nullptr, &w, &h);
- if (w == 0 || h == 0) return false;
-
- image->outline = mpoolReqOutline(tid);
- auto outline = image->outline;
-
- outline->reservedPtsCnt = 5;
- outline->pts = static_cast<SwPoint*>(realloc(outline->pts, outline->reservedPtsCnt * sizeof(SwPoint)));
- outline->types = static_cast<uint8_t*>(realloc(outline->types, outline->reservedPtsCnt * sizeof(uint8_t)));
-
- outline->reservedCntrsCnt = 1;
- outline->cntrs = static_cast<uint32_t*>(realloc(outline->cntrs, outline->reservedCntrsCnt * sizeof(uint32_t)));
-
- Point to[4] = {{0 ,0}, {w, 0}, {w, h}, {0, h}};
- for (int i = 0; i < 4; i++) {
- outline->pts[outline->ptsCnt] = mathTransform(&to[i], transform);
- outline->types[outline->ptsCnt] = SW_CURVE_TYPE_POINT;
- ++outline->ptsCnt;
- }
-
- outline->pts[outline->ptsCnt] = outline->pts[0];
- outline->types[outline->ptsCnt] = SW_CURVE_TYPE_POINT;
- ++outline->ptsCnt;
-
- outline->cntrs[outline->cntrsCnt] = outline->ptsCnt - 1;
- ++outline->cntrsCnt;
-
- outline->opened = false;
-
- image->outline = outline;
- image->w = w;
- image->h = h;
-
- return true;
-}
-
void imageFree(SwImage* image)
{
rleFree(image->rle);
/* Internal Class Implementation */
/************************************************************************/
-static SwOutline* outline = nullptr;
-static SwOutline* strokeOutline = nullptr;
-static unsigned allocSize = 0;
-
/************************************************************************/
/* External Class Implementation */
/************************************************************************/
-SwOutline* mpoolReqOutline(unsigned idx)
+SwOutline* mpoolReqOutline(SwMpool* mpool, unsigned idx)
{
- return &outline[idx];
+ return &mpool->outline[idx];
}
-void mpoolRetOutline(unsigned idx)
+void mpoolRetOutline(SwMpool* mpool, unsigned idx)
{
- outline[idx].cntrsCnt = 0;
- outline[idx].ptsCnt = 0;
+ mpool->outline[idx].cntrsCnt = 0;
+ mpool->outline[idx].ptsCnt = 0;
}
-SwOutline* mpoolReqStrokeOutline(unsigned idx)
+SwOutline* mpoolReqStrokeOutline(SwMpool* mpool, unsigned idx)
{
- return &strokeOutline[idx];
+ return &mpool->strokeOutline[idx];
}
-void mpoolRetStrokeOutline(unsigned idx)
+void mpoolRetStrokeOutline(SwMpool* mpool, unsigned idx)
{
- strokeOutline[idx].cntrsCnt = 0;
- strokeOutline[idx].ptsCnt = 0;
+ mpool->strokeOutline[idx].cntrsCnt = 0;
+ mpool->strokeOutline[idx].ptsCnt = 0;
}
-bool mpoolInit(unsigned threads)
+SwMpool* mpoolInit(unsigned threads)
{
- if (outline || strokeOutline) return false;
+ auto mpool = new SwMpool;
+ if (!mpool) return nullptr;
+
if (threads == 0) threads = 1;
- outline = static_cast<SwOutline*>(calloc(1, sizeof(SwOutline) * threads));
- if (!outline) goto err;
+ mpool->outline = static_cast<SwOutline*>(calloc(1, sizeof(SwOutline) * threads));
+ if (!mpool->outline) goto err;
- strokeOutline = static_cast<SwOutline*>(calloc(1, sizeof(SwOutline) * threads));
- if (!strokeOutline) goto err;
+ mpool->strokeOutline = static_cast<SwOutline*>(calloc(1, sizeof(SwOutline) * threads));
+ if (!mpool->strokeOutline) goto err;
- allocSize = threads;
+ mpool->allocSize = threads;
- return true;
+ return mpool;
err:
- if (outline) {
- free(outline);
- outline = nullptr;
+ if (mpool->outline) {
+ free(mpool->outline);
+ mpool->outline = nullptr;
}
- if (strokeOutline) {
- free(strokeOutline);
- strokeOutline = nullptr;
+ if (mpool->strokeOutline) {
+ free(mpool->strokeOutline);
+ mpool->strokeOutline = nullptr;
}
- return false;
+ delete(mpool);
+ return nullptr;
}
-bool mpoolClear()
+bool mpoolClear(SwMpool* mpool)
{
SwOutline* p;
- for (unsigned i = 0; i < allocSize; ++i) {
+ for (unsigned i = 0; i < mpool->allocSize; ++i) {
- p = &outline[i];
+ p = &mpool->outline[i];
if (p->cntrs) {
free(p->cntrs);
p->cntrsCnt = p->reservedCntrsCnt = 0;
p->ptsCnt = p->reservedPtsCnt = 0;
- p = &strokeOutline[i];
+ p = &mpool->strokeOutline[i];
if (p->cntrs) {
free(p->cntrs);
}
-bool mpoolTerm()
+bool mpoolTerm(SwMpool* mpool)
{
- mpoolClear();
+ if (!mpool) return false;
+
+ mpoolClear(mpool);
- if (outline) {
- free(outline);
- outline = nullptr;
+ if (mpool->outline) {
+ free(mpool->outline);
+ mpool->outline = nullptr;
}
- if (strokeOutline) {
- free(strokeOutline);
- strokeOutline = nullptr;
+ if (mpool->strokeOutline) {
+ free(mpool->strokeOutline);
+ mpool->strokeOutline = nullptr;
}
- allocSize = 0;
+ delete(mpool);
return true;
}
\ No newline at end of file
/************************************************************************/
static int32_t initEngineCnt = false;
static int32_t rendererCnt = 0;
-
+static SwMpool* globalMpool = nullptr;
+static uint32_t threadsCnt = 0;
struct SwTask : Task
{
Matrix* transform = nullptr;
SwSurface* surface = nullptr;
+ SwMpool* mpool = nullptr;
RenderUpdateFlag flags = RenderUpdateFlag::None;
Array<RenderData> clips;
uint32_t opacity;
bool renderShape = (alpha > 0 || sdata->fill());
if (renderShape || validStroke) {
shapeReset(&shape);
- if (!shapePrepare(&shape, sdata, tid, transform, clipRegion, bbox)) goto err;
+ if (!shapePrepare(&shape, sdata, transform, clipRegion, bbox, mpool, tid)) goto err;
if (renderShape) {
/* We assume that if stroke width is bigger than 2,
shape outline below stroke could be full covered by stroke drawing.
if (flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) {
if (validStroke) {
shapeResetStroke(&shape, sdata, transform);
- if (!shapeGenStrokeRle(&shape, sdata, tid, transform, clipRegion, bbox)) goto err;
+ if (!shapeGenStrokeRle(&shape, sdata, transform, clipRegion, bbox, mpool, tid)) goto err;
++addStroking;
if (auto fill = sdata->strokeFill()) {
err:
shapeReset(&shape);
end:
- shapeDelOutline(&shape, tid);
+ shapeDelOutline(&shape, mpool, tid);
if (addStroking > 1 && opacity < 255) cmpStroking = true;
else cmpStroking = false;
}
if (prepareImage) {
imageReset(&image);
- if (!imagePrepare(&image, pdata, tid, transform, clipRegion, bbox)) goto end;
+ if (!imagePrepare(&image, pdata, transform, clipRegion, bbox, mpool, tid)) goto end;
//Clip Path?
if (clips.count > 0) {
}
image.data = const_cast<uint32_t*>(pdata->data());
end:
- imageDelOutline(&image, tid);
+ imageDelOutline(&image, mpool, tid);
}
bool dispose() override
{
if (rendererCnt > 0) return;
- mpoolTerm();
+ mpoolTerm(globalMpool);
+ globalMpool = nullptr;
}
if (surface) delete(surface);
+ if (!sharedMpool) mpoolTerm(mpool);
+
--rendererCnt;
if (rendererCnt == 0 && initEngineCnt == 0) _termEngine();
}
+bool SwRenderer::mempool(bool shared)
+{
+ if (shared) {
+ if (!sharedMpool) {
+ if (!mpoolTerm(mpool)) return false;
+ mpool = globalMpool;
+ }
+ } else {
+ if (sharedMpool) mpool = mpoolInit(threadsCnt);
+ }
+
+ sharedMpool = shared;
+
+ if (mpool) return true;
+ return false;
+}
+
+
Compositor* SwRenderer::target(const RenderRegion& region)
{
auto x = region.x;
task->opacity = opacity;
task->surface = surface;
+ task->mpool = mpool;
task->flags = flags;
task->bbox.min.x = max(static_cast<SwCoord>(0), static_cast<SwCoord>(vport.x));
task->bbox.min.y = max(static_cast<SwCoord>(0), static_cast<SwCoord>(vport.y));
}
+SwRenderer::SwRenderer():mpool(globalMpool)
+{
+}
+
+
bool SwRenderer::init(uint32_t threads)
{
if ((initEngineCnt++) > 0) return true;
- if (!mpoolInit(threads)) return false;
+ threadsCnt = threads;
+
+ //Share the memory pool among the renderer
+ globalMpool = mpoolInit(threads);
+ if (!globalMpool) return false;
return true;
}
{
++rendererCnt;
return new SwRenderer();
-}
+}
\ No newline at end of file
struct SwSurface;
struct SwTask;
struct SwCompositor;
+struct SwMpool;
namespace tvg
{
bool clear() override;
bool sync() override;
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs);
+ bool mempool(bool shared);
Compositor* target(const RenderRegion& region) override;
bool beginComposite(Compositor* cmp, CompositeMethod method, uint32_t opacity) override;
SwSurface* surface = nullptr; //active surface
Array<SwTask*> tasks; //async task list
Array<SwSurface*> compositors; //render targets cache list
+ SwMpool* mpool; //private memory pool
RenderRegion vport; //viewport
- SwRenderer(){};
+ bool sharedMpool = true; //memory-pool behavior policy
+
+ SwRenderer();
~SwRenderer();
RenderData prepareCommon(SwTask* task, const RenderTransform* transform, uint32_t opacity, const Array<RenderData>& clips, RenderUpdateFlag flags);
}
-SwOutline* _genDashOutline(const Shape* sdata, const Matrix* transform)
+static SwOutline* _genDashOutline(const Shape* sdata, const Matrix* transform)
{
const PathCommand* cmds = nullptr;
auto cmdCnt = sdata->pathCommands(&cmds);
}
-bool _fastTrack(const SwOutline* outline)
+static bool _fastTrack(const SwOutline* outline)
{
//Fast Track: Othogonal rectangle?
if (outline->ptsCnt != 5) return false;
}
-/************************************************************************/
-/* External Class Implementation */
-/************************************************************************/
-
-bool shapePrepare(SwShape* shape, const Shape* sdata, unsigned tid, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion)
-{
- if (!shapeGenOutline(shape, sdata, tid, transform)) return false;
- if (!mathUpdateOutlineBBox(shape->outline, clipRegion, renderRegion)) return false;
-
- //Keep it for Rasterization Region
- shape->bbox = renderRegion;
-
- //Check valid region
- if (renderRegion.max.x - renderRegion.min.x < 1 && renderRegion.max.y - renderRegion.min.y < 1) return false;
-
- //Check boundary
- if (renderRegion.min.x >= clipRegion.max.x || renderRegion.min.y >= clipRegion.max.y ||
- renderRegion.max.x <= clipRegion.min.x || renderRegion.max.y <= clipRegion.min.y) return false;
-
- return true;
-}
-
-
-bool shapePrepared(const SwShape* shape)
-{
- return shape->rle ? true : false;
-}
-
-
-bool shapeGenRle(SwShape* shape, TVG_UNUSED const Shape* sdata, bool antiAlias, bool hasComposite)
-{
- //FIXME: Should we draw it?
- //Case: Stroke Line
- //if (shape.outline->opened) return true;
-
- //Case A: Fast Track Rectangle Drawing
- if (!hasComposite && (shape->rect = _fastTrack(shape->outline))) return true;
- //Case B: Normale Shape RLE Drawing
- if ((shape->rle = rleRender(shape->rle, shape->outline, shape->bbox, antiAlias))) return true;
-
- return false;
-}
-
-
-void shapeDelOutline(SwShape* shape, uint32_t tid)
-{
- mpoolRetOutline(tid);
- shape->outline = nullptr;
-}
-
-
-void shapeReset(SwShape* shape)
-{
- rleReset(shape->rle);
- rleReset(shape->strokeRle);
- shape->rect = false;
- shape->bbox.reset();
-}
-
-bool shapeGenOutline(SwShape* shape, const Shape* sdata, unsigned tid, const Matrix* transform)
+static bool _genOutline(SwShape* shape, const Shape* sdata, const Matrix* transform, SwMpool* mpool, unsigned tid)
{
const PathCommand* cmds = nullptr;
auto cmdCnt = sdata->pathCommands(&cmds);
++outlinePtsCnt; //for close
++outlineCntrsCnt; //for end
- shape->outline = mpoolReqOutline(tid);
+ shape->outline = mpoolReqOutline(mpool, tid);
auto outline = shape->outline;
outline->opened = true;
}
+/************************************************************************/
+/* External Class Implementation */
+/************************************************************************/
+
+bool shapePrepare(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid)
+{
+ if (!_genOutline(shape, sdata, transform, mpool, tid)) return false;
+ if (!mathUpdateOutlineBBox(shape->outline, clipRegion, renderRegion)) return false;
+
+ //Keep it for Rasterization Region
+ shape->bbox = renderRegion;
+
+ //Check valid region
+ if (renderRegion.max.x - renderRegion.min.x < 1 && renderRegion.max.y - renderRegion.min.y < 1) return false;
+
+ //Check boundary
+ if (renderRegion.min.x >= clipRegion.max.x || renderRegion.min.y >= clipRegion.max.y ||
+ renderRegion.max.x <= clipRegion.min.x || renderRegion.max.y <= clipRegion.min.y) return false;
+
+ return true;
+}
+
+
+bool shapePrepared(const SwShape* shape)
+{
+ return shape->rle ? true : false;
+}
+
+
+bool shapeGenRle(SwShape* shape, TVG_UNUSED const Shape* sdata, bool antiAlias, bool hasComposite)
+{
+ //FIXME: Should we draw it?
+ //Case: Stroke Line
+ //if (shape.outline->opened) return true;
+
+ //Case A: Fast Track Rectangle Drawing
+ if (!hasComposite && (shape->rect = _fastTrack(shape->outline))) return true;
+ //Case B: Normale Shape RLE Drawing
+ if ((shape->rle = rleRender(shape->rle, shape->outline, shape->bbox, antiAlias))) return true;
+
+ return false;
+}
+
+
+void shapeDelOutline(SwShape* shape, SwMpool* mpool, uint32_t tid)
+{
+ mpoolRetOutline(mpool, tid);
+ shape->outline = nullptr;
+}
+
+
+void shapeReset(SwShape* shape)
+{
+ rleReset(shape->rle);
+ rleReset(shape->strokeRle);
+ shape->rect = false;
+ shape->bbox.reset();
+}
+
+
void shapeFree(SwShape* shape)
{
rleFree(shape->rle);
}
-bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, unsigned tid, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion)
+bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid)
{
SwOutline* shapeOutline = nullptr;
SwOutline* strokeOutline = nullptr;
//Normal Style stroke
} else {
if (!shape->outline) {
- if (!shapeGenOutline(shape, sdata, tid, transform)) return false;
+ if (!_genOutline(shape, sdata, transform, mpool, tid)) return false;
}
shapeOutline = shape->outline;
}
goto fail;
}
- strokeOutline = strokeExportOutline(shape->stroke, tid);
+ strokeOutline = strokeExportOutline(shape->stroke, mpool, tid);
if (!strokeOutline) {
ret = false;
goto fail;
if (shapeOutline->types) free(shapeOutline->types);
free(shapeOutline);
}
- mpoolRetStrokeOutline(tid);
+ mpoolRetStrokeOutline(mpool, tid);
return ret;
}
}
-SwOutline* strokeExportOutline(SwStroke* stroke, unsigned tid)
+SwOutline* strokeExportOutline(SwStroke* stroke, SwMpool* mpool, unsigned tid)
{
uint32_t count1, count2, count3, count4;
auto ptsCnt = count1 + count3;
auto cntrsCnt = count2 + count4;
- auto outline = mpoolReqStrokeOutline(tid);
+ auto outline = mpoolReqStrokeOutline(mpool, tid);
if (outline->reservedPtsCnt < ptsCnt) {
outline->pts = static_cast<SwPoint*>(realloc(outline->pts, sizeof(SwPoint) * ptsCnt));
outline->types = static_cast<uint8_t*>(realloc(outline->types, sizeof(uint8_t) * ptsCnt));
}
+Result SwCanvas::mempool(MempoolPolicy policy) noexcept
+{
+#ifdef THORVG_SW_RASTER_SUPPORT
+ //We know renderer type, avoid dynamic_cast for performance.
+ auto renderer = static_cast<SwRenderer*>(Canvas::pImpl->renderer);
+ if (!renderer) return Result::MemoryCorruption;
+
+ //It can't change the policy during the running.
+ if (Canvas::pImpl->paints.count > 0) return Result::InsufficientCondition;
+
+ if (policy == MempoolPolicy::Individual) renderer->mempool(false);
+ else renderer->mempool(true);
+
+ return Result::Success;
+#endif
+ return Result::NonSupport;
+}
+
+
Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, Colorspace cs) noexcept
{
#ifdef THORVG_SW_RASTER_SUPPORT