engines: manage the update with the precise update flags

this also fixes one broken clipping issue.

issue: https://github.com/thorvg/thorvg/issues/3448
This commit is contained in:
Hermet Park 2025-06-17 16:58:51 +09:00 committed by Hermet Park
parent 033ec78e61
commit 9cb8ef26a5
3 changed files with 29 additions and 25 deletions

View file

@ -1403,7 +1403,7 @@ RenderData GlRenderer::prepare(RenderSurface* image, RenderData data, const Matr
sdata->geometry.tesselate(image, flags); sdata->geometry.tesselate(image, flags);
if (!clips.empty()) { if (flags & RenderUpdateFlag::Clip) {
sdata->clips.clear(); sdata->clips.clear();
sdata->clips.push(clips); sdata->clips.push(clips);
} }
@ -1414,6 +1414,8 @@ RenderData GlRenderer::prepare(RenderSurface* image, RenderData data, const Matr
RenderData GlRenderer::prepare(const RenderShape& rshape, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags, bool clipper) RenderData GlRenderer::prepare(const RenderShape& rshape, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags, bool clipper)
{ {
if (flags == RenderUpdateFlag::None) return data;
// If prepare for clip, only path is meaningful. // If prepare for clip, only path is meaningful.
if (clipper) flags = RenderUpdateFlag::Path; if (clipper) flags = RenderUpdateFlag::Path;
@ -1427,7 +1429,6 @@ RenderData GlRenderer::prepare(const RenderShape& rshape, RenderData data, const
sdata->viewWd = static_cast<float>(surface.w); sdata->viewWd = static_cast<float>(surface.w);
sdata->viewHt = static_cast<float>(surface.h); sdata->viewHt = static_cast<float>(surface.h);
sdata->updateFlag = RenderUpdateFlag::None; sdata->updateFlag = RenderUpdateFlag::None;
sdata->geometry = GlGeometry(); sdata->geometry = GlGeometry();
sdata->opacity = opacity; sdata->opacity = opacity;
@ -1435,10 +1436,7 @@ RenderData GlRenderer::prepare(const RenderShape& rshape, RenderData data, const
auto alphaF = rshape.color.a; auto alphaF = rshape.color.a;
auto alphaS = rshape.stroke ? rshape.stroke->color.a : 0; auto alphaS = rshape.stroke ? rshape.stroke->color.a : 0;
if ( ((flags & RenderUpdateFlag::Gradient) == 0) && if ((flags & RenderUpdateFlag::Gradient) == 0 && ((flags & RenderUpdateFlag::Color) && alphaF == 0) && ((flags & RenderUpdateFlag::Stroke) && alphaS == 0)) {
((flags & RenderUpdateFlag::Color) && alphaF == 0) &&
((flags & RenderUpdateFlag::Stroke) && alphaS == 0) )
{
return sdata; return sdata;
} }
@ -1456,12 +1454,11 @@ RenderData GlRenderer::prepare(const RenderShape& rshape, RenderData data, const
sdata->geometry.matrix = transform; sdata->geometry.matrix = transform;
sdata->geometry.viewport = vport; sdata->geometry.viewport = vport;
if (sdata->updateFlag & (RenderUpdateFlag::Color | RenderUpdateFlag::Stroke | RenderUpdateFlag::Gradient | RenderUpdateFlag::GradientStroke | RenderUpdateFlag::Transform | RenderUpdateFlag::Path)) if (sdata->updateFlag & (RenderUpdateFlag::Color | RenderUpdateFlag::Stroke | RenderUpdateFlag::Gradient | RenderUpdateFlag::GradientStroke | RenderUpdateFlag::Transform | RenderUpdateFlag::Path)) {
{
if (!sdata->geometry.tesselate(rshape, sdata->updateFlag)) return sdata; if (!sdata->geometry.tesselate(rshape, sdata->updateFlag)) return sdata;
} }
if (!clipper && !clips.empty()) { if (flags & RenderUpdateFlag::Clip) {
sdata->clips.clear(); sdata->clips.clear();
sdata->clips.push(clips); sdata->clips.push(clips);
} }

View file

@ -695,9 +695,7 @@ void SwRenderer::dispose(RenderData data)
void* SwRenderer::prepareCommon(SwTask* task, const Matrix& transform, const Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags) void* SwRenderer::prepareCommon(SwTask* task, const Matrix& transform, const Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags)
{ {
if (!surface) return task; if (!surface || (transform.e11 == 0.0f && transform.e12 == 0.0f) || (transform.e21 == 0.0f && transform.e22 == 0.0f)) return task; //invalid
if (flags == RenderUpdateFlag::None) return task;
if ((transform.e11 == 0.0f && transform.e12 == 0.0f) || (transform.e21 == 0.0f && transform.e22 == 0.0f)) return task; //zero size?
task->surface = surface; task->surface = surface;
task->mpool = mpool; task->mpool = mpool;
@ -715,11 +713,13 @@ void* SwRenderer::prepareCommon(SwTask* task, const Matrix& transform, const Arr
//TODO: Failed threading them. It would be better if it's possible. //TODO: Failed threading them. It would be better if it's possible.
//See: https://github.com/thorvg/thorvg/issues/1409 //See: https://github.com/thorvg/thorvg/issues/1409
//Guarantee composition targets get ready. //Guarantee composition targets get ready.
ARRAY_FOREACH(p, clips) { if (flags & RenderUpdateFlag::Clip) {
static_cast<SwTask*>(*p)->done(); ARRAY_FOREACH(p, clips) {
static_cast<SwTask*>(*p)->done();
}
} }
TaskScheduler::request(task); if (flags) TaskScheduler::request(task);
return task; return task;
} }
@ -729,10 +729,11 @@ RenderData SwRenderer::prepare(RenderSurface* surface, RenderData data, const Ma
{ {
//prepare task //prepare task
auto task = static_cast<SwImageTask*>(data); auto task = static_cast<SwImageTask*>(data);
if (!task) task = new SwImageTask; if (task) task->done();
else task->done(); else {
task = new SwImageTask;
task->source = surface; task->source = surface;
}
return prepareCommon(task, transform, clips, opacity, flags); return prepareCommon(task, transform, clips, opacity, flags);
} }
@ -742,10 +743,12 @@ RenderData SwRenderer::prepare(const RenderShape& rshape, RenderData data, const
{ {
//prepare task //prepare task
auto task = static_cast<SwShapeTask*>(data); auto task = static_cast<SwShapeTask*>(data);
if (!task) task = new SwShapeTask; if (task) task->done();
else task->done(); else {
task = new SwShapeTask;
task->rshape = &rshape;
}
task->rshape = &rshape;
task->clipper = clipper; task->clipper = clipper;
return prepareCommon(task, transform, clips, opacity, flags); return prepareCommon(task, transform, clips, opacity, flags);

View file

@ -131,10 +131,12 @@ bool WgRenderer::surfaceConfigure(WGPUSurface surface, WgContext& context, uint3
RenderData WgRenderer::prepare(const RenderShape& rshape, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags, bool clipper) RenderData WgRenderer::prepare(const RenderShape& rshape, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags, bool clipper)
{ {
if (flags == RenderUpdateFlag::None) return data;
auto renderDataShape = data ? (WgRenderDataShape*)data : mRenderDataShapePool.allocate(mContext); auto renderDataShape = data ? (WgRenderDataShape*)data : mRenderDataShapePool.allocate(mContext);
// update geometry // update geometry
if ((!data) || (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Stroke))) { if (!data || (flags & (RenderUpdateFlag::Path | RenderUpdateFlag::Stroke))) {
renderDataShape->updateMeshes(rshape, transform, mBufferPool.pool); renderDataShape->updateMeshes(rshape, transform, mBufferPool.pool);
} }
@ -154,7 +156,7 @@ RenderData WgRenderer::prepare(const RenderShape& rshape, RenderData data, const
else if (flags & RenderUpdateFlag::Stroke) renderDataShape->renderSettingsStroke.update(mContext, rshape.stroke->color); else if (flags & RenderUpdateFlag::Stroke) renderDataShape->renderSettingsStroke.update(mContext, rshape.stroke->color);
} }
renderDataShape->updateClips(clips); if (flags & RenderUpdateFlag::Clip) renderDataShape->updateClips(clips);
return renderDataShape; return renderDataShape;
} }
@ -162,6 +164,8 @@ RenderData WgRenderer::prepare(const RenderShape& rshape, RenderData data, const
RenderData WgRenderer::prepare(RenderSurface* surface, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags) RenderData WgRenderer::prepare(RenderSurface* surface, RenderData data, const Matrix& transform, Array<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags)
{ {
if (flags == RenderUpdateFlag::None) return data;
auto renderDataPicture = data ? (WgRenderDataPicture*)data : mRenderDataPicturePool.allocate(mContext); auto renderDataPicture = data ? (WgRenderDataPicture*)data : mRenderDataPicturePool.allocate(mContext);
// update paint settings // update paint settings
@ -175,7 +179,7 @@ RenderData WgRenderer::prepare(RenderSurface* surface, RenderData data, const Ma
renderDataPicture->updateSurface(mContext, surface); renderDataPicture->updateSurface(mContext, surface);
} }
renderDataPicture->updateClips(clips); if (flags & RenderUpdateFlag::Clip) renderDataPicture->updateClips(clips);
return renderDataPicture; return renderDataPicture;
} }