From 2aabddd5a5cc051c02abb83cbed137d1d5cddcc7 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Sat, 21 Jun 2025 12:28:23 +0900 Subject: [PATCH] common: support static scene mode (internal) This adds support for a static scene mode, allowing a scene to be treated as a static image. In this mode, partial rendering for the inner drawable components is skipped. This is especially useful for scenes designed to be fully updated as a whole, such as those used in fully dynamic Lottie contents. issue: https://github.com/thorvg/thorvg/issues/1747 --- src/loaders/lottie/tvgLottieBuilder.cpp | 6 ++++- src/renderer/tvgScene.h | 34 ++++++++++++++++++++----- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/loaders/lottie/tvgLottieBuilder.cpp b/src/loaders/lottie/tvgLottieBuilder.cpp index ca707e9f..ab79c44d 100644 --- a/src/loaders/lottie/tvgLottieBuilder.cpp +++ b/src/loaders/lottie/tvgLottieBuilder.cpp @@ -23,6 +23,7 @@ #include #include "tvgCommon.h" #include "tvgMath.h" +#include "tvgScene.h" #include "tvgLottieModel.h" #include "tvgLottieBuilder.h" #include "tvgLottieExpressions.h" @@ -1571,4 +1572,7 @@ void LottieBuilder::build(LottieComposition* comp) auto clip = Shape::gen(); clip->appendRect(0, 0, comp->w, comp->h); comp->root->scene->clip(clip); -} + + //turn off partial rendering for children + SCENE(comp->root->scene)->size({comp->w, comp->h}); +} \ No newline at end of file diff --git a/src/renderer/tvgScene.h b/src/renderer/tvgScene.h index ff30e040..81d619c0 100644 --- a/src/renderer/tvgScene.h +++ b/src/renderer/tvgScene.h @@ -66,8 +66,10 @@ struct SceneImpl : Scene list paints; //children list RenderRegion vport = {}; Array* effects = nullptr; - uint8_t opacity; //for composition + Point fsize; //fixed scene size + bool fixed = false; //true: fixed scene size, false: dynamic size bool vdirty = false; + uint8_t opacity; //for composition SceneImpl() : impl(Paint::Impl(this)) { @@ -75,8 +77,14 @@ struct SceneImpl : Scene ~SceneImpl() { - resetEffects(); clearPaints(); + resetEffects(); + } + + void size(const Point& size) + { + this->fsize = size; + fixed = (size.x > 0 && size.y > 0) ? true : false; } uint8_t needComposition(uint8_t opacity) @@ -117,10 +125,17 @@ struct SceneImpl : Scene this->opacity = opacity; opacity = 255; } + + //allow partial rendering? + auto recover = fixed ? renderer->partial(true) : false; + for (auto paint : paints) { PAINT(paint)->update(renderer, transform, clips, opacity, flag, false); } + //recover the condition + if (fixed) renderer->partial(recover); + if (effects) { ARRAY_FOREACH(p, *effects) { renderer->prepare(*p, transform); @@ -129,10 +144,17 @@ struct SceneImpl : Scene //this viewport update is more performant than in bounds(). No idea. vport = renderer->viewport(); - vdirty = true; - //bounds(renderer) here hinders parallelization. - if (effects) impl.damage(vport); + if (fixed) { + auto pt = fsize * transform; + vport.intersect({int32_t(round(transform.e13)), int32_t(round(transform.e23))}, {int32_t(round(pt.x)), int32_t(round(pt.y))}); + } else { + vdirty = true; + } + + //bounds(renderer) here hinders parallelization + //TODO: we can bring the precise effects region here + if (fixed || effects) impl.damage(vport); return true; } @@ -264,6 +286,7 @@ struct SceneImpl : Scene paint->unref(); paints.erase(itr++); } + return Result::Success; } @@ -314,7 +337,6 @@ struct SceneImpl : Scene } delete(effects); effects = nullptr; - impl.damage(vport); } return Result::Success; }