blob: 690a60a470bc281dc5193bb75bfc1fae19e385d3 [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
Doris Liu5876e7d2016-08-02 17:28:30 -070017#include <VectorDrawable.h>
John Reck1bcacfd2017-11-03 10:12:19 -070018#include <gtest/gtest.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:
John Reck1bcacfd2017-11-03 10:12:19 -070035 android::uirenderer::AnimationContext* createAnimationContext(
36 android::uirenderer::renderthread::TimeLord& clock) override {
Doris Liua7952b32016-06-13 14:49:26 -070037 return new android::uirenderer::AnimationContext(clock);
38 }
39};
John Reck44b49f02016-03-25 14:29:48 -070040
41TEST(RenderNode, hasParents) {
John Reck1bcacfd2017-11-03 10:12:19 -070042 auto child = TestUtils::createNode(0, 0, 200, 400, [](RenderProperties& props, Canvas& canvas) {
Mike Reed260ab722016-10-07 15:59:20 -040043 canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
John Reck44b49f02016-03-25 14:29:48 -070044 });
45 auto parent = TestUtils::createNode(0, 0, 200, 400,
John Reck1bcacfd2017-11-03 10:12:19 -070046 [&child](RenderProperties& props, Canvas& canvas) {
47 canvas.drawRenderNode(child.get());
48 });
John Reck44b49f02016-03-25 14:29:48 -070049
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
Stan Iliev06152cd2016-07-27 17:55:43 -040055 TestUtils::recordNode(*parent, [](Canvas& canvas) {
Mike Reed260ab722016-10-07 15:59:20 -040056 canvas.drawColor(Color::Amber_500, SkBlendMode::kSrcOver);
John Reck44b49f02016-03-25 14:29:48 -070057 });
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}
John Reckcd1c3eb2016-04-14 10:38:54 -070067
John Reck2de950d2017-01-25 10:58:30 -080068TEST(RenderNode, validity) {
John Reck1bcacfd2017-11-03 10:12:19 -070069 auto child = TestUtils::createNode(0, 0, 200, 400, [](RenderProperties& props, Canvas& canvas) {
John Reck2de950d2017-01-25 10:58:30 -080070 canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
71 });
72 auto parent = TestUtils::createNode(0, 0, 200, 400,
John Reck1bcacfd2017-11-03 10:12:19 -070073 [&child](RenderProperties& props, Canvas& canvas) {
74 canvas.drawRenderNode(child.get());
75 });
John Reck2de950d2017-01-25 10:58:30 -080076
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
John Reck1bcacfd2017-11-03 10:12:19 -0700112 TestUtils::recordNode(*parent,
113 [&child](Canvas& canvas) { canvas.drawRenderNode(child.get()); });
John Reck2de950d2017-01-25 10:58:30 -0800114
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
John Reck3afd6372017-01-30 10:15:48 -0800130TEST(RenderNode, multiTreeValidity) {
John Reck1bcacfd2017-11-03 10:12:19 -0700131 auto child = TestUtils::createNode(0, 0, 200, 400, [](RenderProperties& props, Canvas& canvas) {
John Reck3afd6372017-01-30 10:15:48 -0800132 canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
133 });
134 auto parent1 = TestUtils::createNode(0, 0, 200, 400,
John Reck1bcacfd2017-11-03 10:12:19 -0700135 [&child](RenderProperties& props, Canvas& canvas) {
136 canvas.drawRenderNode(child.get());
137 });
John Reck3afd6372017-01-30 10:15:48 -0800138 auto parent2 = TestUtils::createNode(0, 0, 200, 400,
John Reck1bcacfd2017-11-03 10:12:19 -0700139 [&child](RenderProperties& props, Canvas& canvas) {
140 canvas.drawRenderNode(child.get());
141 });
John Reck3afd6372017-01-30 10:15:48 -0800142
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
John Reck1bcacfd2017-11-03 10:12:19 -0700199 TestUtils::recordNode(*parent1,
200 [&child](Canvas& canvas) { canvas.drawRenderNode(child.get()); });
John Reck3afd6372017-01-30 10:15:48 -0800201 TestUtils::syncHierarchyPropertiesAndDisplayList(parent1);
202
John Reck1bcacfd2017-11-03 10:12:19 -0700203 TestUtils::recordNode(*parent2,
204 [&child](Canvas& canvas) { canvas.drawRenderNode(child.get()); });
John Reck3afd6372017-01-30 10:15:48 -0800205 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
John Reckcd1c3eb2016-04-14 10:38:54 -0700233TEST(RenderNode, releasedCallback) {
John Reck20a4d682023-07-11 17:11:51 -0400234 int functor = TestUtils::createMockFunctor();
John Reckcd1c3eb2016-04-14 10:38:54 -0700235
John Reck1bcacfd2017-11-03 10:12:19 -0700236 auto node = TestUtils::createNode(0, 0, 200, 400, [&](RenderProperties& props, Canvas& canvas) {
John Reckaa4c9822020-06-25 17:14:13 -0700237 canvas.drawWebViewFunctor(functor);
John Reckcd1c3eb2016-04-14 10:38:54 -0700238 });
John Reckaa4c9822020-06-25 17:14:13 -0700239 TestUtils::runOnRenderThreadUnmanaged([&] (RenderThread&) {
240 TestUtils::syncHierarchyPropertiesAndDisplayList(node);
241 });
Alec Mourie5792782024-07-18 03:59:51 +0000242 auto counts = TestUtils::copyCountsForFunctor(functor);
John Reckaa4c9822020-06-25 17:14:13 -0700243 EXPECT_EQ(1, counts.sync);
244 EXPECT_EQ(0, counts.destroyed);
John Reckcd1c3eb2016-04-14 10:38:54 -0700245
Stan Iliev06152cd2016-07-27 17:55:43 -0400246 TestUtils::recordNode(*node, [&](Canvas& canvas) {
John Reckaa4c9822020-06-25 17:14:13 -0700247 canvas.drawWebViewFunctor(functor);
John Reckcd1c3eb2016-04-14 10:38:54 -0700248 });
Alec Mourie5792782024-07-18 03:59:51 +0000249 counts = TestUtils::copyCountsForFunctor(functor);
John Reckaa4c9822020-06-25 17:14:13 -0700250 EXPECT_EQ(1, counts.sync);
251 EXPECT_EQ(0, counts.destroyed);
John Reckcd1c3eb2016-04-14 10:38:54 -0700252
John Reckaa4c9822020-06-25 17:14:13 -0700253 TestUtils::runOnRenderThreadUnmanaged([&] (RenderThread&) {
254 TestUtils::syncHierarchyPropertiesAndDisplayList(node);
255 });
Alec Mourie5792782024-07-18 03:59:51 +0000256 counts = TestUtils::copyCountsForFunctor(functor);
John Reckaa4c9822020-06-25 17:14:13 -0700257 EXPECT_EQ(2, counts.sync);
258 EXPECT_EQ(0, counts.destroyed);
259
260 WebViewFunctor_release(functor);
261 EXPECT_EQ(2, counts.sync);
262 EXPECT_EQ(0, counts.destroyed);
John Reckcd1c3eb2016-04-14 10:38:54 -0700263
Stan Iliev06152cd2016-07-27 17:55:43 -0400264 TestUtils::recordNode(*node, [](Canvas& canvas) {});
John Reckaa4c9822020-06-25 17:14:13 -0700265 TestUtils::runOnRenderThreadUnmanaged([&] (RenderThread&) {
266 TestUtils::syncHierarchyPropertiesAndDisplayList(node);
267 });
John Reck53eaccb2020-11-24 13:35:45 -0500268 // Fence on any remaining post'd work
269 TestUtils::runOnRenderThreadUnmanaged([] (RenderThread&) {});
Alec Mourie5792782024-07-18 03:59:51 +0000270 counts = TestUtils::copyCountsForFunctor(functor);
John Reckaa4c9822020-06-25 17:14:13 -0700271 EXPECT_EQ(2, counts.sync);
272 EXPECT_EQ(1, counts.destroyed);
John Reckcd1c3eb2016-04-14 10:38:54 -0700273}
Doris Liua7952b32016-06-13 14:49:26 -0700274
275RENDERTHREAD_TEST(RenderNode, prepareTree_nullableDisplayList) {
Derek Sollenberger56ad6ec2016-07-22 12:13:32 -0400276 auto rootNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
Doris Liua7952b32016-06-13 14:49:26 -0700277 ContextFactory contextFactory;
John Reck1bcacfd2017-11-03 10:12:19 -0700278 std::unique_ptr<CanvasContext> canvasContext(
Matt Buckleye9023cf2022-11-23 22:39:25 +0000279 CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory, 0, 0));
Stan Iliev03de0742016-07-07 12:35:54 -0400280 TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
Doris Liua7952b32016-06-13 14:49:26 -0700281 DamageAccumulator damageAccumulator;
282 info.damageAccumulator = &damageAccumulator;
Doris Liua7952b32016-06-13 14:49:26 -0700283
284 {
John Reck1bcacfd2017-11-03 10:12:19 -0700285 auto nonNullDLNode =
286 TestUtils::createNode(0, 0, 200, 400, [](RenderProperties& props, Canvas& canvas) {
287 canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
288 });
Doris Liua7952b32016-06-13 14:49:26 -0700289 TestUtils::syncHierarchyPropertiesAndDisplayList(nonNullDLNode);
290 EXPECT_TRUE(nonNullDLNode->getDisplayList());
291 nonNullDLNode->prepareTree(info);
292 }
293
294 {
295 auto nullDLNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
296 TestUtils::syncHierarchyPropertiesAndDisplayList(nullDLNode);
297 EXPECT_FALSE(nullDLNode->getDisplayList());
298 nullDLNode->prepareTree(info);
299 }
300
John Reck2de950d2017-01-25 10:58:30 -0800301 canvasContext->destroy();
Doris Liua7952b32016-06-13 14:49:26 -0700302}
Doris Liu5876e7d2016-08-02 17:28:30 -0700303
John Reck283bb462018-12-13 16:40:14 -0800304// TODO: Is this supposed to work in SkiaGL/SkiaVK?
305RENDERTHREAD_TEST(DISABLED_RenderNode, prepareTree_HwLayer_AVD_enqueueDamage) {
Doris Liu5876e7d2016-08-02 17:28:30 -0700306 VectorDrawable::Group* group = new VectorDrawable::Group();
Greg Daniel98c78dad2017-01-04 14:45:56 -0500307 sp<VectorDrawableRoot> vectorDrawable(new VectorDrawableRoot(group));
308
John Reck1bcacfd2017-11-03 10:12:19 -0700309 auto rootNode =
310 TestUtils::createNode(0, 0, 200, 400, [&](RenderProperties& props, Canvas& canvas) {
311 canvas.drawVectorDrawable(vectorDrawable.get());
312 });
Doris Liu5876e7d2016-08-02 17:28:30 -0700313 ContextFactory contextFactory;
John Reck1bcacfd2017-11-03 10:12:19 -0700314 std::unique_ptr<CanvasContext> canvasContext(
Matt Buckleye9023cf2022-11-23 22:39:25 +0000315 CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory, 0, 0));
Peiyong Lin3bff1352018-12-11 07:56:07 -0800316 canvasContext->setSurface(nullptr);
Doris Liu5876e7d2016-08-02 17:28:30 -0700317 TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
318 DamageAccumulator damageAccumulator;
319 LayerUpdateQueue layerUpdateQueue;
320 info.damageAccumulator = &damageAccumulator;
321 info.layerUpdateQueue = &layerUpdateQueue;
Doris Liu5876e7d2016-08-02 17:28:30 -0700322
323 // Put node on HW layer
324 rootNode->mutateStagingProperties().mutateLayerProperties().setType(LayerType::RenderLayer);
325
326 TestUtils::syncHierarchyPropertiesAndDisplayList(rootNode);
327 rootNode->prepareTree(info);
328
329 // Check that the VD is in the dislay list, and the layer update queue contains the correct
330 // damage rect.
John Reckbe671952021-01-13 22:39:32 -0500331 EXPECT_TRUE(rootNode->getDisplayList().hasVectorDrawables());
John Reck8e539ca2018-11-15 15:21:29 -0800332 ASSERT_FALSE(info.layerUpdateQueue->entries().empty());
John Reckfc29f7acd2017-03-02 13:23:16 -0800333 EXPECT_EQ(rootNode.get(), info.layerUpdateQueue->entries().at(0).renderNode.get());
Doris Liu5876e7d2016-08-02 17:28:30 -0700334 EXPECT_EQ(uirenderer::Rect(0, 0, 200, 400), info.layerUpdateQueue->entries().at(0).damage);
John Reck2de950d2017-01-25 10:58:30 -0800335 canvasContext->destroy();
Doris Liu5876e7d2016-08-02 17:28:30 -0700336}
Tyler Freemane0faa692023-11-16 00:48:54 +0000337
338TEST(RenderNode, hasNoFill) {
339 auto rootNode =
340 TestUtils::createNode(0, 0, 200, 400, [](RenderProperties& props, Canvas& canvas) {
341 Paint paint;
342 paint.setStyle(SkPaint::Style::kStroke_Style);
343 canvas.drawRect(10, 10, 100, 100, paint);
344 });
345
346 TestUtils::syncHierarchyPropertiesAndDisplayList(rootNode);
347
348 EXPECT_FALSE(rootNode.get()->getDisplayList().hasFill());
349 EXPECT_FALSE(rootNode.get()->getDisplayList().hasText());
350}
351
352TEST(RenderNode, hasFill) {
353 auto rootNode =
354 TestUtils::createNode(0, 0, 200, 400, [](RenderProperties& props, Canvas& canvas) {
355 Paint paint;
356 paint.setStyle(SkPaint::kStrokeAndFill_Style);
357 canvas.drawRect(10, 10, 100, 100, paint);
358 });
359
360 TestUtils::syncHierarchyPropertiesAndDisplayList(rootNode);
361
362 EXPECT_TRUE(rootNode.get()->getDisplayList().hasFill());
363 EXPECT_FALSE(rootNode.get()->getDisplayList().hasText());
364}