mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-14 12:04:29 +00:00
lottie: introduced LottieRenderPooler
LottieRenderPooler is designed to manages rendering instances(paints) efficiently through a simple pooling mechanism to resuse among the animations This replaces the previous individusal paints implemenations among solidfill, precomp vierport and pictures, also fix a potential paints corruption problems.
This commit is contained in:
parent
d13606e14b
commit
1131695ce4
5 changed files with 101 additions and 50 deletions
|
@ -11,6 +11,7 @@ source_file = [
|
|||
'tvgLottieParser.h',
|
||||
'tvgLottieParserHandler.h',
|
||||
'tvgLottieProperty.h',
|
||||
'tvgLottieRenderPooler.h',
|
||||
'tvgLottieAnimation.cpp',
|
||||
'tvgLottieBuilder.cpp',
|
||||
'tvgLottieExpressions.cpp',
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include "tvgPaint.h"
|
||||
#include "tvgShape.h"
|
||||
#include "tvgInlist.h"
|
||||
#include "tvgTaskScheduler.h"
|
||||
#include "tvgLottieModel.h"
|
||||
#include "tvgLottieBuilder.h"
|
||||
#include "tvgLottieExpressions.h"
|
||||
|
@ -1043,44 +1042,24 @@ static void _updatePrecomp(LottieLayer* precomp, float frameNo, LottieExpression
|
|||
}
|
||||
|
||||
//clip the layer viewport
|
||||
if (!precomp->clipper) {
|
||||
precomp->clipper = Shape::gen().release();
|
||||
precomp->clipper->appendRect(0.0f, 0.0f, precomp->w, precomp->h);
|
||||
PP(precomp->clipper)->ref();
|
||||
}
|
||||
precomp->clipper->transform(precomp->cache.matrix);
|
||||
precomp->scene->composite(cast(precomp->clipper), CompositeMethod::ClipPath);
|
||||
auto clipper = precomp->pooling();
|
||||
clipper->transform(precomp->cache.matrix);
|
||||
precomp->scene->composite(cast(clipper), CompositeMethod::ClipPath);
|
||||
}
|
||||
|
||||
|
||||
static void _updateSolid(LottieLayer* layer)
|
||||
{
|
||||
layer->solidFill->opacity(layer->cache.opacity);
|
||||
layer->scene->push(cast(layer->solidFill));
|
||||
auto solidFill = layer->pooling();
|
||||
solidFill->opacity(layer->cache.opacity);
|
||||
layer->scene->push(cast(solidFill));
|
||||
}
|
||||
|
||||
|
||||
static void _updateImage(LottieGroup* layer)
|
||||
{
|
||||
auto image = static_cast<LottieImage*>(layer->children.first());
|
||||
|
||||
if (!image->picture) {
|
||||
image->picture = Picture::gen().release();
|
||||
|
||||
//force to load a picture on the same thread
|
||||
TaskScheduler::async(false);
|
||||
|
||||
if (image->size > 0) image->picture->load((const char*)image->b64Data, image->size, image->mimeType, false);
|
||||
else image->picture->load(image->path);
|
||||
|
||||
TaskScheduler::async(true);
|
||||
|
||||
PP(image->picture)->ref();
|
||||
image->picture->size(image->width, image->height);
|
||||
}
|
||||
|
||||
if (image->refCnt == 1) layer->scene->push(tvg::cast(image->picture));
|
||||
else layer->scene->push(tvg::cast(image->picture->duplicate()));
|
||||
layer->scene->push(tvg::cast(image->pooling()));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1344,7 +1323,6 @@ static void _buildReference(LottieComposition* comp, LottieLayer* layer)
|
|||
layer->reqFragment = assetLayer->reqFragment;
|
||||
}
|
||||
} else if (layer->type == LottieLayer::Image) {
|
||||
++static_cast<LottieImage*>(*asset)->refCnt;
|
||||
layer->children.push(*asset);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "tvgMath.h"
|
||||
#include "tvgPaint.h"
|
||||
#include "tvgFill.h"
|
||||
#include "tvgTaskScheduler.h"
|
||||
#include "tvgLottieModel.h"
|
||||
|
||||
|
||||
|
@ -111,14 +112,32 @@ void LottieSlot::assign(LottieObject* target)
|
|||
|
||||
LottieImage::~LottieImage()
|
||||
{
|
||||
if (picture && PP(picture)->unref() == 0) {
|
||||
delete(picture);
|
||||
}
|
||||
free(b64Data);
|
||||
free(mimeType);
|
||||
}
|
||||
|
||||
|
||||
void LottieImage::prepare()
|
||||
{
|
||||
LottieObject::type = LottieObject::Image;
|
||||
|
||||
auto picture = Picture::gen().release();
|
||||
|
||||
//force to load a picture on the same thread
|
||||
TaskScheduler::async(false);
|
||||
|
||||
if (size > 0) picture->load((const char*)b64Data, size, mimeType, false);
|
||||
else picture->load(path);
|
||||
|
||||
TaskScheduler::async(true);
|
||||
|
||||
picture->size(width, height);
|
||||
PP(picture)->ref();
|
||||
|
||||
pooler.push(picture);
|
||||
}
|
||||
|
||||
|
||||
void LottieTrimpath::segment(float frameNo, float& start, float& end, LottieExpressions* exps)
|
||||
{
|
||||
start = this->start(frameNo, exps) * 0.01f;
|
||||
|
@ -331,10 +350,6 @@ LottieLayer::~LottieLayer()
|
|||
delete(*m);
|
||||
}
|
||||
|
||||
//Remove tvg render paints
|
||||
if (solidFill && PP(solidFill)->unref() == 0) delete(solidFill);
|
||||
if (clipper && PP(clipper)->unref() == 0) delete(clipper);
|
||||
|
||||
delete(transform);
|
||||
free(name);
|
||||
}
|
||||
|
@ -351,12 +366,19 @@ void LottieLayer::prepare(RGB24* color)
|
|||
return;
|
||||
}
|
||||
|
||||
//prepare the viewport clipper
|
||||
if (type == LottieLayer::Precomp) {
|
||||
auto clipper = Shape::gen().release();
|
||||
clipper->appendRect(0.0f, 0.0f, w, h);
|
||||
PP(clipper)->ref();
|
||||
pooler.push(clipper);
|
||||
//prepare solid fill in advance if it is a layer type.
|
||||
if (color && type == LottieLayer::Solid) {
|
||||
solidFill = Shape::gen().release();
|
||||
} else if (color && type == LottieLayer::Solid) {
|
||||
auto solidFill = Shape::gen().release();
|
||||
solidFill->appendRect(0, 0, static_cast<float>(w), static_cast<float>(h));
|
||||
solidFill->fill(color->rgb[0], color->rgb[1], color->rgb[2]);
|
||||
PP(solidFill)->ref();
|
||||
pooler.push(solidFill);
|
||||
}
|
||||
|
||||
LottieGroup::prepare(LottieObject::Layer);
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "tvgCommon.h"
|
||||
#include "tvgRender.h"
|
||||
#include "tvgLottieProperty.h"
|
||||
#include "tvgLottieRenderPooler.h"
|
||||
|
||||
|
||||
struct LottieComposition;
|
||||
|
@ -490,25 +491,19 @@ struct LottieGradientStroke : LottieGradient, LottieStroke
|
|||
};
|
||||
|
||||
|
||||
struct LottieImage : LottieObject
|
||||
struct LottieImage : LottieObject, LottieRenderPooler<tvg::Picture>
|
||||
{
|
||||
union {
|
||||
char* b64Data = nullptr;
|
||||
char* path;
|
||||
};
|
||||
Picture* picture = nullptr; //tvg render data
|
||||
char* mimeType = nullptr;
|
||||
uint32_t size = 0;
|
||||
uint16_t refCnt = 0; //refernce count
|
||||
float width = 0.0f;
|
||||
float height = 0.0f;
|
||||
|
||||
~LottieImage();
|
||||
|
||||
void prepare()
|
||||
{
|
||||
LottieObject::type = LottieObject::Image;
|
||||
}
|
||||
void prepare();
|
||||
};
|
||||
|
||||
|
||||
|
@ -567,7 +562,7 @@ struct LottieGroup : LottieObject
|
|||
};
|
||||
|
||||
|
||||
struct LottieLayer : LottieGroup
|
||||
struct LottieLayer : LottieGroup, LottieRenderPooler<tvg::Shape>
|
||||
{
|
||||
enum Type : uint8_t {Precomp = 0, Solid, Image, Null, Shape, Text};
|
||||
|
||||
|
@ -593,9 +588,6 @@ struct LottieLayer : LottieGroup
|
|||
Array<LottieMask*> masks;
|
||||
LottieLayer* matteTarget = nullptr;
|
||||
|
||||
tvg::Shape* solidFill = nullptr;
|
||||
tvg::Shape* clipper = nullptr;
|
||||
|
||||
float timeStretch = 1.0f;
|
||||
float w = 0.0f, h = 0.0f;
|
||||
float inFrame = 0.0f;
|
||||
|
|
58
src/loaders/lottie/tvgLottieRenderPooler.h
Normal file
58
src/loaders/lottie/tvgLottieRenderPooler.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2024 the ThorVG project. All rights reserved.
|
||||
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _TVG_LOTTIE_RENDER_POOLER_H_
|
||||
#define _TVG_LOTTIE_RENDER_POOLER_H_
|
||||
|
||||
#include "tvgCommon.h"
|
||||
#include "tvgArray.h"
|
||||
#include "tvgPaint.h"
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct LottieRenderPooler
|
||||
{
|
||||
Array<T*> pooler;
|
||||
|
||||
~LottieRenderPooler()
|
||||
{
|
||||
for (auto p = pooler.begin(); p < pooler.end(); ++p) {
|
||||
if (PP(*p)->unref() == 0) delete(*p);
|
||||
}
|
||||
}
|
||||
|
||||
T* pooling()
|
||||
{
|
||||
//return available one.
|
||||
for (auto p = pooler.begin(); p < pooler.end(); ++p) {
|
||||
if (PP(*p)->refCnt == 1) return *p;
|
||||
}
|
||||
|
||||
//no empty, generate a new one.
|
||||
auto p = static_cast<T*>(pooler[0]->duplicate());
|
||||
PP(p)->ref();
|
||||
pooler.push(p);
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //_TVG_LOTTIE_RENDER_POOLER_H_
|
Loading…
Add table
Reference in a new issue