mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-05 22:11:22 +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;
|
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();
|
mRle = VRle();
|
||||||
}
|
}
|
||||||
|
|
||||||
VRle LOTMaskItem::rle()
|
VRle LOTMaskItem::rle()
|
||||||
{
|
{
|
||||||
if (mRleTask.valid()) {
|
if (mRleFuture && mRleFuture->valid()) {
|
||||||
mRle = mRleTask.get();
|
mRle = mRleFuture->get();
|
||||||
if (!vCompare(mCombinedAlpha, 1.0f))
|
if (!vCompare(mCombinedAlpha, 1.0f))
|
||||||
mRle *= (mCombinedAlpha * 255);
|
mRle *= (mCombinedAlpha * 255);
|
||||||
if (mData->mInv) mRle.invert();
|
if (mData->mInv) mRle.invert();
|
||||||
|
|||||||
@ -163,7 +163,7 @@ public:
|
|||||||
VMatrix mCombinedMatrix;
|
VMatrix mCombinedMatrix;
|
||||||
VPath mLocalPath;
|
VPath mLocalPath;
|
||||||
VPath mFinalPath;
|
VPath mFinalPath;
|
||||||
std::future<VRle> mRleTask;
|
RleShare mRleFuture;
|
||||||
VRle mRle;
|
VRle mRle;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -5,16 +5,21 @@
|
|||||||
void VDrawable::preprocess(const VRect &clip)
|
void VDrawable::preprocess(const VRect &clip)
|
||||||
{
|
{
|
||||||
if (mFlag & (DirtyState::Path)) {
|
if (mFlag & (DirtyState::Path)) {
|
||||||
|
|
||||||
|
if (!mRleFuture) mRleFuture = std::make_shared<VSharedState<VRle>>();
|
||||||
|
|
||||||
|
mRleFuture->reuse();
|
||||||
|
|
||||||
if (mStroke.enable) {
|
if (mStroke.enable) {
|
||||||
if (mStroke.mDash.size()) {
|
if (mStroke.mDash.size()) {
|
||||||
VDasher dasher(mStroke.mDash.data(), mStroke.mDash.size());
|
VDasher dasher(mStroke.mDash.data(), mStroke.mDash.size());
|
||||||
mPath = dasher.dashed(mPath);
|
mPath = dasher.dashed(mPath);
|
||||||
}
|
}
|
||||||
mRleTask = VRaster::generateStrokeInfo(
|
VRaster::generateStrokeInfo(mRleFuture,
|
||||||
std::move(mPath), std::move(mRle), mStroke.cap, mStroke.join,
|
std::move(mPath), std::move(mRle), mStroke.cap, mStroke.join,
|
||||||
mStroke.width, mStroke.meterLimit, clip);
|
mStroke.width, mStroke.meterLimit, clip);
|
||||||
} else {
|
} else {
|
||||||
mRleTask = VRaster::generateFillInfo(
|
VRaster::generateFillInfo(mRleFuture,
|
||||||
std::move(mPath), std::move(mRle), mFillRule, clip);
|
std::move(mPath), std::move(mRle), mFillRule, clip);
|
||||||
}
|
}
|
||||||
mRle = VRle();
|
mRle = VRle();
|
||||||
@ -24,8 +29,8 @@ void VDrawable::preprocess(const VRect &clip)
|
|||||||
|
|
||||||
VRle VDrawable::rle()
|
VRle VDrawable::rle()
|
||||||
{
|
{
|
||||||
if (mRleTask.valid()) {
|
if (mRleFuture && mRleFuture->valid()) {
|
||||||
mRle = mRleTask.get();
|
mRle = mRleFuture->get();
|
||||||
}
|
}
|
||||||
return mRle;
|
return mRle;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
#include "vbrush.h"
|
#include "vbrush.h"
|
||||||
#include "vpath.h"
|
#include "vpath.h"
|
||||||
#include "vrle.h"
|
#include "vrle.h"
|
||||||
|
#include "vraster.h"
|
||||||
|
|
||||||
class VDrawable {
|
class VDrawable {
|
||||||
public:
|
public:
|
||||||
@ -40,7 +41,7 @@ public:
|
|||||||
};
|
};
|
||||||
VBrush mBrush;
|
VBrush mBrush;
|
||||||
VPath mPath;
|
VPath mPath;
|
||||||
std::future<VRle> mRleTask;
|
RleShare mRleFuture;
|
||||||
VRle mRle;
|
VRle mRle;
|
||||||
StrokeInfo mStroke;
|
StrokeInfo mStroke;
|
||||||
DirtyFlag mFlag{DirtyState::All};
|
DirtyFlag mFlag{DirtyState::All};
|
||||||
|
|||||||
@ -244,7 +244,7 @@ static void bboxCb(int x, int y, int w, int h, void *user)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct RleTask {
|
struct RleTask {
|
||||||
std::promise<VRle> sender;
|
RleShare mRlePromise;
|
||||||
VPath path;
|
VPath path;
|
||||||
VRle rle;
|
VRle rle;
|
||||||
float width;
|
float width;
|
||||||
@ -348,7 +348,7 @@ class RleTaskScheduler {
|
|||||||
|
|
||||||
if (!success && !_q[i].pop(task)) break;
|
if (!success && !_q[i].pop(task)) break;
|
||||||
|
|
||||||
task.sender.set_value((task)(outlineRef, stroker));
|
task.mRlePromise->set_value((task)(outlineRef, stroker));
|
||||||
}
|
}
|
||||||
|
|
||||||
// cleanup
|
// cleanup
|
||||||
@ -370,21 +370,18 @@ public:
|
|||||||
for (auto &e : _threads) e.join();
|
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++;
|
auto i = _index++;
|
||||||
|
|
||||||
for (unsigned n = 0; n != _count; ++n) {
|
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));
|
_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)
|
float width, float meterLimit, const VRect &clip)
|
||||||
{
|
{
|
||||||
RleTask task;
|
RleTask task;
|
||||||
@ -396,10 +393,12 @@ public:
|
|||||||
task.width = width;
|
task.width = width;
|
||||||
task.meterLimit = meterLimit;
|
task.meterLimit = meterLimit;
|
||||||
task.clip = clip;
|
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;
|
RleTask task;
|
||||||
task.path = std::move(path);
|
task.path = std::move(path);
|
||||||
@ -407,33 +406,33 @@ public:
|
|||||||
task.fillRule = fillRule;
|
task.fillRule = fillRule;
|
||||||
task.clip = clip;
|
task.clip = clip;
|
||||||
task.stroke = false;
|
task.stroke = false;
|
||||||
return async(std::move(task));
|
task.mRlePromise = promise;
|
||||||
|
|
||||||
|
async(std::move(task));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static RleTaskScheduler raster_scheduler;
|
static RleTaskScheduler raster_scheduler;
|
||||||
|
|
||||||
std::future<VRle> VRaster::generateFillInfo(VPath &&path, VRle &&rle,
|
void VRaster::generateFillInfo(RleShare &promise, VPath &&path, VRle &&rle,
|
||||||
FillRule fillRule, const VRect &clip)
|
FillRule fillRule, const VRect &clip)
|
||||||
{
|
{
|
||||||
if (path.empty()) {
|
if (path.empty()) {
|
||||||
std::promise<VRle> promise;
|
promise->set_value(VRle());
|
||||||
promise.set_value(VRle());
|
return;
|
||||||
return promise.get_future();
|
|
||||||
}
|
}
|
||||||
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,
|
void VRaster::generateStrokeInfo(RleShare &promise, VPath &&path, VRle &&rle, CapStyle cap,
|
||||||
JoinStyle join, float width,
|
JoinStyle join, float width,
|
||||||
float meterLimit, const VRect &clip)
|
float meterLimit, const VRect &clip)
|
||||||
{
|
{
|
||||||
if (path.empty()) {
|
if (path.empty()) {
|
||||||
std::promise<VRle> promise;
|
promise->set_value(VRle());
|
||||||
promise.set_value(VRle());
|
return;
|
||||||
return promise.get_future();
|
|
||||||
}
|
}
|
||||||
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
|
V_END_NAMESPACE
|
||||||
|
|||||||
@ -9,14 +9,48 @@ V_BEGIN_NAMESPACE
|
|||||||
class VPath;
|
class VPath;
|
||||||
class VRle;
|
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 {
|
struct VRaster {
|
||||||
|
|
||||||
static std::future<VRle>
|
static void
|
||||||
generateFillInfo(VPath &&path, VRle &&rle,
|
generateFillInfo(RleShare &promise, VPath &&path, VRle &&rle,
|
||||||
FillRule fillRule = FillRule::Winding, const VRect &clip = VRect());
|
FillRule fillRule = FillRule::Winding, const VRect &clip = VRect());
|
||||||
|
|
||||||
static std::future<VRle>
|
static void
|
||||||
generateStrokeInfo(VPath &&path, VRle &&rle,
|
generateStrokeInfo(RleShare &promise, VPath &&path, VRle &&rle,
|
||||||
CapStyle cap, JoinStyle join,
|
CapStyle cap, JoinStyle join,
|
||||||
float width, float meterLimit, const VRect &clip = VRect());
|
float width, float meterLimit, const VRect &clip = VRect());
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user