• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
34 using namespace android;
35 using namespace android::uirenderer;
36 using namespace android::uirenderer::renderthread;
37 using namespace android::uirenderer::skiapipeline;
38 
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,renderFrame)39 RENDERTHREAD_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 
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,renderFrameCheckOpaque)58 RENDERTHREAD_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 
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,renderFrameCheckDirtyRect)83 RENDERTHREAD_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 
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,renderLayer)104 RENDERTHREAD_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 
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,renderOverdraw)147 RENDERTHREAD_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 
198 namespace {
199 template <typename T>
200 class DeferLayer : public SkSurface_Base {
201 public:
DeferLayer()202     DeferLayer() : SkSurface_Base(T().imageInfo(), nullptr) {}
~DeferLayer()203     virtual ~DeferLayer() {}
204 
onNewCanvas()205     SkCanvas* onNewCanvas() override {
206         return new T();
207     }
onNewSurface(const SkImageInfo &)208     sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override {
209         return nullptr;
210     }
onNewImageSnapshot()211     sk_sp<SkImage> onNewImageSnapshot() override {
212         return nullptr;
213     }
canvas()214     T* canvas() { return static_cast<T*>(getCanvas()); }
onCopyOnWrite(ContentChangeMode)215     void onCopyOnWrite(ContentChangeMode) override {}
216 };
217 }
218 
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,deferRenderNodeScene)219 RENDERTHREAD_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 
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,clipped)285 RENDERTHREAD_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 
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,clip_replace)316 RENDERTHREAD_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