Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(216)

Side by Side Diff: cc/surfaces/surface_manager_ref_unittest.cc

Issue 2455663003: Add cc::Surface ref counting. (Closed)
Patch Set: More cleanup. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stddef.h>
6
7 #include <unordered_map>
8 #include <vector>
9
10 #include "base/memory/ptr_util.h"
11 #include "cc/surfaces/surface.h"
12 #include "cc/surfaces/surface_factory.h"
13 #include "cc/surfaces/surface_id.h"
14 #include "cc/surfaces/surface_manager.h"
15 #include "cc/surfaces/surface_sequence_generator.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace cc {
19 namespace {
20
21 constexpr FrameSinkId kFrameSink1(1, 0);
22 constexpr FrameSinkId kFrameSink2(2, 0);
23 constexpr FrameSinkId kFrameSink3(3, 0);
24 constexpr LocalFrameId kLocalFrame1(1, 0);
25 constexpr LocalFrameId kLocalFrame2(2, 0);
26
27 // Tests for reference tracking in SurfaceManager.
28 class SurfaceManagerRefTest : public testing::Test {
29 public:
30 SurfaceManager& manager() { return *manager_; }
31
32 // Creates a new Surface with the provided SurfaceId. Will first create the
33 // SurfaceFactory for |frame_sink_id| if necessary.
34 SurfaceId CreateSurface(const FrameSinkId& frame_sink_id,
35 const LocalFrameId& local_frame_id) {
36 GetFactory(frame_sink_id).Create(local_frame_id);
37 return SurfaceId(frame_sink_id, local_frame_id);
38 }
39
40 // Destroy Surface with |surface_id|.
41 void DestroySurface(const SurfaceId& surface_id) {
42 GetFactory(surface_id.frame_sink_id()).Destroy(surface_id.local_frame_id());
43 }
44
45 protected:
46 SurfaceFactory& GetFactory(const FrameSinkId& frame_sink_id) {
47 auto& factory_ptr = factories_[frame_sink_id];
48 if (!factory_ptr)
49 factory_ptr = base::MakeUnique<SurfaceFactory>(frame_sink_id,
50 manager_.get(), nullptr);
51 return *factory_ptr;
52 }
53
54 // testing::Test:
55 void SetUp() override {
56 // Start each test with a fresh SurfaceManager instance.
57 manager_ = base::MakeUnique<SurfaceManager>();
58 }
59 void TearDown() override {
60 factories_.clear();
61 manager_.reset();
62 }
63
64 std::unordered_map<FrameSinkId,
65 std::unique_ptr<SurfaceFactory>,
66 FrameSinkIdHash>
67 factories_;
68 std::unique_ptr<SurfaceManager> manager_;
69 };
70
71 } // namespace
72
73 TEST_F(SurfaceManagerRefTest, AddReference) {
74 SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1);
75 manager().AddSurfaceReference(SurfaceManager::kRootSurfaceId, id1);
76
77 EXPECT_EQ(manager().GetSurfaceReferenceCount(id1), 1u);
78 EXPECT_EQ(manager().GetSurfaceRefereeCount(id1), 0u);
79 }
80
81 TEST_F(SurfaceManagerRefTest, AddRemoveReference) {
82 SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1);
83 SurfaceId id2 = CreateSurface(kFrameSink2, kLocalFrame1);
84 manager().AddSurfaceReference(SurfaceManager::kRootSurfaceId, id1);
85 manager().AddSurfaceReference(id1, id2);
86
87 EXPECT_EQ(manager().GetSurfaceReferenceCount(id1), 1u);
88 EXPECT_EQ(manager().GetSurfaceReferenceCount(id2), 1u);
89 EXPECT_EQ(manager().GetSurfaceRefereeCount(id1), 1u);
90 EXPECT_EQ(manager().GetSurfaceRefereeCount(id2), 0u);
91
92 manager().RemoveSurfaceReference(id1, id2);
93 EXPECT_EQ(manager().GetSurfaceReferenceCount(id1), 1u);
94 EXPECT_EQ(manager().GetSurfaceReferenceCount(id2), 0u);
95 EXPECT_EQ(manager().GetSurfaceRefereeCount(id1), 0u);
96 EXPECT_EQ(manager().GetSurfaceRefereeCount(id2), 0u);
97 }
98
99 TEST_F(SurfaceManagerRefTest, AddRemoveReferenceRecursive) {
100 SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1);
101 SurfaceId id2 = CreateSurface(kFrameSink2, kLocalFrame1);
102 SurfaceId id3 = CreateSurface(kFrameSink3, kLocalFrame1);
103
104 manager().AddSurfaceReference(SurfaceManager::kRootSurfaceId, id1);
105 manager().AddSurfaceReference(id1, id2);
106 manager().AddSurfaceReference(id2, id3);
107 EXPECT_EQ(manager().GetSurfaceReferenceCount(id1), 1u);
108 EXPECT_EQ(manager().GetSurfaceReferenceCount(id2), 1u);
109 EXPECT_EQ(manager().GetSurfaceReferenceCount(id3), 1u);
110 EXPECT_EQ(manager().GetSurfaceRefereeCount(id1), 1u);
111 EXPECT_EQ(manager().GetSurfaceRefereeCount(id2), 1u);
112 EXPECT_EQ(manager().GetSurfaceRefereeCount(id3), 0u);
113
114 // Should remove reference from id1 -> id2 and then since id2 has zero
115 // references all references it holds should be removed.
116 manager().RemoveSurfaceReference(id1, id2);
117 EXPECT_EQ(manager().GetSurfaceReferenceCount(id1), 1u);
118 EXPECT_EQ(manager().GetSurfaceReferenceCount(id2), 0u);
119 EXPECT_EQ(manager().GetSurfaceReferenceCount(id3), 0u);
120 EXPECT_EQ(manager().GetSurfaceRefereeCount(id1), 0u);
121 EXPECT_EQ(manager().GetSurfaceRefereeCount(id2), 0u);
122 EXPECT_EQ(manager().GetSurfaceRefereeCount(id3), 0u);
123 }
124
125 TEST_F(SurfaceManagerRefTest, NewSurfaceFromFrameSink) {
126 SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1);
127 SurfaceId id2 = CreateSurface(kFrameSink2, kLocalFrame1);
128 SurfaceId id3 = CreateSurface(kFrameSink3, kLocalFrame1);
129
130 manager().AddSurfaceReference(SurfaceManager::kRootSurfaceId, id1);
131 manager().AddSurfaceReference(id1, id2);
132 manager().AddSurfaceReference(id2, id3);
133
134 // |kFramesink2| received a CompositorFrame with a new size, so it destroys
135 // |id2| and creates |id2_next|. No reference have been removed yet.
136 DestroySurface(id2);
137 SurfaceId id2_next = CreateSurface(kFrameSink2, kLocalFrame2);
138 EXPECT_NE(manager().GetSurfaceForId(id2), nullptr);
139 EXPECT_NE(manager().GetSurfaceForId(id2_next), nullptr);
140
141 // Add references to and from |id2_next|.
142 manager().AddSurfaceReference(id1, id2_next);
143 manager().AddSurfaceReference(id2_next, id3);
144 EXPECT_EQ(manager().GetSurfaceReferenceCount(id2), 1u);
145 EXPECT_EQ(manager().GetSurfaceReferenceCount(id2_next), 1u);
146 EXPECT_EQ(manager().GetSurfaceReferenceCount(id3), 2u);
147
148 manager().RemoveSurfaceReference(id1, id2);
149 EXPECT_EQ(manager().GetSurfaceReferenceCount(id2), 0u);
150 EXPECT_EQ(manager().GetSurfaceReferenceCount(id2_next), 1u);
151 EXPECT_EQ(manager().GetSurfaceReferenceCount(id3), 1u);
152
153 // |id2| should be deleted during GC but other surfaces shouldn't.
154 EXPECT_EQ(manager().GetSurfaceForId(id2), nullptr);
155 EXPECT_NE(manager().GetSurfaceForId(id2_next), nullptr);
156 EXPECT_NE(manager().GetSurfaceForId(id3), nullptr);
157 }
158
159 TEST_F(SurfaceManagerRefTest, CheckGC) {
160 SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1);
161 SurfaceId id2 = CreateSurface(kFrameSink2, kLocalFrame1);
162
163 manager().AddSurfaceReference(SurfaceManager::kRootSurfaceId, id1);
164 manager().AddSurfaceReference(id1, id2);
165
166 EXPECT_NE(manager().GetSurfaceForId(id1), nullptr);
167 EXPECT_NE(manager().GetSurfaceForId(id2), nullptr);
168
169 // Destroying the surfaces shouldn't delete them yet, since there is still an
170 // active reference on all surfaces.
171 DestroySurface(id1);
172 DestroySurface(id2);
173 EXPECT_NE(manager().GetSurfaceForId(id1), nullptr);
174 EXPECT_NE(manager().GetSurfaceForId(id2), nullptr);
175
176 // Should delete |id2| when the only reference to it is removed.
177 manager().RemoveSurfaceReference(id1, id2);
178 EXPECT_EQ(manager().GetSurfaceForId(id2), nullptr);
179
180 // Should delete |id1| when the only reference to it is removed.
181 manager().RemoveSurfaceReference(SurfaceManager::kRootSurfaceId, id1);
182 EXPECT_EQ(manager().GetSurfaceForId(id1), nullptr);
183 }
184
185 TEST_F(SurfaceManagerRefTest, CheckGCRecusiveFull) {
186 SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1);
187 SurfaceId id2 = CreateSurface(kFrameSink2, kLocalFrame1);
188 SurfaceId id3 = CreateSurface(kFrameSink3, kLocalFrame1);
189
190 manager().AddSurfaceReference(SurfaceManager::kRootSurfaceId, id1);
191 manager().AddSurfaceReference(id1, id2);
192 manager().AddSurfaceReference(id2, id3);
193
194 DestroySurface(id3);
195 DestroySurface(id2);
196 DestroySurface(id1);
197
198 // Destroying the surfaces shouldn't delete them yet, since there is still an
199 // active reference on all surfaces.
200 EXPECT_NE(manager().GetSurfaceForId(id3), nullptr);
201 EXPECT_NE(manager().GetSurfaceForId(id2), nullptr);
202 EXPECT_NE(manager().GetSurfaceForId(id1), nullptr);
203
204 manager().RemoveSurfaceReference(SurfaceManager::kRootSurfaceId, id1);
205
206 // Removing the reference from the root to id1 should allow all three surfaces
207 // to be deleted during GC.
208 EXPECT_EQ(manager().GetSurfaceForId(id1), nullptr);
209 EXPECT_EQ(manager().GetSurfaceForId(id2), nullptr);
210 EXPECT_EQ(manager().GetSurfaceForId(id3), nullptr);
211 }
212
213 TEST_F(SurfaceManagerRefTest, CheckGCWithSequences) {
214 SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1);
215 SurfaceId id2 = CreateSurface(kFrameSink2, kLocalFrame1);
216
217 manager().AddSurfaceReference(SurfaceManager::kRootSurfaceId, id1);
218 manager().AddSurfaceReference(id1, id2);
219
220 SurfaceId id3 = CreateSurface(kFrameSink3, kLocalFrame1);
221 Surface* surface3 = manager().GetSurfaceForId(id3);
222
223 // Add destruction dependency from |id2| to |id3|.
224 manager().RegisterFrameSinkId(kFrameSink2);
225 SurfaceSequence sequence(kFrameSink2, 1u);
226 surface3->AddDestructionDependency(sequence);
227 EXPECT_EQ(surface3->GetDestructionDependencyCount(), 1u);
228
229 // Surface for |id3| isn't delete yet because it has a valid destruction
230 // dependency from |kFrameSink2|
Fady Samuel 2016/11/02 03:10:36 nit: period at the end of the sentence.
kylechar 2016/11/02 13:58:59 Done.
231 DestroySurface(id3);
232 EXPECT_NE(manager().GetSurfaceForId(id3), nullptr);
233
234 // Surface for |id2| isn't deleted because it has a reference.
235 DestroySurface(id2);
236 EXPECT_NE(manager().GetSurfaceForId(id2), nullptr);
237
238 // Satisfy destruction dependency on |id3| and delete during GC.
239 std::vector<uint32_t> satisfied({sequence.sequence});
240 manager().DidSatisfySequences(kFrameSink2, &satisfied);
241 EXPECT_EQ(manager().GetSurfaceForId(id3), nullptr);
242
243 // Remove ref on |id2| and delete during GC.
244 manager().RemoveSurfaceReference(id1, id2);
245 EXPECT_EQ(manager().GetSurfaceForId(id2), nullptr);
246 }
247
248 TEST_F(SurfaceManagerRefTest, TryAddReferenceToBadSurface) {
249 // Not creating an accompanying Surface and SurfaceFactory.
250 SurfaceId id(FrameSinkId(100u, 200u), LocalFrameId(1u, 123123u));
251
252 // Adding reference from root to the Surface should do nothing because
253 // SurfaceManager doesn't know Surface for |id| exists.
254 manager().AddSurfaceReference(SurfaceManager::kRootSurfaceId, id);
255 EXPECT_EQ(manager().GetSurfaceReferenceCount(id), 0u);
256 }
257
258 TEST_F(SurfaceManagerRefTest, TryDoubleAddReference) {
259 SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1);
260 SurfaceId id2 = CreateSurface(kFrameSink2, kLocalFrame1);
261
262 manager().AddSurfaceReference(SurfaceManager::kRootSurfaceId, id1);
263 manager().AddSurfaceReference(id1, id2);
264 EXPECT_EQ(manager().GetSurfaceReferenceCount(id2), 1u);
265 EXPECT_EQ(manager().GetSurfaceRefereeCount(id1), 1u);
266
267 // The second request should be ignored without crashing.
268 manager().AddSurfaceReference(id1, id2);
269 EXPECT_EQ(manager().GetSurfaceReferenceCount(id2), 1u);
270 EXPECT_EQ(manager().GetSurfaceRefereeCount(id1), 1u);
271 }
272
273 TEST_F(SurfaceManagerRefTest, TryAddSelfReference) {
274 SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1);
275
276 // Adding a self reference should be ignored without crashing.
277 manager().AddSurfaceReference(id1, id1);
278 EXPECT_EQ(manager().GetSurfaceReferenceCount(id1), 0u);
279 EXPECT_EQ(manager().GetSurfaceRefereeCount(id1), 0u);
280 }
281
282 TEST_F(SurfaceManagerRefTest, TryRemoveBadReference) {
283 SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1);
284 SurfaceId id2 = CreateSurface(kFrameSink2, kLocalFrame1);
285
286 // Removing non-existent reference should be ignored.
287 manager().AddSurfaceReference(id1, id2);
288 manager().RemoveSurfaceReference(id2, id1);
289 EXPECT_EQ(manager().GetSurfaceRefereeCount(id1), 1u);
290 EXPECT_EQ(manager().GetSurfaceReferenceCount(id2), 1u);
291 }
Fady Samuel 2016/11/02 03:10:36 This is a very comprehensive set of tests! Thanks!
kylechar 2016/11/02 13:58:59 Huh. Interesting. Fixing that would require the GC
292
293 } // namespace cc
OLDNEW
« cc/surfaces/surface_manager.cc ('K') | « cc/surfaces/surface_manager.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698