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