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 = WebViewFunctor_create(
235              nullptr, TestUtils::createMockFunctor(RenderMode::OpenGL_ES), RenderMode::OpenGL_ES);
236  
237      auto node = TestUtils::createNode(0, 0, 200, 400, [&](RenderProperties& props, Canvas& canvas) {
238          canvas.drawWebViewFunctor(functor);
239      });
240      TestUtils::runOnRenderThreadUnmanaged([&] (RenderThread&) {
241          TestUtils::syncHierarchyPropertiesAndDisplayList(node);
242      });
243      auto& counts = TestUtils::countsForFunctor(functor);
244      EXPECT_EQ(1, counts.sync);
245      EXPECT_EQ(0, counts.destroyed);
246  
247      TestUtils::recordNode(*node, [&](Canvas& canvas) {
248          canvas.drawWebViewFunctor(functor);
249      });
250      EXPECT_EQ(1, counts.sync);
251      EXPECT_EQ(0, counts.destroyed);
252  
253      TestUtils::runOnRenderThreadUnmanaged([&] (RenderThread&) {
254          TestUtils::syncHierarchyPropertiesAndDisplayList(node);
255      });
256      EXPECT_EQ(2, counts.sync);
257      EXPECT_EQ(0, counts.destroyed);
258  
259      WebViewFunctor_release(functor);
260      EXPECT_EQ(2, counts.sync);
261      EXPECT_EQ(0, counts.destroyed);
262  
263      TestUtils::recordNode(*node, [](Canvas& canvas) {});
264      TestUtils::runOnRenderThreadUnmanaged([&] (RenderThread&) {
265          TestUtils::syncHierarchyPropertiesAndDisplayList(node);
266      });
267      // Fence on any remaining post'd work
268      TestUtils::runOnRenderThreadUnmanaged([] (RenderThread&) {});
269      EXPECT_EQ(2, counts.sync);
270      EXPECT_EQ(1, counts.destroyed);
271  }
272  
RENDERTHREAD_TEST(RenderNode,prepareTree_nullableDisplayList)273  RENDERTHREAD_TEST(RenderNode, prepareTree_nullableDisplayList) {
274      auto rootNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
275      ContextFactory contextFactory;
276      std::unique_ptr<CanvasContext> canvasContext(
277              CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory, 0, 0));
278      TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
279      DamageAccumulator damageAccumulator;
280      info.damageAccumulator = &damageAccumulator;
281  
282      {
283          auto nonNullDLNode =
284                  TestUtils::createNode(0, 0, 200, 400, [](RenderProperties& props, Canvas& canvas) {
285                      canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
286                  });
287          TestUtils::syncHierarchyPropertiesAndDisplayList(nonNullDLNode);
288          EXPECT_TRUE(nonNullDLNode->getDisplayList());
289          nonNullDLNode->prepareTree(info);
290      }
291  
292      {
293          auto nullDLNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
294          TestUtils::syncHierarchyPropertiesAndDisplayList(nullDLNode);
295          EXPECT_FALSE(nullDLNode->getDisplayList());
296          nullDLNode->prepareTree(info);
297      }
298  
299      canvasContext->destroy();
300  }
301  
302  // TODO: Is this supposed to work in SkiaGL/SkiaVK?
RENDERTHREAD_TEST(DISABLED_RenderNode,prepareTree_HwLayer_AVD_enqueueDamage)303  RENDERTHREAD_TEST(DISABLED_RenderNode, prepareTree_HwLayer_AVD_enqueueDamage) {
304      VectorDrawable::Group* group = new VectorDrawable::Group();
305      sp<VectorDrawableRoot> vectorDrawable(new VectorDrawableRoot(group));
306  
307      auto rootNode =
308              TestUtils::createNode(0, 0, 200, 400, [&](RenderProperties& props, Canvas& canvas) {
309                  canvas.drawVectorDrawable(vectorDrawable.get());
310              });
311      ContextFactory contextFactory;
312      std::unique_ptr<CanvasContext> canvasContext(
313              CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory, 0, 0));
314      canvasContext->setSurface(nullptr);
315      TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
316      DamageAccumulator damageAccumulator;
317      LayerUpdateQueue layerUpdateQueue;
318      info.damageAccumulator = &damageAccumulator;
319      info.layerUpdateQueue = &layerUpdateQueue;
320  
321      // Put node on HW layer
322      rootNode->mutateStagingProperties().mutateLayerProperties().setType(LayerType::RenderLayer);
323  
324      TestUtils::syncHierarchyPropertiesAndDisplayList(rootNode);
325      rootNode->prepareTree(info);
326  
327      // Check that the VD is in the dislay list, and the layer update queue contains the correct
328      // damage rect.
329      EXPECT_TRUE(rootNode->getDisplayList().hasVectorDrawables());
330      ASSERT_FALSE(info.layerUpdateQueue->entries().empty());
331      EXPECT_EQ(rootNode.get(), info.layerUpdateQueue->entries().at(0).renderNode.get());
332      EXPECT_EQ(uirenderer::Rect(0, 0, 200, 400), info.layerUpdateQueue->entries().at(0).damage);
333      canvasContext->destroy();
334  }
335