summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Stan Iliev <stani@google.com> 2018-02-07 14:07:30 -0500
committer Stan Iliev <stani@google.com> 2018-02-08 19:01:08 +0000
commit65e678fdb1375fe183e628ff158f66b2f04331d0 (patch)
treeeb90b484d1781974f7e5200e0d4eba87ce367b19
parentbc48bd8f6137955b99f51562ab4959783f827e22 (diff)
Cache VectorDrawable bounds at record time
Cache VectorDrawable bounds at record time, because the same drawable object may be used several times with different bounds. Bug: 71737362 Test: Wrote a new unit test, tried sample app attached to the bug Change-Id: If7be934acf0c16b328cb0f95d849e463dcd3b88b
-rw-r--r--libs/hwui/VectorDrawable.cpp8
-rw-r--r--libs/hwui/VectorDrawable.h2
-rw-r--r--libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp11
-rw-r--r--libs/hwui/tests/unit/RenderNodeDrawableTests.cpp45
4 files changed, 56 insertions, 10 deletions
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index f118e8d0a53e..f662406bdc38 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -557,13 +557,12 @@ void Tree::Cache::clear() {
mAtlasKey = INVALID_ATLAS_KEY;
}
-void Tree::draw(SkCanvas* canvas) {
+void Tree::draw(SkCanvas* canvas, const SkRect& bounds) {
SkRect src;
sk_sp<SkSurface> vdSurface = mCache.getSurface(&src);
if (vdSurface) {
canvas->drawImageRect(vdSurface->makeImageSnapshot().get(), src,
- mutateProperties()->getBounds(), getPaint(),
- SkCanvas::kFast_SrcRectConstraint);
+ bounds, getPaint(), SkCanvas::kFast_SrcRectConstraint);
} else {
// Handle the case when VectorDrawableAtlas has been destroyed, because of memory pressure.
// We render the VD into a temporary standalone buffer and mark the frame as dirty. Next
@@ -575,8 +574,7 @@ void Tree::draw(SkCanvas* canvas) {
int scaledWidth = SkScalarCeilToInt(mProperties.getScaledWidth());
int scaledHeight = SkScalarCeilToInt(mProperties.getScaledHeight());
canvas->drawBitmapRect(skiaBitmap, SkRect::MakeWH(scaledWidth, scaledHeight),
- mutateProperties()->getBounds(), getPaint(),
- SkCanvas::kFast_SrcRectConstraint);
+ bounds, getPaint(), SkCanvas::kFast_SrcRectConstraint);
mCache.clear();
markDirty();
}
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index d9cf8ab7eedf..da52a9503377 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -644,7 +644,7 @@ public:
* Draws VD cache into a canvas. This should always be called from RT and it works with Skia
* pipelines only.
*/
- void draw(SkCanvas* canvas);
+ void draw(SkCanvas* canvas, const SkRect& bounds);
/**
* Draws VD into a GPU backed surface.
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index eabe2e87fc49..25c76eb4db3e 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -124,14 +124,19 @@ void SkiaRecordingCanvas::callDrawGLFunction(Functor* functor,
class VectorDrawable : public SkDrawable {
public:
- VectorDrawable(VectorDrawableRoot* tree) : mRoot(tree) {}
+ VectorDrawable(VectorDrawableRoot* tree)
+ : mRoot(tree)
+ , mBounds(tree->stagingProperties()->getBounds()) {}
protected:
- virtual SkRect onGetBounds() override { return SkRect::MakeLargest(); }
- virtual void onDraw(SkCanvas* canvas) override { mRoot->draw(canvas); }
+ virtual SkRect onGetBounds() override { return mBounds; }
+ virtual void onDraw(SkCanvas* canvas) override {
+ mRoot->draw(canvas, mBounds);
+ }
private:
sp<VectorDrawableRoot> mRoot;
+ SkRect mBounds;
};
void SkiaRecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
index 2953ea8b21e9..182e3647d5a4 100644
--- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
@@ -1143,4 +1143,47 @@ TEST(ReorderBarrierDrawable, testShadowMatrix) {
RenderNodeDrawable drawable(parent.get(), &canvas, false);
canvas.drawDrawable(&drawable);
EXPECT_EQ(6, canvas.getIndex());
-} \ No newline at end of file
+}
+
+// Draw a vector drawable twice but with different bounds and verify correct bounds are used.
+RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaRecordingCanvas, drawVectorDrawable) {
+ static const int CANVAS_WIDTH = 100;
+ static const int CANVAS_HEIGHT = 200;
+ class VectorDrawableTestCanvas : public TestCanvasBase {
+ public:
+ VectorDrawableTestCanvas() : TestCanvasBase(CANVAS_WIDTH, CANVAS_HEIGHT) {}
+ void onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
+ const SkPaint* paint, SrcRectConstraint constraint) override {
+ const int index = mDrawCounter++;
+ switch (index) {
+ case 0:
+ EXPECT_EQ(dst, SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT));
+ break;
+ case 1:
+ EXPECT_EQ(dst, SkRect::MakeWH(CANVAS_WIDTH/2, CANVAS_HEIGHT));
+ break;
+ default:
+ ADD_FAILURE();
+ }
+ }
+ };
+
+ VectorDrawable::Group* group = new VectorDrawable::Group();
+ sp<VectorDrawableRoot> vectorDrawable(new VectorDrawableRoot(group));
+ vectorDrawable->mutateStagingProperties()->setScaledSize(CANVAS_WIDTH/10, CANVAS_HEIGHT/10);
+
+ auto node = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
+ [&](RenderProperties& props, SkiaRecordingCanvas& canvas) {
+ vectorDrawable->mutateStagingProperties()->setBounds(SkRect::MakeWH(CANVAS_WIDTH,
+ CANVAS_HEIGHT));
+ canvas.drawVectorDrawable(vectorDrawable.get());
+ vectorDrawable->mutateStagingProperties()->setBounds(SkRect::MakeWH(CANVAS_WIDTH/2,
+ CANVAS_HEIGHT));
+ canvas.drawVectorDrawable(vectorDrawable.get());
+ });
+
+ VectorDrawableTestCanvas canvas;
+ RenderNodeDrawable drawable(node.get(), &canvas, true);
+ canvas.drawDrawable(&drawable);
+ EXPECT_EQ(2, canvas.mDrawCounter);
+}