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/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index 22cfe29..efbb695 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -19,6 +19,7 @@
#include "hwui/Canvas.h"
#include "hwui/Bitmap.h"
+#include "renderthread/CacheManager.h"
#include "DisplayList.h"
#include <SkBitmap.h>
@@ -687,35 +688,61 @@
bool getPropertyChangeWillBeConsumed() const { return mWillBeConsumed; }
void setPropertyChangeWillBeConsumed(bool willBeConsumed) { mWillBeConsumed = willBeConsumed; }
- // Returns true if VD cache surface is big enough. This should always be called from RT and it
- // works with Skia pipelines only.
- bool canReuseSurface() {
- SkSurface* surface = mCache.surface.get();
- return surface && surface->width() >= mProperties.getScaledWidth()
- && surface->height() >= mProperties.getScaledHeight();
- }
-
- // Draws VD cache into a canvas. This should always be called from RT and it works with Skia
- // pipelines only.
+ /**
+ * Draws VD cache into a canvas. This should always be called from RT and it works with Skia
+ * pipelines only.
+ */
void draw(SkCanvas* canvas);
- // Draws VD into a GPU backed surface. If canReuseSurface returns false, then "surface" must
- // contain a new surface. This should always be called from RT and it works with Skia pipelines
- // only.
- void updateCache(sk_sp<SkSurface> surface);
+ /**
+ * Draws VD into a GPU backed surface.
+ * This should always be called from RT and it works with Skia pipeline only.
+ */
+ void updateCache(sp<skiapipeline::VectorDrawableAtlas>& atlas, GrContext* context);
private:
- struct Cache {
+ class Cache {
+ public:
sk_sp<Bitmap> bitmap; //used by HWUI pipeline and software
//TODO: use surface instead of bitmap when drawing in software canvas
- sk_sp<SkSurface> surface; //used only by Skia pipelines
bool dirty = true;
+
+ // the rest of the code in Cache is used by Skia pipelines only
+
+ ~Cache() { clear(); }
+
+ /**
+ * Stores a weak pointer to the atlas and a key.
+ */
+ void setAtlas(sp<skiapipeline::VectorDrawableAtlas> atlas,
+ skiapipeline::AtlasKey newAtlasKey);
+
+ /**
+ * Gets a surface and bounds from the atlas.
+ *
+ * @return nullptr if the altas has been deleted.
+ */
+ sk_sp<SkSurface> getSurface(SkRect* bounds);
+
+ /**
+ * Releases atlas key from the atlas, which makes it available for reuse.
+ */
+ void clear();
+ private:
+ wp<skiapipeline::VectorDrawableAtlas> mAtlas;
+ skiapipeline::AtlasKey mAtlasKey = INVALID_ATLAS_KEY;
};
SkPaint* updatePaint(SkPaint* outPaint, TreeProperties* prop);
bool allocateBitmapIfNeeded(Cache& cache, int width, int height);
bool canReuseBitmap(Bitmap*, int width, int height);
void updateBitmapCache(Bitmap& outCache, bool useStagingData);
+
+ /**
+ * Draws the root node into "surface" at a given "dst" position.
+ */
+ void draw(SkSurface* surface, const SkRect& dst);
+
// Cap the bitmap size, such that it won't hurt the performance too much
// and it won't crash due to a very large scale.
// The drawable will look blurry above this size.