Home | History | Annotate | Download | only in unit
      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