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 <SkBlendMode.h>
21 #include <SkClipStack.h>
22 #include <SkSurface_Base.h>
23 #include <string.h>
24 #include "AnimationContext.h"
25 #include "DamageAccumulator.h"
26 #include "IContextFactory.h"
27 #include "hwui/Paint.h"
28 #include "SkiaCanvas.h"
29 #include "pipeline/skia/SkiaDisplayList.h"
30 #include "pipeline/skia/SkiaOpenGLPipeline.h"
31 #include "pipeline/skia/SkiaRecordingCanvas.h"
32 #include "pipeline/skia/SkiaUtils.h"
33 #include "renderthread/CanvasContext.h"
34 #include "tests/common/TestContext.h"
35 #include "tests/common/TestUtils.h"
36
37 #include <gui/BufferItemConsumer.h>
38 #include <gui/Surface.h>
39
40 using namespace android;
41 using namespace android::uirenderer;
42 using namespace android::uirenderer::renderthread;
43 using namespace android::uirenderer::skiapipeline;
44
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,renderFrame)45 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderFrame) {
46 auto redNode = TestUtils::createSkiaNode(
47 0, 0, 1, 1, [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
48 redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
49 });
50 LayerUpdateQueue layerUpdateQueue;
51 SkRect dirty = SkRectMakeLargest();
52 std::vector<sp<RenderNode>> renderNodes;
53 renderNodes.push_back(redNode);
54 bool opaque = true;
55 android::uirenderer::Rect contentDrawBounds(0, 0, 1, 1);
56 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
57 auto surface = SkSurface::MakeRasterN32Premul(1, 1);
58 surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
59 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
60 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
61 SkMatrix::I());
62 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED);
63 }
64
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,renderFrameCheckOpaque)65 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderFrameCheckOpaque) {
66 auto halfGreenNode = TestUtils::createSkiaNode(
67 0, 0, 2, 2, [](RenderProperties& props, SkiaRecordingCanvas& bottomHalfGreenCanvas) {
68 Paint greenPaint;
69 greenPaint.setColor(SK_ColorGREEN);
70 greenPaint.setStyle(SkPaint::kFill_Style);
71 bottomHalfGreenCanvas.drawRect(0, 1, 2, 2, greenPaint);
72 });
73 LayerUpdateQueue layerUpdateQueue;
74 SkRect dirty = SkRectMakeLargest();
75 std::vector<sp<RenderNode>> renderNodes;
76 renderNodes.push_back(halfGreenNode);
77 android::uirenderer::Rect contentDrawBounds(0, 0, 2, 2);
78 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
79 auto surface = SkSurface::MakeRasterN32Premul(2, 2);
80 surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
81 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
82 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, contentDrawBounds, surface,
83 SkMatrix::I());
84 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
85 ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorGREEN);
86 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, false, contentDrawBounds, surface,
87 SkMatrix::I());
88 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned int)SK_ColorTRANSPARENT);
89 ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorGREEN);
90 }
91
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,renderFrameCheckDirtyRect)92 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderFrameCheckDirtyRect) {
93 auto redNode = TestUtils::createSkiaNode(
94 0, 0, 2, 2, [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
95 redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
96 });
97 LayerUpdateQueue layerUpdateQueue;
98 SkRect dirty = SkRect::MakeXYWH(0, 1, 2, 1);
99 std::vector<sp<RenderNode>> renderNodes;
100 renderNodes.push_back(redNode);
101 android::uirenderer::Rect contentDrawBounds(0, 0, 2, 2);
102 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
103 auto surface = SkSurface::MakeRasterN32Premul(2, 2);
104 surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
105 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
106 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, contentDrawBounds, surface,
107 SkMatrix::I());
108 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
109 ASSERT_EQ(TestUtils::getColor(surface, 1, 0), SK_ColorBLUE);
110 ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorRED);
111 ASSERT_EQ(TestUtils::getColor(surface, 1, 1), SK_ColorRED);
112 }
113
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,renderLayer)114 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderLayer) {
115 auto redNode = TestUtils::createSkiaNode(
116 0, 0, 1, 1, [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
117 redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
118 });
119 auto surfaceLayer1 = SkSurface::MakeRasterN32Premul(1, 1);
120 surfaceLayer1->getCanvas()->drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
121 ASSERT_EQ(TestUtils::getColor(surfaceLayer1, 0, 0), SK_ColorWHITE);
122 redNode->setLayerSurface(surfaceLayer1);
123
124 // create a 2nd 2x2 layer and add it to the queue as well.
125 // make the layer's dirty area one half of the layer and verify only the dirty half is updated.
126 auto blueNode = TestUtils::createSkiaNode(
127 0, 0, 2, 2, [](RenderProperties& props, SkiaRecordingCanvas& blueCanvas) {
128 blueCanvas.drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
129 });
130 auto surfaceLayer2 = SkSurface::MakeRasterN32Premul(2, 2);
131 surfaceLayer2->getCanvas()->drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
132 ASSERT_EQ(TestUtils::getColor(surfaceLayer2, 0, 0), SK_ColorWHITE);
133 blueNode->setLayerSurface(surfaceLayer2);
134
135 // attach both layers to the update queue
136 LayerUpdateQueue layerUpdateQueue;
137 SkRect dirty = SkRectMakeLargest();
138 layerUpdateQueue.enqueueLayerWithDamage(redNode.get(), dirty);
139 layerUpdateQueue.enqueueLayerWithDamage(blueNode.get(), SkRect::MakeWH(2, 1));
140 ASSERT_EQ(layerUpdateQueue.entries().size(), 2UL);
141
142 bool opaque = true;
143 LightGeometry lightGeometry;
144 lightGeometry.radius = 1.0f;
145 lightGeometry.center = {0.0f, 0.0f, 0.0f};
146 LightInfo lightInfo;
147 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
148 pipeline->renderLayers(lightGeometry, &layerUpdateQueue, opaque, lightInfo);
149 ASSERT_EQ(TestUtils::getColor(surfaceLayer1, 0, 0), SK_ColorRED);
150 ASSERT_EQ(TestUtils::getColor(surfaceLayer2, 0, 0), SK_ColorBLUE);
151 ASSERT_EQ(TestUtils::getColor(surfaceLayer2, 0, 1), SK_ColorWHITE);
152 ASSERT_TRUE(layerUpdateQueue.entries().empty());
153 redNode->setLayerSurface(sk_sp<SkSurface>());
154 blueNode->setLayerSurface(sk_sp<SkSurface>());
155 }
156
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,renderOverdraw)157 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderOverdraw) {
158 ScopedProperty<bool> prop(Properties::debugOverdraw, true);
159
160 auto whiteNode = TestUtils::createSkiaNode(
161 0, 0, 1, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
162 canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
163 });
164 LayerUpdateQueue layerUpdateQueue;
165 SkRect dirty = SkRect::MakeXYWH(0, 0, 1, 1);
166 std::vector<sp<RenderNode>> renderNodes;
167 renderNodes.push_back(whiteNode);
168 bool opaque = true;
169 // empty contentDrawBounds is avoiding backdrop/content logic, which would lead to less overdraw
170 android::uirenderer::Rect contentDrawBounds(0, 0, 0, 0);
171 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
172 auto surface = SkSurface::MakeRasterN32Premul(1, 1);
173
174 // Initialize the canvas to blue.
175 surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
176 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
177
178 // Single draw, should be white.
179 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
180 SkMatrix::I());
181 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorWHITE);
182
183 // 1 Overdraw, should be blue blended onto white.
184 renderNodes.push_back(whiteNode);
185 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
186 SkMatrix::I());
187 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffd0d0ff);
188
189 // 2 Overdraw, should be green blended onto white
190 renderNodes.push_back(whiteNode);
191 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
192 SkMatrix::I());
193 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffd0ffd0);
194
195 // 3 Overdraw, should be pink blended onto white.
196 renderNodes.push_back(whiteNode);
197 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
198 SkMatrix::I());
199 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffffc0c0);
200
201 // 4 Overdraw, should be red blended onto white.
202 renderNodes.push_back(whiteNode);
203 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
204 SkMatrix::I());
205 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffff8080);
206
207 // 5 Overdraw, should be red blended onto white.
208 renderNodes.push_back(whiteNode);
209 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
210 SkMatrix::I());
211 ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffff8080);
212 }
213
214 namespace {
215 template <typename T>
216 class DeferLayer : public SkSurface_Base {
217 public:
DeferLayer()218 DeferLayer() : SkSurface_Base(T().imageInfo(), nullptr) {}
~DeferLayer()219 virtual ~DeferLayer() {}
220
onNewCanvas()221 SkCanvas* onNewCanvas() override { return new T(); }
onNewSurface(const SkImageInfo &)222 sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override { return nullptr; }
onNewImageSnapshot(const SkIRect * bounds)223 sk_sp<SkImage> onNewImageSnapshot(const SkIRect* bounds) override { return nullptr; }
canvas()224 T* canvas() { return static_cast<T*>(getCanvas()); }
onCopyOnWrite(ContentChangeMode)225 bool onCopyOnWrite(ContentChangeMode) override { return true; }
onWritePixels(const SkPixmap &,int x,int y)226 void onWritePixels(const SkPixmap&, int x, int y) override {}
227 };
228 }
229
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,deferRenderNodeScene)230 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, deferRenderNodeScene) {
231 class DeferTestCanvas : public SkCanvas {
232 public:
233 DeferTestCanvas() : SkCanvas(800, 600) {}
234 void onDrawRect(const SkRect& rect, const SkPaint& paint) override {
235 SkMatrix expected;
236 switch (mDrawCounter++) {
237 case 0:
238 // background - left side
239 EXPECT_EQ(SkRect::MakeLTRB(600, 100, 700, 500), TestUtils::getClipBounds(this));
240 expected.setTranslate(100, 100);
241 break;
242 case 1:
243 // background - top side
244 EXPECT_EQ(SkRect::MakeLTRB(100, 400, 600, 500), TestUtils::getClipBounds(this));
245 expected.setTranslate(100, 100);
246 break;
247 case 2:
248 // content
249 EXPECT_EQ(SkRect::MakeLTRB(100, 100, 700, 500), TestUtils::getClipBounds(this));
250 expected.setTranslate(-50, -50);
251 break;
252 case 3:
253 // overlay
254 EXPECT_EQ(SkRect::MakeLTRB(0, 0, 800, 600), TestUtils::getClipBounds(this));
255 expected.reset();
256 break;
257 default:
258 ADD_FAILURE() << "Too many rects observed";
259 }
260 EXPECT_EQ(expected, getTotalMatrix());
261 }
262 int mDrawCounter = 0;
263 };
264
265 std::vector<sp<RenderNode>> nodes;
266 Paint transparentPaint;
267 transparentPaint.setAlpha(128);
268
269 // backdrop
270 nodes.push_back(TestUtils::createSkiaNode(
271 100, 100, 700, 500, // 600x400
272 [&transparentPaint](RenderProperties& props, SkiaRecordingCanvas& canvas) {
273 canvas.drawRect(0, 0, 600, 400, transparentPaint);
274 }));
275
276 // content
277 android::uirenderer::Rect contentDrawBounds(150, 150, 650, 450); // 500x300
278 nodes.push_back(TestUtils::createSkiaNode(
279 0, 0, 800, 600,
280 [&transparentPaint](RenderProperties& props, SkiaRecordingCanvas& canvas) {
281 canvas.drawRect(0, 0, 800, 600, transparentPaint);
282 }));
283
284 // overlay
285 nodes.push_back(TestUtils::createSkiaNode(
286 0, 0, 800, 600,
287 [&transparentPaint](RenderProperties& props, SkiaRecordingCanvas& canvas) {
288 canvas.drawRect(0, 0, 800, 200, transparentPaint);
289 }));
290
291 LayerUpdateQueue layerUpdateQueue;
292 SkRect dirty = SkRect::MakeWH(800, 600);
293 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
294 sk_sp<DeferLayer<DeferTestCanvas>> surface(new DeferLayer<DeferTestCanvas>());
295 pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true, contentDrawBounds, surface,
296 SkMatrix::I());
297 EXPECT_EQ(4, surface->canvas()->mDrawCounter);
298 }
299
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,clipped)300 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, clipped) {
301 static const int CANVAS_WIDTH = 200;
302 static const int CANVAS_HEIGHT = 200;
303 class ClippedTestCanvas : public SkCanvas {
304 public:
305 ClippedTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {}
306 void onDrawImage2(const SkImage*, SkScalar dx, SkScalar dy, const SkSamplingOptions&,
307 const SkPaint*) override {
308 EXPECT_EQ(0, mDrawCounter++);
309 EXPECT_EQ(SkRect::MakeLTRB(10, 20, 30, 40), TestUtils::getClipBounds(this));
310 EXPECT_TRUE(getTotalMatrix().isIdentity());
311 }
312 int mDrawCounter = 0;
313 };
314
315 std::vector<sp<RenderNode>> nodes;
316 nodes.push_back(TestUtils::createSkiaNode(
317 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
318 [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
319 sk_sp<Bitmap> bitmap(TestUtils::createBitmap(CANVAS_WIDTH, CANVAS_HEIGHT));
320 canvas.drawBitmap(*bitmap, 0, 0, nullptr);
321 }));
322
323 LayerUpdateQueue layerUpdateQueue;
324 SkRect dirty = SkRect::MakeLTRB(10, 20, 30, 40);
325 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
326 sk_sp<DeferLayer<ClippedTestCanvas>> surface(new DeferLayer<ClippedTestCanvas>());
327 pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true,
328 SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface, SkMatrix::I());
329 EXPECT_EQ(1, surface->canvas()->mDrawCounter);
330 }
331
332 // Test renderFrame with a dirty clip and a pre-transform matrix.
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,clipped_rotated)333 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, clipped_rotated) {
334 static const int CANVAS_WIDTH = 200;
335 static const int CANVAS_HEIGHT = 100;
336 static const SkMatrix rotateMatrix = SkMatrix::MakeAll(0, -1, CANVAS_HEIGHT, 1, 0, 0, 0, 0, 1);
337 static const SkRect dirty = SkRect::MakeLTRB(10, 20, 20, 40);
338 class ClippedTestCanvas : public SkCanvas {
339 public:
340 ClippedTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {}
341 void onDrawImage2(const SkImage*, SkScalar dx, SkScalar dy, const SkSamplingOptions&,
342 const SkPaint*) override {
343 EXPECT_EQ(0, mDrawCounter++);
344 // Expect clip to be rotated.
345 EXPECT_EQ(SkRect::MakeLTRB(CANVAS_HEIGHT - dirty.fTop - dirty.height(), dirty.fLeft,
346 CANVAS_HEIGHT - dirty.fTop, dirty.fLeft + dirty.width()),
347 TestUtils::getClipBounds(this));
348 EXPECT_EQ(rotateMatrix, getTotalMatrix());
349 }
350 int mDrawCounter = 0;
351 };
352
353 std::vector<sp<RenderNode>> nodes;
354 nodes.push_back(TestUtils::createSkiaNode(
355 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT,
356 [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
357 sk_sp<Bitmap> bitmap(TestUtils::createBitmap(CANVAS_WIDTH, CANVAS_HEIGHT));
358 canvas.drawBitmap(*bitmap, 0, 0, nullptr);
359 }));
360
361 LayerUpdateQueue layerUpdateQueue;
362 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
363 sk_sp<DeferLayer<ClippedTestCanvas>> surface(new DeferLayer<ClippedTestCanvas>());
364 pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true,
365 SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface, rotateMatrix);
366 EXPECT_EQ(1, surface->canvas()->mDrawCounter);
367 }
368
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,clip_replace)369 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, clip_replace) {
370 static const int CANVAS_WIDTH = 50;
371 static const int CANVAS_HEIGHT = 50;
372 class ClipReplaceTestCanvas : public SkCanvas {
373 public:
374 ClipReplaceTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {}
375 void onDrawPaint(const SkPaint&) {
376 EXPECT_EQ(0, mDrawCounter++);
377 EXPECT_EQ(SkRect::MakeLTRB(20, 10, 30, 40), TestUtils::getClipBounds(this))
378 << "Expect resolved clip to be intersection of viewport clip and clip op";
379 }
380 int mDrawCounter = 0;
381 };
382
383 std::vector<sp<RenderNode>> nodes;
384 nodes.push_back(TestUtils::createSkiaNode(
385 20, 20, 30, 30, [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
386 canvas.replaceClipRect_deprecated(0, -20, 10, 30);
387 canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
388 }));
389
390 LayerUpdateQueue layerUpdateQueue;
391 SkRect dirty = SkRect::MakeLTRB(10, 10, 40, 40);
392 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
393 sk_sp<DeferLayer<ClipReplaceTestCanvas>> surface(new DeferLayer<ClipReplaceTestCanvas>());
394 pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true,
395 SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface, SkMatrix::I());
396 EXPECT_EQ(1, surface->canvas()->mDrawCounter);
397 }
398
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,context_lost)399 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, context_lost) {
400 test::TestContext context;
401 auto surface = context.surface();
402 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
403 EXPECT_FALSE(pipeline->isSurfaceReady());
404 EXPECT_TRUE(pipeline->setSurface(surface.get(), SwapBehavior::kSwap_default));
405 EXPECT_TRUE(pipeline->isSurfaceReady());
406 renderThread.destroyRenderingContext();
407 EXPECT_FALSE(pipeline->isSurfaceReady());
408
409 pipeline->makeCurrent();
410 EXPECT_TRUE(pipeline->isSurfaceReady());
411 }
412
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline,pictureCallback)413 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, pictureCallback) {
414 // create a pipeline and add a picture callback
415 auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
416 int callbackCount = 0;
417 pipeline->setPictureCapturedCallback(
418 [&callbackCount](sk_sp<SkPicture>&& picture) { callbackCount += 1; });
419
420 // create basic red frame and render it
421 auto redNode = TestUtils::createSkiaNode(
422 0, 0, 1, 1, [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
423 redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
424 });
425 LayerUpdateQueue layerUpdateQueue;
426 SkRect dirty = SkRectMakeLargest();
427 std::vector<sp<RenderNode>> renderNodes;
428 renderNodes.push_back(redNode);
429 bool opaque = true;
430 android::uirenderer::Rect contentDrawBounds(0, 0, 1, 1);
431 auto surface = SkSurface::MakeRasterN32Premul(1, 1);
432 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
433 SkMatrix::I());
434
435 // verify the callback was called
436 EXPECT_EQ(1, callbackCount);
437
438 // render a second frame and check the callback count
439 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
440 SkMatrix::I());
441 EXPECT_EQ(2, callbackCount);
442
443 // unset the callback, render another frame, check callback was not invoked
444 pipeline->setPictureCapturedCallback(nullptr);
445 pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
446 SkMatrix::I());
447 EXPECT_EQ(2, callbackCount);
448 }
449