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