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