From d7e4fc7d6a66c2a406c19beae72a59058a479b59 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Mon, 22 Jul 2024 15:37:59 +0900 Subject: [PATCH] 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. --- src/loaders/lottie/tvgLottieBuilder.cpp | 7 +++-- src/loaders/lottie/tvgLottieModel.cpp | 38 ++++++++++++++++++------- src/loaders/lottie/tvgLottieModel.h | 16 +++++++---- 3 files changed, 43 insertions(+), 18 deletions(-) diff --git a/src/loaders/lottie/tvgLottieBuilder.cpp b/src/loaders/lottie/tvgLottieBuilder.cpp index 5cde36eb..0696830d 100644 --- a/src/loaders/lottie/tvgLottieBuilder.cpp +++ b/src/loaders/lottie/tvgLottieBuilder.cpp @@ -268,7 +268,7 @@ static void _updateGroup(LottieGroup* parent, LottieObject** child, float frameN { auto group = static_cast(*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, Inlistpropagator->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)); } diff --git a/src/loaders/lottie/tvgLottieModel.cpp b/src/loaders/lottie/tvgLottieModel.cpp index 1238d098..bbafebb2 100644 --- a/src/loaders/lottie/tvgLottieModel.cpp +++ b/src/loaders/lottie/tvgLottieModel.cpp @@ -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(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. diff --git a/src/loaders/lottie/tvgLottieModel.h b/src/loaders/lottie/tvgLottieModel.h index 687d63ac..5d8fb6bc 100644 --- a/src/loaders/lottie/tvgLottieModel.h +++ b/src/loaders/lottie/tvgLottieModel.h @@ -277,7 +277,10 @@ struct LottieShape : LottieObject, LottieRenderPooler 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 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. };