Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 68885e38 authored by Stan Iliev's avatar Stan Iliev
Browse files

Modify savelayer to save matrix and clip for Skia pipeline

Modify SkiaCanvas::saveLayer to always save matrix and clip and
match HWUI behaviour. Also ensure android state tracking
behavior matches that of the Skia API (partial saves not
supported). This change is fixing SaveLayerAnimation
macrobench when buffer age is disabled.
Add a HWUI unit test that verifies clip and matrix are restored.

Test: built and ran angler-eng, ran hwui unit tests
bug:33429678
Change-Id: I62e429f9746518fef67663b0dd99ac499bf31af3
parent ed4d58cc
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -199,11 +199,11 @@ static inline SkCanvas::SaveLayerFlags layerFlags(SaveFlags::Flags flags) {
int SkiaCanvas::saveLayer(float left, float top, float right, float bottom,
            const SkPaint* paint, SaveFlags::Flags flags) {
    const SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom);
    const SkCanvas::SaveLayerRec rec(&bounds, paint, layerFlags(flags));
    //always save matrix and clip to match the behaviour of Skia and HWUI pipelines and to ensure
    //android state tracking behavior matches that of the Skia API (partial save is not supported)
    const SkCanvas::SaveLayerRec rec(&bounds, paint, layerFlags(flags | SaveFlags::MatrixClip));

    int count = mCanvas->saveLayer(rec);
    recordPartialSave(flags);
    return count;
    return mCanvas->saveLayer(rec);
}

int SkiaCanvas::saveLayerAlpha(float left, float top, float right, float bottom,
+53 −0
Original line number Diff line number Diff line
@@ -167,6 +167,59 @@ TEST(RenderNodeDrawable, composeOnLayer)
    rootNode->setLayerSurface(sk_sp<SkSurface>());
}

namespace {
static SkRect getRecorderClipBounds(const SkiaRecordingCanvas& recorder) {
    SkRect clipBounds;
    recorder.getClipBounds(&clipBounds);
    return clipBounds;
}

static SkMatrix getRecorderMatrix(const SkiaRecordingCanvas& recorder) {
    SkMatrix matrix;
    recorder.getMatrix(&matrix);
    return matrix;
}
}

TEST(RenderNodeDrawable, saveLayerClipAndMatrixRestore)
{
    auto surface = SkSurface::MakeRasterN32Premul(400, 800);
    SkCanvas& canvas = *surface->getCanvas();
    canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorWHITE);

    auto rootNode = TestUtils::createSkiaNode(0, 0, 400, 800,
        [](RenderProperties& props, SkiaRecordingCanvas& recorder) {
            SkPaint layerPaint;
            ASSERT_EQ(SkRect::MakeLTRB(0, 0, 400, 800), getRecorderClipBounds(recorder));
            EXPECT_TRUE(getRecorderMatrix(recorder).isIdentity());

            //note we don't pass SaveFlags::MatrixClip, but matrix and clip will be saved
            recorder.saveLayer(0, 0, 400, 400, &layerPaint, SaveFlags::ClipToLayer);
            ASSERT_EQ(SkRect::MakeLTRB(0, 0, 400, 400), getRecorderClipBounds(recorder));
            EXPECT_TRUE(getRecorderMatrix(recorder).isIdentity());

            recorder.clipRect(50, 50, 350, 350, SkClipOp::kIntersect);
            ASSERT_EQ(SkRect::MakeLTRB(50, 50, 350, 350), getRecorderClipBounds(recorder));

            recorder.translate(300.0f, 400.0f);
            EXPECT_EQ(SkMatrix::MakeTrans(300.0f, 400.0f), getRecorderMatrix(recorder));

            recorder.restore();
            ASSERT_EQ(SkRect::MakeLTRB(0, 0, 400, 800), getRecorderClipBounds(recorder));
            EXPECT_TRUE(getRecorderMatrix(recorder).isIdentity());

            SkPaint paint;
            paint.setAntiAlias(true);
            paint.setColor(SK_ColorGREEN);
            recorder.drawRect(0.0f, 400.0f, 400.0f, 800.0f, paint);
        });

    RenderNodeDrawable drawable(rootNode.get(), &canvas, true);
    canvas.drawDrawable(&drawable);
    ASSERT_EQ(SK_ColorGREEN, TestUtils::getColor(surface, 200, 600));
}

namespace {
class ContextFactory : public IContextFactory {
public: