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};
|
||||
mStringMap["ROMDirectory"] = {"", ""};
|
||||
mStringMap["UIMode_passkey"] = {"uuddlrlrba", "uuddlrlrba"};
|
||||
mIntMap["LottieMaxFileCache"] = {100, 100};
|
||||
mIntMap["LottieMaxTotalCache"] = {1024, 1024};
|
||||
|
||||
//
|
||||
// Hardcoded or program-internal settings.
|
||||
|
|
|
@ -17,6 +17,10 @@
|
|||
|
||||
LottieComponent::LottieComponent(Window* window)
|
||||
: GuiComponent{window}
|
||||
, mCacheFrames{true}
|
||||
, mMaxCacheSize{0}
|
||||
, mCacheSize{0}
|
||||
, mFrameSize{0}
|
||||
, mAnimation{nullptr}
|
||||
, mSurface{nullptr}
|
||||
, mTotalFrames{0}
|
||||
|
@ -35,6 +39,17 @@ LottieComponent::LottieComponent(Window* window)
|
|||
mTexture->setFormat(Renderer::Texture::BGRA);
|
||||
#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.
|
||||
setOrigin(0.5f, 0.5f);
|
||||
setSize(Renderer::getScreenWidth() * 0.2f, Renderer::getScreenHeight() * 0.2f);
|
||||
|
@ -43,6 +58,13 @@ LottieComponent::LottieComponent(Window* window)
|
|||
setZIndex(30.0f);
|
||||
}
|
||||
|
||||
LottieComponent::~LottieComponent()
|
||||
{
|
||||
if (mFuture.valid())
|
||||
mFuture.get();
|
||||
mTotalFrameCache -= mCacheSize;
|
||||
}
|
||||
|
||||
void LottieComponent::setAnimation(const std::string& path)
|
||||
{
|
||||
if (mAnimation != nullptr) {
|
||||
|
@ -51,6 +73,7 @@ void LottieComponent::setAnimation(const std::string& path)
|
|||
mSurface.reset();
|
||||
mAnimation.reset();
|
||||
mPictureRGBA.clear();
|
||||
mCacheSize = 0;
|
||||
}
|
||||
|
||||
mPath = path;
|
||||
|
@ -98,6 +121,7 @@ void LottieComponent::setAnimation(const std::string& path)
|
|||
double duration = mAnimation->duration();
|
||||
mTotalFrames = mAnimation->totalFrame();
|
||||
mFrameRate = mAnimation->frameRate();
|
||||
mFrameSize = width * height * 4;
|
||||
|
||||
mTargetPacing = static_cast<int>(1000.0 / mFrameRate);
|
||||
|
||||
|
@ -109,6 +133,7 @@ void LottieComponent::setAnimation(const std::string& path)
|
|||
void LottieComponent::onSizeChanged()
|
||||
{
|
||||
// Setting the animation again will completely reinitialize it.
|
||||
if (mPath != "")
|
||||
setAnimation(mPath);
|
||||
}
|
||||
|
||||
|
@ -156,16 +181,45 @@ void LottieComponent::render(const glm::mat4& parentTrans)
|
|||
|
||||
if (mFuture.valid()) {
|
||||
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),
|
||||
static_cast<size_t>(mSize.y));
|
||||
mFuture.get();
|
||||
|
||||
++mFrameNum;
|
||||
|
||||
if (mFrameNum == mTotalFrames)
|
||||
renderNextFrame = false;
|
||||
else
|
||||
renderNextFrame = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
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)
|
||||
mFuture = mAnimation->render(mFrameNum, *mSurface, mKeepAspectRatio);
|
||||
|
||||
|
|
|
@ -12,19 +12,27 @@
|
|||
#include "GuiComponent.h"
|
||||
#include "renderers/Renderer.h"
|
||||
#include "resources/TextureResource.h"
|
||||
#include "utils/MathUtil.h"
|
||||
|
||||
#include "rlottie.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <future>
|
||||
#include <unordered_map>
|
||||
|
||||
class LottieComponent : public GuiComponent
|
||||
{
|
||||
public:
|
||||
LottieComponent(Window* window);
|
||||
~LottieComponent();
|
||||
|
||||
void setAnimation(const std::string& path);
|
||||
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;
|
||||
|
||||
|
@ -39,6 +47,14 @@ private:
|
|||
|
||||
std::shared_ptr<TextureResource> mTexture;
|
||||
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::Surface> mSurface;
|
||||
|
@ -53,6 +69,7 @@ private:
|
|||
|
||||
bool mKeepAspectRatio;
|
||||
|
||||
// TEMPORARY.
|
||||
std::chrono::time_point<std::chrono::system_clock> mAnimationStartTime;
|
||||
std::chrono::time_point<std::chrono::system_clock> mAnimationEndTime;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue