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 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 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 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 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 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 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: 248 DeferLayer() : SkSurface_Base(T().imageInfo(), nullptr) {} 249 virtual ~DeferLayer() {} 250 251 SkCanvas* onNewCanvas() override { return new T(); } 252 sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override { return nullptr; } 253 sk_sp<SkImage> onNewImageSnapshot(const SkIRect* bounds) override { return nullptr; } 254 T* canvas() { return static_cast<T*>(getCanvas()); } 255 void onCopyOnWrite(ContentChangeMode) override {} 256 void onWritePixels(const SkPixmap&, int x, int y) override {} 257 }; 258 } 259 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 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. 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 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 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 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