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 "RenderNode.h"
     24 #include "TreeInfo.h"
     25 #include "renderthread/CanvasContext.h"
     26 #include "tests/common/TestUtils.h"
     27 #include "utils/Color.h"
     28 
     29 using namespace android;
     30 using namespace android::uirenderer;
     31 using namespace android::uirenderer::renderthread;
     32 
     33 class ContextFactory : public android::uirenderer::IContextFactory {
     34 public:
     35     android::uirenderer::AnimationContext* createAnimationContext
     36         (android::uirenderer::renderthread::TimeLord& clock) override {
     37         return new android::uirenderer::AnimationContext(clock);
     38     }
     39 };
     40 
     41 TEST(RenderNode, hasParents) {
     42     auto child = TestUtils::createNode(0, 0, 200, 400,
     43             [](RenderProperties& props, Canvas& canvas) {
     44         canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
     45     });
     46     auto parent = TestUtils::createNode(0, 0, 200, 400,
     47             [&child](RenderProperties& props, Canvas& canvas) {
     48         canvas.drawRenderNode(child.get());
     49     });
     50 
     51     TestUtils::syncHierarchyPropertiesAndDisplayList(parent);
     52 
     53     EXPECT_TRUE(child->hasParents()) << "Child node has no parent";
     54     EXPECT_FALSE(parent->hasParents()) << "Root node shouldn't have any parents";
     55 
     56     TestUtils::recordNode(*parent, [](Canvas& canvas) {
     57         canvas.drawColor(Color::Amber_500, SkBlendMode::kSrcOver);
     58     });
     59 
     60     EXPECT_TRUE(child->hasParents()) << "Child should still have a parent";
     61     EXPECT_FALSE(parent->hasParents()) << "Root node shouldn't have any parents";
     62 
     63     TestUtils::syncHierarchyPropertiesAndDisplayList(parent);
     64 
     65     EXPECT_FALSE(child->hasParents()) << "Child should be removed";
     66     EXPECT_FALSE(parent->hasParents()) << "Root node shouldn't have any parents";
     67 }
     68 
     69 TEST(RenderNode, validity) {
     70     auto child = TestUtils::createNode(0, 0, 200, 400,
     71             [](RenderProperties& props, Canvas& canvas) {
     72         canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
     73     });
     74     auto parent = TestUtils::createNode(0, 0, 200, 400,
     75             [&child](RenderProperties& props, Canvas& canvas) {
     76         canvas.drawRenderNode(child.get());
     77     });
     78 
     79     EXPECT_TRUE(child->isValid());
     80     EXPECT_TRUE(parent->isValid());
     81     EXPECT_TRUE(child->nothingToDraw());
     82     EXPECT_TRUE(parent->nothingToDraw());
     83 
     84     TestUtils::syncHierarchyPropertiesAndDisplayList(parent);
     85 
     86     EXPECT_TRUE(child->isValid());
     87     EXPECT_TRUE(parent->isValid());
     88     EXPECT_FALSE(child->nothingToDraw());
     89     EXPECT_FALSE(parent->nothingToDraw());
     90 
     91     TestUtils::recordNode(*parent, [](Canvas& canvas) {
     92         canvas.drawColor(Color::Amber_500, SkBlendMode::kSrcOver);
     93     });
     94 
     95     EXPECT_TRUE(child->isValid());
     96     EXPECT_TRUE(parent->isValid());
     97     EXPECT_FALSE(child->nothingToDraw());
     98     EXPECT_FALSE(parent->nothingToDraw());
     99 
    100     TestUtils::syncHierarchyPropertiesAndDisplayList(parent);
    101 
    102     EXPECT_FALSE(child->isValid());
    103     EXPECT_TRUE(parent->isValid());
    104     EXPECT_TRUE(child->nothingToDraw());
    105     EXPECT_FALSE(parent->nothingToDraw());
    106 
    107     TestUtils::recordNode(*child, [](Canvas& canvas) {
    108         canvas.drawColor(Color::Amber_500, SkBlendMode::kSrcOver);
    109     });
    110 
    111     EXPECT_TRUE(child->isValid());
    112     EXPECT_TRUE(child->nothingToDraw());
    113 
    114     TestUtils::recordNode(*parent, [&child](Canvas& canvas) {
    115         canvas.drawRenderNode(child.get());
    116     });
    117 
    118     TestUtils::syncHierarchyPropertiesAndDisplayList(parent);
    119 
    120     EXPECT_TRUE(child->isValid());
    121     EXPECT_TRUE(parent->isValid());
    122     EXPECT_FALSE(child->nothingToDraw());
    123     EXPECT_FALSE(parent->nothingToDraw());
    124 
    125     parent->destroyHardwareResources();
    126 
    127     EXPECT_FALSE(child->isValid());
    128     EXPECT_FALSE(parent->isValid());
    129     EXPECT_TRUE(child->nothingToDraw());
    130     EXPECT_TRUE(parent->nothingToDraw());
    131 }
    132 
    133 TEST(RenderNode, multiTreeValidity) {
    134     auto child = TestUtils::createNode(0, 0, 200, 400,
    135             [](RenderProperties& props, Canvas& canvas) {
    136         canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
    137     });
    138     auto parent1 = TestUtils::createNode(0, 0, 200, 400,
    139             [&child](RenderProperties& props, Canvas& canvas) {
    140         canvas.drawRenderNode(child.get());
    141     });
    142     auto parent2 = TestUtils::createNode(0, 0, 200, 400,
    143             [&child](RenderProperties& props, Canvas& canvas) {
    144         canvas.drawRenderNode(child.get());
    145     });
    146 
    147     EXPECT_TRUE(child->isValid());
    148     EXPECT_TRUE(parent1->isValid());
    149     EXPECT_TRUE(parent2->isValid());
    150     EXPECT_TRUE(child->nothingToDraw());
    151     EXPECT_TRUE(parent1->nothingToDraw());
    152     EXPECT_TRUE(parent2->nothingToDraw());
    153 
    154     TestUtils::syncHierarchyPropertiesAndDisplayList(parent1);
    155 
    156     EXPECT_TRUE(child->isValid());
    157     EXPECT_TRUE(parent1->isValid());
    158     EXPECT_TRUE(parent2->isValid());
    159     EXPECT_FALSE(child->nothingToDraw());
    160     EXPECT_FALSE(parent1->nothingToDraw());
    161     EXPECT_TRUE(parent2->nothingToDraw());
    162 
    163     TestUtils::syncHierarchyPropertiesAndDisplayList(parent2);
    164 
    165     EXPECT_TRUE(child->isValid());
    166     EXPECT_TRUE(parent1->isValid());
    167     EXPECT_TRUE(parent2->isValid());
    168     EXPECT_FALSE(child->nothingToDraw());
    169     EXPECT_FALSE(parent1->nothingToDraw());
    170     EXPECT_FALSE(parent2->nothingToDraw());
    171 
    172     TestUtils::recordNode(*parent1, [](Canvas& canvas) {
    173         canvas.drawColor(Color::Amber_500, SkBlendMode::kSrcOver);
    174     });
    175 
    176     TestUtils::syncHierarchyPropertiesAndDisplayList(parent1);
    177 
    178     EXPECT_TRUE(child->isValid());
    179     EXPECT_TRUE(parent1->isValid());
    180     EXPECT_TRUE(parent2->isValid());
    181     EXPECT_FALSE(child->nothingToDraw());
    182     EXPECT_FALSE(parent1->nothingToDraw());
    183     EXPECT_FALSE(parent2->nothingToDraw());
    184 
    185     TestUtils::recordNode(*parent2, [](Canvas& canvas) {
    186         canvas.drawColor(Color::Amber_500, SkBlendMode::kSrcOver);
    187     });
    188 
    189     TestUtils::syncHierarchyPropertiesAndDisplayList(parent2);
    190 
    191     EXPECT_FALSE(child->isValid());
    192     EXPECT_TRUE(parent1->isValid());
    193     EXPECT_TRUE(parent2->isValid());
    194     EXPECT_TRUE(child->nothingToDraw());
    195     EXPECT_FALSE(parent1->nothingToDraw());
    196     EXPECT_FALSE(parent2->nothingToDraw());
    197 
    198     TestUtils::recordNode(*child, [](Canvas& canvas) {
    199         canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
    200     });
    201     TestUtils::syncHierarchyPropertiesAndDisplayList(child);
    202 
    203     TestUtils::recordNode(*parent1, [&child](Canvas& canvas) {
    204         canvas.drawRenderNode(child.get());
    205     });
    206     TestUtils::syncHierarchyPropertiesAndDisplayList(parent1);
    207 
    208     TestUtils::recordNode(*parent2, [&child](Canvas& canvas) {
    209         canvas.drawRenderNode(child.get());
    210     });
    211     TestUtils::syncHierarchyPropertiesAndDisplayList(parent2);
    212 
    213     EXPECT_TRUE(child->isValid());
    214     EXPECT_TRUE(parent1->isValid());
    215     EXPECT_TRUE(parent2->isValid());
    216     EXPECT_FALSE(child->nothingToDraw());
    217     EXPECT_FALSE(parent1->nothingToDraw());
    218     EXPECT_FALSE(parent2->nothingToDraw());
    219 
    220     parent1->destroyHardwareResources();
    221 
    222     EXPECT_TRUE(child->isValid());
    223     EXPECT_FALSE(parent1->isValid());
    224     EXPECT_TRUE(parent2->isValid());
    225     EXPECT_FALSE(child->nothingToDraw());
    226     EXPECT_TRUE(parent1->nothingToDraw());
    227     EXPECT_FALSE(parent2->nothingToDraw());
    228 
    229     parent2->destroyHardwareResources();
    230 
    231     EXPECT_FALSE(child->isValid());
    232     EXPECT_FALSE(parent1->isValid());
    233     EXPECT_FALSE(parent2->isValid());
    234     EXPECT_TRUE(child->nothingToDraw());
    235     EXPECT_TRUE(parent1->nothingToDraw());
    236     EXPECT_TRUE(parent2->nothingToDraw());
    237 }
    238 
    239 TEST(RenderNode, releasedCallback) {
    240     class DecRefOnReleased : public GlFunctorLifecycleListener {
    241     public:
    242         explicit DecRefOnReleased(int* refcnt) : mRefCnt(refcnt) {}
    243         void onGlFunctorReleased(Functor* functor) override {
    244             *mRefCnt -= 1;
    245         }
    246     private:
    247         int* mRefCnt;
    248     };
    249 
    250     int refcnt = 0;
    251     sp<DecRefOnReleased> listener(new DecRefOnReleased(&refcnt));
    252     Functor noopFunctor;
    253 
    254     auto node = TestUtils::createNode(0, 0, 200, 400,
    255             [&](RenderProperties& props, Canvas& canvas) {
    256         refcnt++;
    257         canvas.callDrawGLFunction(&noopFunctor, listener.get());
    258     });
    259     TestUtils::syncHierarchyPropertiesAndDisplayList(node);
    260     EXPECT_EQ(1, refcnt);
    261 
    262     TestUtils::recordNode(*node, [&](Canvas& canvas) {
    263         refcnt++;
    264         canvas.callDrawGLFunction(&noopFunctor, listener.get());
    265     });
    266     EXPECT_EQ(2, refcnt);
    267 
    268     TestUtils::syncHierarchyPropertiesAndDisplayList(node);
    269     EXPECT_EQ(1, refcnt);
    270 
    271     TestUtils::recordNode(*node, [](Canvas& canvas) {});
    272     EXPECT_EQ(1, refcnt);
    273     TestUtils::syncHierarchyPropertiesAndDisplayList(node);
    274     EXPECT_EQ(0, refcnt);
    275 }
    276 
    277 RENDERTHREAD_TEST(RenderNode, prepareTree_nullableDisplayList) {
    278     auto rootNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
    279     ContextFactory contextFactory;
    280     std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
    281             renderThread, false, rootNode.get(), &contextFactory));
    282     TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
    283     DamageAccumulator damageAccumulator;
    284     info.damageAccumulator = &damageAccumulator;
    285 
    286     {
    287         auto nonNullDLNode = TestUtils::createNode(0, 0, 200, 400,
    288                 [](RenderProperties& props, Canvas& canvas) {
    289             canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
    290         });
    291         TestUtils::syncHierarchyPropertiesAndDisplayList(nonNullDLNode);
    292         EXPECT_TRUE(nonNullDLNode->getDisplayList());
    293         nonNullDLNode->prepareTree(info);
    294     }
    295 
    296     {
    297         auto nullDLNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
    298         TestUtils::syncHierarchyPropertiesAndDisplayList(nullDLNode);
    299         EXPECT_FALSE(nullDLNode->getDisplayList());
    300         nullDLNode->prepareTree(info);
    301     }
    302 
    303     canvasContext->destroy();
    304 }
    305 
    306 RENDERTHREAD_TEST(RenderNode, prepareTree_HwLayer_AVD_enqueueDamage) {
    307 
    308     VectorDrawable::Group* group = new VectorDrawable::Group();
    309     sp<VectorDrawableRoot> vectorDrawable(new VectorDrawableRoot(group));
    310 
    311     auto rootNode = TestUtils::createNode(0, 0, 200, 400,
    312             [&](RenderProperties& props, Canvas& canvas) {
    313         canvas.drawVectorDrawable(vectorDrawable.get());
    314     });
    315     ContextFactory contextFactory;
    316     std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
    317             renderThread, false, rootNode.get(), &contextFactory));
    318     TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
    319     DamageAccumulator damageAccumulator;
    320     LayerUpdateQueue layerUpdateQueue;
    321     info.damageAccumulator = &damageAccumulator;
    322     info.layerUpdateQueue = &layerUpdateQueue;
    323 
    324     // Put node on HW layer
    325     rootNode->mutateStagingProperties().mutateLayerProperties().setType(LayerType::RenderLayer);
    326 
    327     TestUtils::syncHierarchyPropertiesAndDisplayList(rootNode);
    328     rootNode->prepareTree(info);
    329 
    330     // Check that the VD is in the dislay list, and the layer update queue contains the correct
    331     // damage rect.
    332     EXPECT_TRUE(rootNode->getDisplayList()->hasVectorDrawables());
    333     EXPECT_FALSE(info.layerUpdateQueue->entries().empty());
    334     EXPECT_EQ(rootNode.get(), info.layerUpdateQueue->entries().at(0).renderNode.get());
    335     EXPECT_EQ(uirenderer::Rect(0, 0, 200, 400), info.layerUpdateQueue->entries().at(0).damage);
    336     canvasContext->destroy();
    337 }
    338