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:
createAnimationContext(android::uirenderer::renderthread::TimeLord & clock)35     android::uirenderer::AnimationContext* createAnimationContext(
36             android::uirenderer::renderthread::TimeLord& clock) override {
37         return new android::uirenderer::AnimationContext(clock);
38     }
39 };
40 
TEST(RenderNode,hasParents)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 
TEST(RenderNode,validity)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 
TEST(RenderNode,multiTreeValidity)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 
TEST(RenderNode,releasedCallback)233 TEST(RenderNode, releasedCallback) {
234     int functor = TestUtils::createMockFunctor();
235 
236     auto node = TestUtils::createNode(0, 0, 200, 400, [&](RenderProperties& props, Canvas& canvas) {
237         canvas.drawWebViewFunctor(functor);
238     });
239     TestUtils::runOnRenderThreadUnmanaged([&] (RenderThread&) {
240         TestUtils::syncHierarchyPropertiesAndDisplayList(node);
241     });
242     auto& counts = TestUtils::countsForFunctor(functor);
243     EXPECT_EQ(1, counts.sync);
244     EXPECT_EQ(0, counts.destroyed);
245 
246     TestUtils::recordNode(*node, [&](Canvas& canvas) {
247         canvas.drawWebViewFunctor(functor);
248     });
249     EXPECT_EQ(1, counts.sync);
250     EXPECT_EQ(0, counts.destroyed);
251 
252     TestUtils::runOnRenderThreadUnmanaged([&] (RenderThread&) {
253         TestUtils::syncHierarchyPropertiesAndDisplayList(node);
254     });
255     EXPECT_EQ(2, counts.sync);
256     EXPECT_EQ(0, counts.destroyed);
257 
258     WebViewFunctor_release(functor);
259     EXPECT_EQ(2, counts.sync);
260     EXPECT_EQ(0, counts.destroyed);
261 
262     TestUtils::recordNode(*node, [](Canvas& canvas) {});
263     TestUtils::runOnRenderThreadUnmanaged([&] (RenderThread&) {
264         TestUtils::syncHierarchyPropertiesAndDisplayList(node);
265     });
266     // Fence on any remaining post'd work
267     TestUtils::runOnRenderThreadUnmanaged([] (RenderThread&) {});
268     EXPECT_EQ(2, counts.sync);
269     EXPECT_EQ(1, counts.destroyed);
270 }
271 
RENDERTHREAD_TEST(RenderNode,prepareTree_nullableDisplayList)272 RENDERTHREAD_TEST(RenderNode, prepareTree_nullableDisplayList) {
273     auto rootNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
274     ContextFactory contextFactory;
275     std::unique_ptr<CanvasContext> canvasContext(
276             CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory, 0, 0));
277     TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
278     DamageAccumulator damageAccumulator;
279     info.damageAccumulator = &damageAccumulator;
280 
281     {
282         auto nonNullDLNode =
283                 TestUtils::createNode(0, 0, 200, 400, [](RenderProperties& props, Canvas& canvas) {
284                     canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
285                 });
286         TestUtils::syncHierarchyPropertiesAndDisplayList(nonNullDLNode);
287         EXPECT_TRUE(nonNullDLNode->getDisplayList());
288         nonNullDLNode->prepareTree(info);
289     }
290 
291     {
292         auto nullDLNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
293         TestUtils::syncHierarchyPropertiesAndDisplayList(nullDLNode);
294         EXPECT_FALSE(nullDLNode->getDisplayList());
295         nullDLNode->prepareTree(info);
296     }
297 
298     canvasContext->destroy();
299 }
300 
301 // TODO: Is this supposed to work in SkiaGL/SkiaVK?
RENDERTHREAD_TEST(DISABLED_RenderNode,prepareTree_HwLayer_AVD_enqueueDamage)302 RENDERTHREAD_TEST(DISABLED_RenderNode, prepareTree_HwLayer_AVD_enqueueDamage) {
303     VectorDrawable::Group* group = new VectorDrawable::Group();
304     sp<VectorDrawableRoot> vectorDrawable(new VectorDrawableRoot(group));
305 
306     auto rootNode =
307             TestUtils::createNode(0, 0, 200, 400, [&](RenderProperties& props, Canvas& canvas) {
308                 canvas.drawVectorDrawable(vectorDrawable.get());
309             });
310     ContextFactory contextFactory;
311     std::unique_ptr<CanvasContext> canvasContext(
312             CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory, 0, 0));
313     canvasContext->setSurface(nullptr);
314     TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
315     DamageAccumulator damageAccumulator;
316     LayerUpdateQueue layerUpdateQueue;
317     info.damageAccumulator = &damageAccumulator;
318     info.layerUpdateQueue = &layerUpdateQueue;
319 
320     // Put node on HW layer
321     rootNode->mutateStagingProperties().mutateLayerProperties().setType(LayerType::RenderLayer);
322 
323     TestUtils::syncHierarchyPropertiesAndDisplayList(rootNode);
324     rootNode->prepareTree(info);
325 
326     // Check that the VD is in the dislay list, and the layer update queue contains the correct
327     // damage rect.
328     EXPECT_TRUE(rootNode->getDisplayList().hasVectorDrawables());
329     ASSERT_FALSE(info.layerUpdateQueue->entries().empty());
330     EXPECT_EQ(rootNode.get(), info.layerUpdateQueue->entries().at(0).renderNode.get());
331     EXPECT_EQ(uirenderer::Rect(0, 0, 200, 400), info.layerUpdateQueue->entries().at(0).damage);
332     canvasContext->destroy();
333 }
334 
TEST(RenderNode,hasNoFill)335 TEST(RenderNode, hasNoFill) {
336     auto rootNode =
337             TestUtils::createNode(0, 0, 200, 400, [](RenderProperties& props, Canvas& canvas) {
338                 Paint paint;
339                 paint.setStyle(SkPaint::Style::kStroke_Style);
340                 canvas.drawRect(10, 10, 100, 100, paint);
341             });
342 
343     TestUtils::syncHierarchyPropertiesAndDisplayList(rootNode);
344 
345     EXPECT_FALSE(rootNode.get()->getDisplayList().hasFill());
346     EXPECT_FALSE(rootNode.get()->getDisplayList().hasText());
347 }
348 
TEST(RenderNode,hasFill)349 TEST(RenderNode, hasFill) {
350     auto rootNode =
351             TestUtils::createNode(0, 0, 200, 400, [](RenderProperties& props, Canvas& canvas) {
352                 Paint paint;
353                 paint.setStyle(SkPaint::kStrokeAndFill_Style);
354                 canvas.drawRect(10, 10, 100, 100, paint);
355             });
356 
357     TestUtils::syncHierarchyPropertiesAndDisplayList(rootNode);
358 
359     EXPECT_TRUE(rootNode.get()->getDisplayList().hasFill());
360     EXPECT_FALSE(rootNode.get()->getDisplayList().hasText());
361 }
362