lottie: optimization++

Use a clipper instead of masking when the condition is satisfied.
Generally, clipping is cheaper than masking in fps & memory usage.

issue: https://github.com/thorvg/thorvg/issues/2647
This commit is contained in:
Hermet Park 2024-09-29 15:21:11 +09:00
parent ec65501079
commit 1a795e2ed4

View file

@ -1125,6 +1125,25 @@ void LottieBuilder::updateMaskings(LottieLayer* layer, float frameNo)
{ {
if (layer->masks.count == 0) return; if (layer->masks.count == 0) return;
//Apply the base mask
auto pMask = static_cast<LottieMask*>(layer->masks[0]);
auto pMethod = pMask->method;
auto opacity = pMask->opacity(frameNo);
auto pShape = layer->pooling();
pShape->reset();
pShape->fill(255, 255, 255, opacity);
pShape->transform(layer->cache.matrix);
pMask->pathset(frameNo, P(pShape)->rs.path.cmds, P(pShape)->rs.path.pts, nullptr, nullptr, nullptr, exps);
auto compMethod = (pMethod == CompositeMethod::SubtractMask || pMethod == CompositeMethod::InvAlphaMask) ? CompositeMethod::InvAlphaMask : CompositeMethod::AlphaMask;
//Cheaper. Replace the masking with a clipper
if (layer->masks.count == 1 && compMethod == CompositeMethod::AlphaMask && opacity == 255) {
layer->scene->clip(tvg::cast(pShape));
return;
}
//Introduce an intermediate scene for embracing the matte + masking //Introduce an intermediate scene for embracing the matte + masking
if (layer->matteTarget) { if (layer->matteTarget) {
auto scene = Scene::gen().release(); auto scene = Scene::gen().release();
@ -1132,21 +1151,7 @@ void LottieBuilder::updateMaskings(LottieLayer* layer, float frameNo)
layer->scene = scene; layer->scene = scene;
} }
//Apply the base mask layer->scene->composite(tvg::cast(pShape), compMethod);
auto pMask = static_cast<LottieMask*>(layer->masks[0]);
auto pMethod = pMask->method;
auto pShape = layer->pooling();
pShape->reset();
pShape->fill(255, 255, 255, pMask->opacity(frameNo));
pShape->transform(layer->cache.matrix);
pMask->pathset(frameNo, P(pShape)->rs.path.cmds, P(pShape)->rs.path.pts, nullptr, nullptr, nullptr, exps);
if (pMethod == CompositeMethod::SubtractMask || pMethod == CompositeMethod::InvAlphaMask) {
layer->scene->composite(tvg::cast(pShape), CompositeMethod::InvAlphaMask);
} else {
layer->scene->composite(tvg::cast(pShape), CompositeMethod::AlphaMask);
}
//Apply the subsquent masks //Apply the subsquent masks
for (auto m = layer->masks.begin() + 1; m < layer->masks.end(); ++m) { for (auto m = layer->masks.begin() + 1; m < layer->masks.end(); ++m) {