optimization: added SurfaceCache to reduce intermediate buffers. accepted/tizen/unified/20200701.032327 submit/tizen/20200629.001406 submit/tizen/20200629.234316 submit/tizen/20200630.101739
authorSubhransu Mohanty <smohantty@gmail.com>
Thu, 25 Jun 2020 07:41:15 +0000 (16:41 +0900)
committerJongmin Lee <jm105.lee@samsung.com>
Mon, 29 Jun 2020 00:02:29 +0000 (09:02 +0900)
During rendering layers with mask/matte we need intermediate buffers
by keeping the surface cache we can reuse the same buffer for different
layer rendering to reduce memory footprint.

src/lottie/lottieitem.cpp
src/lottie/lottieitem.h

index 8586a69..4791d4f 100644 (file)
@@ -157,7 +157,7 @@ bool LOTCompItem::render(const rlottie::Surface &surface)
     painter.setDrawRegion(
         VRect(int(surface.drawRegionPosX()), int(surface.drawRegionPosY()),
               int(surface.drawRegionWidth()), int(surface.drawRegionHeight())));
-    mRootLayer->render(&painter, {}, {});
+    mRootLayer->render(&painter, {}, {}, mSurfaceCache);
     painter.end();
     return true;
 }
@@ -200,7 +200,7 @@ void LOTMaskItem::preprocess(const VRect &clip)
 }
 
 void LOTLayerItem::render(VPainter *painter, const VRle &inheritMask,
-                          const VRle &matteRle)
+                          const VRle &matteRle, SurfaceCache& cache)
 {
     auto renderlist = renderList();
 
@@ -468,30 +468,30 @@ LOTCompLayerItem::LOTCompLayerItem(LOTLayerData *layerModel, VArenaAlloc* alloca
 }
 
 void LOTCompLayerItem::render(VPainter *painter, const VRle &inheritMask,
-                              const VRle &matteRle)
+                              const VRle &matteRle, SurfaceCache& cache)
 {
     if (vIsZero(combinedAlpha())) return;
 
     if (vCompare(combinedAlpha(), 1.0)) {
-        renderHelper(painter, inheritMask, matteRle);
+        renderHelper(painter, inheritMask, matteRle, cache);
     } else {
         if (complexContent()) {
             VSize    size = painter->clipBoundingRect().size();
             VPainter srcPainter;
-            VBitmap  srcBitmap(size.width(), size.height(),
-                              VBitmap::Format::ARGB32_Premultiplied);
+            VBitmap  srcBitmap = cache.make_surface(size.width(), size.height());
             srcPainter.begin(&srcBitmap);
-            renderHelper(&srcPainter, inheritMask, matteRle);
+            renderHelper(&srcPainter, inheritMask, matteRle, cache);
             srcPainter.end();
             painter->drawBitmap(VPoint(), srcBitmap, uchar(combinedAlpha() * 255.0f));
+            cache.release_surface(srcBitmap);
         } else {
-            renderHelper(painter, inheritMask, matteRle);
+            renderHelper(painter, inheritMask, matteRle, cache);
         }
     }
 }
 
 void LOTCompLayerItem::renderHelper(VPainter *painter, const VRle &inheritMask,
-                                    const VRle &matteRle)
+                                    const VRle &matteRle, SurfaceCache& cache)
 {
     VRle mask;
     if (mLayerMask) {
@@ -517,9 +517,9 @@ void LOTCompLayerItem::renderHelper(VPainter *painter, const VRle &inheritMask,
                 if (matte) {
                     if (matte->visible())
                         renderMatteLayer(painter, mask, matteRle, matte,
-                                         layer);
+                                         layer, cache);
                 } else {
-                    layer->render(painter, mask, matteRle);
+                    layer->render(painter, mask, matteRle, cache);
                 }
             }
             matte = nullptr;
@@ -529,24 +529,22 @@ void LOTCompLayerItem::renderHelper(VPainter *painter, const VRle &inheritMask,
 
 void LOTCompLayerItem::renderMatteLayer(VPainter *painter, const VRle &mask,
                                         const VRle &  matteRle,
-                                        LOTLayerItem *layer, LOTLayerItem *src)
+                                        LOTLayerItem *layer, LOTLayerItem *src, SurfaceCache& cache)
 {
     VSize size = painter->clipBoundingRect().size();
     // Decide if we can use fast matte.
     // 1. draw src layer to matte buffer
     VPainter srcPainter;
-    src->bitmap().reset(size.width(), size.height(),
-                        VBitmap::Format::ARGB32_Premultiplied);
-    srcPainter.begin(&src->bitmap());
-    src->render(&srcPainter, mask, matteRle);
+    VBitmap srcBitmap = cache.make_surface(size.width(), size.height());
+    srcPainter.begin(&srcBitmap);
+    src->render(&srcPainter, mask, matteRle, cache);
     srcPainter.end();
 
     // 2. draw layer to layer buffer
     VPainter layerPainter;
-    layer->bitmap().reset(size.width(), size.height(),
-                          VBitmap::Format::ARGB32_Premultiplied);
-    layerPainter.begin(&layer->bitmap());
-    layer->render(&layerPainter, mask, matteRle);
+    VBitmap layerBitmap = cache.make_surface(size.width(), size.height());
+    layerPainter.begin(&layerBitmap);
+    layer->render(&layerPainter, mask, matteRle, cache);
 
     // 2.1update composition mode
     switch (layer->matteType()) {
@@ -567,14 +565,17 @@ void LOTCompLayerItem::renderMatteLayer(VPainter *painter, const VRle &mask,
     // 2.2 update srcBuffer if the matte is luma type
     if (layer->matteType() == MatteType::Luma ||
         layer->matteType() == MatteType::LumaInv) {
-        src->bitmap().updateLuma();
+        srcBitmap.updateLuma();
     }
 
     // 2.3 draw src buffer as mask
-    layerPainter.drawBitmap(VPoint(), src->bitmap());
+    layerPainter.drawBitmap(VPoint(), srcBitmap);
     layerPainter.end();
     // 3. draw the result buffer into painter
-    painter->drawBitmap(VPoint(), layer->bitmap());
+    painter->drawBitmap(VPoint(), layerBitmap);
+
+    cache.release_surface(srcBitmap);
+    cache.release_surface(layerBitmap);
 }
 
 void LOTClipperItem::update(const VMatrix &matrix)
index 7bbed9c..09bc5d5 100644 (file)
@@ -61,6 +61,31 @@ public:
     }
 };
 
+class SurfaceCache
+{
+public:  
+  SurfaceCache(){mCache.reserve(10);}
+
+  VBitmap make_surface(size_t width, size_t height, VBitmap::Format format=VBitmap::Format::ARGB32_Premultiplied)
+  {
+    if (mCache.empty()) return {width, height, format};
+
+    auto surface = mCache.back();
+    surface.reset(width, height, format);
+
+    mCache.pop_back();
+    return surface;
+  }
+
+  void release_surface(VBitmap& surface)
+  {
+     mCache.push_back(surface);
+  }
+
+private:
+  std::vector<VBitmap> mCache;
+};
+
 class LOTCompItem
 {
 public:
@@ -72,6 +97,7 @@ public:
    bool render(const rlottie::Surface &surface);
    void setValue(const std::string &keypath, LOTVariant &value);
 private:
+   SurfaceCache                                mSurfaceCache;
    VBitmap                                     mSurface;
    VMatrix                                     mScaleMatrix;
    VSize                                       mViewSize;
@@ -157,7 +183,7 @@ public:
    VMatrix matrix(int frameNo) const;
    void preprocess(const VRect& clip);
    virtual DrawableList renderList(){ return {};}
-   virtual void render(VPainter *painter, const VRle &mask, const VRle &matteRle);
+   virtual void render(VPainter *painter, const VRle &mask, const VRle &matteRle, SurfaceCache& cache);
    bool hasMatte() { if (mLayerData->mMatteType == MatteType::None) return false; return true; }
    MatteType matteType() const { return mLayerData->mMatteType;}
    bool visible() const;
@@ -168,7 +194,6 @@ public:
    std::vector<LOTNode *>& cnodes() {return mCApiData->mCNodeList;}
    const char* name() const {return mLayerData->name();}
    virtual bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value);
-   VBitmap& bitmap() {return mRenderBuffer;}
 protected:
    virtual void preprocessStage(const VRect& clip) = 0;
    virtual void updateContent() = 0;
@@ -184,7 +209,6 @@ protected:
    LOTLayerData                               *mLayerData{nullptr};
    LOTLayerItem                               *mParentLayer{nullptr};
    VMatrix                                     mCombinedMatrix;
-   VBitmap                                     mRenderBuffer;
    float                                       mCombinedAlpha{0.0};
    int                                         mFrameNo{-1};
    DirtyFlag                                   mDirtyFlag{DirtyFlagBit::All};
@@ -197,16 +221,16 @@ class LOTCompLayerItem: public LOTLayerItem
 public:
    explicit LOTCompLayerItem(LOTLayerData *layerData, VArenaAlloc* allocator);
 
-   void render(VPainter *painter, const VRle &mask, const VRle &matteRle) final;
+   void render(VPainter *painter, const VRle &mask, const VRle &matteRle, SurfaceCache& cache) final;
    void buildLayerNode() final;
    bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) override;
 protected:
    void preprocessStage(const VRect& clip) final;
    void updateContent() final;
 private:
-    void renderHelper(VPainter *painter, const VRle &mask, const VRle &matteRle);
+    void renderHelper(VPainter *painter, const VRle &mask, const VRle &matteRle, SurfaceCache& cache);
     void renderMatteLayer(VPainter *painter, const VRle &inheritMask, const VRle &matteRle,
-                          LOTLayerItem *layer, LOTLayerItem *src);
+                          LOTLayerItem *layer, LOTLayerItem *src, SurfaceCache& cache);
 private:
    std::vector<LOTLayerItem*>            mLayers;
    std::unique_ptr<LOTClipperItem>       mClipper;