Cache VectorDrawables in an atlas

Optimize VectorDrawables for Skia pipeline: draw small VectorDrawables
in a GPU atlas instead of seprate offscreen buffers.
This implementation is using CacheManger and allows for the atlas to
be released if there is a memory pressure.

Test: A new unit test for VectorDrawableAtlas is passing. Systrace shows
0.5ms faster DrawFrame for fling in Settings app main screen.
Change-Id: Ide3884eefae777e1547f1dfdb67b807185839fb4
diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp
index f0d6b38..55694d0 100644
--- a/libs/hwui/renderthread/CacheManager.cpp
+++ b/libs/hwui/renderthread/CacheManager.cpp
@@ -43,7 +43,8 @@
 
 CacheManager::CacheManager(const DisplayInfo& display)
         : mMaxSurfaceArea(display.w * display.h) {
-    mVectorDrawableAtlas.reset(new VectorDrawableAtlas);
+    mVectorDrawableAtlas = new skiapipeline::VectorDrawableAtlas(mMaxSurfaceArea/2,
+            skiapipeline::VectorDrawableAtlas::StorageMode::allowSharedSurface);
 }
 
 void CacheManager::reset(GrContext* context) {
@@ -61,7 +62,7 @@
 void CacheManager::destroy() {
     // cleanup any caches here as the GrContext is about to go away...
     mGrContext.reset(nullptr);
-    mVectorDrawableAtlas.reset(new VectorDrawableAtlas);
+    mVectorDrawableAtlas = new skiapipeline::VectorDrawableAtlas(mMaxSurfaceArea/2);
 }
 
 void CacheManager::updateContextCacheSizes() {
@@ -104,7 +105,7 @@
 
     switch (mode) {
         case TrimMemoryMode::Complete:
-            mVectorDrawableAtlas.reset(new VectorDrawableAtlas);
+            mVectorDrawableAtlas = new skiapipeline::VectorDrawableAtlas(mMaxSurfaceArea/2);
             mGrContext->freeGpuResources();
             break;
         case TrimMemoryMode::UiHidden:
@@ -121,24 +122,14 @@
     mGrContext->purgeResourcesNotUsedInMs(std::chrono::seconds(30));
 }
 
-VectorDrawableAtlas* CacheManager::acquireVectorDrawableAtlas() {
+sp<skiapipeline::VectorDrawableAtlas> CacheManager::acquireVectorDrawableAtlas() {
     LOG_ALWAYS_FATAL_IF(mVectorDrawableAtlas.get() == nullptr);
     LOG_ALWAYS_FATAL_IF(mGrContext == nullptr);
 
     /**
-     * TODO LIST:
-     *    1) compute the atlas based on the surfaceArea surface
-     *    2) identify a way to reuse cache entries
-     *    3) add ability to repack the cache?
-     *    4) define memory conditions where we clear the cache (e.g. surface->reset())
+     * TODO: define memory conditions where we clear the cache (e.g. surface->reset())
      */
-
-    return mVectorDrawableAtlas.release();
-}
-void CacheManager::releaseVectorDrawableAtlas(VectorDrawableAtlas* atlas) {
-    LOG_ALWAYS_FATAL_IF(mVectorDrawableAtlas.get() != nullptr);
-    mVectorDrawableAtlas.reset(atlas);
-    mVectorDrawableAtlas->isNewAtlas = false;
+    return mVectorDrawableAtlas;
 }
 
 void CacheManager::dumpMemoryUsage(String8& log, const RenderState* renderState) {
diff --git a/libs/hwui/renderthread/CacheManager.h b/libs/hwui/renderthread/CacheManager.h
index 43d58f2..90362f3 100644
--- a/libs/hwui/renderthread/CacheManager.h
+++ b/libs/hwui/renderthread/CacheManager.h
@@ -22,6 +22,7 @@
 #include <ui/DisplayInfo.h>
 #include <utils/String8.h>
 #include <vector>
+#include "pipeline/skia/VectorDrawableAtlas.h"
 
 namespace android {
 
@@ -36,11 +37,6 @@
 class IRenderPipeline;
 class RenderThread;
 
-struct VectorDrawableAtlas {
-    sk_sp<SkSurface> surface;
-    bool isNewAtlas = true;
-};
-
 class CacheManager {
 public:
     enum class TrimMemoryMode {
@@ -53,8 +49,7 @@
     void trimStaleResources();
     void dumpMemoryUsage(String8& log, const RenderState* renderState = nullptr);
 
-    VectorDrawableAtlas* acquireVectorDrawableAtlas();
-    void releaseVectorDrawableAtlas(VectorDrawableAtlas*);
+    sp<skiapipeline::VectorDrawableAtlas> acquireVectorDrawableAtlas();
 
     size_t getCacheSize() const { return mMaxResourceBytes; }
     size_t getBackgroundCacheSize() const { return mBackgroundResourceBytes; }
@@ -81,7 +76,7 @@
         size_t surfaceArea = 0;
     };
 
-    std::unique_ptr<VectorDrawableAtlas> mVectorDrawableAtlas;
+    sp<skiapipeline::VectorDrawableAtlas> mVectorDrawableAtlas;
 };
 
 } /* namespace renderthread */
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 370cf52..7fe966d 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -21,6 +21,7 @@
 #include "Properties.h"
 #include "Readback.h"
 #include "Rect.h"
+#include "pipeline/skia/VectorDrawableAtlas.h"
 #include "renderthread/CanvasContext.h"
 #include "renderthread/EglManager.h"
 #include "renderthread/RenderTask.h"
@@ -718,6 +719,19 @@
     mRenderThread.queue(task);
 }
 
+CREATE_BRIDGE1(repackVectorDrawableAtlas, RenderThread* thread) {
+    args->thread->cacheManager().acquireVectorDrawableAtlas()->repackIfNeeded(
+            args->thread->getGrContext());
+    return nullptr;
+}
+
+void RenderProxy::repackVectorDrawableAtlas() {
+    RenderThread& thread = RenderThread::getInstance();
+    SETUP_TASK(repackVectorDrawableAtlas);
+    args->thread = &thread;
+    thread.queue(task);
+}
+
 void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) {
     void* retval;
     task->setReturnPtr(&retval);
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 31f0ce6..06eaebd 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -140,6 +140,9 @@
     static void onBitmapDestroyed(uint32_t pixelRefId);
 
     ANDROID_API static void disableVsync();
+
+    static void repackVectorDrawableAtlas();
+
 private:
     RenderThread& mRenderThread;
     CanvasContext* mContext;