lottie: ++optimization with object culling

More precisely, culling the render objects by
determining if the group has no renderable objects.

Additionally, check opacity to quickly return
in the rendering process.
This commit is contained in:
Hermet Park 2024-07-22 15:37:59 +09:00
parent 935d3d83ae
commit d7e4fc7d6a
3 changed files with 43 additions and 18 deletions

View file

@ -268,7 +268,7 @@ static void _updateGroup(LottieGroup* parent, LottieObject** child, float frameN
{
auto group = static_cast<LottieGroup*>(*child);
if (group->children.empty()) return;
if (!group->visible) return;
//Prepare render data
group->scene = parent->scene;
@ -1028,6 +1028,7 @@ static void _updateChildren(LottieGroup* parent, float frameNo, Inlist<RenderCon
}
default: break;
}
if (ctx->propagator->opacity() == 0) break;
}
delete(ctx);
}
@ -1053,7 +1054,7 @@ static void _updatePrecomp(LottieLayer* precomp, float frameNo, LottieExpression
}
//clip the layer viewport
auto clipper = precomp->pooling();
auto clipper = precomp->pooling(true);
clipper->transform(precomp->cache.matrix);
precomp->scene->composite(cast(clipper), CompositeMethod::ClipPath);
}
@ -1061,7 +1062,7 @@ static void _updatePrecomp(LottieLayer* precomp, float frameNo, LottieExpression
static void _updateSolid(LottieLayer* layer)
{
auto solidFill = layer->pooling();
auto solidFill = layer->pooling(true);
solidFill->opacity(layer->cache.opacity);
layer->scene->push(cast(solidFill));
}

View file

@ -37,16 +37,6 @@
/* External Class Implementation */
/************************************************************************/
void LottieShape::prepare(LottieObject::Type type)
{
LottieObject::type = type;
auto shape = tvg::Shape::gen().release();
PP(shape)->ref();
pooler.push(shape);
}
void LottieSlot::reset()
{
if (!overridden) return;
@ -296,6 +286,16 @@ Fill* LottieGradient::fill(float frameNo, LottieExpressions* exps)
}
LottieGroup::LottieGroup()
{
reqFragment = false;
buildDone = false;
trimpath = false;
visible = false;
allowMerge = true;
}
void LottieGroup::prepare(LottieObject::Type type)
{
LottieObject::type = type;
@ -314,6 +314,24 @@ void LottieGroup::prepare(LottieObject::Type type)
In that case, the rendering context can be sharable with the parent's. */
if (allowMerge && (child->type == LottieObject::Group || !child->mergeable())) allowMerge = false;
//Figure out this group has visible contents
switch (child->type) {
case LottieObject::Group: {
visible |= static_cast<LottieGroup*>(child)->visible;
break;
}
case LottieObject::Rect:
case LottieObject::Ellipse:
case LottieObject::Path:
case LottieObject::Polystar:
case LottieObject::Image:
case LottieObject::Text: {
visible = true;
break;
}
default: break;
}
if (reqFragment) continue;
/* Figure out if the rendering context should be fragmented.

View file

@ -277,7 +277,10 @@ struct LottieShape : LottieObject, LottieRenderPooler<tvg::Shape>
return true;
}
void prepare(LottieObject::Type type);
void prepare(LottieObject::Type type)
{
LottieObject::type = type;
}
};
@ -533,6 +536,8 @@ struct LottieRepeater : LottieObject
struct LottieGroup : LottieObject
{
LottieGroup();
virtual ~LottieGroup()
{
for (auto p = children.begin(); p < children.end(); ++p) delete(*p);
@ -558,10 +563,11 @@ struct LottieGroup : LottieObject
Scene* scene = nullptr;
Array<LottieObject*> children;
bool reqFragment = false; //requirement to fragment the render context
bool buildDone = false; //completed in building the composition.
bool allowMerge = true; //if this group is consisted of simple (transformed) shapes.
bool trimpath = false; //this group has a trimpath.
bool reqFragment : 1; //requirement to fragment the render context
bool buildDone : 1; //completed in building the composition.
bool trimpath : 1; //this group has a trimpath.
bool visible : 1; //this group has visible contents.
bool allowMerge : 1; //if this group is consisted of simple (transformed) shapes.
};