diff options
author | Martin Capitanio <capnm@capitanio.org> | 2023-09-29 14:58:36 +0200 |
---|---|---|
committer | Martin Capitanio <capnm@capitanio.org> | 2023-09-29 19:50:19 +0200 |
commit | aab650f2ef97915e22312e5da543e01989bbfd76 (patch) | |
tree | 847d2e5c6033ab1d06122c57beefa6dc6c019aad /thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp | |
parent | 19890614c6a78ec36030ce65c7da05f07fcdb9ed (diff) | |
download | redot-engine-aab650f2ef97915e22312e5da543e01989bbfd76.tar.gz |
ThorVG: update to v0.11.0 release.
See https://github.com/thorvg/thorvg/releases/tag/v0.11.0
+ Infrastructure
Repository folder structure was make it more intuitive and coherent.
"thorvg/src/lib" -> "thorvg/src/common"
(providing essential common functionalities
used internally among the renderer and sub-modules)
"thorvg/src/lib" -> "thorvg/src/renderer"
(for vector drawing features)
+ SVG related
Fix stroke regression https://github.com/thorvg/thorvg/issues/1670
Support stroke dash offset function https://github.com/thorvg/thorvg/issues/1591#issuecomment-1681319321
Support Focal property in Radial Gradient https://github.com/thorvg/thorvg/issues/1558
Diffstat (limited to 'thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp')
-rw-r--r-- | thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp | 852 |
1 files changed, 0 insertions, 852 deletions
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp deleted file mode 100644 index 091b72fa97..0000000000 --- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp +++ /dev/null @@ -1,852 +0,0 @@ -/* - * Copyright (c) 2020 - 2023 the ThorVG project. 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 "tvgMath.h" -#include "tvgSwCommon.h" -#include "tvgTaskScheduler.h" -#include "tvgSwRenderer.h" - -/************************************************************************/ -/* Internal Class Implementation */ -/************************************************************************/ -static int32_t initEngineCnt = false; -static int32_t rendererCnt = 0; -static SwMpool* globalMpool = nullptr; -static uint32_t threadsCnt = 0; - -struct SwTask : Task -{ - SwSurface* surface = nullptr; - SwMpool* mpool = nullptr; - SwBBox bbox = {{0, 0}, {0, 0}}; //Whole Rendering Region - Matrix* transform = nullptr; - Array<RenderData> clips; - RenderUpdateFlag flags = RenderUpdateFlag::None; - uint8_t opacity; - bool pushed = false; //Pushed into task list? - bool disposed = false; //Disposed task? - - RenderRegion bounds() const - { - RenderRegion region; - - //Range over? - region.x = bbox.min.x > 0 ? bbox.min.x : 0; - region.y = bbox.min.y > 0 ? bbox.min.y : 0; - region.w = bbox.max.x - region.x; - region.h = bbox.max.y - region.y; - if (region.w < 0) region.w = 0; - if (region.h < 0) region.h = 0; - - return region; - } - - virtual bool dispose() = 0; - virtual bool clip(SwRleData* target) = 0; - virtual SwRleData* rle() = 0; - - virtual ~SwTask() - { - free(transform); - } -}; - - -struct SwShapeTask : SwTask -{ - SwShape shape; - const RenderShape* rshape = nullptr; - bool cmpStroking = false; - bool clipper = false; - - /* We assume that if the stroke width is greater than 2, - the shape's outline beneath the stroke could be adequately covered by the stroke drawing. - Therefore, antialiasing is disabled under this condition. - Additionally, the stroke style should not be dashed. */ - bool antialiasing(float strokeWidth) - { - return strokeWidth < 2.0f || rshape->stroke->dashCnt > 0 || rshape->stroke->strokeFirst; - } - - float validStrokeWidth() - { - if (!rshape->stroke) return 0.0f; - - auto width = rshape->stroke->width; - if (mathZero(width)) return 0.0f; - - if (!rshape->stroke->fill && (MULTIPLY(rshape->stroke->color[3], opacity) == 0)) return 0.0f; - if (mathZero(rshape->stroke->trim.begin - rshape->stroke->trim.end)) return 0.0f; - - if (transform) return (width * sqrt(transform->e11 * transform->e11 + transform->e12 * transform->e12)); - else return width; - } - - - bool clip(SwRleData* target) override - { - if (shape.fastTrack) rleClipRect(target, &bbox); - else if (shape.rle) rleClipPath(target, shape.rle); - else return false; - - return true; - } - - SwRleData* rle() override - { - if (!shape.rle && shape.fastTrack) { - shape.rle = rleRender(&shape.bbox); - } - return shape.rle; - } - - void run(unsigned tid) override - { - if (opacity == 0 && !clipper) return; //Invisible - - auto strokeWidth = validStrokeWidth(); - bool visibleFill = false; - auto clipRegion = bbox; - - //This checks also for the case, if the invisible shape turned to visible by alpha. - auto prepareShape = false; - if (!shapePrepared(&shape) && (flags & RenderUpdateFlag::Color)) prepareShape = true; - - //Shape - if (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Transform) || prepareShape) { - uint8_t alpha = 0; - rshape->fillColor(nullptr, nullptr, nullptr, &alpha); - alpha = MULTIPLY(alpha, opacity); - visibleFill = (alpha > 0 || rshape->fill); - if (visibleFill || clipper) { - shapeReset(&shape); - if (!shapePrepare(&shape, rshape, transform, clipRegion, bbox, mpool, tid, clips.count > 0 ? true : false)) goto err; - } - } - //Fill - if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) { - if (visibleFill || clipper) { - if (!shapeGenRle(&shape, rshape, antialiasing(strokeWidth))) goto err; - } - if (auto fill = rshape->fill) { - auto ctable = (flags & RenderUpdateFlag::Gradient) ? true : false; - if (ctable) shapeResetFill(&shape); - if (!shapeGenFillColors(&shape, fill, transform, surface, opacity, ctable)) goto err; - } else { - shapeDelFill(&shape); - } - } - //Stroke - if (flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform)) { - if (strokeWidth > 0.0f) { - shapeResetStroke(&shape, rshape, transform); - if (!shapeGenStrokeRle(&shape, rshape, transform, clipRegion, bbox, mpool, tid)) goto err; - - if (auto fill = rshape->strokeFill()) { - auto ctable = (flags & RenderUpdateFlag::GradientStroke) ? true : false; - if (ctable) shapeResetStrokeFill(&shape); - if (!shapeGenStrokeFillColors(&shape, fill, transform, surface, opacity, ctable)) goto err; - } else { - shapeDelStrokeFill(&shape); - } - } else { - shapeDelStroke(&shape); - } - } - - //Clear current task memorypool here if the clippers would use the same memory pool - shapeDelOutline(&shape, mpool, tid); - - //Clip Path - for (auto clip = clips.data; clip < clips.end(); ++clip) { - auto clipper = static_cast<SwTask*>(*clip); - //Clip shape rle - if (shape.rle && !clipper->clip(shape.rle)) goto err; - //Clip stroke rle - if (shape.strokeRle && !clipper->clip(shape.strokeRle)) goto err; - } - return; - - err: - shapeReset(&shape); - shapeDelOutline(&shape, mpool, tid); - } - - bool dispose() override - { - shapeFree(&shape); - return true; - } -}; - - -struct SwSceneTask : SwTask -{ - Array<RenderData> scene; //list of paints render data (SwTask) - SwRleData* sceneRle = nullptr; - - bool clip(SwRleData* target) override - { - //Only one shape - if (scene.count == 1) { - return static_cast<SwTask*>(*scene.data)->clip(target); - } - - //More than one shapes - if (sceneRle) rleClipPath(target, sceneRle); - else TVGLOG("SW_ENGINE", "No clippers in a scene?"); - - return true; - } - - SwRleData* rle() override - { - return sceneRle; - } - - void run(unsigned tid) override - { - //TODO: Skip the run if the scene hans't changed. - if (!sceneRle) sceneRle = static_cast<SwRleData*>(calloc(1, sizeof(SwRleData))); - else rleReset(sceneRle); - - //Merge shapes if it has more than one shapes - if (scene.count > 1) { - //Merge first two clippers - auto clipper1 = static_cast<SwTask*>(*scene.data); - auto clipper2 = static_cast<SwTask*>(*(scene.data + 1)); - - rleMerge(sceneRle, clipper1->rle(), clipper2->rle()); - - //Unify the remained clippers - for (auto rd = scene.data + 2; rd < scene.end(); ++rd) { - auto clipper = static_cast<SwTask*>(*rd); - rleMerge(sceneRle, sceneRle, clipper->rle()); - } - } - } - - bool dispose() override - { - rleFree(sceneRle); - return true; - } -}; - - -struct SwImageTask : SwTask -{ - SwImage image; - Surface* source; //Image source - const RenderMesh* mesh = nullptr; //Should be valid ptr in action - - bool clip(SwRleData* target) override - { - TVGERR("SW_ENGINE", "Image is used as ClipPath?"); - return true; - } - - SwRleData* rle() override - { - TVGERR("SW_ENGINE", "Image is used as Scene ClipPath?"); - return nullptr; - } - - void run(unsigned tid) override - { - auto clipRegion = bbox; - - //Convert colorspace if it's not aligned. - if (source->owner) { - if (source->cs != surface->cs) rasterConvertCS(source, surface->cs); - if (!source->premultiplied) rasterPremultiply(source); - } - - image.data = source->data; - image.w = source->w; - image.h = source->h; - image.stride = source->stride; - image.channelSize = source->channelSize; - - //Invisible shape turned to visible by alpha. - if ((flags & (RenderUpdateFlag::Image | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) && (opacity > 0)) { - imageReset(&image); - if (!image.data || image.w == 0 || image.h == 0) goto end; - - if (!imagePrepare(&image, mesh, transform, clipRegion, bbox, mpool, tid)) goto end; - - // TODO: How do we clip the triangle mesh? Only clip non-meshed images for now - if (mesh->triangleCnt == 0 && clips.count > 0) { - if (!imageGenRle(&image, bbox, false)) goto end; - if (image.rle) { - //Clear current task memorypool here if the clippers would use the same memory pool - imageDelOutline(&image, mpool, tid); - for (auto clip = clips.data; clip < clips.end(); ++clip) { - auto clipper = static_cast<SwTask*>(*clip); - if (!clipper->clip(image.rle)) goto err; - } - return; - } - } - } - goto end; - err: - rleReset(image.rle); - end: - imageDelOutline(&image, mpool, tid); - } - - bool dispose() override - { - imageFree(&image); - return true; - } -}; - - -static void _termEngine() -{ - if (rendererCnt > 0) return; - - mpoolTerm(globalMpool); - globalMpool = nullptr; -} - - -static void _renderFill(SwShapeTask* task, SwSurface* surface, uint8_t opacity) -{ - uint8_t r, g, b, a; - if (auto fill = task->rshape->fill) { - rasterGradientShape(surface, &task->shape, fill->identifier()); - } else { - task->rshape->fillColor(&r, &g, &b, &a); - a = MULTIPLY(opacity, a); - if (a > 0) rasterShape(surface, &task->shape, r, g, b, a); - } -} - -static void _renderStroke(SwShapeTask* task, SwSurface* surface, uint8_t opacity) -{ - uint8_t r, g, b, a; - if (auto strokeFill = task->rshape->strokeFill()) { - rasterGradientStroke(surface, &task->shape, strokeFill->identifier()); - } else { - if (task->rshape->strokeColor(&r, &g, &b, &a)) { - a = MULTIPLY(opacity, a); - if (a > 0) rasterStroke(surface, &task->shape, r, g, b, a); - } - } -} - -/************************************************************************/ -/* External Class Implementation */ -/************************************************************************/ - -SwRenderer::~SwRenderer() -{ - clearCompositors(); - - delete(surface); - - if (!sharedMpool) mpoolTerm(mpool); - - --rendererCnt; - - if (rendererCnt == 0 && initEngineCnt == 0) _termEngine(); -} - - -bool SwRenderer::clear() -{ - for (auto task = tasks.data; task < tasks.end(); ++task) { - if ((*task)->disposed) { - delete(*task); - } else { - (*task)->done(); - (*task)->pushed = false; - } - } - tasks.clear(); - - if (!sharedMpool) mpoolClear(mpool); - - if (surface) { - vport.x = vport.y = 0; - vport.w = surface->w; - vport.h = surface->h; - } - - return true; -} - - -bool SwRenderer::sync() -{ - return true; -} - - -RenderRegion SwRenderer::viewport() -{ - return vport; -} - - -bool SwRenderer::viewport(const RenderRegion& vp) -{ - vport = vp; - return true; -} - - -bool SwRenderer::target(pixel_t* data, uint32_t stride, uint32_t w, uint32_t h, ColorSpace cs) -{ - if (!data || stride == 0 || w == 0 || h == 0 || w > stride) return false; - - if (!surface) surface = new SwSurface; - - surface->data = data; - surface->stride = stride; - surface->w = w; - surface->h = h; - surface->cs = cs; - surface->channelSize = CHANNEL_SIZE(cs); - surface->premultiplied = true; - surface->owner = true; - - vport.x = vport.y = 0; - vport.w = surface->w; - vport.h = surface->h; - - return rasterCompositor(surface); -} - - -bool SwRenderer::preRender() -{ - return rasterClear(surface, 0, 0, surface->w, surface->h); -} - - -void SwRenderer::clearCompositors() -{ - //Free Composite Caches - for (auto comp = compositors.data; comp < compositors.end(); ++comp) { - free((*comp)->compositor->image.data); - delete((*comp)->compositor); - delete(*comp); - } - compositors.reset(); -} - - -bool SwRenderer::postRender() -{ - //Unmultiply alpha if needed - if (surface->cs == ColorSpace::ABGR8888S || surface->cs == ColorSpace::ARGB8888S) { - rasterUnpremultiply(surface); - } - - for (auto task = tasks.data; task < tasks.end(); ++task) { - if ((*task)->disposed) delete(*task); - else (*task)->pushed = false; - } - tasks.clear(); - - clearCompositors(); - return true; -} - - -bool SwRenderer::renderImage(RenderData data) -{ - auto task = static_cast<SwImageTask*>(data); - task->done(); - - if (task->opacity == 0) return true; - - return rasterImage(surface, &task->image, task->mesh, task->transform, task->bbox, task->opacity); -} - - -bool SwRenderer::renderShape(RenderData data) -{ - auto task = static_cast<SwShapeTask*>(data); - if (!task) return false; - - task->done(); - - if (task->opacity == 0) return true; - - //Main raster stage - if (task->rshape->stroke && task->rshape->stroke->strokeFirst) { - _renderStroke(task, surface, task->opacity); - _renderFill(task, surface, task->opacity); - } else { - _renderFill(task, surface, task->opacity); - _renderStroke(task, surface, task->opacity); - } - - return true; -} - - -bool SwRenderer::blend(BlendMethod method) -{ - if (surface->blendMethod == method) return true; - surface->blendMethod = method; - - switch (method) { - case BlendMethod::Add: - surface->blender = opBlendAdd; - break; - case BlendMethod::Screen: - surface->blender = opBlendScreen; - break; - case BlendMethod::Multiply: - surface->blender = opBlendMultiply; - break; - case BlendMethod::Overlay: - surface->blender = opBlendOverlay; - break; - case BlendMethod::Difference: - surface->blender = opBlendDifference; - break; - case BlendMethod::Exclusion: - surface->blender = opBlendExclusion; - break; - case BlendMethod::SrcOver: - surface->blender = opBlendSrcOver; - break; - case BlendMethod::Darken: - surface->blender = opBlendDarken; - break; - case BlendMethod::Lighten: - surface->blender = opBlendLighten; - break; - case BlendMethod::ColorDodge: - surface->blender = opBlendColorDodge; - break; - case BlendMethod::ColorBurn: - surface->blender = opBlendColorBurn; - break; - case BlendMethod::HardLight: - surface->blender = opBlendHardLight; - break; - case BlendMethod::SoftLight: - surface->blender = opBlendSoftLight; - break; - default: - surface->blender = nullptr; - break; - } - return false; -} - - -RenderRegion SwRenderer::region(RenderData data) -{ - return static_cast<SwTask*>(data)->bounds(); -} - - -bool SwRenderer::beginComposite(Compositor* cmp, CompositeMethod method, uint8_t opacity) -{ - if (!cmp) return false; - auto p = static_cast<SwCompositor*>(cmp); - - p->method = method; - p->opacity = opacity; - - //Current Context? - if (p->method != CompositeMethod::None) { - surface = p->recoverSfc; - surface->compositor = p; - } - - return true; -} - - -bool SwRenderer::mempool(bool shared) -{ - if (shared == sharedMpool) return true; - - 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, ColorSpace cs) -{ - auto x = region.x; - auto y = region.y; - auto w = region.w; - auto h = region.h; - auto sw = static_cast<int32_t>(surface->w); - auto sh = static_cast<int32_t>(surface->h); - - //Out of boundary - if (x >= sw || y >= sh || x + w < 0 || y + h < 0) return nullptr; - - SwSurface* cmp = nullptr; - - auto reqChannelSize = CHANNEL_SIZE(cs); - - //Use cached data - for (auto p = compositors.data; p < compositors.end(); ++p) { - if ((*p)->compositor->valid && (*p)->compositor->image.channelSize == reqChannelSize) { - cmp = *p; - break; - } - } - - //New Composition - if (!cmp) { - cmp = new SwSurface; - - //Inherits attributes from main surface - *cmp = *surface; - - cmp->compositor = new SwCompositor; - - //TODO: We can optimize compositor surface size from (surface->stride x surface->h) to Parameter(w x h) - cmp->compositor->image.data = (pixel_t*)malloc(reqChannelSize * surface->stride * surface->h); - cmp->channelSize = cmp->compositor->image.channelSize = reqChannelSize; - - compositors.push(cmp); - } - - //Boundary Check - if (x + w > sw) w = (sw - x); - if (y + h > sh) h = (sh - y); - - cmp->compositor->recoverSfc = surface; - cmp->compositor->recoverCmp = surface->compositor; - cmp->compositor->valid = false; - cmp->compositor->bbox.min.x = x; - cmp->compositor->bbox.min.y = y; - cmp->compositor->bbox.max.x = x + w; - cmp->compositor->bbox.max.y = y + h; - cmp->compositor->image.stride = surface->stride; - cmp->compositor->image.w = surface->w; - cmp->compositor->image.h = surface->h; - cmp->compositor->image.direct = true; - - cmp->data = cmp->compositor->image.data; - cmp->w = cmp->compositor->image.w; - cmp->h = cmp->compositor->image.h; - - rasterClear(cmp, x, y, w, h); - - //Switch render target - surface = cmp; - - return cmp->compositor; -} - - -bool SwRenderer::endComposite(Compositor* cmp) -{ - if (!cmp) return false; - - auto p = static_cast<SwCompositor*>(cmp); - p->valid = true; - - //Recover Context - surface = p->recoverSfc; - surface->compositor = p->recoverCmp; - - //Default is alpha blending - if (p->method == CompositeMethod::None) { - return rasterImage(surface, &p->image, nullptr, nullptr, p->bbox, p->opacity); - } - - return true; -} - - -ColorSpace SwRenderer::colorSpace() -{ - if (surface) return surface->cs; - else return ColorSpace::Unsupported; -} - - -bool SwRenderer::dispose(RenderData data) -{ - auto task = static_cast<SwTask*>(data); - if (!task) return true; - task->done(); - task->dispose(); - - if (task->pushed) task->disposed = true; - else delete(task); - - return true; -} - - -void* SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform, const Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags) -{ - if (!surface) return task; - if (flags == RenderUpdateFlag::None) return task; - - //Finish previous task if it has duplicated request. - task->done(); - - //TODO: Failed threading them. It would be better if it's possible. - //See: https://github.com/thorvg/thorvg/issues/1409 - //Guarantee composition targets get ready. - for (auto clip = clips.data; clip < clips.end(); ++clip) { - static_cast<SwTask*>(*clip)->done(); - } - - task->clips = clips; - - if (transform) { - if (!task->transform) task->transform = static_cast<Matrix*>(malloc(sizeof(Matrix))); - *task->transform = transform->m; - } else { - if (task->transform) free(task->transform); - task->transform = nullptr; - } - - task->opacity = opacity; - task->surface = surface; - task->mpool = mpool; - task->flags = flags; - task->bbox.min.x = mathMax(static_cast<SwCoord>(0), static_cast<SwCoord>(vport.x)); - task->bbox.min.y = mathMax(static_cast<SwCoord>(0), static_cast<SwCoord>(vport.y)); - task->bbox.max.x = mathMin(static_cast<SwCoord>(surface->w), static_cast<SwCoord>(vport.x + vport.w)); - task->bbox.max.y = mathMin(static_cast<SwCoord>(surface->h), static_cast<SwCoord>(vport.y + vport.h)); - - if (!task->pushed) { - task->pushed = true; - tasks.push(task); - } - - TaskScheduler::request(task); - - return task; -} - - -RenderData SwRenderer::prepare(Surface* surface, const RenderMesh* mesh, RenderData data, const RenderTransform* transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags) -{ - //prepare task - auto task = static_cast<SwImageTask*>(data); - if (!task) task = new SwImageTask; - if (flags & RenderUpdateFlag::Image) { - task->source = surface; - task->mesh = mesh; - } - return prepareCommon(task, transform, clips, opacity, flags); -} - - -RenderData SwRenderer::prepare(const Array<RenderData>& scene, RenderData data, const RenderTransform* transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags) -{ - //prepare task - auto task = static_cast<SwSceneTask*>(data); - if (!task) task = new SwSceneTask; - task->scene = scene; - - //TODO: Failed threading them. It would be better if it's possible. - //See: https://github.com/thorvg/thorvg/issues/1409 - //Guarantee composition targets get ready. - for (auto task = scene.data; task < scene.end(); ++task) { - static_cast<SwTask*>(*task)->done(); - } - return prepareCommon(task, transform, clips, opacity, flags); -} - - -RenderData SwRenderer::prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags, bool clipper) -{ - //prepare task - auto task = static_cast<SwShapeTask*>(data); - if (!task) { - task = new SwShapeTask; - task->rshape = &rshape; - } - task->clipper = clipper; - - return prepareCommon(task, transform, clips, opacity, flags); -} - - -SwRenderer::SwRenderer():mpool(globalMpool) -{ -} - - -bool SwRenderer::init(uint32_t threads) -{ - if ((initEngineCnt++) > 0) return true; - - threadsCnt = threads; - - //Share the memory pool among the renderer - globalMpool = mpoolInit(threads); - if (!globalMpool) { - --initEngineCnt; - return false; - } - - return true; -} - - -int32_t SwRenderer::init() -{ - return initEngineCnt; -} - - -bool SwRenderer::term() -{ - if ((--initEngineCnt) > 0) return true; - - initEngineCnt = 0; - - _termEngine(); - - return true; -} - -SwRenderer* SwRenderer::gen() -{ - ++rendererCnt; - return new SwRenderer(); -} |