SkiaPipelineTests.cpp revision 624ad836ec7f174369df30219099260b951b7ef4
1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <gtest/gtest.h>
18#include <VectorDrawable.h>
19
20#include "AnimationContext.h"
21#include "DamageAccumulator.h"
22#include "IContextFactory.h"
23#include "pipeline/skia/SkiaDisplayList.h"
24#include "pipeline/skia/SkiaRecordingCanvas.h"
25#include "pipeline/skia/SkiaOpenGLPipeline.h"
26#include "renderthread/CanvasContext.h"
27#include "tests/common/TestUtils.h"
28#include "SkiaCanvas.h"
29#include <SkClipStack.h>
30#include <SkLiteRecorder.h>
31#include <SkSurface_Base.h>
32#include <string.h>
33
34using namespace android;
35using namespace android::uirenderer;
36using namespace android::uirenderer::renderthread;
37using namespace android::uirenderer::skiapipeline;
38
39RENDERTHREAD_TEST(SkiaPipeline, renderFrame) {
40    auto redNode = TestUtils::createSkiaNode(0, 0, 1, 1,
41        [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
42            redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
43        });
44    LayerUpdateQueue layerUpdateQueue;
45    SkRect dirty = SkRect::MakeLargest();
46    std::vector<sp<RenderNode>> renderNodes;
47    renderNodes.push_back(redNode);
48    bool opaque = true;
49    android::uirenderer::Rect contentDrawBounds(0, 0, 1, 1);
50    auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
51    auto surface = SkSurface::MakeRasterN32Premul(1, 1);
52    surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
53    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
54    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
55    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED);
56}
57
58RENDERTHREAD_TEST(SkiaPipeline, renderFrameCheckOpaque) {
59    auto halfGreenNode = TestUtils::createSkiaNode(0, 0, 2, 2,
60        [](RenderProperties& props, SkiaRecordingCanvas& bottomHalfGreenCanvas) {
61            SkPaint greenPaint;
62            greenPaint.setColor(SK_ColorGREEN);
63            greenPaint.setStyle(SkPaint::kFill_Style);
64            bottomHalfGreenCanvas.drawRect(0, 1, 2, 2, greenPaint);
65        });
66    LayerUpdateQueue layerUpdateQueue;
67    SkRect dirty = SkRect::MakeLargest();
68    std::vector<sp<RenderNode>> renderNodes;
69    renderNodes.push_back(halfGreenNode);
70    android::uirenderer::Rect contentDrawBounds(0, 0, 2, 2);
71    auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
72    auto surface = SkSurface::MakeRasterN32Premul(2, 2);
73    surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
74    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
75    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, contentDrawBounds, surface);
76    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
77    ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorGREEN);
78    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, false, contentDrawBounds, surface);
79    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned int)SK_ColorTRANSPARENT);
80    ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorGREEN);
81}
82
83RENDERTHREAD_TEST(SkiaPipeline, renderFrameCheckDirtyRect) {
84    auto redNode = TestUtils::createSkiaNode(0, 0, 2, 2,
85        [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
86            redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
87        });
88    LayerUpdateQueue layerUpdateQueue;
89    SkRect dirty = SkRect::MakeXYWH(0, 1, 2, 1);
90    std::vector<sp<RenderNode>> renderNodes;
91    renderNodes.push_back(redNode);
92    android::uirenderer::Rect contentDrawBounds(0, 0, 2, 2);
93    auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
94    auto surface = SkSurface::MakeRasterN32Premul(2, 2);
95    surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
96    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
97    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, contentDrawBounds, surface);
98    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
99    ASSERT_EQ(TestUtils::getColor(surface, 1, 0), SK_ColorBLUE);
100    ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorRED);
101    ASSERT_EQ(TestUtils::getColor(surface, 1, 1), SK_ColorRED);
102}
103
104RENDERTHREAD_TEST(SkiaPipeline, renderLayer) {
105    auto redNode = TestUtils::createSkiaNode(0, 0, 1, 1,
106        [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
107            redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
108        });
109    auto surfaceLayer1 = SkSurface::MakeRasterN32Premul(1, 1);
110    surfaceLayer1->getCanvas()->drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
111    ASSERT_EQ(TestUtils::getColor(surfaceLayer1, 0, 0), SK_ColorWHITE);
112    redNode->setLayerSurface(surfaceLayer1);
113
114    //create a 2nd 2x2 layer and add it to the queue as well.
115    //make the layer's dirty area one half of the layer and verify only the dirty half is updated.
116    auto blueNode = TestUtils::createSkiaNode(0, 0, 2, 2,
117        [](RenderProperties& props, SkiaRecordingCanvas& blueCanvas) {
118            blueCanvas.drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
119        });
120    auto surfaceLayer2 = SkSurface::MakeRasterN32Premul(2, 2);
121    surfaceLayer2->getCanvas()->drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
122    ASSERT_EQ(TestUtils::getColor(surfaceLayer2, 0, 0), SK_ColorWHITE);
123    blueNode->setLayerSurface(surfaceLayer2);
124
125    //attach both layers to the update queue
126    LayerUpdateQueue layerUpdateQueue;
127    SkRect dirty = SkRect::MakeLargest();
128    layerUpdateQueue.enqueueLayerWithDamage(redNode.get(), dirty);
129    layerUpdateQueue.enqueueLayerWithDamage(blueNode.get(), SkRect::MakeWH(2, 1));
130    ASSERT_EQ(layerUpdateQueue.entries().size(), 2UL);
131
132    bool opaque = true;
133    FrameBuilder::LightGeometry lightGeometry;
134    lightGeometry.radius = 1.0f;
135    lightGeometry.center = { 0.0f, 0.0f, 0.0f };
136    BakedOpRenderer::LightInfo lightInfo;
137    auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
138    pipeline->renderLayers(lightGeometry, &layerUpdateQueue, opaque, lightInfo);
139    ASSERT_EQ(TestUtils::getColor(surfaceLayer1, 0, 0), SK_ColorRED);
140    ASSERT_EQ(TestUtils::getColor(surfaceLayer2, 0, 0), SK_ColorBLUE);
141    ASSERT_EQ(TestUtils::getColor(surfaceLayer2, 0, 1), SK_ColorWHITE);
142    ASSERT_TRUE(layerUpdateQueue.entries().empty());
143    redNode->setLayerSurface(sk_sp<SkSurface>());
144    blueNode->setLayerSurface(sk_sp<SkSurface>());
145}
146
147RENDERTHREAD_TEST(SkiaPipeline, renderOverdraw) {
148    ScopedProperty<bool> prop(Properties::debugOverdraw, true);
149
150    auto whiteNode = TestUtils::createSkiaNode(0, 0, 1, 1,
151        [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
152            canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
153        });
154    LayerUpdateQueue layerUpdateQueue;
155    SkRect dirty = SkRect::MakeXYWH(0, 0, 1, 1);
156    std::vector<sp<RenderNode>> renderNodes;
157    renderNodes.push_back(whiteNode);
158    bool opaque = true;
159    //empty contentDrawBounds is avoiding backdrop/content logic, which would lead to less overdraw
160    android::uirenderer::Rect contentDrawBounds(0, 0, 0, 0);
161    auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
162    auto surface = SkSurface::MakeRasterN32Premul(1, 1);
163
164    // Initialize the canvas to blue.
165    surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
166    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
167
168    // Single draw, should be white.
169    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
170    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorWHITE);
171
172    // 1 Overdraw, should be blue blended onto white.
173    renderNodes.push_back(whiteNode); //this is the "content" node
174    renderNodes.push_back(whiteNode); //the "content" node above does not cause an overdraw, because
175    //it clips the first "background" node
176    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
177    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned) 0xffd0d0ff);
178
179    // 2 Overdraw, should be green blended onto white
180    renderNodes.push_back(whiteNode);
181    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
182    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned) 0xffd0ffd0);
183
184    // 3 Overdraw, should be pink blended onto white.
185    renderNodes.push_back(whiteNode);
186    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
187    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned) 0xffffc0c0);
188
189    // 4 Overdraw, should be red blended onto white.
190    renderNodes.push_back(whiteNode);
191    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
192    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned) 0xffff8080);
193
194    // 5 Overdraw, should be red blended onto white.
195    renderNodes.push_back(whiteNode);
196    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
197    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned) 0xffff8080);
198}
199
200namespace {
201template <typename T>
202class DeferLayer : public SkSurface_Base {
203public:
204    DeferLayer() : SkSurface_Base(T().imageInfo(), nullptr) {}
205    virtual ~DeferLayer() {}
206
207    SkCanvas* onNewCanvas() override {
208        return new T();
209    }
210    sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override {
211        return sk_sp<SkSurface>();
212    }
213    sk_sp<SkImage> onNewImageSnapshot(SkBudgeted) override {
214        return sk_sp<SkImage>();
215    }
216    T* canvas() { return static_cast<T*>(getCanvas()); }
217    void onCopyOnWrite(ContentChangeMode) override {}
218};
219}
220
221RENDERTHREAD_TEST(SkiaPipeline, deferRenderNodeScene) {
222    class DeferTestCanvas : public SkCanvas {
223    public:
224        DeferTestCanvas() : SkCanvas(800, 600) {}
225        void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
226            SkMatrix expected;
227            switch (mDrawCounter++) {
228            case 0:
229                // background - left side
230                EXPECT_EQ(SkRect::MakeLTRB(600, 100, 700, 500), TestUtils::getClipBounds(this));
231                expected.setTranslate(100, 100);
232                break;
233            case 1:
234                // background - top side
235                EXPECT_EQ(SkRect::MakeLTRB(100, 400, 600, 500), TestUtils::getClipBounds(this));
236                expected.setTranslate(100, 100);
237                break;
238            case 2:
239                // content
240                EXPECT_EQ(SkRect::MakeLTRB(100, 100, 700, 500), TestUtils::getClipBounds(this));
241                expected.setTranslate(-50, -50);
242                break;
243            case 3:
244                // overlay
245                EXPECT_EQ(SkRect::MakeLTRB(0, 0, 800, 600), TestUtils::getClipBounds(this));
246                expected.reset();
247                break;
248            default:
249                ADD_FAILURE() << "Too many rects observed";
250            }
251            EXPECT_EQ(expected, getTotalMatrix());
252        }
253        int mDrawCounter = 0;
254    };
255
256    std::vector<sp<RenderNode>> nodes;
257    SkPaint transparentPaint;
258    transparentPaint.setAlpha(128);
259
260    // backdrop
261    nodes.push_back(TestUtils::createSkiaNode(100, 100, 700, 500, // 600x400
262            [&transparentPaint](RenderProperties& props, SkiaRecordingCanvas& canvas) {
263        canvas.drawRect(0, 0, 600, 400, transparentPaint);
264    }));
265
266    // content
267    android::uirenderer::Rect contentDrawBounds(150, 150, 650, 450); // 500x300
268    nodes.push_back(TestUtils::createSkiaNode(0, 0, 800, 600,
269            [&transparentPaint](RenderProperties& props, SkiaRecordingCanvas& canvas) {
270        canvas.drawRect(0, 0, 800, 600, transparentPaint);
271    }));
272
273    // overlay
274    nodes.push_back(TestUtils::createSkiaNode(0, 0, 800, 600,
275            [&transparentPaint](RenderProperties& props, SkiaRecordingCanvas& canvas) {
276        canvas.drawRect(0, 0, 800, 200, transparentPaint);
277    }));
278
279    LayerUpdateQueue layerUpdateQueue;
280    SkRect dirty = SkRect::MakeWH(800, 600);
281    auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
282    sk_sp<DeferLayer<DeferTestCanvas>> surface(new DeferLayer<DeferTestCanvas>());
283    pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true, contentDrawBounds, surface);
284    EXPECT_EQ(4, surface->canvas()->mDrawCounter);
285}
286
287RENDERTHREAD_TEST(SkiaPipeline, clipped) {
288    static const int CANVAS_WIDTH = 200;
289    static const int CANVAS_HEIGHT = 200;
290    class ClippedTestCanvas : public SkCanvas {
291    public:
292        ClippedTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {
293        }
294        void onDrawImage(const SkImage*, SkScalar dx, SkScalar dy, const SkPaint*) override {
295            EXPECT_EQ(0, mDrawCounter++);
296            EXPECT_EQ(SkRect::MakeLTRB(10, 20, 30, 40), TestUtils::getClipBounds(this));
297            EXPECT_TRUE(getTotalMatrix().isIdentity());
298        }
299        int mDrawCounter = 0;
300    };
301
302    std::vector<sp<RenderNode>> nodes;
303    nodes.push_back(TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
304            [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
305        sk_sp<Bitmap> bitmap(TestUtils::createBitmap(CANVAS_WIDTH, CANVAS_HEIGHT));
306        canvas.drawBitmap(*bitmap, 0, 0, nullptr);
307    }));
308
309    LayerUpdateQueue layerUpdateQueue;
310    SkRect dirty = SkRect::MakeLTRB(10, 20, 30, 40);
311    auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
312    sk_sp<DeferLayer<ClippedTestCanvas>> surface(new DeferLayer<ClippedTestCanvas>());
313    pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true,
314            SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface);
315    EXPECT_EQ(1, surface->canvas()->mDrawCounter);
316}
317
318RENDERTHREAD_TEST(SkiaPipeline, clip_replace) {
319    static const int CANVAS_WIDTH = 50;
320    static const int CANVAS_HEIGHT = 50;
321    class ClipReplaceTestCanvas : public SkCanvas {
322    public:
323        ClipReplaceTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {
324        }
325        void onDrawPaint(const SkPaint&) {
326            EXPECT_EQ(0, mDrawCounter++);
327            EXPECT_EQ(SkRect::MakeLTRB(20, 10, 30, 40), TestUtils::getClipBounds(this))
328                    << "Expect resolved clip to be intersection of viewport clip and clip op";
329        }
330        int mDrawCounter = 0;
331    };
332
333    std::vector<sp<RenderNode>> nodes;
334    nodes.push_back(TestUtils::createSkiaNode(20, 20, 30, 30,
335            [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
336        canvas.clipRect(0, -20, 10, 30, SkClipOp::kReplace);
337        canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
338    }));
339
340    LayerUpdateQueue layerUpdateQueue;
341    SkRect dirty = SkRect::MakeLTRB(10, 10, 40, 40);
342    auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
343    sk_sp<DeferLayer<ClipReplaceTestCanvas>> surface(new DeferLayer<ClipReplaceTestCanvas>());
344    pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true,
345            SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface);
346    EXPECT_EQ(1, surface->canvas()->mDrawCounter);
347}
348