blob: 5bb0b6db06b526bb2ad8f803ee2cdd2940e99f0c [file] [log] [blame]
Stan Iliev500a0c32016-10-26 10:30:09 -04001/*
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"
Stan Iliev52771272016-11-17 09:54:38 -050029#include <SkClipStack.h>
Stan Iliev500a0c32016-10-26 10:30:09 -040030#include <SkLiteRecorder.h>
Stan Iliev52771272016-11-17 09:54:38 -050031#include <SkSurface_Base.h>
Stan Iliev500a0c32016-10-26 10:30:09 -040032#include <string.h>
33
34using namespace android;
35using namespace android::uirenderer;
36using namespace android::uirenderer::renderthread;
37using namespace android::uirenderer::skiapipeline;
38
Greg Daniel98c78dad2017-01-04 14:45:56 -050039RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderFrame) {
Stan Iliev500a0c32016-10-26 10:30:09 -040040 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
Greg Daniel98c78dad2017-01-04 14:45:56 -050058RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderFrameCheckOpaque) {
Stan Iliev500a0c32016-10-26 10:30:09 -040059 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
Greg Daniel98c78dad2017-01-04 14:45:56 -050083RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderFrameCheckDirtyRect) {
Stan Iliev500a0c32016-10-26 10:30:09 -040084 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
Greg Daniel98c78dad2017-01-04 14:45:56 -0500104RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderLayer) {
Stan Iliev500a0c32016-10-26 10:30:09 -0400105 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}
Matt Sarettf58cc922016-11-14 18:33:38 -0500146
Greg Daniel98c78dad2017-01-04 14:45:56 -0500147RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderOverdraw) {
Matt Sarettf58cc922016-11-14 18:33:38 -0500148 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;
Stan Iliev52771272016-11-17 09:54:38 -0500159 //empty contentDrawBounds is avoiding backdrop/content logic, which would lead to less overdraw
160 android::uirenderer::Rect contentDrawBounds(0, 0, 0, 0);
Matt Sarettf58cc922016-11-14 18:33:38 -0500161 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.
Matt Sarett341480b2017-01-23 19:45:42 -0500173 renderNodes.push_back(whiteNode);
Matt Sarettf58cc922016-11-14 18:33:38 -0500174 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}
Stan Iliev52771272016-11-17 09:54:38 -0500197
198namespace {
199template <typename T>
200class DeferLayer : public SkSurface_Base {
201public:
Derek Sollenberger624ad832017-01-11 11:09:48 -0500202 DeferLayer() : SkSurface_Base(T().imageInfo(), nullptr) {}
203 virtual ~DeferLayer() {}
204
Stan Iliev52771272016-11-17 09:54:38 -0500205 SkCanvas* onNewCanvas() override {
Stan Ilieved4d58c2016-12-14 14:05:04 -0500206 return new T();
Stan Iliev52771272016-11-17 09:54:38 -0500207 }
208 sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override {
209 return sk_sp<SkSurface>();
210 }
Derek Sollenberger624ad832017-01-11 11:09:48 -0500211 sk_sp<SkImage> onNewImageSnapshot(SkBudgeted) override {
Stan Iliev52771272016-11-17 09:54:38 -0500212 return sk_sp<SkImage>();
213 }
Stan Ilieved4d58c2016-12-14 14:05:04 -0500214 T* canvas() { return static_cast<T*>(getCanvas()); }
Stan Iliev52771272016-11-17 09:54:38 -0500215 void onCopyOnWrite(ContentChangeMode) override {}
Stan Iliev52771272016-11-17 09:54:38 -0500216};
217}
218
Greg Daniel98c78dad2017-01-04 14:45:56 -0500219RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, deferRenderNodeScene) {
Stan Iliev52771272016-11-17 09:54:38 -0500220 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);
Stan Ilieved4d58c2016-12-14 14:05:04 -0500280 sk_sp<DeferLayer<DeferTestCanvas>> surface(new DeferLayer<DeferTestCanvas>());
Stan Iliev52771272016-11-17 09:54:38 -0500281 pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true, contentDrawBounds, surface);
Stan Ilieved4d58c2016-12-14 14:05:04 -0500282 EXPECT_EQ(4, surface->canvas()->mDrawCounter);
Stan Iliev52771272016-11-17 09:54:38 -0500283}
284
Greg Daniel98c78dad2017-01-04 14:45:56 -0500285RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, clipped) {
Stan Iliev52771272016-11-17 09:54:38 -0500286 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);
Stan Ilieved4d58c2016-12-14 14:05:04 -0500310 sk_sp<DeferLayer<ClippedTestCanvas>> surface(new DeferLayer<ClippedTestCanvas>());
Stan Iliev52771272016-11-17 09:54:38 -0500311 pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true,
312 SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface);
Stan Ilieved4d58c2016-12-14 14:05:04 -0500313 EXPECT_EQ(1, surface->canvas()->mDrawCounter);
Stan Iliev52771272016-11-17 09:54:38 -0500314}
315
Greg Daniel98c78dad2017-01-04 14:45:56 -0500316RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, clip_replace) {
Stan Iliev52771272016-11-17 09:54:38 -0500317 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++);
Stan Ilievb66b8bb2016-12-15 18:17:42 -0500325 EXPECT_EQ(SkRect::MakeLTRB(20, 10, 30, 40), TestUtils::getClipBounds(this))
326 << "Expect resolved clip to be intersection of viewport clip and clip op";
Stan Iliev52771272016-11-17 09:54:38 -0500327 }
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) {
Chris Craik66b9d442016-12-16 17:49:48 +0000334 canvas.clipRect(0, -20, 10, 30, SkClipOp::kReplace);
Stan Iliev52771272016-11-17 09:54:38 -0500335 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);
Stan Ilieved4d58c2016-12-14 14:05:04 -0500341 sk_sp<DeferLayer<ClipReplaceTestCanvas>> surface(new DeferLayer<ClipReplaceTestCanvas>());
Stan Iliev52771272016-11-17 09:54:38 -0500342 pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true,
343 SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface);
Stan Ilieved4d58c2016-12-14 14:05:04 -0500344 EXPECT_EQ(1, surface->canvas()->mDrawCounter);
Stan Iliev52771272016-11-17 09:54:38 -0500345}