mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 13:43:43 +00:00
sw_engine: support Scene ClipPath behavior.
Introduced SceneTask, it implements scene clippath behavior by merging RLE of the scene children render data on any running thread. Co-authored-by: Michal Szczecinski <m.szczecinsk@partner.samsung.com> @Issue: https://github.com/thorvg/thorvg/issues/524
This commit is contained in:
parent
a45275b779
commit
b26672a1f6
8 changed files with 227 additions and 18 deletions
|
@ -201,6 +201,13 @@ RenderData GlRenderer::prepare(TVG_UNUSED Surface* image, TVG_UNUSED Polygon* tr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RenderData GlRenderer::prepare(TVG_UNUSED const Array<RenderData>& scene, TVG_UNUSED RenderData data, TVG_UNUSED const RenderTransform* transform, TVG_UNUSED uint32_t opacity, TVG_UNUSED Array<RenderData>& clips, TVG_UNUSED RenderUpdateFlag flags)
|
||||||
|
{
|
||||||
|
//TODO:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
RenderData GlRenderer::prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, TVG_UNUSED uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags, TVG_UNUSED bool clipper)
|
RenderData GlRenderer::prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, TVG_UNUSED uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags, TVG_UNUSED bool clipper)
|
||||||
{
|
{
|
||||||
//prepare shape data
|
//prepare shape data
|
||||||
|
|
|
@ -31,6 +31,7 @@ public:
|
||||||
Surface surface = {nullptr, 0, 0, 0};
|
Surface surface = {nullptr, 0, 0, 0};
|
||||||
|
|
||||||
RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags, bool clipper) override;
|
RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags, bool clipper) override;
|
||||||
|
RenderData prepare(const Array<RenderData>& scene, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
|
||||||
RenderData prepare(Surface* image, Polygon* triangles, uint32_t triangleCnt, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
|
RenderData prepare(Surface* image, Polygon* triangles, uint32_t triangleCnt, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
|
||||||
bool preRender() override;
|
bool preRender() override;
|
||||||
bool renderShape(RenderData data) override;
|
bool renderShape(RenderData data) override;
|
||||||
|
|
|
@ -335,10 +335,12 @@ void fillFetchLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x,
|
||||||
void fillFetchRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len);
|
void fillFetchRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len);
|
||||||
|
|
||||||
SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& renderRegion, bool antiAlias);
|
SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& renderRegion, bool antiAlias);
|
||||||
|
SwRleData* rleRender(const SwBBox* bbox);
|
||||||
void rleFree(SwRleData* rle);
|
void rleFree(SwRleData* rle);
|
||||||
void rleReset(SwRleData* rle);
|
void rleReset(SwRleData* rle);
|
||||||
void rleClipPath(SwRleData *rle, const SwRleData *clip);
|
void rleMerge(SwRleData* rle, SwRleData* clip1, SwRleData* clip2);
|
||||||
void rleClipRect(SwRleData *rle, const SwBBox* clip);
|
void rleClipPath(SwRleData* rle, const SwRleData* clip);
|
||||||
|
void rleClipRect(SwRleData* rle, const SwBBox* clip);
|
||||||
|
|
||||||
SwMpool* mpoolInit(uint32_t threads);
|
SwMpool* mpoolInit(uint32_t threads);
|
||||||
bool mpoolTerm(SwMpool* mpool);
|
bool mpoolTerm(SwMpool* mpool);
|
||||||
|
|
|
@ -62,6 +62,7 @@ struct SwTask : Task
|
||||||
|
|
||||||
virtual bool dispose() = 0;
|
virtual bool dispose() = 0;
|
||||||
virtual bool clip(SwRleData* target) = 0;
|
virtual bool clip(SwRleData* target) = 0;
|
||||||
|
virtual SwRleData* rle() = 0;
|
||||||
|
|
||||||
virtual ~SwTask()
|
virtual ~SwTask()
|
||||||
{
|
{
|
||||||
|
@ -86,6 +87,14 @@ struct SwShapeTask : SwTask
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SwRleData* rle() override
|
||||||
|
{
|
||||||
|
if (!shape.rle && shape.fastTrack) {
|
||||||
|
shape.rle = rleRender(&shape.bbox);
|
||||||
|
}
|
||||||
|
return shape.rle;
|
||||||
|
}
|
||||||
|
|
||||||
void run(unsigned tid) override
|
void run(unsigned tid) override
|
||||||
{
|
{
|
||||||
if (opacity == 0 && !clipper) return; //Invisible
|
if (opacity == 0 && !clipper) return; //Invisible
|
||||||
|
@ -184,6 +193,68 @@ struct SwShapeTask : SwTask
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
//Only one shape
|
||||||
|
if (scene.count == 1) {
|
||||||
|
auto clipper = static_cast<SwTask*>(*scene.data);
|
||||||
|
clipper->done(tid);
|
||||||
|
//Merge shapes if it has more than one shapes
|
||||||
|
} else {
|
||||||
|
//Merge first two clippers
|
||||||
|
auto clipper1 = static_cast<SwTask*>(*scene.data);
|
||||||
|
clipper1->done(tid);
|
||||||
|
|
||||||
|
auto clipper2 = static_cast<SwTask*>(*(scene.data + 1));
|
||||||
|
clipper2->done(tid);
|
||||||
|
|
||||||
|
rleMerge(sceneRle, clipper1->rle(), clipper2->rle());
|
||||||
|
|
||||||
|
//Unify the remained clippers
|
||||||
|
for (auto rd = scene.data + 2; rd < (scene.data + scene.count); ++rd) {
|
||||||
|
auto clipper = static_cast<SwTask*>(*rd);
|
||||||
|
clipper->done(tid);
|
||||||
|
rleMerge(sceneRle, sceneRle, clipper->rle());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dispose() override
|
||||||
|
{
|
||||||
|
rleFree(sceneRle);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct SwImageTask : SwTask
|
struct SwImageTask : SwTask
|
||||||
{
|
{
|
||||||
SwImage image;
|
SwImage image;
|
||||||
|
@ -196,6 +267,12 @@ struct SwImageTask : SwTask
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SwRleData* rle() override
|
||||||
|
{
|
||||||
|
TVGERR("SW_ENGINE", "Image is used as Scene ClipPath?");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void run(unsigned tid) override
|
void run(unsigned tid) override
|
||||||
{
|
{
|
||||||
auto clipRegion = bbox;
|
auto clipRegion = bbox;
|
||||||
|
@ -600,7 +677,7 @@ void* SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform,
|
||||||
//Finish previous task if it has duplicated request.
|
//Finish previous task if it has duplicated request.
|
||||||
task->done();
|
task->done();
|
||||||
|
|
||||||
if (clips.count > 0) task->clips = clips;
|
task->clips = clips;
|
||||||
|
|
||||||
if (transform) {
|
if (transform) {
|
||||||
if (!task->transform) task->transform = static_cast<Matrix*>(malloc(sizeof(Matrix)));
|
if (!task->transform) task->transform = static_cast<Matrix*>(malloc(sizeof(Matrix)));
|
||||||
|
@ -647,6 +724,17 @@ RenderData SwRenderer::prepare(Surface* image, Polygon* triangles, uint32_t tria
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RenderData SwRenderer::prepare(const Array<RenderData>& scene, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags)
|
||||||
|
{
|
||||||
|
//prepare task
|
||||||
|
auto task = static_cast<SwSceneTask*>(data);
|
||||||
|
if (!task) task = new SwSceneTask;
|
||||||
|
task->scene = scene;
|
||||||
|
|
||||||
|
return prepareCommon(task, transform, opacity, clips, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
RenderData SwRenderer::prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags, bool clipper)
|
RenderData SwRenderer::prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags, bool clipper)
|
||||||
{
|
{
|
||||||
//prepare task
|
//prepare task
|
||||||
|
@ -654,8 +742,9 @@ RenderData SwRenderer::prepare(const RenderShape& rshape, RenderData data, const
|
||||||
if (!task) {
|
if (!task) {
|
||||||
task = new SwShapeTask;
|
task = new SwShapeTask;
|
||||||
task->rshape = &rshape;
|
task->rshape = &rshape;
|
||||||
task->clipper = clipper;
|
|
||||||
}
|
}
|
||||||
|
task->clipper = clipper;
|
||||||
|
|
||||||
return prepareCommon(task, transform, opacity, clips, flags);
|
return prepareCommon(task, transform, opacity, clips, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ class SwRenderer : public RenderMethod
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags, bool clipper) override;
|
RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags, bool clipper) override;
|
||||||
|
RenderData prepare(const Array<RenderData>& scene, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
|
||||||
RenderData prepare(Surface* image, Polygon* triangles, uint32_t triangleCnt, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
|
RenderData prepare(Surface* image, Polygon* triangles, uint32_t triangleCnt, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) override;
|
||||||
bool preRender() override;
|
bool preRender() override;
|
||||||
bool renderShape(RenderData data) override;
|
bool renderShape(RenderData data) override;
|
||||||
|
|
|
@ -773,7 +773,7 @@ static int _genRle(RleWorker& rw)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SwSpan* _intersectSpansRegion(const SwRleData *clip, const SwRleData *targetRle, SwSpan *outSpans, uint32_t spanCnt)
|
static SwSpan* _intersectSpansRegion(const SwRleData *clip, const SwRleData *targetRle, SwSpan *outSpans, uint32_t spanCnt)
|
||||||
{
|
{
|
||||||
auto out = outSpans;
|
auto out = outSpans;
|
||||||
auto spans = targetRle->spans;
|
auto spans = targetRle->spans;
|
||||||
|
@ -826,7 +826,7 @@ SwSpan* _intersectSpansRegion(const SwRleData *clip, const SwRleData *targetRle,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SwSpan* _intersectSpansRect(const SwBBox *bbox, const SwRleData *targetRle, SwSpan *outSpans, uint32_t spanCnt)
|
static SwSpan* _intersectSpansRect(const SwBBox *bbox, const SwRleData *targetRle, SwSpan *outSpans, uint32_t spanCnt)
|
||||||
{
|
{
|
||||||
auto out = outSpans;
|
auto out = outSpans;
|
||||||
auto spans = targetRle->spans;
|
auto spans = targetRle->spans;
|
||||||
|
@ -865,6 +865,46 @@ SwSpan* _intersectSpansRect(const SwBBox *bbox, const SwRleData *targetRle, SwSp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static SwSpan* _mergeSpansRegion(const SwRleData *clip1, const SwRleData *clip2, SwSpan *outSpans)
|
||||||
|
{
|
||||||
|
auto out = outSpans;
|
||||||
|
auto spans1 = clip1->spans;
|
||||||
|
auto end1 = clip1->spans + clip1->size;
|
||||||
|
auto spans2 = clip2->spans;
|
||||||
|
auto end2 = clip2->spans + clip2->size;
|
||||||
|
|
||||||
|
//list two spans up in y order
|
||||||
|
//TODO: Remove duplicated regions?
|
||||||
|
while (spans1 < end1 && spans2 < end2) {
|
||||||
|
while (spans1 < end1 && spans1->y <= spans2->y) {
|
||||||
|
*out = *spans1;
|
||||||
|
++spans1;
|
||||||
|
++out;
|
||||||
|
}
|
||||||
|
if (spans1 >= end1) break;
|
||||||
|
while (spans2 < end2 && spans2->y <= spans1->y) {
|
||||||
|
*out = *spans2;
|
||||||
|
++spans2;
|
||||||
|
++out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Leftovers
|
||||||
|
while (spans1 < end1) {
|
||||||
|
*out = *spans1;
|
||||||
|
++spans1;
|
||||||
|
++out;
|
||||||
|
}
|
||||||
|
while (spans2 < end2) {
|
||||||
|
*out = *spans2;
|
||||||
|
++spans2;
|
||||||
|
++out;
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void _replaceClipSpan(SwRleData *rle, SwSpan* clippedSpans, uint32_t size)
|
void _replaceClipSpan(SwRleData *rle, SwSpan* clippedSpans, uint32_t size)
|
||||||
{
|
{
|
||||||
free(rle->spans);
|
free(rle->spans);
|
||||||
|
@ -1001,6 +1041,28 @@ error:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SwRleData* rleRender(const SwBBox* bbox)
|
||||||
|
{
|
||||||
|
auto width = static_cast<uint16_t>(bbox->max.x - bbox->min.x);
|
||||||
|
auto height = static_cast<uint16_t>(bbox->max.y - bbox->min.y);
|
||||||
|
|
||||||
|
auto rle = static_cast<SwRleData*>(malloc(sizeof(SwRleData)));
|
||||||
|
rle->spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * height));
|
||||||
|
rle->size = height;
|
||||||
|
rle->alloc = height;
|
||||||
|
|
||||||
|
auto span = rle->spans;
|
||||||
|
for (uint16_t i = 0; i < height; ++i, ++span) {
|
||||||
|
span->x = bbox->min.x;
|
||||||
|
span->y = bbox->min.y + i;
|
||||||
|
span->len = width;
|
||||||
|
span->coverage = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void rleReset(SwRleData* rle)
|
void rleReset(SwRleData* rle)
|
||||||
{
|
{
|
||||||
if (!rle) return;
|
if (!rle) return;
|
||||||
|
@ -1016,12 +1078,50 @@ void rleFree(SwRleData* rle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void rleMerge(SwRleData* rle, SwRleData* clip1, SwRleData* clip2)
|
||||||
|
{
|
||||||
|
if (!rle || (!clip1 && !clip2)) return;
|
||||||
|
if (clip1 && clip1->size == 0 && clip2 && clip2->size == 0) return;
|
||||||
|
|
||||||
|
TVGLOG("SW_ENGINE", "Unifying Rle!");
|
||||||
|
|
||||||
|
//clip1 is empty, just copy clip2
|
||||||
|
if (!clip1 || clip1->size == 0) {
|
||||||
|
if (clip2) {
|
||||||
|
auto spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * (clip2->size)));
|
||||||
|
memcpy(spans, clip2->spans, clip2->size);
|
||||||
|
_replaceClipSpan(rle, spans, clip2->size);
|
||||||
|
} else {
|
||||||
|
_replaceClipSpan(rle, nullptr, 0);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//clip2 is empty, just copy clip1
|
||||||
|
if (!clip2 || clip2->size == 0) {
|
||||||
|
if (clip1) {
|
||||||
|
auto spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * (clip1->size)));
|
||||||
|
memcpy(spans, clip1->spans, clip1->size);
|
||||||
|
_replaceClipSpan(rle, spans, clip1->size);
|
||||||
|
} else {
|
||||||
|
_replaceClipSpan(rle, nullptr, 0);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto spanCnt = clip1->size + clip2->size;
|
||||||
|
auto spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * spanCnt));
|
||||||
|
auto spansEnd = _mergeSpansRegion(clip1, clip2, spans);
|
||||||
|
|
||||||
|
_replaceClipSpan(rle, spans, spansEnd - spans);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void rleClipPath(SwRleData *rle, const SwRleData *clip)
|
void rleClipPath(SwRleData *rle, const SwRleData *clip)
|
||||||
{
|
{
|
||||||
if (rle->size == 0 || clip->size == 0) return;
|
if (rle->size == 0 || clip->size == 0) return;
|
||||||
auto spanCnt = rle->size > clip->size ? rle->size : clip->size;
|
auto spanCnt = rle->size > clip->size ? rle->size : clip->size;
|
||||||
auto spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * (spanCnt)));
|
auto spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * (spanCnt)));
|
||||||
if (!spans) return;
|
|
||||||
auto spansEnd = _intersectSpansRegion(clip, rle, spans, spanCnt);
|
auto spansEnd = _intersectSpansRegion(clip, rle, spans, spanCnt);
|
||||||
|
|
||||||
_replaceClipSpan(rle, spans, spansEnd - spans);
|
_replaceClipSpan(rle, spans, spansEnd - spans);
|
||||||
|
@ -1034,10 +1134,9 @@ void rleClipRect(SwRleData *rle, const SwBBox* clip)
|
||||||
{
|
{
|
||||||
if (rle->size == 0) return;
|
if (rle->size == 0) return;
|
||||||
auto spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * (rle->size)));
|
auto spans = static_cast<SwSpan*>(malloc(sizeof(SwSpan) * (rle->size)));
|
||||||
if (!spans) return;
|
|
||||||
auto spansEnd = _intersectSpansRect(clip, rle, spans, rle->size);
|
auto spansEnd = _intersectSpansRect(clip, rle, spans, rle->size);
|
||||||
|
|
||||||
_replaceClipSpan(rle, spans, spansEnd - spans);
|
_replaceClipSpan(rle, spans, spansEnd - spans);
|
||||||
|
|
||||||
TVGLOG("SW_ENGINE", "Using ClipRect!");
|
TVGLOG("SW_ENGINE", "Using ClipRect!");
|
||||||
}
|
}
|
|
@ -186,6 +186,7 @@ class RenderMethod
|
||||||
public:
|
public:
|
||||||
virtual ~RenderMethod() {}
|
virtual ~RenderMethod() {}
|
||||||
virtual RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags, bool clipper) = 0;
|
virtual RenderData prepare(const RenderShape& rshape, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags, bool clipper) = 0;
|
||||||
|
virtual RenderData prepare(const Array<RenderData>& scene, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) = 0;
|
||||||
virtual RenderData prepare(Surface* image, Polygon* triangles, uint32_t triangleCnt, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) = 0;
|
virtual RenderData prepare(Surface* image, Polygon* triangles, uint32_t triangleCnt, RenderData data, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags) = 0;
|
||||||
virtual bool preRender() = 0;
|
virtual bool preRender() = 0;
|
||||||
virtual bool renderShape(RenderData data) = 0;
|
virtual bool renderShape(RenderData data) = 0;
|
||||||
|
|
|
@ -61,6 +61,7 @@ struct Scene::Impl
|
||||||
Array<Paint*> paints;
|
Array<Paint*> paints;
|
||||||
uint8_t opacity; //for composition
|
uint8_t opacity; //for composition
|
||||||
RenderMethod* renderer = nullptr; //keep it for explicit clear
|
RenderMethod* renderer = nullptr; //keep it for explicit clear
|
||||||
|
RenderData rd = nullptr;
|
||||||
Scene* scene = nullptr;
|
Scene* scene = nullptr;
|
||||||
|
|
||||||
Impl(Scene* s) : scene(s)
|
Impl(Scene* s) : scene(s)
|
||||||
|
@ -80,9 +81,11 @@ struct Scene::Impl
|
||||||
(*paint)->pImpl->dispose(renderer);
|
(*paint)->pImpl->dispose(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto ret = renderer.dispose(rd);
|
||||||
this->renderer = nullptr;
|
this->renderer = nullptr;
|
||||||
|
this->rd = nullptr;
|
||||||
|
|
||||||
return true;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool needComposition(uint32_t opacity)
|
bool needComposition(uint32_t opacity)
|
||||||
|
@ -109,16 +112,22 @@ struct Scene::Impl
|
||||||
this->opacity = static_cast<uint8_t>(opacity);
|
this->opacity = static_cast<uint8_t>(opacity);
|
||||||
if (needComposition(opacity)) opacity = 255;
|
if (needComposition(opacity)) opacity = 255;
|
||||||
|
|
||||||
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
|
||||||
(*paint)->pImpl->update(renderer, transform, opacity, clips, static_cast<uint32_t>(flag), clipper);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FXIME: it requires to return list of children engine data
|
|
||||||
This is necessary for scene composition */
|
|
||||||
|
|
||||||
this->renderer = &renderer;
|
this->renderer = &renderer;
|
||||||
|
|
||||||
return nullptr;
|
if (clipper) {
|
||||||
|
Array<RenderData> rds;
|
||||||
|
rds.reserve(paints.count);
|
||||||
|
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
||||||
|
rds.push((*paint)->pImpl->update(renderer, transform, opacity, clips, flag, true));
|
||||||
|
}
|
||||||
|
rd = renderer.prepare(rds, rd, transform, opacity, clips, flag);
|
||||||
|
return rd;
|
||||||
|
} else {
|
||||||
|
for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) {
|
||||||
|
(*paint)->pImpl->update(renderer, transform, opacity, clips, flag, false);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool render(RenderMethod& renderer)
|
bool render(RenderMethod& renderer)
|
||||||
|
|
Loading…
Add table
Reference in a new issue