RenderNodeDrawableTests.cpp revision 2f06e8ad1a1c4d0866bb66854d2759e275898635
1021693b967a2c5556dddd183eb0247df4079e1adStan Iliev/*
2021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * Copyright (C) 2016 The Android Open Source Project
3021693b967a2c5556dddd183eb0247df4079e1adStan Iliev *
4021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * Licensed under the Apache License, Version 2.0 (the "License");
5021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * you may not use this file except in compliance with the License.
6021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * You may obtain a copy of the License at
7021693b967a2c5556dddd183eb0247df4079e1adStan Iliev *
8021693b967a2c5556dddd183eb0247df4079e1adStan Iliev *      http://www.apache.org/licenses/LICENSE-2.0
9021693b967a2c5556dddd183eb0247df4079e1adStan Iliev *
10021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * Unless required by applicable law or agreed to in writing, software
11021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * distributed under the License is distributed on an "AS IS" BASIS,
12021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * See the License for the specific language governing permissions and
14021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * limitations under the License.
15021693b967a2c5556dddd183eb0247df4079e1adStan Iliev */
16021693b967a2c5556dddd183eb0247df4079e1adStan Iliev
17021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include <gtest/gtest.h>
18021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include <VectorDrawable.h>
19021693b967a2c5556dddd183eb0247df4079e1adStan Iliev
20021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "AnimationContext.h"
21021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "DamageAccumulator.h"
22021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "IContextFactory.h"
23021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "pipeline/skia/SkiaDisplayList.h"
24021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "pipeline/skia/SkiaRecordingCanvas.h"
25021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "renderthread/CanvasContext.h"
26021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "tests/common/TestUtils.h"
27021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "SkiaCanvas.h"
28021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include <SkLiteRecorder.h>
29021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include <string.h>
30021693b967a2c5556dddd183eb0247df4079e1adStan Iliev
31021693b967a2c5556dddd183eb0247df4079e1adStan Iliev
32021693b967a2c5556dddd183eb0247df4079e1adStan Ilievusing namespace android;
33021693b967a2c5556dddd183eb0247df4079e1adStan Ilievusing namespace android::uirenderer;
34021693b967a2c5556dddd183eb0247df4079e1adStan Ilievusing namespace android::uirenderer::renderthread;
35021693b967a2c5556dddd183eb0247df4079e1adStan Ilievusing namespace android::uirenderer::skiapipeline;
36021693b967a2c5556dddd183eb0247df4079e1adStan Iliev
37021693b967a2c5556dddd183eb0247df4079e1adStan IlievTEST(RenderNodeDrawable, create) {
38021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    auto rootNode = TestUtils::createNode(0, 0, 200, 400,
39021693b967a2c5556dddd183eb0247df4079e1adStan Iliev            [](RenderProperties& props, Canvas& canvas) {
40021693b967a2c5556dddd183eb0247df4079e1adStan Iliev                canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
41021693b967a2c5556dddd183eb0247df4079e1adStan Iliev            });
42021693b967a2c5556dddd183eb0247df4079e1adStan Iliev
43021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    auto skLiteDL = SkLiteDL::New(SkRect::MakeWH(1, 1));
44021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    SkLiteRecorder canvas;
45021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    canvas.reset(skLiteDL.get());
46021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    canvas.translate(100, 100);
47021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    RenderNodeDrawable drawable(rootNode.get(), &canvas);
48021693b967a2c5556dddd183eb0247df4079e1adStan Iliev
49021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    ASSERT_EQ(drawable.getRenderNode(), rootNode.get());
50021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    ASSERT_EQ(&drawable.getNodeProperties(), &rootNode->properties());
51021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    ASSERT_EQ(drawable.getRecordedMatrix(), canvas.getTotalMatrix());
52021693b967a2c5556dddd183eb0247df4079e1adStan Iliev}
53021693b967a2c5556dddd183eb0247df4079e1adStan Iliev
542f06e8ad1a1c4d0866bb66854d2759e275898635Stan Ilievstatic void drawOrderedRect(Canvas* canvas, uint8_t expectedDrawOrder) {
552f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev    SkPaint paint;
562f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev    // order put in blue channel, transparent so overlapped content doesn't get rejected
572f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev    paint.setColor(SkColorSetARGB(1, 0, 0, expectedDrawOrder));
582f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev    canvas->drawRect(0, 0, 100, 100, paint);
59021693b967a2c5556dddd183eb0247df4079e1adStan Iliev}
60021693b967a2c5556dddd183eb0247df4079e1adStan Iliev
612f06e8ad1a1c4d0866bb66854d2759e275898635Stan Ilievstatic void drawOrderedNode(Canvas* canvas, uint8_t expectedDrawOrder, float z) {
622f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev    auto node = TestUtils::createSkiaNode(0, 0, 100, 100,
632f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev            [expectedDrawOrder, z](RenderProperties& props, SkiaRecordingCanvas& canvas) {
642f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev        drawOrderedRect(&canvas, expectedDrawOrder);
652f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev        props.setTranslationZ(z);
662f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev    });
672f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev    canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership
682f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev}
69021693b967a2c5556dddd183eb0247df4079e1adStan Iliev
702f06e8ad1a1c4d0866bb66854d2759e275898635Stan IlievTEST(RenderNodeDrawable, zReorder) {
712f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev    class ZReorderCanvas : public SkCanvas {
722f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev    public:
732f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev        ZReorderCanvas(int width, int height) : SkCanvas(width, height) {}
742f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev        void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
752f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev            int expectedOrder = SkColorGetB(paint.getColor()); // extract order from blue channel
762f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev            EXPECT_EQ(expectedOrder, mIndex++) << "An op was drawn out of order";
772f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev        }
782f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev        int getIndex() { return mIndex; }
792f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev    protected:
802f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev        int mIndex = 0;
812f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev    };
822f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev
832f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev    auto parent = TestUtils::createSkiaNode(0, 0, 100, 100,
842f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev            [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
852f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev        drawOrderedNode(&canvas, 0, 10.0f); // in reorder=false at this point, so played inorder
862f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev        drawOrderedRect(&canvas, 1);
872f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev        canvas.insertReorderBarrier(true);
882f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev        drawOrderedNode(&canvas, 6, 2.0f);
892f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev        drawOrderedRect(&canvas, 3);
902f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev        drawOrderedNode(&canvas, 4, 0.0f);
912f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev        drawOrderedRect(&canvas, 5);
922f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev        drawOrderedNode(&canvas, 2, -2.0f);
932f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev        drawOrderedNode(&canvas, 7, 2.0f);
942f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev        canvas.insertReorderBarrier(false);
952f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev        drawOrderedRect(&canvas, 8);
962f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev        drawOrderedNode(&canvas, 9, -10.0f); // in reorder=false at this point, so played inorder
972f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev    });
982f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev
992f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev    //create a canvas not backed by any device/pixels, but with dimensions to avoid quick rejection
1002f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev    ZReorderCanvas canvas(100, 100);
1012f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev    RenderNodeDrawable drawable(parent.get(), &canvas, false);
1022f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev    canvas.drawDrawable(&drawable);
1032f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev    EXPECT_EQ(10, canvas.getIndex());
104021693b967a2c5556dddd183eb0247df4079e1adStan Iliev}
105021693b967a2c5556dddd183eb0247df4079e1adStan Iliev
106021693b967a2c5556dddd183eb0247df4079e1adStan IlievTEST(RenderNodeDrawable, composeOnLayer)
107021693b967a2c5556dddd183eb0247df4079e1adStan Iliev{
108021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    auto surface = SkSurface::MakeRasterN32Premul(1, 1);
109021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    SkCanvas& canvas = *surface->getCanvas();
110021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    canvas.drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
111021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
112021693b967a2c5556dddd183eb0247df4079e1adStan Iliev
113500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    auto rootNode = TestUtils::createSkiaNode(0, 0, 1, 1,
114021693b967a2c5556dddd183eb0247df4079e1adStan Iliev        [](RenderProperties& props, SkiaRecordingCanvas& recorder) {
115021693b967a2c5556dddd183eb0247df4079e1adStan Iliev            recorder.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
116021693b967a2c5556dddd183eb0247df4079e1adStan Iliev        });
117021693b967a2c5556dddd183eb0247df4079e1adStan Iliev
118021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    //attach a layer to the render node
119021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    auto surfaceLayer = SkSurface::MakeRasterN32Premul(1, 1);
120021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    auto canvas2 = surfaceLayer->getCanvas();
121021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    canvas2->drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
122500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    rootNode->setLayerSurface(surfaceLayer);
123021693b967a2c5556dddd183eb0247df4079e1adStan Iliev
124021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    RenderNodeDrawable drawable1(rootNode.get(), &canvas, false);
125021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    canvas.drawDrawable(&drawable1);
126021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    ASSERT_EQ(SK_ColorRED, TestUtils::getColor(surface, 0, 0));
127021693b967a2c5556dddd183eb0247df4079e1adStan Iliev
128021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    RenderNodeDrawable drawable2(rootNode.get(), &canvas, true);
129021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    canvas.drawDrawable(&drawable2);
130021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    ASSERT_EQ(SK_ColorWHITE, TestUtils::getColor(surface, 0, 0));
131021693b967a2c5556dddd183eb0247df4079e1adStan Iliev
132021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    RenderNodeDrawable drawable3(rootNode.get(), &canvas, false);
133021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    canvas.drawDrawable(&drawable3);
134021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    ASSERT_EQ(SK_ColorRED, TestUtils::getColor(surface, 0, 0));
135021693b967a2c5556dddd183eb0247df4079e1adStan Iliev
136500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    rootNode->setLayerSurface(sk_sp<SkSurface>());
137021693b967a2c5556dddd183eb0247df4079e1adStan Iliev}
138021693b967a2c5556dddd183eb0247df4079e1adStan Iliev
139021693b967a2c5556dddd183eb0247df4079e1adStan Iliev//TODO: refactor to cover test cases from FrameBuilderTests_projectionReorder
140021693b967a2c5556dddd183eb0247df4079e1adStan Iliev//validate with bounds and projection path mask.
141021693b967a2c5556dddd183eb0247df4079e1adStan Iliev//TODO: research if we could hook in and mock/validate different aspects of the drawing,
142021693b967a2c5556dddd183eb0247df4079e1adStan Iliev//instead of validating pixels
143021693b967a2c5556dddd183eb0247df4079e1adStan IlievTEST(RenderNodeDrawable, projectDraw) {
144021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    auto surface = SkSurface::MakeRasterN32Premul(1, 1);
145021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    SkCanvas& canvas = *surface->getCanvas();
146021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    canvas.drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
147021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
148021693b967a2c5556dddd183eb0247df4079e1adStan Iliev
149500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    auto redNode = TestUtils::createSkiaNode(0, 0, 1, 1,
150021693b967a2c5556dddd183eb0247df4079e1adStan Iliev        [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
151021693b967a2c5556dddd183eb0247df4079e1adStan Iliev            redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
152021693b967a2c5556dddd183eb0247df4079e1adStan Iliev        }, "redNode");
153021693b967a2c5556dddd183eb0247df4079e1adStan Iliev
154500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    auto greenNodeWithRedChild = TestUtils::createSkiaNode(0, 0, 1, 1,
155021693b967a2c5556dddd183eb0247df4079e1adStan Iliev        [&](RenderProperties& props, SkiaRecordingCanvas& greenCanvasWithRedChild) {
156021693b967a2c5556dddd183eb0247df4079e1adStan Iliev            greenCanvasWithRedChild.drawRenderNode(redNode.get());
157021693b967a2c5556dddd183eb0247df4079e1adStan Iliev            greenCanvasWithRedChild.drawColor(SK_ColorGREEN, SkBlendMode::kSrcOver);
158021693b967a2c5556dddd183eb0247df4079e1adStan Iliev        }, "greenNodeWithRedChild");
159021693b967a2c5556dddd183eb0247df4079e1adStan Iliev
160500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    auto rootNode = TestUtils::createSkiaNode(0, 0, 1, 1,
161021693b967a2c5556dddd183eb0247df4079e1adStan Iliev        [&](RenderProperties& props, SkiaRecordingCanvas& rootCanvas) {
162021693b967a2c5556dddd183eb0247df4079e1adStan Iliev            rootCanvas.drawRenderNode(greenNodeWithRedChild.get());
163021693b967a2c5556dddd183eb0247df4079e1adStan Iliev        }, "rootNode");
164021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    SkiaDisplayList* rootDisplayList = static_cast<SkiaDisplayList*>(
165021693b967a2c5556dddd183eb0247df4079e1adStan Iliev        (const_cast<DisplayList*>(rootNode->getDisplayList())));
166021693b967a2c5556dddd183eb0247df4079e1adStan Iliev
167021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    RenderNodeDrawable rootDrawable(rootNode.get(), &canvas, false);
168021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    canvas.drawDrawable(&rootDrawable);
169021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorGREEN);
170021693b967a2c5556dddd183eb0247df4079e1adStan Iliev
171021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    //project redNode on rootNode, which will change the test outcome,
172021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    //because redNode will draw after greenNodeWithRedChild
173021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    rootDisplayList->mIsProjectionReceiver = true;
174021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    redNode->animatorProperties().setProjectBackwards(true);
175021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    canvas.drawDrawable(&rootDrawable);
176021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED);
177021693b967a2c5556dddd183eb0247df4079e1adStan Iliev}
178