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