Fix pop-up shadow drawn in the wrong place with Skia pipeline

Fix a bug in DrawShadow matrix calculation. Recorded matrix does
not need to be applied, because parent display lists have already
replayed matrix transformations.

Test: added a new HWUI unit test that is passing only after this fix
Bug: 33103723
Change-Id: I7a47dbe879df6b9e5920a47c0e1168d9902a3e70
This commit is contained in:
Stan Iliev
2017-04-04 15:23:54 -04:00
parent 5879d28f4d
commit d7410f7829
2 changed files with 65 additions and 1 deletions

View File

@@ -162,7 +162,7 @@ void EndReorderBarrierDrawable::drawShadow(SkCanvas* canvas, RenderNodeDrawable*
SkAutoCanvasRestore acr(canvas, true);
SkMatrix shadowMatrix;
mat4 hwuiMatrix(caster->getRecordedMatrix());
mat4 hwuiMatrix;
// TODO we don't pass the optional boolean to treat it as a 4x4 matrix
caster->getRenderNode()->applyViewPropertyTransforms(hwuiMatrix);
hwuiMatrix.copyTo(shadowMatrix);

View File

@@ -941,3 +941,67 @@ TEST(RenderNodeDrawable, renderNode) {
EXPECT_EQ(2, canvas.mDrawCounter);
}
TEST(ReorderBarrierDrawable, testShadowMatrix) {
static const int CANVAS_WIDTH = 100;
static const int CANVAS_HEIGHT = 100;
static const float TRANSLATE_X = 11.0f;
static const float TRANSLATE_Y = 22.0f;
static const float CASTER_X = 40.0f;
static const float CASTER_Y = 40.0f;
static const float CASTER_WIDTH = 20.0f;
static const float CASTER_HEIGHT = 20.0f;
class ShadowTestCanvas : public SkCanvas {
public:
ShadowTestCanvas(int width, int height) : SkCanvas(width, height) {}
int getIndex() { return mDrawCounter; }
virtual void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override {
// expect to draw 2 RenderNodeDrawable, 1 StartReorderBarrierDrawable,
// 1 EndReorderBarrierDrawable
mDrawCounter++;
SkCanvas::onDrawDrawable(drawable, matrix);
}
virtual void didTranslate(SkScalar dx, SkScalar dy) override {
mDrawCounter++;
EXPECT_EQ(dx, TRANSLATE_X);
EXPECT_EQ(dy, TRANSLATE_Y);
}
virtual void didConcat(const SkMatrix& matrix) override {
// This function is invoked by EndReorderBarrierDrawable::drawShadow to apply shadow
// matrix.
mDrawCounter++;
EXPECT_EQ(SkMatrix::MakeTrans(CASTER_X, CASTER_Y), matrix);
EXPECT_EQ(SkMatrix::MakeTrans(CASTER_X+TRANSLATE_X, CASTER_Y+TRANSLATE_Y),
getTotalMatrix());
}
protected:
int mDrawCounter = 0;
};
auto parent = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
[](RenderProperties& props, SkiaRecordingCanvas& canvas) {
canvas.translate(TRANSLATE_X, TRANSLATE_Y);
canvas.insertReorderBarrier(true);
auto node = TestUtils::createSkiaNode(CASTER_X, CASTER_Y, CASTER_X + CASTER_WIDTH,
CASTER_Y + CASTER_HEIGHT,
[](RenderProperties& props, SkiaRecordingCanvas& canvas) {
props.setElevation(42);
props.mutableOutline().setRoundRect(0, 0, 20, 20, 5, 1);
props.mutableOutline().setShouldClip(true);
});
canvas.drawRenderNode(node.get());
canvas.insertReorderBarrier(false);
});
//create a canvas not backed by any device/pixels, but with dimensions to avoid quick rejection
ShadowTestCanvas canvas(CANVAS_WIDTH, CANVAS_HEIGHT);
RenderNodeDrawable drawable(parent.get(), &canvas, false);
canvas.drawDrawable(&drawable);
EXPECT_EQ(6, canvas.getIndex());
}