• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <gtest/gtest.h>
18 #include <VectorDrawable.h>
19 
20 #include "AnimationContext.h"
21 #include "DamageAccumulator.h"
22 #include "IContextFactory.h"
23 #include "pipeline/skia/SkiaDisplayList.h"
24 #include "renderthread/CanvasContext.h"
25 #include "tests/common/TestUtils.h"
26 
27 using namespace android;
28 using namespace android::uirenderer;
29 using namespace android::uirenderer::renderthread;
30 using namespace android::uirenderer::skiapipeline;
31 
TEST(SkiaDisplayList,create)32 TEST(SkiaDisplayList, create) {
33     SkiaDisplayList skiaDL;
34     ASSERT_TRUE(skiaDL.isEmpty());
35     ASSERT_FALSE(skiaDL.mProjectionReceiver);
36 }
37 
TEST(SkiaDisplayList,reset)38 TEST(SkiaDisplayList, reset) {
39     SkiaDisplayList skiaDL;
40 
41     SkCanvas dummyCanvas;
42     RenderNodeDrawable drawable(nullptr, &dummyCanvas);
43     skiaDL.mChildNodes.emplace_back(nullptr, &dummyCanvas);
44     skiaDL.mChildFunctors.emplace_back(nullptr, nullptr, &dummyCanvas);
45     skiaDL.mMutableImages.push_back(nullptr);
46     skiaDL.mVectorDrawables.push_back(nullptr);
47     skiaDL.mDisplayList.drawAnnotation(SkRect::MakeWH(200, 200), "testAnnotation", nullptr);
48     skiaDL.mProjectionReceiver = &drawable;
49 
50     ASSERT_FALSE(skiaDL.mChildNodes.empty());
51     ASSERT_FALSE(skiaDL.mChildFunctors.empty());
52     ASSERT_FALSE(skiaDL.mMutableImages.empty());
53     ASSERT_FALSE(skiaDL.mVectorDrawables.empty());
54     ASSERT_FALSE(skiaDL.isEmpty());
55     ASSERT_TRUE(skiaDL.mProjectionReceiver);
56 
57     skiaDL.reset();
58 
59     ASSERT_TRUE(skiaDL.mChildNodes.empty());
60     ASSERT_TRUE(skiaDL.mChildFunctors.empty());
61     ASSERT_TRUE(skiaDL.mMutableImages.empty());
62     ASSERT_TRUE(skiaDL.mVectorDrawables.empty());
63     ASSERT_TRUE(skiaDL.isEmpty());
64     ASSERT_FALSE(skiaDL.mProjectionReceiver);
65 }
66 
TEST(SkiaDisplayList,reuseDisplayList)67 TEST(SkiaDisplayList, reuseDisplayList) {
68     sp<RenderNode> renderNode = new RenderNode();
69     std::unique_ptr<SkiaDisplayList> availableList;
70 
71     // no list has been attached so it should return a nullptr
72     availableList = renderNode->detachAvailableList();
73     ASSERT_EQ(availableList.get(), nullptr);
74 
75     // attach a displayList for reuse
76     SkiaDisplayList skiaDL;
77     ASSERT_TRUE(skiaDL.reuseDisplayList(renderNode.get(), nullptr));
78 
79     // detach the list that you just attempted to reuse
80     availableList = renderNode->detachAvailableList();
81     ASSERT_EQ(availableList.get(), &skiaDL);
82     availableList.release(); // prevents an invalid free since our DL is stack allocated
83 
84     // after detaching there should return no available list
85     availableList = renderNode->detachAvailableList();
86     ASSERT_EQ(availableList.get(), nullptr);
87 }
88 
TEST(SkiaDisplayList,syncContexts)89 TEST(SkiaDisplayList, syncContexts) {
90     SkiaDisplayList skiaDL;
91 
92     SkCanvas dummyCanvas;
93     TestUtils::MockFunctor functor;
94     skiaDL.mChildFunctors.emplace_back(&functor, nullptr, &dummyCanvas);
95 
96     SkRect bounds = SkRect::MakeWH(200, 200);
97     VectorDrawableRoot vectorDrawable(new VectorDrawable::Group());
98     vectorDrawable.mutateStagingProperties()->setBounds(bounds);
99     skiaDL.mVectorDrawables.push_back(&vectorDrawable);
100 
101     // ensure that the functor and vectorDrawable are properly synced
102     skiaDL.syncContents();
103 
104     ASSERT_EQ(functor.getLastMode(), DrawGlInfo::kModeSync);
105     ASSERT_EQ(vectorDrawable.mutateProperties()->getBounds(), bounds);
106 }
107 
108 class ContextFactory : public IContextFactory {
109 public:
createAnimationContext(renderthread::TimeLord & clock)110     virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) override {
111         return new AnimationContext(clock);
112     }
113 };
114 
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaDisplayList,prepareListAndChildren)115 RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaDisplayList, prepareListAndChildren) {
116     auto rootNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
117     ContextFactory contextFactory;
118     std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create(
119             renderThread, false, rootNode.get(), &contextFactory));
120     TreeInfo info(TreeInfo::MODE_FULL, *canvasContext.get());
121     DamageAccumulator damageAccumulator;
122     info.damageAccumulator = &damageAccumulator;
123 
124     SkiaDisplayList skiaDL;
125 
126     // prepare with a clean VD
127     VectorDrawableRoot cleanVD(new VectorDrawable::Group());
128     skiaDL.mVectorDrawables.push_back(&cleanVD);
129     cleanVD.getBitmapUpdateIfDirty(); // this clears the dirty bit
130 
131     ASSERT_FALSE(cleanVD.isDirty());
132     ASSERT_FALSE(cleanVD.getPropertyChangeWillBeConsumed());
133     TestUtils::MockTreeObserver observer;
134     ASSERT_FALSE(skiaDL.prepareListAndChildren(observer, info, false,
135             [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
136     ASSERT_TRUE(cleanVD.getPropertyChangeWillBeConsumed());
137 
138     // prepare again this time adding a dirty VD
139     VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
140     skiaDL.mVectorDrawables.push_back(&dirtyVD);
141 
142     ASSERT_TRUE(dirtyVD.isDirty());
143     ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
144     ASSERT_TRUE(skiaDL.prepareListAndChildren(observer, info, false,
145             [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
146     ASSERT_TRUE(dirtyVD.getPropertyChangeWillBeConsumed());
147 
148     // prepare again this time adding a RenderNode and a callback
149     sp<RenderNode> renderNode = new RenderNode();
150     TreeInfo* infoPtr = &info;
151     SkCanvas dummyCanvas;
152     skiaDL.mChildNodes.emplace_back(renderNode.get(), &dummyCanvas);
153     bool hasRun = false;
154     ASSERT_TRUE(skiaDL.prepareListAndChildren(observer, info, false,
155             [&hasRun, renderNode, infoPtr](RenderNode* n, TreeObserver& observer, TreeInfo& i, bool r) {
156         hasRun = true;
157         ASSERT_EQ(renderNode.get(), n);
158         ASSERT_EQ(infoPtr, &i);
159         ASSERT_FALSE(r);
160     }));
161     ASSERT_TRUE(hasRun);
162 
163     canvasContext->destroy();
164 }
165 
TEST(SkiaDisplayList,updateChildren)166 TEST(SkiaDisplayList, updateChildren) {
167     SkiaDisplayList skiaDL;
168 
169     sp<RenderNode> renderNode = new RenderNode();
170     SkCanvas dummyCanvas;
171     skiaDL.mChildNodes.emplace_back(renderNode.get(), &dummyCanvas);
172     skiaDL.updateChildren([renderNode](RenderNode* n) {
173         ASSERT_EQ(renderNode.get(), n);
174     });
175 }
176