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;