From: subhransu mohanty Date: Wed, 12 Dec 2018 10:47:23 +0000 (+0900) Subject: lottie/render: Added custome future/promise to optimize the heap allocation. X-Git-Tag: submit/tizen/20181217.041818~10 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fb6bf7bef90771997f6c67c2297f9d03a4ada45a;p=platform%2Fcore%2Fuifw%2Flottie-player.git 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 --- diff --git a/src/lottie/lottieitem.cpp b/src/lottie/lottieitem.cpp index 631dae1..621f64c 100644 --- a/src/lottie/lottieitem.cpp +++ b/src/lottie/lottieitem.cpp @@ -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>(); + + 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(); diff --git a/src/lottie/lottieitem.h b/src/lottie/lottieitem.h index 737ce43..891e94c 100644 --- a/src/lottie/lottieitem.h +++ b/src/lottie/lottieitem.h @@ -163,7 +163,7 @@ public: VMatrix mCombinedMatrix; VPath mLocalPath; VPath mFinalPath; - std::future mRleTask; + RleShare mRleFuture; VRle mRle; }; diff --git a/src/vector/vdrawable.cpp b/src/vector/vdrawable.cpp index 13b0a2d..0eaad64 100644 --- a/src/vector/vdrawable.cpp +++ b/src/vector/vdrawable.cpp @@ -5,16 +5,21 @@ void VDrawable::preprocess(const VRect &clip) { if (mFlag & (DirtyState::Path)) { + + if (!mRleFuture) mRleFuture = std::make_shared>(); + + 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; } diff --git a/src/vector/vdrawable.h b/src/vector/vdrawable.h index 9d157f6..d07ad7e 100644 --- a/src/vector/vdrawable.h +++ b/src/vector/vdrawable.h @@ -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 mRleTask; + RleShare mRleFuture; VRle mRle; StrokeInfo mStroke; DirtyFlag mFlag{DirtyState::All}; diff --git a/src/vector/vraster.cpp b/src/vector/vraster.cpp index cb2a7ae..25185c3 100644 --- a/src/vector/vraster.cpp +++ b/src/vector/vraster.cpp @@ -244,7 +244,7 @@ static void bboxCb(int x, int y, int w, int h, void *user) } struct RleTask { - std::promise 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 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 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 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 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 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 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 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 diff --git a/src/vector/vraster.h b/src/vector/vraster.h index a25b0d2..d159420 100644 --- a/src/vector/vraster.h +++ b/src/vector/vraster.h @@ -9,14 +9,48 @@ V_BEGIN_NAMESPACE class VPath; class VRle; +template +class VSharedState { +public: + void set_value(R value) { + if (_ready) return; + + { + std::lock_guard lock(_mutex); + _value = std::move(value); + _ready = true; + } + _cv.notify_one(); + } + R get(){ + std::unique_lock 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>; + struct VRaster { - static std::future - 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 - 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()); };