mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-25 07:35:38 +00:00
Added rudimentary frame caching support to LottieComponent.
This commit is contained in:
parent
3f629b6c1e
commit
b3421823a7
|
@ -277,6 +277,8 @@ void Settings::setDefaults()
|
||||||
mBoolMap["DebugSkipInputLogging"] = {false, false};
|
mBoolMap["DebugSkipInputLogging"] = {false, false};
|
||||||
mStringMap["ROMDirectory"] = {"", ""};
|
mStringMap["ROMDirectory"] = {"", ""};
|
||||||
mStringMap["UIMode_passkey"] = {"uuddlrlrba", "uuddlrlrba"};
|
mStringMap["UIMode_passkey"] = {"uuddlrlrba", "uuddlrlrba"};
|
||||||
|
mIntMap["LottieMaxFileCache"] = {100, 100};
|
||||||
|
mIntMap["LottieMaxTotalCache"] = {1024, 1024};
|
||||||
|
|
||||||
//
|
//
|
||||||
// Hardcoded or program-internal settings.
|
// Hardcoded or program-internal settings.
|
||||||
|
|
|
@ -17,6 +17,10 @@
|
||||||
|
|
||||||
LottieComponent::LottieComponent(Window* window)
|
LottieComponent::LottieComponent(Window* window)
|
||||||
: GuiComponent{window}
|
: GuiComponent{window}
|
||||||
|
, mCacheFrames{true}
|
||||||
|
, mMaxCacheSize{0}
|
||||||
|
, mCacheSize{0}
|
||||||
|
, mFrameSize{0}
|
||||||
, mAnimation{nullptr}
|
, mAnimation{nullptr}
|
||||||
, mSurface{nullptr}
|
, mSurface{nullptr}
|
||||||
, mTotalFrames{0}
|
, mTotalFrames{0}
|
||||||
|
@ -35,6 +39,17 @@ LottieComponent::LottieComponent(Window* window)
|
||||||
mTexture->setFormat(Renderer::Texture::BGRA);
|
mTexture->setFormat(Renderer::Texture::BGRA);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Keep per-file cache size within 0 to 1024 MiB.
|
||||||
|
mMaxCacheSize = static_cast<size_t>(
|
||||||
|
glm::clamp(Settings::getInstance()->getInt("LottieMaxFileCache"), 0, 1024) * 1024 * 1024);
|
||||||
|
|
||||||
|
// Keep total cache size within 0 to 4096 MiB.
|
||||||
|
int maxTotalCache =
|
||||||
|
glm::clamp(Settings::getInstance()->getInt("LottieMaxTotalCache"), 0, 4096) * 1024 * 1024;
|
||||||
|
|
||||||
|
if (mMaxTotalFrameCache != static_cast<size_t>(maxTotalCache))
|
||||||
|
mMaxTotalFrameCache = static_cast<size_t>(maxTotalCache);
|
||||||
|
|
||||||
// Set component defaults.
|
// Set component defaults.
|
||||||
setOrigin(0.5f, 0.5f);
|
setOrigin(0.5f, 0.5f);
|
||||||
setSize(Renderer::getScreenWidth() * 0.2f, Renderer::getScreenHeight() * 0.2f);
|
setSize(Renderer::getScreenWidth() * 0.2f, Renderer::getScreenHeight() * 0.2f);
|
||||||
|
@ -43,6 +58,13 @@ LottieComponent::LottieComponent(Window* window)
|
||||||
setZIndex(30.0f);
|
setZIndex(30.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LottieComponent::~LottieComponent()
|
||||||
|
{
|
||||||
|
if (mFuture.valid())
|
||||||
|
mFuture.get();
|
||||||
|
mTotalFrameCache -= mCacheSize;
|
||||||
|
}
|
||||||
|
|
||||||
void LottieComponent::setAnimation(const std::string& path)
|
void LottieComponent::setAnimation(const std::string& path)
|
||||||
{
|
{
|
||||||
if (mAnimation != nullptr) {
|
if (mAnimation != nullptr) {
|
||||||
|
@ -51,6 +73,7 @@ void LottieComponent::setAnimation(const std::string& path)
|
||||||
mSurface.reset();
|
mSurface.reset();
|
||||||
mAnimation.reset();
|
mAnimation.reset();
|
||||||
mPictureRGBA.clear();
|
mPictureRGBA.clear();
|
||||||
|
mCacheSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
mPath = path;
|
mPath = path;
|
||||||
|
@ -98,6 +121,7 @@ void LottieComponent::setAnimation(const std::string& path)
|
||||||
double duration = mAnimation->duration();
|
double duration = mAnimation->duration();
|
||||||
mTotalFrames = mAnimation->totalFrame();
|
mTotalFrames = mAnimation->totalFrame();
|
||||||
mFrameRate = mAnimation->frameRate();
|
mFrameRate = mAnimation->frameRate();
|
||||||
|
mFrameSize = width * height * 4;
|
||||||
|
|
||||||
mTargetPacing = static_cast<int>(1000.0 / mFrameRate);
|
mTargetPacing = static_cast<int>(1000.0 / mFrameRate);
|
||||||
|
|
||||||
|
@ -109,7 +133,8 @@ void LottieComponent::setAnimation(const std::string& path)
|
||||||
void LottieComponent::onSizeChanged()
|
void LottieComponent::onSizeChanged()
|
||||||
{
|
{
|
||||||
// Setting the animation again will completely reinitialize it.
|
// Setting the animation again will completely reinitialize it.
|
||||||
setAnimation(mPath);
|
if (mPath != "")
|
||||||
|
setAnimation(mPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LottieComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
void LottieComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
|
@ -156,16 +181,45 @@ void LottieComponent::render(const glm::mat4& parentTrans)
|
||||||
|
|
||||||
if (mFuture.valid()) {
|
if (mFuture.valid()) {
|
||||||
if (mFuture.wait_for(std::chrono::milliseconds(1)) == std::future_status::ready) {
|
if (mFuture.wait_for(std::chrono::milliseconds(1)) == std::future_status::ready) {
|
||||||
|
mFuture.get();
|
||||||
|
|
||||||
|
// Cache frame if caching is enabled and we're not exceeding either the per-file
|
||||||
|
// max cache size or the total cache size. Note that this is completely unrelated
|
||||||
|
// to the texture caching used for images.
|
||||||
|
if (mCacheFrames && mFrameCache.find(mFrameNum) == mFrameCache.end()) {
|
||||||
|
size_t newCacheSize = mCacheSize + mFrameSize;
|
||||||
|
if (newCacheSize < mMaxCacheSize &&
|
||||||
|
mTotalFrameCache + mFrameSize < mMaxTotalFrameCache) {
|
||||||
|
mFrameCache[mFrameNum] = mPictureRGBA;
|
||||||
|
mCacheSize += mFrameSize;
|
||||||
|
mTotalFrameCache += mFrameSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mTexture->initFromPixels(&mPictureRGBA.at(0), static_cast<size_t>(mSize.x),
|
mTexture->initFromPixels(&mPictureRGBA.at(0), static_cast<size_t>(mSize.x),
|
||||||
static_cast<size_t>(mSize.y));
|
static_cast<size_t>(mSize.y));
|
||||||
mFuture.get();
|
|
||||||
++mFrameNum;
|
++mFrameNum;
|
||||||
renderNextFrame = true;
|
|
||||||
|
if (mFrameNum == mTotalFrames)
|
||||||
|
renderNextFrame = false;
|
||||||
|
else
|
||||||
|
renderNextFrame = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
renderNextFrame = true;
|
if (mFrameCache.find(mFrameNum) != mFrameCache.end()) {
|
||||||
|
if (!mHoldFrame) {
|
||||||
|
mTexture->initFromPixels(&mFrameCache[mFrameNum][0], static_cast<size_t>(mSize.x),
|
||||||
|
static_cast<size_t>(mSize.y));
|
||||||
|
++mFrameNum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
renderNextFrame = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (renderNextFrame && !mHoldFrame)
|
if (renderNextFrame && !mHoldFrame)
|
||||||
mFuture = mAnimation->render(mFrameNum, *mSurface, mKeepAspectRatio);
|
mFuture = mAnimation->render(mFrameNum, *mSurface, mKeepAspectRatio);
|
||||||
|
|
||||||
|
|
|
@ -12,19 +12,27 @@
|
||||||
#include "GuiComponent.h"
|
#include "GuiComponent.h"
|
||||||
#include "renderers/Renderer.h"
|
#include "renderers/Renderer.h"
|
||||||
#include "resources/TextureResource.h"
|
#include "resources/TextureResource.h"
|
||||||
|
#include "utils/MathUtil.h"
|
||||||
|
|
||||||
#include "rlottie.h"
|
#include "rlottie.h"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <future>
|
#include <future>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
class LottieComponent : public GuiComponent
|
class LottieComponent : public GuiComponent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LottieComponent(Window* window);
|
LottieComponent(Window* window);
|
||||||
|
~LottieComponent();
|
||||||
|
|
||||||
void setAnimation(const std::string& path);
|
void setAnimation(const std::string& path);
|
||||||
void setKeepAspectRatio(bool value) { mKeepAspectRatio = value; }
|
void setKeepAspectRatio(bool value) { mKeepAspectRatio = value; }
|
||||||
|
void setFrameCaching(bool value) { mCacheFrames = value; }
|
||||||
|
void setMaxCacheSize(int value)
|
||||||
|
{
|
||||||
|
mMaxCacheSize = static_cast<size_t>(glm::clamp(value, 0, 1024) * 1024 * 1024);
|
||||||
|
}
|
||||||
|
|
||||||
void onSizeChanged() override;
|
void onSizeChanged() override;
|
||||||
|
|
||||||
|
@ -39,6 +47,14 @@ private:
|
||||||
|
|
||||||
std::shared_ptr<TextureResource> mTexture;
|
std::shared_ptr<TextureResource> mTexture;
|
||||||
std::vector<uint8_t> mPictureRGBA;
|
std::vector<uint8_t> mPictureRGBA;
|
||||||
|
std::unordered_map<size_t, std::vector<uint8_t>> mFrameCache;
|
||||||
|
// Set a 1024 MiB total Lottie animation cache as default.
|
||||||
|
inline static size_t mMaxTotalFrameCache = 1024 * 1024 * 1024;
|
||||||
|
inline static size_t mTotalFrameCache;
|
||||||
|
bool mCacheFrames;
|
||||||
|
size_t mMaxCacheSize;
|
||||||
|
size_t mCacheSize;
|
||||||
|
size_t mFrameSize;
|
||||||
|
|
||||||
std::unique_ptr<rlottie::Animation> mAnimation;
|
std::unique_ptr<rlottie::Animation> mAnimation;
|
||||||
std::unique_ptr<rlottie::Surface> mSurface;
|
std::unique_ptr<rlottie::Surface> mSurface;
|
||||||
|
@ -53,6 +69,7 @@ private:
|
||||||
|
|
||||||
bool mKeepAspectRatio;
|
bool mKeepAspectRatio;
|
||||||
|
|
||||||
|
// TEMPORARY.
|
||||||
std::chrono::time_point<std::chrono::system_clock> mAnimationStartTime;
|
std::chrono::time_point<std::chrono::system_clock> mAnimationStartTime;
|
||||||
std::chrono::time_point<std::chrono::system_clock> mAnimationEndTime;
|
std::chrono::time_point<std::chrono::system_clock> mAnimationEndTime;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue