diff options
author | 2018-02-07 14:07:30 -0500 | |
---|---|---|
committer | 2018-02-08 19:01:08 +0000 | |
commit | 65e678fdb1375fe183e628ff158f66b2f04331d0 (patch) | |
tree | eb90b484d1781974f7e5200e0d4eba87ce367b19 | |
parent | bc48bd8f6137955b99f51562ab4959783f827e22 (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.cpp | 8 | ||||
-rw-r--r-- | libs/hwui/VectorDrawable.h | 2 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp | 11 | ||||
-rw-r--r-- | libs/hwui/tests/unit/RenderNodeDrawableTests.cpp | 45 |
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); +} |