blob: 2925243d9f1c5fba0ac9b66dcb8e7aef72f9428d [file] [log] [blame]
John Reck44b49f02016-03-25 14:29:48 -07001/*
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>
Doris Liu5876e7d2016-08-02 17:28:30 -070018#include <VectorDrawable.h>
John Reck44b49f02016-03-25 14:29:48 -070019
Doris Liua7952b32016-06-13 14:49:26 -070020#include "AnimationContext.h"
21#include "DamageAccumulator.h"
22#include "IContextFactory.h"
John Reck44b49f02016-03-25 14:29:48 -070023#include "RenderNode.h"
24#include "TreeInfo.h"
Doris Liua7952b32016-06-13 14:49:26 -070025#include "renderthread/CanvasContext.h"
John Reck44b49f02016-03-25 14:29:48 -070026#include "tests/common/TestUtils.h"
27#include "utils/Color.h"
28
29using namespace android;
30using namespace android::uirenderer;
Doris Liua7952b32016-06-13 14:49:26 -070031using 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};
John Reck44b49f02016-03-25 14:29:48 -070040
41TEST(RenderNode, hasParents) {
42 auto child = TestUtils::createNode(0, 0, 200, 400,
Stan Iliev06152cd2016-07-27 17:55:43 -040043 [](RenderProperties& props, Canvas& canvas) {
Mike Reed260ab722016-10-07 15:59:20 -040044 canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
John Reck44b49f02016-03-25 14:29:48 -070045 });
46 auto parent = TestUtils::createNode(0, 0, 200, 400,
Stan Iliev06152cd2016-07-27 17:55:43 -040047 [&child](RenderProperties& props, Canvas& canvas) {
John Reck44b49f02016-03-25 14:29:48 -070048 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
Stan Iliev06152cd2016-07-27 17:55:43 -040056 TestUtils::recordNode(*parent, [](Canvas& canvas) {
Mike Reed260ab722016-10-07 15:59:20 -040057 canvas.drawColor(Color::Amber_500, SkBlendMode::kSrcOver);
John Reck44b49f02016-03-25 14:29:48 -070058 });
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}
John Reckcd1c3eb2016-04-14 10:38:54 -070068
John Reck2de950d2017-01-25 10:58:30 -080069TEST(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
John Reck3afd6372017-01-30 10:15:48 -0800133TEST(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
John Reckcd1c3eb2016-04-14 10:38:54 -0700239TEST(RenderNode, releasedCallback) {
240 class DecRefOnReleased : public GlFunctorLifecycleListener {
241 public:
Chih-Hung Hsiehd53e3be2016-05-03 10:02:51 -0700242 explicit DecRefOnReleased(int* refcnt) : mRefCnt(refcnt) {}
John Reckcd1c3eb2016-04-14 10:38:54 -0700243 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,
Stan Iliev06152cd2016-07-27 17:55:43 -0400255 [&](RenderProperties& props, Canvas& canvas) {
John Reckcd1c3eb2016-04-14 10:38:54 -0700256 refcnt++;
257 canvas.callDrawGLFunction(&noopFunctor, listener.get());
258 });
259 TestUtils::syncHierarchyPropertiesAndDisplayList(node);
260 EXPECT_EQ(1, refcnt);
261
Stan Iliev06152cd2016-07-27 17:55:43 -0400262 TestUtils::recordNode(*node, [&](Canvas& canvas) {
John Reckcd1c3eb2016-04-14 10:38:54 -0700263 refcnt++;
264 canvas.callDrawGLFunction(&noopFunctor, listener.get());
265 });
266 EXPECT_EQ(2, refcnt);
267
268 TestUtils::syncHierarchyPropertiesAndDisplayList(node);
269 EXPECT_EQ(1, refcnt);
270
Stan Iliev06152cd2016-07-27 17:55:43 -0400271 TestUtils::recordNode(*node, [](Canvas& canvas) {});
John Reckcd1c3eb2016-04-14 10:38:54 -0700272 EXPECT_EQ(1, refcnt);
273 TestUtils::syncHierarchyPropertiesAndDisplayList(node);
274 EXPECT_EQ(0, refcnt);
275}
Doris Liua7952b32016-06-13 14:49:26 -0700276
277RENDERTHREAD_TEST(RenderNode, prepareTree_nullableDisplayList) {
Derek Sollenberger56ad6ec2016-07-22 12:13:32 -0400278 auto rootNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
Doris Liua7952b32016-06-13 14:49:26 -0700279 ContextFactory contextFactory;
Stan Iliev03de0742016-07-07 12:35:54 -0400280 std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
Derek Sollenberger56ad6ec2016-07-22 12:13:32 -0400281 renderThread, false, rootNode.get(), &contextFactory));
Stan Iliev03de0742016-07-07 12:35:54 -0400282 TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
Doris Liua7952b32016-06-13 14:49:26 -0700283 DamageAccumulator damageAccumulator;
284 info.damageAccumulator = &damageAccumulator;
Doris Liua7952b32016-06-13 14:49:26 -0700285
286 {
287 auto nonNullDLNode = TestUtils::createNode(0, 0, 200, 400,
Stan Iliev06152cd2016-07-27 17:55:43 -0400288 [](RenderProperties& props, Canvas& canvas) {
Mike Reed260ab722016-10-07 15:59:20 -0400289 canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
Doris Liua7952b32016-06-13 14:49:26 -0700290 });
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
John Reck2de950d2017-01-25 10:58:30 -0800303 canvasContext->destroy();
Doris Liua7952b32016-06-13 14:49:26 -0700304}
Doris Liu5876e7d2016-08-02 17:28:30 -0700305
306RENDERTHREAD_TEST(RenderNode, prepareTree_HwLayer_AVD_enqueueDamage) {
307
308 VectorDrawable::Group* group = new VectorDrawable::Group();
Greg Daniel98c78dad2017-01-04 14:45:56 -0500309 sp<VectorDrawableRoot> vectorDrawable(new VectorDrawableRoot(group));
310
Doris Liu5876e7d2016-08-02 17:28:30 -0700311 auto rootNode = TestUtils::createNode(0, 0, 200, 400,
312 [&](RenderProperties& props, Canvas& canvas) {
Greg Daniel98c78dad2017-01-04 14:45:56 -0500313 canvas.drawVectorDrawable(vectorDrawable.get());
Doris Liu5876e7d2016-08-02 17:28:30 -0700314 });
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;
Doris Liu5876e7d2016-08-02 17:28:30 -0700323
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.
Derek Sollenberger0df62092016-09-27 16:04:42 -0400332 EXPECT_TRUE(rootNode->getDisplayList()->hasVectorDrawables());
Doris Liu5876e7d2016-08-02 17:28:30 -0700333 EXPECT_FALSE(info.layerUpdateQueue->entries().empty());
334 EXPECT_EQ(rootNode.get(), info.layerUpdateQueue->entries().at(0).renderNode);
335 EXPECT_EQ(uirenderer::Rect(0, 0, 200, 400), info.layerUpdateQueue->entries().at(0).damage);
John Reck2de950d2017-01-25 10:58:30 -0800336 canvasContext->destroy();
Doris Liu5876e7d2016-08-02 17:28:30 -0700337}