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