blob: 0d90afa06ab44bb2d3bca4b0a24183c72410c469 [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) {
John Reck44b49f02016-03-25 14:29:48 -070044 canvas.drawColor(Color::Red_500, SkXfermode::kSrcOver_Mode);
45 });
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) {
John Reck44b49f02016-03-25 14:29:48 -070057 canvas.drawColor(Color::Amber_500, SkXfermode::kSrcOver_Mode);
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}
John Reckcd1c3eb2016-04-14 10:38:54 -070068
69TEST(RenderNode, releasedCallback) {
70 class DecRefOnReleased : public GlFunctorLifecycleListener {
71 public:
Chih-Hung Hsiehd53e3be2016-05-03 10:02:51 -070072 explicit DecRefOnReleased(int* refcnt) : mRefCnt(refcnt) {}
John Reckcd1c3eb2016-04-14 10:38:54 -070073 void onGlFunctorReleased(Functor* functor) override {
74 *mRefCnt -= 1;
75 }
76 private:
77 int* mRefCnt;
78 };
79
80 int refcnt = 0;
81 sp<DecRefOnReleased> listener(new DecRefOnReleased(&refcnt));
82 Functor noopFunctor;
83
84 auto node = TestUtils::createNode(0, 0, 200, 400,
Stan Iliev06152cd2016-07-27 17:55:43 -040085 [&](RenderProperties& props, Canvas& canvas) {
John Reckcd1c3eb2016-04-14 10:38:54 -070086 refcnt++;
87 canvas.callDrawGLFunction(&noopFunctor, listener.get());
88 });
89 TestUtils::syncHierarchyPropertiesAndDisplayList(node);
90 EXPECT_EQ(1, refcnt);
91
Stan Iliev06152cd2016-07-27 17:55:43 -040092 TestUtils::recordNode(*node, [&](Canvas& canvas) {
John Reckcd1c3eb2016-04-14 10:38:54 -070093 refcnt++;
94 canvas.callDrawGLFunction(&noopFunctor, listener.get());
95 });
96 EXPECT_EQ(2, refcnt);
97
98 TestUtils::syncHierarchyPropertiesAndDisplayList(node);
99 EXPECT_EQ(1, refcnt);
100
Stan Iliev06152cd2016-07-27 17:55:43 -0400101 TestUtils::recordNode(*node, [](Canvas& canvas) {});
John Reckcd1c3eb2016-04-14 10:38:54 -0700102 EXPECT_EQ(1, refcnt);
103 TestUtils::syncHierarchyPropertiesAndDisplayList(node);
104 EXPECT_EQ(0, refcnt);
105}
Doris Liua7952b32016-06-13 14:49:26 -0700106
107RENDERTHREAD_TEST(RenderNode, prepareTree_nullableDisplayList) {
Derek Sollenberger56ad6ec2016-07-22 12:13:32 -0400108 auto rootNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
Doris Liua7952b32016-06-13 14:49:26 -0700109 ContextFactory contextFactory;
Stan Iliev03de0742016-07-07 12:35:54 -0400110 std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
Derek Sollenberger56ad6ec2016-07-22 12:13:32 -0400111 renderThread, false, rootNode.get(), &contextFactory));
Stan Iliev03de0742016-07-07 12:35:54 -0400112 TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
Doris Liua7952b32016-06-13 14:49:26 -0700113 DamageAccumulator damageAccumulator;
114 info.damageAccumulator = &damageAccumulator;
115 info.observer = nullptr;
116
117 {
118 auto nonNullDLNode = TestUtils::createNode(0, 0, 200, 400,
Stan Iliev06152cd2016-07-27 17:55:43 -0400119 [](RenderProperties& props, Canvas& canvas) {
Doris Liua7952b32016-06-13 14:49:26 -0700120 canvas.drawColor(Color::Red_500, SkXfermode::kSrcOver_Mode);
121 });
122 TestUtils::syncHierarchyPropertiesAndDisplayList(nonNullDLNode);
123 EXPECT_TRUE(nonNullDLNode->getDisplayList());
124 nonNullDLNode->prepareTree(info);
125 }
126
127 {
128 auto nullDLNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
129 TestUtils::syncHierarchyPropertiesAndDisplayList(nullDLNode);
130 EXPECT_FALSE(nullDLNode->getDisplayList());
131 nullDLNode->prepareTree(info);
132 }
133
Stan Iliev03de0742016-07-07 12:35:54 -0400134 canvasContext->destroy(nullptr);
Doris Liua7952b32016-06-13 14:49:26 -0700135}
Doris Liu5876e7d2016-08-02 17:28:30 -0700136
137RENDERTHREAD_TEST(RenderNode, prepareTree_HwLayer_AVD_enqueueDamage) {
138
139 VectorDrawable::Group* group = new VectorDrawable::Group();
140 VectorDrawableRoot* vectorDrawable = new VectorDrawableRoot(group);
141 auto rootNode = TestUtils::createNode(0, 0, 200, 400,
142 [&](RenderProperties& props, Canvas& canvas) {
143 canvas.drawVectorDrawable(vectorDrawable);
144 });
145 ContextFactory contextFactory;
146 std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
147 renderThread, false, rootNode.get(), &contextFactory));
148 TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
149 DamageAccumulator damageAccumulator;
150 LayerUpdateQueue layerUpdateQueue;
151 info.damageAccumulator = &damageAccumulator;
152 info.layerUpdateQueue = &layerUpdateQueue;
153 info.observer = nullptr;
154
155 // Put node on HW layer
156 rootNode->mutateStagingProperties().mutateLayerProperties().setType(LayerType::RenderLayer);
157
158 TestUtils::syncHierarchyPropertiesAndDisplayList(rootNode);
159 rootNode->prepareTree(info);
160
161 // Check that the VD is in the dislay list, and the layer update queue contains the correct
162 // damage rect.
163 EXPECT_FALSE(rootNode->getDisplayList()->getVectorDrawables().empty());
164 EXPECT_FALSE(info.layerUpdateQueue->entries().empty());
165 EXPECT_EQ(rootNode.get(), info.layerUpdateQueue->entries().at(0).renderNode);
166 EXPECT_EQ(uirenderer::Rect(0, 0, 200, 400), info.layerUpdateQueue->entries().at(0).damage);
167
168 delete vectorDrawable;
169 canvasContext->destroy(nullptr);
170}