• 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 <VectorDrawable.h>
18 #include <gtest/gtest.h>
19 
20 #include <SkClipStack.h>
21 #include <SkLiteRecorder.h>
22 #include <SkSurface_Base.h>
23 #include <string.h>
24 #include "AnimationContext.h"
25 #include "DamageAccumulator.h"
26 #include "IContextFactory.h"
27 #include "SkiaCanvas.h"
28 #include "pipeline/skia/SkiaDisplayList.h"
29 #include "pipeline/skia/SkiaOpenGLPipeline.h"
30 #include "pipeline/skia/SkiaRecordingCanvas.h"
31 #include "renderthread/CanvasContext.h"
32 #include "tests/common/TestUtils.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(
41             0, 0, 1, 1, [](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, false, contentDrawBounds,
55                           surface);
56     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED);
57 }
58 
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,testOnPrepareTree)59 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, testOnPrepareTree) {
60     auto redNode = TestUtils::createSkiaNode(
61             0, 0, 1, 1, [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
62                 redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
63             });
64 
65     LayerUpdateQueue layerUpdateQueue;
66     SkRect dirty = SkRect::MakeLargest();
67     std::vector<sp<RenderNode>> renderNodes;
68     renderNodes.push_back(redNode);
69     bool opaque = true;
70     android::uirenderer::Rect contentDrawBounds(0, 0, 1, 1);
71     auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
72     {
73         // add a pointer to a deleted vector drawable object in the pipeline
74         sp<VectorDrawableRoot> dirtyVD(new VectorDrawableRoot(new VectorDrawable::Group()));
75         dirtyVD->mutateProperties()->setScaledSize(5, 5);
76         pipeline->getVectorDrawables()->push_back(dirtyVD.get());
77     }
78 
79     // pipeline should clean list of dirty vector drawables before prepare tree
80     pipeline->onPrepareTree();
81 
82     auto surface = SkSurface::MakeRasterN32Premul(1, 1);
83     surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
84     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
85 
86     // drawFrame will crash if "SkiaPipeline::onPrepareTree" did not clean invalid VD pointer
87     pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds,
88                           surface);
89     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED);
90 }
91 
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,renderFrameCheckOpaque)92 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderFrameCheckOpaque) {
93     auto halfGreenNode = TestUtils::createSkiaNode(
94             0, 0, 2, 2, [](RenderProperties& props, SkiaRecordingCanvas& bottomHalfGreenCanvas) {
95                 SkPaint greenPaint;
96                 greenPaint.setColor(SK_ColorGREEN);
97                 greenPaint.setStyle(SkPaint::kFill_Style);
98                 bottomHalfGreenCanvas.drawRect(0, 1, 2, 2, greenPaint);
99             });
100     LayerUpdateQueue layerUpdateQueue;
101     SkRect dirty = SkRect::MakeLargest();
102     std::vector<sp<RenderNode>> renderNodes;
103     renderNodes.push_back(halfGreenNode);
104     android::uirenderer::Rect contentDrawBounds(0, 0, 2, 2);
105     auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
106     auto surface = SkSurface::MakeRasterN32Premul(2, 2);
107     surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
108     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
109     pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, false, contentDrawBounds,
110                           surface);
111     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
112     ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorGREEN);
113     pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, false, false, contentDrawBounds,
114                           surface);
115     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned int)SK_ColorTRANSPARENT);
116     ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorGREEN);
117 }
118 
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,renderFrameCheckDirtyRect)119 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderFrameCheckDirtyRect) {
120     auto redNode = TestUtils::createSkiaNode(
121             0, 0, 2, 2, [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
122                 redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
123             });
124     LayerUpdateQueue layerUpdateQueue;
125     SkRect dirty = SkRect::MakeXYWH(0, 1, 2, 1);
126     std::vector<sp<RenderNode>> renderNodes;
127     renderNodes.push_back(redNode);
128     android::uirenderer::Rect contentDrawBounds(0, 0, 2, 2);
129     auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
130     auto surface = SkSurface::MakeRasterN32Premul(2, 2);
131     surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
132     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
133     pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, false, contentDrawBounds,
134                           surface);
135     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
136     ASSERT_EQ(TestUtils::getColor(surface, 1, 0), SK_ColorBLUE);
137     ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorRED);
138     ASSERT_EQ(TestUtils::getColor(surface, 1, 1), SK_ColorRED);
139 }
140 
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,renderLayer)141 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderLayer) {
142     auto redNode = TestUtils::createSkiaNode(
143             0, 0, 1, 1, [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
144                 redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
145             });
146     auto surfaceLayer1 = SkSurface::MakeRasterN32Premul(1, 1);
147     surfaceLayer1->getCanvas()->drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
148     ASSERT_EQ(TestUtils::getColor(surfaceLayer1, 0, 0), SK_ColorWHITE);
149     redNode->setLayerSurface(surfaceLayer1);
150 
151     // create a 2nd 2x2 layer and add it to the queue as well.
152     // make the layer's dirty area one half of the layer and verify only the dirty half is updated.
153     auto blueNode = TestUtils::createSkiaNode(
154             0, 0, 2, 2, [](RenderProperties& props, SkiaRecordingCanvas& blueCanvas) {
155                 blueCanvas.drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
156             });
157     auto surfaceLayer2 = SkSurface::MakeRasterN32Premul(2, 2);
158     surfaceLayer2->getCanvas()->drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
159     ASSERT_EQ(TestUtils::getColor(surfaceLayer2, 0, 0), SK_ColorWHITE);
160     blueNode->setLayerSurface(surfaceLayer2);
161 
162     // attach both layers to the update queue
163     LayerUpdateQueue layerUpdateQueue;
164     SkRect dirty = SkRect::MakeLargest();
165     layerUpdateQueue.enqueueLayerWithDamage(redNode.get(), dirty);
166     layerUpdateQueue.enqueueLayerWithDamage(blueNode.get(), SkRect::MakeWH(2, 1));
167     ASSERT_EQ(layerUpdateQueue.entries().size(), 2UL);
168 
169     bool opaque = true;
170     FrameBuilder::LightGeometry lightGeometry;
171     lightGeometry.radius = 1.0f;
172     lightGeometry.center = {0.0f, 0.0f, 0.0f};
173     BakedOpRenderer::LightInfo lightInfo;
174     auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
175     pipeline->renderLayers(lightGeometry, &layerUpdateQueue, opaque, false, lightInfo);
176     ASSERT_EQ(TestUtils::getColor(surfaceLayer1, 0, 0), SK_ColorRED);
177     ASSERT_EQ(TestUtils::getColor(surfaceLayer2, 0, 0), SK_ColorBLUE);
178     ASSERT_EQ(TestUtils::getColor(surfaceLayer2, 0, 1), SK_ColorWHITE);
179     ASSERT_TRUE(layerUpdateQueue.entries().empty());
180     redNode->setLayerSurface(sk_sp<SkSurface>());
181     blueNode->setLayerSurface(sk_sp<SkSurface>());
182 }
183 
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,renderOverdraw)184 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderOverdraw) {
185     ScopedProperty<bool> prop(Properties::debugOverdraw, true);
186 
187     auto whiteNode = TestUtils::createSkiaNode(
188             0, 0, 1, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
189                 canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
190             });
191     LayerUpdateQueue layerUpdateQueue;
192     SkRect dirty = SkRect::MakeXYWH(0, 0, 1, 1);
193     std::vector<sp<RenderNode>> renderNodes;
194     renderNodes.push_back(whiteNode);
195     bool opaque = true;
196     // empty contentDrawBounds is avoiding backdrop/content logic, which would lead to less overdraw
197     android::uirenderer::Rect contentDrawBounds(0, 0, 0, 0);
198     auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
199     auto surface = SkSurface::MakeRasterN32Premul(1, 1);
200 
201     // Initialize the canvas to blue.
202     surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
203     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
204 
205     // Single draw, should be white.
206     pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds,
207                           surface);
208     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorWHITE);
209 
210     // 1 Overdraw, should be blue blended onto white.
211     renderNodes.push_back(whiteNode);
212     pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds,
213                           surface);
214     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffd0d0ff);
215 
216     // 2 Overdraw, should be green blended onto white
217     renderNodes.push_back(whiteNode);
218     pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds,
219                           surface);
220     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffd0ffd0);
221 
222     // 3 Overdraw, should be pink blended onto white.
223     renderNodes.push_back(whiteNode);
224     pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds,
225                           surface);
226     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffffc0c0);
227 
228     // 4 Overdraw, should be red blended onto white.
229     renderNodes.push_back(whiteNode);
230     pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds,
231                           surface);
232     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffff8080);
233 
234     // 5 Overdraw, should be red blended onto white.
235     renderNodes.push_back(whiteNode);
236     pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, false, contentDrawBounds,
237                           surface);
238     ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffff8080);
239 }
240 
241 namespace {
242 template <typename T>
243 class DeferLayer : public SkSurface_Base {
244 public:
DeferLayer()245     DeferLayer() : SkSurface_Base(T().imageInfo(), nullptr) {}
~DeferLayer()246     virtual ~DeferLayer() {}
247 
onNewCanvas()248     SkCanvas* onNewCanvas() override { return new T(); }
onNewSurface(const SkImageInfo &)249     sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override { return nullptr; }
onNewImageSnapshot()250     sk_sp<SkImage> onNewImageSnapshot() override { return nullptr; }
canvas()251     T* canvas() { return static_cast<T*>(getCanvas()); }
onCopyOnWrite(ContentChangeMode)252     void onCopyOnWrite(ContentChangeMode) override {}
onWritePixels(const SkPixmap &,int x,int y)253     void onWritePixels(const SkPixmap&, int x, int y) override {}
254 };
255 }
256 
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,deferRenderNodeScene)257 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, deferRenderNodeScene) {
258     class DeferTestCanvas : public SkCanvas {
259     public:
260         DeferTestCanvas() : SkCanvas(800, 600) {}
261         void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
262             SkMatrix expected;
263             switch (mDrawCounter++) {
264                 case 0:
265                     // background - left side
266                     EXPECT_EQ(SkRect::MakeLTRB(600, 100, 700, 500), TestUtils::getClipBounds(this));
267                     expected.setTranslate(100, 100);
268                     break;
269                 case 1:
270                     // background - top side
271                     EXPECT_EQ(SkRect::MakeLTRB(100, 400, 600, 500), TestUtils::getClipBounds(this));
272                     expected.setTranslate(100, 100);
273                     break;
274                 case 2:
275                     // content
276                     EXPECT_EQ(SkRect::MakeLTRB(100, 100, 700, 500), TestUtils::getClipBounds(this));
277                     expected.setTranslate(-50, -50);
278                     break;
279                 case 3:
280                     // overlay
281                     EXPECT_EQ(SkRect::MakeLTRB(0, 0, 800, 600), TestUtils::getClipBounds(this));
282                     expected.reset();
283                     break;
284                 default:
285                     ADD_FAILURE() << "Too many rects observed";
286             }
287             EXPECT_EQ(expected, getTotalMatrix());
288         }
289         int mDrawCounter = 0;
290     };
291 
292     std::vector<sp<RenderNode>> nodes;
293     SkPaint transparentPaint;
294     transparentPaint.setAlpha(128);
295 
296     // backdrop
297     nodes.push_back(TestUtils::createSkiaNode(
298             100, 100, 700, 500,  // 600x400
299             [&transparentPaint](RenderProperties& props, SkiaRecordingCanvas& canvas) {
300                 canvas.drawRect(0, 0, 600, 400, transparentPaint);
301             }));
302 
303     // content
304     android::uirenderer::Rect contentDrawBounds(150, 150, 650, 450);  // 500x300
305     nodes.push_back(TestUtils::createSkiaNode(
306             0, 0, 800, 600,
307             [&transparentPaint](RenderProperties& props, SkiaRecordingCanvas& canvas) {
308                 canvas.drawRect(0, 0, 800, 600, transparentPaint);
309             }));
310 
311     // overlay
312     nodes.push_back(TestUtils::createSkiaNode(
313             0, 0, 800, 600,
314             [&transparentPaint](RenderProperties& props, SkiaRecordingCanvas& canvas) {
315                 canvas.drawRect(0, 0, 800, 200, transparentPaint);
316             }));
317 
318     LayerUpdateQueue layerUpdateQueue;
319     SkRect dirty = SkRect::MakeWH(800, 600);
320     auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
321     sk_sp<DeferLayer<DeferTestCanvas>> surface(new DeferLayer<DeferTestCanvas>());
322     pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true, false, contentDrawBounds, surface);
323     EXPECT_EQ(4, surface->canvas()->mDrawCounter);
324 }
325 
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,clipped)326 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, clipped) {
327     static const int CANVAS_WIDTH = 200;
328     static const int CANVAS_HEIGHT = 200;
329     class ClippedTestCanvas : public SkCanvas {
330     public:
331         ClippedTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {}
332         void onDrawImage(const SkImage*, SkScalar dx, SkScalar dy, const SkPaint*) override {
333             EXPECT_EQ(0, mDrawCounter++);
334             EXPECT_EQ(SkRect::MakeLTRB(10, 20, 30, 40), TestUtils::getClipBounds(this));
335             EXPECT_TRUE(getTotalMatrix().isIdentity());
336         }
337         int mDrawCounter = 0;
338     };
339 
340     std::vector<sp<RenderNode>> nodes;
341     nodes.push_back(TestUtils::createSkiaNode(
342             0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
343             [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
344                 sk_sp<Bitmap> bitmap(TestUtils::createBitmap(CANVAS_WIDTH, CANVAS_HEIGHT));
345                 canvas.drawBitmap(*bitmap, 0, 0, nullptr);
346             }));
347 
348     LayerUpdateQueue layerUpdateQueue;
349     SkRect dirty = SkRect::MakeLTRB(10, 20, 30, 40);
350     auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
351     sk_sp<DeferLayer<ClippedTestCanvas>> surface(new DeferLayer<ClippedTestCanvas>());
352     pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true, false,
353                           SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface);
354     EXPECT_EQ(1, surface->canvas()->mDrawCounter);
355 }
356 
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,clip_replace)357 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, clip_replace) {
358     static const int CANVAS_WIDTH = 50;
359     static const int CANVAS_HEIGHT = 50;
360     class ClipReplaceTestCanvas : public SkCanvas {
361     public:
362         ClipReplaceTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {}
363         void onDrawPaint(const SkPaint&) {
364             EXPECT_EQ(0, mDrawCounter++);
365             EXPECT_EQ(SkRect::MakeLTRB(20, 10, 30, 40), TestUtils::getClipBounds(this))
366                     << "Expect resolved clip to be intersection of viewport clip and clip op";
367         }
368         int mDrawCounter = 0;
369     };
370 
371     std::vector<sp<RenderNode>> nodes;
372     nodes.push_back(TestUtils::createSkiaNode(
373             20, 20, 30, 30, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
374                 canvas.clipRect(0, -20, 10, 30, SkClipOp::kReplace_deprecated);
375                 canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
376             }));
377 
378     LayerUpdateQueue layerUpdateQueue;
379     SkRect dirty = SkRect::MakeLTRB(10, 10, 40, 40);
380     auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
381     sk_sp<DeferLayer<ClipReplaceTestCanvas>> surface(new DeferLayer<ClipReplaceTestCanvas>());
382     pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true, false,
383                           SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface);
384     EXPECT_EQ(1, surface->canvas()->mDrawCounter);
385 }
386