From 1d8d3d38723d2f2234bf0b1ee6337b2a2f330030 Mon Sep 17 00:00:00 2001 From: subhransu mohanty Date: Mon, 4 Nov 2019 10:11:23 +0900 Subject: [PATCH] rlottie: refactor to use a local arena allocator for shadow tree creation This usecase is best suitable for local arena allocator as we have a fixed number of objects to create and they all gets deleted at once. so by keeping a allocator in the composition and use it to create all the objects using it will basically flattened the memory layout of the shadow tree as all the memory comes from the one memory allocator pool. This improves the bencmark performance by 5%. --- src/lottie/lottieitem.cpp | 140 +++++++++++++++++++++++----------------------- src/lottie/lottieitem.h | 33 +++++------ 2 files changed, 87 insertions(+), 86 deletions(-) diff --git a/src/lottie/lottieitem.cpp b/src/lottie/lottieitem.cpp index 6f9c584..44f1350 100644 --- a/src/lottie/lottieitem.cpp +++ b/src/lottie/lottieitem.cpp @@ -68,39 +68,24 @@ static bool strokeProp(rlottie::Property prop) } } -LOTCompItem::LOTCompItem(LOTModel *model) - : mCurFrameNo(-1) -{ - mCompData = model->mRoot.get(); - mRootLayer = createLayerItem(mCompData->mRootLayer.get()); - mRootLayer->setComplexContent(false); - mViewSize = mCompData->size(); -} - -void LOTCompItem::setValue(const std::string &keypath, LOTVariant &value) -{ - LOTKeyPath key(keypath); - mRootLayer->resolveKeyPath(key, 0, value); -} - -std::unique_ptr LOTCompItem::createLayerItem( - LOTLayerData *layerData) +static LOTLayerItem* +createLayerItem(LOTLayerData *layerData, VArenaAlloc *allocator) { switch (layerData->mLayerType) { case LayerType::Precomp: { - return std::make_unique(layerData); + return allocator->make(layerData, allocator); } case LayerType::Solid: { - return std::make_unique(layerData); + return allocator->make(layerData); } case LayerType::Shape: { - return std::make_unique(layerData); + return allocator->make(layerData, allocator); } case LayerType::Null: { - return std::make_unique(layerData); + return allocator->make(layerData); } case LayerType::Image: { - return std::make_unique(layerData); + return allocator->make(layerData); } default: return nullptr; @@ -108,6 +93,21 @@ std::unique_ptr LOTCompItem::createLayerItem( } } +LOTCompItem::LOTCompItem(LOTModel *model) + : mCurFrameNo(-1) +{ + mCompData = model->mRoot.get(); + mRootLayer = createLayerItem(mCompData->mRootLayer.get(), &mAllocator); + mRootLayer->setComplexContent(false); + mViewSize = mCompData->size(); +} + +void LOTCompItem::setValue(const std::string &keypath, LOTVariant &value) +{ + LOTKeyPath key(keypath); + mRootLayer->resolveKeyPath(key, 0, value); +} + bool LOTCompItem::update(int frameNo, const VSize &size, bool keepAspectRatio) { // check if cached frame is same as requested frame. @@ -433,7 +433,7 @@ void LOTLayerItem::preprocess(const VRect& clip) preprocessStage(clip); } -LOTCompLayerItem::LOTCompLayerItem(LOTLayerData *layerModel) +LOTCompLayerItem::LOTCompLayerItem(LOTLayerData *layerModel, VArenaAlloc* allocator) : LOTLayerItem(layerModel) { if (!mLayerData->mChildren.empty()) @@ -444,8 +444,8 @@ LOTCompLayerItem::LOTCompLayerItem(LOTLayerData *layerModel) for (auto it = mLayerData->mChildren.crbegin(); it != mLayerData->mChildren.rend(); ++it ) { auto model = static_cast((*it).get()); - auto item = LOTCompItem::createLayerItem(model); - if (item) mLayers.push_back(std::move(item)); + auto item = createLayerItem(model, allocator); + if (item) mLayers.push_back(item); } // 2. update parent layer @@ -455,7 +455,7 @@ LOTCompLayerItem::LOTCompLayerItem(LOTLayerData *layerModel) auto search = std::find_if(mLayers.begin(), mLayers.end(), [id](const auto &val) { return val->id() == id; }); - if (search != mLayers.end()) layer->setParentLayer((*search).get()); + if (search != mLayers.end()) layer->setParentLayer(*search); } } @@ -511,13 +511,13 @@ void LOTCompLayerItem::renderHelper(VPainter *painter, const VRle &inheritMask, LOTLayerItem *matte = nullptr; for (const auto &layer : mLayers) { if (layer->hasMatte()) { - matte = layer.get(); + matte = layer; } else { if (layer->visible()) { if (matte) { if (matte->visible()) renderMatteLayer(painter, mask, matteRle, matte, - layer.get()); + layer); } else { layer->render(painter, mask, matteRle); } @@ -624,7 +624,7 @@ void LOTCompLayerItem::preprocessStage(const VRect &clip) LOTLayerItem *matte = nullptr; for (const auto &layer : mLayers) { if (layer->hasMatte()) { - matte = layer.get(); + matte = layer; } else { if (layer->visible()) { if (matte) { @@ -728,67 +728,52 @@ LOTNullLayerItem::LOTNullLayerItem(LOTLayerData *layerData) } void LOTNullLayerItem::updateContent() {} -LOTShapeLayerItem::LOTShapeLayerItem(LOTLayerData *layerData) - : LOTLayerItem(layerData), - mRoot(std::make_unique(nullptr)) -{ - mRoot->addChildren(layerData); - - std::vector list; - mRoot->processPaintItems(list); - - if (layerData->hasPathOperator()) { - list.clear(); - mRoot->processTrimItems(list); - } -} - -std::unique_ptr LOTShapeLayerItem::createContentItem( - LOTData *contentData) +static LOTContentItem* +createContentItem(LOTData *contentData, VArenaAlloc* allocator) { switch (contentData->type()) { case LOTData::Type::ShapeGroup: { - return std::make_unique( - static_cast(contentData)); + return allocator->make( + static_cast(contentData), allocator); } case LOTData::Type::Rect: { - return std::make_unique( + return allocator->make( static_cast(contentData)); } case LOTData::Type::Ellipse: { - return std::make_unique( + return allocator->make( static_cast(contentData)); } case LOTData::Type::Shape: { - return std::make_unique( + return allocator->make( static_cast(contentData)); } case LOTData::Type::Polystar: { - return std::make_unique( + return allocator->make( static_cast(contentData)); } case LOTData::Type::Fill: { - return std::make_unique( + return allocator->make( static_cast(contentData)); } case LOTData::Type::GFill: { - return std::make_unique( + return allocator->make( static_cast(contentData)); } case LOTData::Type::Stroke: { - return std::make_unique( + return allocator->make( static_cast(contentData)); } case LOTData::Type::GStroke: { - return std::make_unique( + return allocator->make( static_cast(contentData)); } case LOTData::Type::Repeater: { - return std::make_unique( - static_cast(contentData)); + return allocator->make( + static_cast(contentData), allocator); } case LOTData::Type::Trim: { - return std::make_unique( + return allocator->make( static_cast(contentData)); } default: @@ -797,6 +782,21 @@ std::unique_ptr LOTShapeLayerItem::createContentItem( } } +LOTShapeLayerItem::LOTShapeLayerItem(LOTLayerData *layerData, VArenaAlloc* allocator) + : LOTLayerItem(layerData), + mRoot(allocator->make(nullptr, allocator)) +{ + mRoot->addChildren(layerData, allocator); + + std::vector list; + mRoot->processPaintItems(list); + + if (layerData->hasPathOperator()) { + list.clear(); + mRoot->processTrimItems(list); + } +} + void LOTShapeLayerItem::updateContent() { mRoot->update(frameNo(), combinedMatrix(), combinedAlpha(), flag()); @@ -880,13 +880,13 @@ bool LOTStrokeItem::resolveKeyPath(LOTKeyPath &keyPath, uint depth, return false; } -LOTContentGroupItem::LOTContentGroupItem(LOTGroupData *data) +LOTContentGroupItem::LOTContentGroupItem(LOTGroupData *data, VArenaAlloc* allocator) : mData(data) { - addChildren(mData); + addChildren(mData, allocator); } -void LOTContentGroupItem::addChildren(LOTGroupData *data) +void LOTContentGroupItem::addChildren(LOTGroupData *data, VArenaAlloc* allocator) { if (!data) return; @@ -896,9 +896,9 @@ void LOTContentGroupItem::addChildren(LOTGroupData *data) // as lottie model keeps it in front-to-back order. for (auto it = data->mChildren.crbegin(); it != data->mChildren.rend(); ++it ) { - auto content = LOTShapeLayerItem::createContentItem((*it).get()); + auto content = createContentItem((*it).get(), allocator); if (content) { - mContents.push_back(std::move(content)); + mContents.push_back(content); } } } @@ -937,7 +937,7 @@ void LOTContentGroupItem::update(int frameNo, const VMatrix &parentMatrix, void LOTContentGroupItem::applyTrim() { for (auto i = mContents.rbegin(); i != mContents.rend(); ++i) { - auto content = (*i).get(); + auto content = (*i); switch (content->type()) { case ContentType::Trim: { static_cast(content)->update(); @@ -965,7 +965,7 @@ void LOTContentGroupItem::processPaintItems( { size_t curOpCount = list.size(); for (auto i = mContents.rbegin(); i != mContents.rend(); ++i) { - auto content = (*i).get(); + auto content = (*i); switch (content->type()) { case ContentType::Path: { auto pathItem = static_cast(content); @@ -993,7 +993,7 @@ void LOTContentGroupItem::processTrimItems(std::vector &list) { size_t curOpCount = list.size(); for (auto i = mContents.rbegin(); i != mContents.rend(); ++i) { - auto content = (*i).get(); + auto content = (*i); switch (content->type()) { case ContentType::Path: { @@ -1395,7 +1395,7 @@ void LOTTrimItem::addPathItems(std::vector &list, back_inserter(mPathItems)); } -LOTRepeaterItem::LOTRepeaterItem(LOTRepeaterData *data) : mRepeaterData(data) +LOTRepeaterItem::LOTRepeaterItem(LOTRepeaterData *data, VArenaAlloc* allocator) : mRepeaterData(data) { assert(mRepeaterData->content()); @@ -1403,9 +1403,9 @@ LOTRepeaterItem::LOTRepeaterItem(LOTRepeaterData *data) : mRepeaterData(data) for (int i = 0; i < mCopies; i++) { auto content = - std::make_unique(mRepeaterData->content()); + allocator->make(mRepeaterData->content(), allocator); //content->setParent(this); - mContents.push_back(std::move(content)); + mContents.push_back(content); } } diff --git a/src/lottie/lottieitem.h b/src/lottie/lottieitem.h index 0ed30ce..b6cda32 100644 --- a/src/lottie/lottieitem.h +++ b/src/lottie/lottieitem.h @@ -1,16 +1,16 @@ -/* +/* * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -32,6 +32,7 @@ #include"vpainter.h" #include"vdrawable.h" #include"lottiekeypath.h" +#include"varenaalloc.h" V_USE_NAMESPACE @@ -64,7 +65,6 @@ class LOTCompItem { public: explicit LOTCompItem(LOTModel *model); - static std::unique_ptr createLayerItem(LOTLayerData *layerData); bool update(int frameNo, const VSize &size, bool keepAspectRatio); VSize size() const { return mViewSize;} void buildRenderTree(); @@ -76,7 +76,8 @@ private: VMatrix mScaleMatrix; VSize mViewSize; LOTCompositionData *mCompData; - std::unique_ptr mRootLayer; + LOTLayerItem *mRootLayer; + VArenaAlloc mAllocator{2048}; int mCurFrameNo; bool mKeepAspectRatio{true}; }; @@ -194,7 +195,7 @@ protected: class LOTCompLayerItem: public LOTLayerItem { public: - explicit LOTCompLayerItem(LOTLayerData *layerData); + explicit LOTCompLayerItem(LOTLayerData *layerData, VArenaAlloc* allocator); void render(VPainter *painter, const VRle &mask, const VRle &matteRle) final; void buildLayerNode() final; @@ -207,8 +208,8 @@ private: void renderMatteLayer(VPainter *painter, const VRle &inheritMask, const VRle &matteRle, LOTLayerItem *layer, LOTLayerItem *src); private: - std::vector> mLayers; - std::unique_ptr mClipper; + std::vector mLayers; + std::unique_ptr mClipper; }; class LOTSolidLayerItem: public LOTLayerItem @@ -230,8 +231,7 @@ class LOTContentGroupItem; class LOTShapeLayerItem: public LOTLayerItem { public: - explicit LOTShapeLayerItem(LOTLayerData *layerData); - static std::unique_ptr createContentItem(LOTData *contentData); + explicit LOTShapeLayerItem(LOTLayerData *layerData, VArenaAlloc* allocator); DrawableList renderList() final; void buildLayerNode() final; bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) override; @@ -239,7 +239,7 @@ protected: void preprocessStage(const VRect& clip) final; void updateContent() final; std::vector mDrawableList; - std::unique_ptr mRoot; + LOTContentGroupItem *mRoot; }; class LOTNullLayerItem: public LOTLayerItem @@ -328,8 +328,9 @@ public: class LOTContentGroupItem: public LOTContentItem { public: - explicit LOTContentGroupItem(LOTGroupData *data=nullptr); - void addChildren(LOTGroupData *data); + LOTContentGroupItem() = default; + explicit LOTContentGroupItem(LOTGroupData *data, VArenaAlloc* allocator); + void addChildren(LOTGroupData *data, VArenaAlloc* allocator); void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) override; void applyTrim(); void processTrimItems(std::vector &list); @@ -345,7 +346,7 @@ public: bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) override; protected: LOTGroupData *mData{nullptr}; - std::vector> mContents; + std::vector mContents; VMatrix mMatrix; }; @@ -542,7 +543,7 @@ private: class LOTRepeaterItem : public LOTContentGroupItem { public: - explicit LOTRepeaterItem(LOTRepeaterData *data); + explicit LOTRepeaterItem(LOTRepeaterData *data, VArenaAlloc* allocator); void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) final; void renderList(std::vector &list) final; private: -- 2.7.4