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
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -1143,4 +1143,47 @@ TEST(ReorderBarrierDrawable, testShadowMatrix) {
|
||||
RenderNodeDrawable drawable(parent.get(), &canvas, false);
|
||||
canvas.drawDrawable(&drawable);
|
||||
EXPECT_EQ(6, canvas.getIndex());
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user