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