RenderNodeTests.cpp revision 2de950d5a8b47c7b4648ada1b1260ce4b7342798
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
29using namespace android;
30using namespace android::uirenderer;
31using namespace android::uirenderer::renderthread;
32
33class ContextFactory : public android::uirenderer::IContextFactory {
34public:
35    android::uirenderer::AnimationContext* createAnimationContext
36        (android::uirenderer::renderthread::TimeLord& clock) override {
37        return new android::uirenderer::AnimationContext(clock);
38    }
39};
40
41TEST(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
69TEST(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
133TEST(RenderNode, releasedCallback) {
134    class DecRefOnReleased : public GlFunctorLifecycleListener {
135    public:
136        explicit DecRefOnReleased(int* refcnt) : mRefCnt(refcnt) {}
137        void onGlFunctorReleased(Functor* functor) override {
138            *mRefCnt -= 1;
139        }
140    private:
141        int* mRefCnt;
142    };
143
144    int refcnt = 0;
145    sp<DecRefOnReleased> listener(new DecRefOnReleased(&refcnt));
146    Functor noopFunctor;
147
148    auto node = TestUtils::createNode(0, 0, 200, 400,
149            [&](RenderProperties& props, Canvas& canvas) {
150        refcnt++;
151        canvas.callDrawGLFunction(&noopFunctor, listener.get());
152    });
153    TestUtils::syncHierarchyPropertiesAndDisplayList(node);
154    EXPECT_EQ(1, refcnt);
155
156    TestUtils::recordNode(*node, [&](Canvas& canvas) {
157        refcnt++;
158        canvas.callDrawGLFunction(&noopFunctor, listener.get());
159    });
160    EXPECT_EQ(2, refcnt);
161
162    TestUtils::syncHierarchyPropertiesAndDisplayList(node);
163    EXPECT_EQ(1, refcnt);
164
165    TestUtils::recordNode(*node, [](Canvas& canvas) {});
166    EXPECT_EQ(1, refcnt);
167    TestUtils::syncHierarchyPropertiesAndDisplayList(node);
168    EXPECT_EQ(0, refcnt);
169}
170
171RENDERTHREAD_TEST(RenderNode, prepareTree_nullableDisplayList) {
172    auto rootNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
173    ContextFactory contextFactory;
174    std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
175            renderThread, false, rootNode.get(), &contextFactory));
176    TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
177    DamageAccumulator damageAccumulator;
178    info.damageAccumulator = &damageAccumulator;
179
180    {
181        auto nonNullDLNode = TestUtils::createNode(0, 0, 200, 400,
182                [](RenderProperties& props, Canvas& canvas) {
183            canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
184        });
185        TestUtils::syncHierarchyPropertiesAndDisplayList(nonNullDLNode);
186        EXPECT_TRUE(nonNullDLNode->getDisplayList());
187        nonNullDLNode->prepareTree(info);
188    }
189
190    {
191        auto nullDLNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
192        TestUtils::syncHierarchyPropertiesAndDisplayList(nullDLNode);
193        EXPECT_FALSE(nullDLNode->getDisplayList());
194        nullDLNode->prepareTree(info);
195    }
196
197    canvasContext->destroy();
198}
199
200RENDERTHREAD_TEST(RenderNode, prepareTree_HwLayer_AVD_enqueueDamage) {
201
202    VectorDrawable::Group* group = new VectorDrawable::Group();
203    sp<VectorDrawableRoot> vectorDrawable(new VectorDrawableRoot(group));
204
205    auto rootNode = TestUtils::createNode(0, 0, 200, 400,
206            [&](RenderProperties& props, Canvas& canvas) {
207        canvas.drawVectorDrawable(vectorDrawable.get());
208    });
209    ContextFactory contextFactory;
210    std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
211            renderThread, false, rootNode.get(), &contextFactory));
212    TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
213    DamageAccumulator damageAccumulator;
214    LayerUpdateQueue layerUpdateQueue;
215    info.damageAccumulator = &damageAccumulator;
216    info.layerUpdateQueue = &layerUpdateQueue;
217
218    // Put node on HW layer
219    rootNode->mutateStagingProperties().mutateLayerProperties().setType(LayerType::RenderLayer);
220
221    TestUtils::syncHierarchyPropertiesAndDisplayList(rootNode);
222    rootNode->prepareTree(info);
223
224    // Check that the VD is in the dislay list, and the layer update queue contains the correct
225    // damage rect.
226    EXPECT_TRUE(rootNode->getDisplayList()->hasVectorDrawables());
227    EXPECT_FALSE(info.layerUpdateQueue->entries().empty());
228    EXPECT_EQ(rootNode.get(), info.layerUpdateQueue->entries().at(0).renderNode);
229    EXPECT_EQ(uirenderer::Rect(0, 0, 200, 400), info.layerUpdateQueue->entries().at(0).damage);
230    canvasContext->destroy();
231}
232