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 "AnimationContext.h"
     21 #include "DamageAccumulator.h"
     22 #include "IContextFactory.h"
     23 #include "pipeline/skia/SkiaDisplayList.h"
     24 #include "renderthread/CanvasContext.h"
     25 #include "tests/common/TestUtils.h"
     26 
     27 using namespace android;
     28 using namespace android::uirenderer;
     29 using namespace android::uirenderer::renderthread;
     30 using namespace android::uirenderer::skiapipeline;
     31 
     32 TEST(SkiaDisplayList, create) {
     33     SkiaDisplayList skiaDL;
     34     ASSERT_TRUE(skiaDL.isEmpty());
     35     ASSERT_FALSE(skiaDL.mProjectionReceiver);
     36 }
     37 
     38 TEST(SkiaDisplayList, reset) {
     39     SkiaDisplayList skiaDL;
     40 
     41     SkCanvas dummyCanvas;
     42     RenderNodeDrawable drawable(nullptr, &dummyCanvas);
     43     skiaDL.mChildNodes.emplace_back(nullptr, &dummyCanvas);
     44     skiaDL.mChildFunctors.emplace_back(nullptr, nullptr, &dummyCanvas);
     45     skiaDL.mMutableImages.push_back(nullptr);
     46     skiaDL.mVectorDrawables.push_back(nullptr);
     47     skiaDL.mDisplayList.drawAnnotation(SkRect::MakeWH(200, 200), "testAnnotation", nullptr);
     48     skiaDL.mProjectionReceiver = &drawable;
     49 
     50     ASSERT_FALSE(skiaDL.mChildNodes.empty());
     51     ASSERT_FALSE(skiaDL.mChildFunctors.empty());
     52     ASSERT_FALSE(skiaDL.mMutableImages.empty());
     53     ASSERT_FALSE(skiaDL.mVectorDrawables.empty());
     54     ASSERT_FALSE(skiaDL.isEmpty());
     55     ASSERT_TRUE(skiaDL.mProjectionReceiver);
     56 
     57     skiaDL.reset();
     58 
     59     ASSERT_TRUE(skiaDL.mChildNodes.empty());
     60     ASSERT_TRUE(skiaDL.mChildFunctors.empty());
     61     ASSERT_TRUE(skiaDL.mMutableImages.empty());
     62     ASSERT_TRUE(skiaDL.mVectorDrawables.empty());
     63     ASSERT_TRUE(skiaDL.isEmpty());
     64     ASSERT_FALSE(skiaDL.mProjectionReceiver);
     65 }
     66 
     67 TEST(SkiaDisplayList, reuseDisplayList) {
     68     sp<RenderNode> renderNode = new RenderNode();
     69     std::unique_ptr<SkiaDisplayList> availableList;
     70 
     71     // no list has been attached so it should return a nullptr
     72     availableList = renderNode->detachAvailableList();
     73     ASSERT_EQ(availableList.get(), nullptr);
     74 
     75     // attach a displayList for reuse
     76     SkiaDisplayList skiaDL;
     77     ASSERT_TRUE(skiaDL.reuseDisplayList(renderNode.get(), nullptr));
     78 
     79     // detach the list that you just attempted to reuse
     80     availableList = renderNode->detachAvailableList();
     81     ASSERT_EQ(availableList.get(), &skiaDL);
     82     availableList.release();  // prevents an invalid free since our DL is stack allocated
     83 
     84     // after detaching there should return no available list
     85     availableList = renderNode->detachAvailableList();
     86     ASSERT_EQ(availableList.get(), nullptr);
     87 }
     88 
     89 TEST(SkiaDisplayList, syncContexts) {
     90     SkiaDisplayList skiaDL;
     91 
     92     SkCanvas dummyCanvas;
     93     TestUtils::MockFunctor functor;
     94     skiaDL.mChildFunctors.emplace_back(&functor, nullptr, &dummyCanvas);
     95 
     96     SkRect bounds = SkRect::MakeWH(200, 200);
     97     VectorDrawableRoot vectorDrawable(new VectorDrawable::Group());
     98     vectorDrawable.mutateStagingProperties()->setBounds(bounds);
     99     skiaDL.mVectorDrawables.push_back(&vectorDrawable);
    100 
    101     // ensure that the functor and vectorDrawable are properly synced
    102     skiaDL.syncContents();
    103 
    104     ASSERT_EQ(functor.getLastMode(), DrawGlInfo::kModeSync);
    105     ASSERT_EQ(vectorDrawable.mutateProperties()->getBounds(), bounds);
    106 }
    107 
    108 class ContextFactory : public IContextFactory {
    109 public:
    110     virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) override {
    111         return new AnimationContext(clock);
    112     }
    113 };
    114 
    115 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaDisplayList, prepareListAndChildren) {
    116     auto rootNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
    117     ContextFactory contextFactory;
    118     std::unique_ptr<CanvasContext> canvasContext(
    119             CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory));
    120     TreeInfo info(TreeInfo::MODE_FULL, *canvasContext.get());
    121     DamageAccumulator damageAccumulator;
    122     info.damageAccumulator = &damageAccumulator;
    123 
    124     SkiaDisplayList skiaDL;
    125 
    126     // prepare with a clean VD
    127     VectorDrawableRoot cleanVD(new VectorDrawable::Group());
    128     skiaDL.mVectorDrawables.push_back(&cleanVD);
    129     cleanVD.getBitmapUpdateIfDirty();  // this clears the dirty bit
    130 
    131     ASSERT_FALSE(cleanVD.isDirty());
    132     ASSERT_FALSE(cleanVD.getPropertyChangeWillBeConsumed());
    133     TestUtils::MockTreeObserver observer;
    134     ASSERT_FALSE(skiaDL.prepareListAndChildren(observer, info, false,
    135                                                [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
    136     ASSERT_TRUE(cleanVD.getPropertyChangeWillBeConsumed());
    137 
    138     // prepare again this time adding a dirty VD
    139     VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
    140     skiaDL.mVectorDrawables.push_back(&dirtyVD);
    141 
    142     ASSERT_TRUE(dirtyVD.isDirty());
    143     ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
    144     ASSERT_TRUE(skiaDL.prepareListAndChildren(observer, info, false,
    145                                               [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
    146     ASSERT_TRUE(dirtyVD.getPropertyChangeWillBeConsumed());
    147 
    148     // prepare again this time adding a RenderNode and a callback
    149     sp<RenderNode> renderNode = new RenderNode();
    150     TreeInfo* infoPtr = &info;
    151     SkCanvas dummyCanvas;
    152     skiaDL.mChildNodes.emplace_back(renderNode.get(), &dummyCanvas);
    153     bool hasRun = false;
    154     ASSERT_TRUE(skiaDL.prepareListAndChildren(
    155             observer, info, false,
    156             [&hasRun, renderNode, infoPtr](RenderNode* n, TreeObserver& observer, TreeInfo& i,
    157                                            bool r) {
    158                 hasRun = true;
    159                 ASSERT_EQ(renderNode.get(), n);
    160                 ASSERT_EQ(infoPtr, &i);
    161                 ASSERT_FALSE(r);
    162             }));
    163     ASSERT_TRUE(hasRun);
    164 
    165     canvasContext->destroy();
    166 }
    167 
    168 TEST(SkiaDisplayList, updateChildren) {
    169     SkiaDisplayList skiaDL;
    170 
    171     sp<RenderNode> renderNode = new RenderNode();
    172     SkCanvas dummyCanvas;
    173     skiaDL.mChildNodes.emplace_back(renderNode.get(), &dummyCanvas);
    174     skiaDL.updateChildren([renderNode](RenderNode* n) { ASSERT_EQ(renderNode.get(), n); });
    175 }
    176