diff --git a/src/loaders/lottie/tvgLottieBuilder.cpp b/src/loaders/lottie/tvgLottieBuilder.cpp index 302d03ae..4dbccba3 100644 --- a/src/loaders/lottie/tvgLottieBuilder.cpp +++ b/src/loaders/lottie/tvgLottieBuilder.cpp @@ -84,7 +84,7 @@ struct RenderContext static void _updateChildren(LottieGroup* parent, float frameNo, queue& contexts); -static void _updateLayer(LottieLayer* root, LottieLayer* layer, float frameNo); +static void _updateLayer(LottieLayer* root, LottieLayer* layer, float frameNo, bool caching); static bool _buildComposition(LottieComposition* comp, LottieGroup* parent); static void _rotateX(Matrix* m, float degree) @@ -803,15 +803,14 @@ static void _updateChildren(LottieGroup* parent, float frameNo, queuechildren.count == 0) return; frameNo = precomp->remap(frameNo); - //TODO: skip if the layer is static. for (auto child = precomp->children.end() - 1; child >= precomp->children.data; --child) { - _updateLayer(precomp, static_cast(*child), frameNo); + _updateLayer(precomp, static_cast(*child), frameNo, caching); } //clip the layer viewport @@ -875,12 +874,18 @@ static void _updateMaskings(LottieLayer* layer, float frameNo) } -static bool _updateMatte(LottieLayer* root, LottieLayer* layer, float frameNo) +static bool _updateMatte(LottieLayer* root, LottieLayer* layer, float frameNo, bool caching) { auto target = layer->matte.target; if (!target) return true; - _updateLayer(root, target, frameNo); + if (target->cache.scene) { + //TODO: remove duplicate, share the scene. + layer->scene->composite(cast(target->cache.scene->duplicate()), layer->matte.type); + return true; + } + + _updateLayer(root, target, frameNo, caching); if (target->scene) { layer->scene->composite(cast(target->scene), layer->matte.type); @@ -894,18 +899,31 @@ static bool _updateMatte(LottieLayer* root, LottieLayer* layer, float frameNo) } -static void _updateLayer(LottieLayer* root, LottieLayer* layer, float frameNo) +static void _updateLayer(LottieLayer* root, LottieLayer* layer, float frameNo, bool caching) { layer->scene = nullptr; //visibility if (frameNo < layer->inFrame || frameNo >= layer->outFrame) return; + //static layer, no need to update it again. use a cache. + if (layer->cache.scene) { + //TODO: remove duplicate, share the scene. + root->scene->push(cast(layer->cache.scene->duplicate())); + return; + } + _updateTransform(layer, frameNo); //full transparent scene. no need to perform if (layer->type != LottieLayer::Null && layer->cache.opacity == 0) return; + //figure out this scene is static, reusable. + auto cache = false; + if (layer->statical && !layer->cache.scene && !caching) { + cache = caching = true; + } + //Prepare render data layer->scene = Scene::gen().release(); @@ -916,14 +934,14 @@ static void _updateLayer(LottieLayer* root, LottieLayer* layer, float frameNo) if (layer->matte.target && layer->masks.count > 0) TVGERR("LOTTIE", "FIXME: Matte + Masking??"); - if (!_updateMatte(root, layer, frameNo)) return; + if (!_updateMatte(root, layer, frameNo, caching)) return; _updateMaskings(layer, frameNo); switch (layer->type) { case LottieLayer::Precomp: { if (!layer->children.empty()) { - _updatePrecomp(layer, frameNo); + _updatePrecomp(layer, frameNo, caching); } break; } @@ -943,6 +961,12 @@ static void _updateLayer(LottieLayer* root, LottieLayer* layer, float frameNo) //the given matte source was composited by the target earlier. if (!layer->matteSrc) root->scene->push(cast(layer->scene)); + + //cache this static layer scene + if (cache) { + //TODO: remove duplicate, share the scene. + layer->cache.scene = layer->scene->duplicate(); + } } @@ -1037,10 +1061,14 @@ static bool _buildComposition(LottieComposition* comp, LottieGroup* parent) _bulidHierarchy(parent, child->matte.target); //precomp referencing if (child->matte.target->refId) _buildReference(comp, child->matte.target); + child->statical &= child->matte.target->statical; } _bulidHierarchy(parent, child); _checkFragment(static_cast(*c)); + + child->statical &= parent->statical; + parent->statical &= child->statical; } return true; } @@ -1069,9 +1097,8 @@ bool LottieBuilder::update(LottieComposition* comp, float frameNo) } //update children layers - //TODO: skip if the layer is static. for (auto child = root->children.end() - 1; child >= root->children.data; --child) { - _updateLayer(root, static_cast(*child), frameNo); + _updateLayer(root, static_cast(*child), frameNo, false); } return true; } diff --git a/src/loaders/lottie/tvgLottieModel.cpp b/src/loaders/lottie/tvgLottieModel.cpp index 493c0b10..662b4418 100644 --- a/src/loaders/lottie/tvgLottieModel.cpp +++ b/src/loaders/lottie/tvgLottieModel.cpp @@ -145,6 +145,7 @@ void LottieGroup::prepare(LottieObject::Type type) void LottieLayer::prepare() { if (transform) statical &= transform->statical; + if (timeRemap.frames) statical = false; /* if layer is hidden, only useful data is its transform matrix. so force it to be a Null Layer and release all resource. */ diff --git a/src/loaders/lottie/tvgLottieModel.h b/src/loaders/lottie/tvgLottieModel.h index 97dcf3e5..36255d7b 100644 --- a/src/loaders/lottie/tvgLottieModel.h +++ b/src/loaders/lottie/tvgLottieModel.h @@ -173,7 +173,7 @@ struct LottieGradient } else { colorStops.count = populate(colorStops.value); } - if (start.frames || end.frames || height.frames || angle.frames || colorStops.frames) return true; + if (start.frames || end.frames || height.frames || angle.frames || opacity.frames || colorStops.frames) return true; return false; } @@ -475,7 +475,6 @@ struct LottieGroup : LottieObject void prepare(LottieObject::Type type = LottieObject::Group); Scene* scene = nullptr; //tvg render data - Array children; bool reqFragment = false; //requirment to fragment the render context @@ -500,6 +499,7 @@ struct LottieLayer : LottieGroup delete(matte.target); delete(transform); + delete(cache.scene); } uint8_t opacity(float frameNo) @@ -539,6 +539,7 @@ struct LottieLayer : LottieGroup float frameNo = -1.0f; Matrix matrix; uint8_t opacity; + Paint* scene = nullptr; //tvg statc render ddata } cache; Type type = Null; diff --git a/src/loaders/lottie/tvgLottieParser.cpp b/src/loaders/lottie/tvgLottieParser.cpp index 3a78a43c..d7931015 100644 --- a/src/loaders/lottie/tvgLottieParser.cpp +++ b/src/loaders/lottie/tvgLottieParser.cpp @@ -971,7 +971,9 @@ void LottieParser::parseMasks(LottieLayer* layer) { enterArray(); while (nextArrayValue()) { - layer->masks.push(parseMask()); + auto mask = parseMask(); + if (mask->dynamic()) layer->statical = false; + layer->masks.push(mask); } } @@ -1053,13 +1055,11 @@ LottieLayer* LottieParser::parseLayers() auto matte = static_cast(root->children.last()); if (matte->matteSrc) { layer->matte.target = matte; - layer->statical &= layer->matte.target->statical; } else { TVGLOG("LOTTIE", "Matte Source(%s) is not designated?", matte->name); } root->children.last() = layer; } - root->statical &= layer->statical; } } root->prepare();