SkiaPipelineTests.cpp revision d9770c3c6c5b6a4fc7fa8774cf041e1ed1623119
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_SKIA_PIPELINE_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_SKIA_PIPELINE_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_SKIA_PIPELINE_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_SKIA_PIPELINE_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_SKIA_PIPELINE_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);
174    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
175    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned) 0xffd0d0ff);
176
177    // 2 Overdraw, should be green blended onto white
178    renderNodes.push_back(whiteNode);
179    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
180    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned) 0xffd0ffd0);
181
182    // 3 Overdraw, should be pink blended onto white.
183    renderNodes.push_back(whiteNode);
184    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
185    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned) 0xffffc0c0);
186
187    // 4 Overdraw, should be red blended onto white.
188    renderNodes.push_back(whiteNode);
189    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
190    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned) 0xffff8080);
191
192    // 5 Overdraw, should be red blended onto white.
193    renderNodes.push_back(whiteNode);
194    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
195    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned) 0xffff8080);
196}
197
198namespace {
199template <typename T>
200class DeferLayer : public SkSurface_Base {
201public:
202    DeferLayer() : SkSurface_Base(T().imageInfo(), nullptr) {}
203    virtual ~DeferLayer() {}
204
205    SkCanvas* onNewCanvas() override {
206        return new T();
207    }
208    sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override {
209        return nullptr;
210    }
211    sk_sp<SkImage> onNewImageSnapshot() override {
212        return nullptr;
213    }
214    T* canvas() { return static_cast<T*>(getCanvas()); }
215    void onCopyOnWrite(ContentChangeMode) override {}
216};
217}
218
219RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, deferRenderNodeScene) {
220    class DeferTestCanvas : public SkCanvas {
221    public:
222        DeferTestCanvas() : SkCanvas(800, 600) {}
223        void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
224            SkMatrix expected;
225            switch (mDrawCounter++) {
226            case 0:
227                // background - left side
228                EXPECT_EQ(SkRect::MakeLTRB(600, 100, 700, 500), TestUtils::getClipBounds(this));
229                expected.setTranslate(100, 100);
230                break;
231            case 1:
232                // background - top side
233                EXPECT_EQ(SkRect::MakeLTRB(100, 400, 600, 500), TestUtils::getClipBounds(this));
234                expected.setTranslate(100, 100);
235                break;
236            case 2:
237                // content
238                EXPECT_EQ(SkRect::MakeLTRB(100, 100, 700, 500), TestUtils::getClipBounds(this));
239                expected.setTranslate(-50, -50);
240                break;
241            case 3:
242                // overlay
243                EXPECT_EQ(SkRect::MakeLTRB(0, 0, 800, 600), TestUtils::getClipBounds(this));
244                expected.reset();
245                break;
246            default:
247                ADD_FAILURE() << "Too many rects observed";
248            }
249            EXPECT_EQ(expected, getTotalMatrix());
250        }
251        int mDrawCounter = 0;
252    };
253
254    std::vector<sp<RenderNode>> nodes;
255    SkPaint transparentPaint;
256    transparentPaint.setAlpha(128);
257
258    // backdrop
259    nodes.push_back(TestUtils::createSkiaNode(100, 100, 700, 500, // 600x400
260            [&transparentPaint](RenderProperties& props, SkiaRecordingCanvas& canvas) {
261        canvas.drawRect(0, 0, 600, 400, transparentPaint);
262    }));
263
264    // content
265    android::uirenderer::Rect contentDrawBounds(150, 150, 650, 450); // 500x300
266    nodes.push_back(TestUtils::createSkiaNode(0, 0, 800, 600,
267            [&transparentPaint](RenderProperties& props, SkiaRecordingCanvas& canvas) {
268        canvas.drawRect(0, 0, 800, 600, transparentPaint);
269    }));
270
271    // overlay
272    nodes.push_back(TestUtils::createSkiaNode(0, 0, 800, 600,
273            [&transparentPaint](RenderProperties& props, SkiaRecordingCanvas& canvas) {
274        canvas.drawRect(0, 0, 800, 200, transparentPaint);
275    }));
276
277    LayerUpdateQueue layerUpdateQueue;
278    SkRect dirty = SkRect::MakeWH(800, 600);
279    auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
280    sk_sp<DeferLayer<DeferTestCanvas>> surface(new DeferLayer<DeferTestCanvas>());
281    pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true, contentDrawBounds, surface);
282    EXPECT_EQ(4, surface->canvas()->mDrawCounter);
283}
284
285RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, clipped) {
286    static const int CANVAS_WIDTH = 200;
287    static const int CANVAS_HEIGHT = 200;
288    class ClippedTestCanvas : public SkCanvas {
289    public:
290        ClippedTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {
291        }
292        void onDrawImage(const SkImage*, SkScalar dx, SkScalar dy, const SkPaint*) override {
293            EXPECT_EQ(0, mDrawCounter++);
294            EXPECT_EQ(SkRect::MakeLTRB(10, 20, 30, 40), TestUtils::getClipBounds(this));
295            EXPECT_TRUE(getTotalMatrix().isIdentity());
296        }
297        int mDrawCounter = 0;
298    };
299
300    std::vector<sp<RenderNode>> nodes;
301    nodes.push_back(TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
302            [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
303        sk_sp<Bitmap> bitmap(TestUtils::createBitmap(CANVAS_WIDTH, CANVAS_HEIGHT));
304        canvas.drawBitmap(*bitmap, 0, 0, nullptr);
305    }));
306
307    LayerUpdateQueue layerUpdateQueue;
308    SkRect dirty = SkRect::MakeLTRB(10, 20, 30, 40);
309    auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
310    sk_sp<DeferLayer<ClippedTestCanvas>> surface(new DeferLayer<ClippedTestCanvas>());
311    pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true,
312            SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface);
313    EXPECT_EQ(1, surface->canvas()->mDrawCounter);
314}
315
316RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, clip_replace) {
317    static const int CANVAS_WIDTH = 50;
318    static const int CANVAS_HEIGHT = 50;
319    class ClipReplaceTestCanvas : public SkCanvas {
320    public:
321        ClipReplaceTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {
322        }
323        void onDrawPaint(const SkPaint&) {
324            EXPECT_EQ(0, mDrawCounter++);
325            EXPECT_EQ(SkRect::MakeLTRB(20, 10, 30, 40), TestUtils::getClipBounds(this))
326                    << "Expect resolved clip to be intersection of viewport clip and clip op";
327        }
328        int mDrawCounter = 0;
329    };
330
331    std::vector<sp<RenderNode>> nodes;
332    nodes.push_back(TestUtils::createSkiaNode(20, 20, 30, 30,
333            [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
334        canvas.clipRect(0, -20, 10, 30, SkClipOp::kReplace_deprecated);
335        canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
336    }));
337
338    LayerUpdateQueue layerUpdateQueue;
339    SkRect dirty = SkRect::MakeLTRB(10, 10, 40, 40);
340    auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
341    sk_sp<DeferLayer<ClipReplaceTestCanvas>> surface(new DeferLayer<ClipReplaceTestCanvas>());
342    pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true,
343            SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface);
344    EXPECT_EQ(1, surface->canvas()->mDrawCounter);
345}
346