mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-04 21:41:45 +00:00
lottie/render: Added custome future/promise to optimize the heap allocation.
As every future/promise shared data allocates in heap there was lot of heap allocation when we generate span info using RleThread pool. this custome future/promise will allocate 1 shared resource per drawable and will reuse for all subsequent span info request for that drawable. This reduced the number of heap allocation drastically and improves render performance. Change-Id: Ic480030e7c36ad7ab730683e71417de026220297
This commit is contained in:
parent
7e774a7bcd
commit
fb6bf7bef9
@ -158,14 +158,17 @@ void LOTMaskItem::update(int frameNo, const VMatrix &parentMatrix,
|
||||
|
||||
VPath tmp = mFinalPath;
|
||||
|
||||
mRleTask = VRaster::generateFillInfo(std::move(tmp), std::move(mRle));
|
||||
if (!mRleFuture) mRleFuture = std::make_shared<VSharedState<VRle>>();
|
||||
|
||||
mRleFuture->reuse();
|
||||
VRaster::generateFillInfo(mRleFuture, std::move(tmp), std::move(mRle));
|
||||
mRle = VRle();
|
||||
}
|
||||
|
||||
VRle LOTMaskItem::rle()
|
||||
{
|
||||
if (mRleTask.valid()) {
|
||||
mRle = mRleTask.get();
|
||||
if (mRleFuture && mRleFuture->valid()) {
|
||||
mRle = mRleFuture->get();
|
||||
if (!vCompare(mCombinedAlpha, 1.0f))
|
||||
mRle *= (mCombinedAlpha * 255);
|
||||
if (mData->mInv) mRle.invert();
|
||||
|
||||
@ -163,7 +163,7 @@ public:
|
||||
VMatrix mCombinedMatrix;
|
||||
VPath mLocalPath;
|
||||
VPath mFinalPath;
|
||||
std::future<VRle> mRleTask;
|
||||
RleShare mRleFuture;
|
||||
VRle mRle;
|
||||
};
|
||||
|
||||
|
||||
@ -5,16 +5,21 @@
|
||||
void VDrawable::preprocess(const VRect &clip)
|
||||
{
|
||||
if (mFlag & (DirtyState::Path)) {
|
||||
|
||||
if (!mRleFuture) mRleFuture = std::make_shared<VSharedState<VRle>>();
|
||||
|
||||
mRleFuture->reuse();
|
||||
|
||||
if (mStroke.enable) {
|
||||
if (mStroke.mDash.size()) {
|
||||
VDasher dasher(mStroke.mDash.data(), mStroke.mDash.size());
|
||||
mPath = dasher.dashed(mPath);
|
||||
}
|
||||
mRleTask = VRaster::generateStrokeInfo(
|
||||
VRaster::generateStrokeInfo(mRleFuture,
|
||||
std::move(mPath), std::move(mRle), mStroke.cap, mStroke.join,
|
||||
mStroke.width, mStroke.meterLimit, clip);
|
||||
} else {
|
||||
mRleTask = VRaster::generateFillInfo(
|
||||
VRaster::generateFillInfo(mRleFuture,
|
||||
std::move(mPath), std::move(mRle), mFillRule, clip);
|
||||
}
|
||||
mRle = VRle();
|
||||
@ -24,8 +29,8 @@ void VDrawable::preprocess(const VRect &clip)
|
||||
|
||||
VRle VDrawable::rle()
|
||||
{
|
||||
if (mRleTask.valid()) {
|
||||
mRle = mRleTask.get();
|
||||
if (mRleFuture && mRleFuture->valid()) {
|
||||
mRle = mRleFuture->get();
|
||||
}
|
||||
return mRle;
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#include "vbrush.h"
|
||||
#include "vpath.h"
|
||||
#include "vrle.h"
|
||||
#include "vraster.h"
|
||||
|
||||
class VDrawable {
|
||||
public:
|
||||
@ -40,7 +41,7 @@ public:
|
||||
};
|
||||
VBrush mBrush;
|
||||
VPath mPath;
|
||||
std::future<VRle> mRleTask;
|
||||
RleShare mRleFuture;
|
||||
VRle mRle;
|
||||
StrokeInfo mStroke;
|
||||
DirtyFlag mFlag{DirtyState::All};
|
||||
|
||||
@ -244,7 +244,7 @@ static void bboxCb(int x, int y, int w, int h, void *user)
|
||||
}
|
||||
|
||||
struct RleTask {
|
||||
std::promise<VRle> sender;
|
||||
RleShare mRlePromise;
|
||||
VPath path;
|
||||
VRle rle;
|
||||
float width;
|
||||
@ -348,7 +348,7 @@ class RleTaskScheduler {
|
||||
|
||||
if (!success && !_q[i].pop(task)) break;
|
||||
|
||||
task.sender.set_value((task)(outlineRef, stroker));
|
||||
task.mRlePromise->set_value((task)(outlineRef, stroker));
|
||||
}
|
||||
|
||||
// cleanup
|
||||
@ -370,21 +370,18 @@ public:
|
||||
for (auto &e : _threads) e.join();
|
||||
}
|
||||
|
||||
std::future<VRle> async(RleTask &&task)
|
||||
void async(RleTask &&task)
|
||||
{
|
||||
auto receiver = std::move(task.sender.get_future());
|
||||
auto i = _index++;
|
||||
|
||||
for (unsigned n = 0; n != _count; ++n) {
|
||||
if (_q[(i + n) % _count].try_push(std::move(task))) return receiver;
|
||||
if (_q[(i + n) % _count].try_push(std::move(task))) return;
|
||||
}
|
||||
|
||||
_q[i % _count].push(std::move(task));
|
||||
|
||||
return receiver;
|
||||
}
|
||||
|
||||
std::future<VRle> strokeRle(VPath &&path, VRle &&rle, CapStyle cap, JoinStyle join,
|
||||
void strokeRle(RleShare &promise, VPath &&path, VRle &&rle, CapStyle cap, JoinStyle join,
|
||||
float width, float meterLimit, const VRect &clip)
|
||||
{
|
||||
RleTask task;
|
||||
@ -396,10 +393,12 @@ public:
|
||||
task.width = width;
|
||||
task.meterLimit = meterLimit;
|
||||
task.clip = clip;
|
||||
return async(std::move(task));
|
||||
task.mRlePromise = promise;
|
||||
|
||||
async(std::move(task));
|
||||
}
|
||||
|
||||
std::future<VRle> fillRle(VPath &&path, VRle &&rle, FillRule fillRule, const VRect &clip)
|
||||
void fillRle(RleShare &promise, VPath &&path, VRle &&rle, FillRule fillRule, const VRect &clip)
|
||||
{
|
||||
RleTask task;
|
||||
task.path = std::move(path);
|
||||
@ -407,33 +406,33 @@ public:
|
||||
task.fillRule = fillRule;
|
||||
task.clip = clip;
|
||||
task.stroke = false;
|
||||
return async(std::move(task));
|
||||
task.mRlePromise = promise;
|
||||
|
||||
async(std::move(task));
|
||||
}
|
||||
};
|
||||
|
||||
static RleTaskScheduler raster_scheduler;
|
||||
|
||||
std::future<VRle> VRaster::generateFillInfo(VPath &&path, VRle &&rle,
|
||||
FillRule fillRule, const VRect &clip)
|
||||
void VRaster::generateFillInfo(RleShare &promise, VPath &&path, VRle &&rle,
|
||||
FillRule fillRule, const VRect &clip)
|
||||
{
|
||||
if (path.empty()) {
|
||||
std::promise<VRle> promise;
|
||||
promise.set_value(VRle());
|
||||
return promise.get_future();
|
||||
promise->set_value(VRle());
|
||||
return;
|
||||
}
|
||||
return raster_scheduler.fillRle(std::move(path), std::move(rle), fillRule, clip);
|
||||
return raster_scheduler.fillRle(promise, std::move(path), std::move(rle), fillRule, clip);
|
||||
}
|
||||
|
||||
std::future<VRle> VRaster::generateStrokeInfo(VPath &&path, VRle &&rle, CapStyle cap,
|
||||
JoinStyle join, float width,
|
||||
float meterLimit, const VRect &clip)
|
||||
void VRaster::generateStrokeInfo(RleShare &promise, VPath &&path, VRle &&rle, CapStyle cap,
|
||||
JoinStyle join, float width,
|
||||
float meterLimit, const VRect &clip)
|
||||
{
|
||||
if (path.empty()) {
|
||||
std::promise<VRle> promise;
|
||||
promise.set_value(VRle());
|
||||
return promise.get_future();
|
||||
promise->set_value(VRle());
|
||||
return;
|
||||
}
|
||||
return raster_scheduler.strokeRle(std::move(path), std::move(rle), cap, join, width, meterLimit, clip);
|
||||
return raster_scheduler.strokeRle(promise, std::move(path), std::move(rle), cap, join, width, meterLimit, clip);
|
||||
}
|
||||
|
||||
V_END_NAMESPACE
|
||||
|
||||
@ -9,14 +9,48 @@ V_BEGIN_NAMESPACE
|
||||
class VPath;
|
||||
class VRle;
|
||||
|
||||
template <class R>
|
||||
class VSharedState {
|
||||
public:
|
||||
void set_value(R value) {
|
||||
if (_ready) return;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
_value = std::move(value);
|
||||
_ready = true;
|
||||
}
|
||||
_cv.notify_one();
|
||||
}
|
||||
R get(){
|
||||
std::unique_lock<std::mutex> lock(_mutex);
|
||||
while(!_ready) _cv.wait(lock);
|
||||
_valid = false;
|
||||
return std::move(_value);
|
||||
}
|
||||
bool valid() const {return _valid;}
|
||||
void reuse() {
|
||||
_ready = false;
|
||||
_valid = true;
|
||||
}
|
||||
private:
|
||||
R _value;
|
||||
std::mutex _mutex;
|
||||
std::condition_variable _cv;
|
||||
bool _ready{false};
|
||||
bool _valid{true};
|
||||
};
|
||||
|
||||
using RleShare = std::shared_ptr<VSharedState<VRle>>;
|
||||
|
||||
struct VRaster {
|
||||
|
||||
static std::future<VRle>
|
||||
generateFillInfo(VPath &&path, VRle &&rle,
|
||||
static void
|
||||
generateFillInfo(RleShare &promise, VPath &&path, VRle &&rle,
|
||||
FillRule fillRule = FillRule::Winding, const VRect &clip = VRect());
|
||||
|
||||
static std::future<VRle>
|
||||
generateStrokeInfo(VPath &&path, VRle &&rle,
|
||||
static void
|
||||
generateStrokeInfo(RleShare &promise, VPath &&path, VRle &&rle,
|
||||
CapStyle cap, JoinStyle join,
|
||||
float width, float meterLimit, const VRect &clip = VRect());
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user