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

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

Issue 2638833002: Moving temporary reference logic to SurfaceManager (Closed)
Patch Set: c Created 3 years, 11 months 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
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <stddef.h> 5 #include <stddef.h>
6 6
7 #include <unordered_map> 7 #include <unordered_map>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/memory/ptr_util.h" 10 #include "base/memory/ptr_util.h"
11 #include "cc/surfaces/surface.h" 11 #include "cc/surfaces/surface.h"
12 #include "cc/surfaces/surface_factory.h" 12 #include "cc/surfaces/surface_factory.h"
13 #include "cc/surfaces/surface_factory_client.h" 13 #include "cc/surfaces/surface_factory_client.h"
14 #include "cc/surfaces/surface_id.h" 14 #include "cc/surfaces/surface_id.h"
15 #include "cc/surfaces/surface_info.h"
15 #include "cc/surfaces/surface_manager.h" 16 #include "cc/surfaces/surface_manager.h"
16 #include "cc/surfaces/surface_sequence_generator.h" 17 #include "cc/surfaces/surface_sequence_generator.h"
17 #include "testing/gtest/include/gtest/gtest.h" 18 #include "testing/gtest/include/gtest/gtest.h"
18 namespace cc { 19 namespace cc {
19 namespace {
20 20
21 constexpr FrameSinkId kFrameSink1(1, 0); 21 constexpr FrameSinkId kFrameSink1(1, 0);
22 constexpr FrameSinkId kFrameSink2(2, 0); 22 constexpr FrameSinkId kFrameSink2(2, 0);
23 constexpr FrameSinkId kFrameSink3(3, 0); 23 constexpr FrameSinkId kFrameSink3(3, 0);
24 const LocalFrameId kLocalFrame1(1, base::UnguessableToken::Create()); 24 const LocalFrameId kLocalFrame1(1, base::UnguessableToken::Create());
25 const LocalFrameId kLocalFrame2(2, base::UnguessableToken::Create()); 25 const LocalFrameId kLocalFrame2(2, base::UnguessableToken::Create());
26 26
27 class StubSurfaceFactoryClient : public SurfaceFactoryClient { 27 class StubSurfaceFactoryClient : public SurfaceFactoryClient {
28 public: 28 public:
29 void ReturnResources(const ReturnedResourceArray& resources) override {} 29 void ReturnResources(const ReturnedResourceArray& resources) override {}
30 void SetBeginFrameSource(BeginFrameSource* begin_frame_source) override {} 30 void SetBeginFrameSource(BeginFrameSource* begin_frame_source) override {}
31 }; 31 };
32 32
33 // Tests for reference tracking in SurfaceManager. 33 // Tests for reference tracking in SurfaceManager.
34 class SurfaceManagerRefTest : public testing::Test { 34 class SurfaceManagerRefTest : public testing::Test {
35 public: 35 public:
36 SurfaceManager& manager() { return *manager_; } 36 SurfaceManager& manager() { return *manager_; }
37 37
38 // Creates a new Surface with the provided SurfaceId. Will first create the 38 // Creates a new Surface with the provided SurfaceId. Will first create the
39 // SurfaceFactory for |frame_sink_id| if necessary. 39 // SurfaceFactory for |frame_sink_id| if necessary.
40 SurfaceId CreateSurface(const FrameSinkId& frame_sink_id, 40 SurfaceId CreateSurface(const FrameSinkId& frame_sink_id,
41 const LocalFrameId& local_frame_id) { 41 const LocalFrameId& local_frame_id) {
42 GetFactory(frame_sink_id) 42 GetFactory(frame_sink_id)
43 .SubmitCompositorFrame(local_frame_id, CompositorFrame(), 43 .SubmitCompositorFrame(local_frame_id, CompositorFrame(),
44 SurfaceFactory::DrawCallback()); 44 SurfaceFactory::DrawCallback());
45 return SurfaceId(frame_sink_id, local_frame_id); 45 return SurfaceId(frame_sink_id, local_frame_id);
46 } 46 }
47 47
48 SurfaceId CreateSurface(uint32_t client_id,
kylechar 2017/01/17 15:04:19 This approach won't work after you fix the AddSurf
Saman Sami 2017/01/17 15:32:25 Could you elaborate? This method internally uses t
kylechar 2017/01/17 16:15:35 Oh I missed that it used the method above! That's
49 uint32_t sink_id,
50 uint32_t local_id) {
51 return CreateSurface(
52 FrameSinkId(client_id, sink_id),
53 LocalFrameId(local_id, base::UnguessableToken::Deserialize(0, 1u)));
54 }
55
48 // Destroy Surface with |surface_id|. 56 // Destroy Surface with |surface_id|.
49 void DestroySurface(const SurfaceId& surface_id) { 57 void DestroySurface(const SurfaceId& surface_id) {
50 GetFactory(surface_id.frame_sink_id()).EvictSurface(); 58 GetFactory(surface_id.frame_sink_id()).EvictSurface();
51 } 59 }
52 60
53 protected: 61 protected:
54 SurfaceFactory& GetFactory(const FrameSinkId& frame_sink_id) { 62 SurfaceFactory& GetFactory(const FrameSinkId& frame_sink_id) {
55 auto& factory_ptr = factories_[frame_sink_id]; 63 auto& factory_ptr = factories_[frame_sink_id];
56 if (!factory_ptr) 64 if (!factory_ptr)
57 factory_ptr = base::MakeUnique<SurfaceFactory>(frame_sink_id, 65 factory_ptr = base::MakeUnique<SurfaceFactory>(frame_sink_id,
58 manager_.get(), &client_); 66 manager_.get(), &client_);
59 return *factory_ptr; 67 return *factory_ptr;
60 } 68 }
61 69
62 // testing::Test: 70 // testing::Test:
63 void SetUp() override { 71 void SetUp() override {
64 // Start each test with a fresh SurfaceManager instance. 72 // Start each test with a fresh SurfaceManager instance.
65 manager_ = base::MakeUnique<SurfaceManager>(); 73 manager_ = base::MakeUnique<SurfaceManager>(
74 SurfaceManager::LifetimeType::REFERENCES);
66 } 75 }
67 void TearDown() override { 76 void TearDown() override {
68 for (auto& factory : factories_) 77 for (auto& factory : factories_)
69 factory.second->EvictSurface(); 78 factory.second->EvictSurface();
70 factories_.clear(); 79 factories_.clear();
71 manager_.reset(); 80 manager_.reset();
72 } 81 }
73 82
83 SurfaceManager::SurfaceIdSet refs(SurfaceId surface_id) {
84 return manager().parent_to_child_refs_[surface_id];
85 }
86
87 std::unordered_map<FrameSinkId, std::vector<LocalFrameId>, FrameSinkIdHash>
88 tmp_refs() {
89 return manager().temp_references_;
90 }
91
74 std::unordered_map<FrameSinkId, 92 std::unordered_map<FrameSinkId,
75 std::unique_ptr<SurfaceFactory>, 93 std::unique_ptr<SurfaceFactory>,
76 FrameSinkIdHash> 94 FrameSinkIdHash>
77 factories_; 95 factories_;
78 std::unique_ptr<SurfaceManager> manager_; 96 std::unique_ptr<SurfaceManager> manager_;
79 StubSurfaceFactoryClient client_; 97 StubSurfaceFactoryClient client_;
80 }; 98 };
81 99
82 } // namespace
83
84 TEST_F(SurfaceManagerRefTest, AddReference) { 100 TEST_F(SurfaceManagerRefTest, AddReference) {
85 SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1); 101 SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1);
86 manager().AddSurfaceReference(manager().GetRootSurfaceId(), id1); 102 manager().AddSurfaceReference(manager().GetRootSurfaceId(), id1);
87 103
88 EXPECT_EQ(manager().GetSurfaceReferenceCount(id1), 1u); 104 EXPECT_EQ(manager().GetSurfaceReferenceCount(id1), 1u);
89 EXPECT_EQ(manager().GetReferencedSurfaceCount(id1), 0u); 105 EXPECT_EQ(manager().GetReferencedSurfaceCount(id1), 0u);
90 } 106 }
91 107
92 TEST_F(SurfaceManagerRefTest, AddRemoveReference) { 108 TEST_F(SurfaceManagerRefTest, AddRemoveReference) {
93 SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1); 109 SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1);
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 230
215 manager().RemoveSurfaceReference(manager().GetRootSurfaceId(), id1); 231 manager().RemoveSurfaceReference(manager().GetRootSurfaceId(), id1);
216 232
217 // Removing the reference from the root to id1 should allow all three surfaces 233 // Removing the reference from the root to id1 should allow all three surfaces
218 // to be deleted during GC. 234 // to be deleted during GC.
219 EXPECT_EQ(manager().GetSurfaceForId(id1), nullptr); 235 EXPECT_EQ(manager().GetSurfaceForId(id1), nullptr);
220 EXPECT_EQ(manager().GetSurfaceForId(id2), nullptr); 236 EXPECT_EQ(manager().GetSurfaceForId(id2), nullptr);
221 EXPECT_EQ(manager().GetSurfaceForId(id3), nullptr); 237 EXPECT_EQ(manager().GetSurfaceForId(id3), nullptr);
222 } 238 }
223 239
224 TEST_F(SurfaceManagerRefTest, CheckGCWithSequences) {
225 SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1);
226 SurfaceId id2 = CreateSurface(kFrameSink2, kLocalFrame1);
227
228 manager().AddSurfaceReference(manager().GetRootSurfaceId(), id1);
229 manager().AddSurfaceReference(id1, id2);
230
231 SurfaceId id3 = CreateSurface(kFrameSink3, kLocalFrame1);
232 Surface* surface3 = manager().GetSurfaceForId(id3);
233
234 // Add destruction dependency from |id2| to |id3|.
235 manager().RegisterFrameSinkId(kFrameSink2);
236 SurfaceSequence sequence(kFrameSink2, 1u);
237 surface3->AddDestructionDependency(sequence);
238 EXPECT_EQ(surface3->GetDestructionDependencyCount(), 1u);
239
240 // Surface for |id3| isn't delete yet because it has a valid destruction
241 // dependency from |kFrameSink2|.
242 DestroySurface(id3);
243 EXPECT_NE(manager().GetSurfaceForId(id3), nullptr);
244
245 // Surface for |id2| isn't deleted because it has a reference.
246 DestroySurface(id2);
247 EXPECT_NE(manager().GetSurfaceForId(id2), nullptr);
248
249 // Satisfy destruction dependency on |id3| and delete during GC.
250 manager().SatisfySequence(sequence);
251 EXPECT_EQ(manager().GetSurfaceForId(id3), nullptr);
252
253 // Remove ref on |id2| and delete during GC.
254 manager().RemoveSurfaceReference(id1, id2);
255 EXPECT_EQ(manager().GetSurfaceForId(id2), nullptr);
256 }
257
258 TEST_F(SurfaceManagerRefTest, TryAddReferenceToBadSurface) { 240 TEST_F(SurfaceManagerRefTest, TryAddReferenceToBadSurface) {
259 // Not creating an accompanying Surface and SurfaceFactory. 241 // Not creating an accompanying Surface and SurfaceFactory.
260 SurfaceId id(FrameSinkId(100u, 200u), 242 SurfaceId id(FrameSinkId(100u, 200u),
261 LocalFrameId(1u, base::UnguessableToken::Create())); 243 LocalFrameId(1u, base::UnguessableToken::Create()));
262 244
263 // Adding reference from root to the Surface should do nothing because 245 // Adding reference from root to the Surface should do nothing because
264 // SurfaceManager doesn't know Surface for |id| exists. 246 // SurfaceManager doesn't know Surface for |id| exists.
265 manager().AddSurfaceReference(manager().GetRootSurfaceId(), id); 247 manager().AddSurfaceReference(manager().GetRootSurfaceId(), id);
266 EXPECT_EQ(manager().GetSurfaceReferenceCount(id), 0u); 248 EXPECT_EQ(manager().GetSurfaceReferenceCount(id), 0u);
267 } 249 }
(...skipping 26 matching lines...) Expand all
294 SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1); 276 SurfaceId id1 = CreateSurface(kFrameSink1, kLocalFrame1);
295 SurfaceId id2 = CreateSurface(kFrameSink2, kLocalFrame1); 277 SurfaceId id2 = CreateSurface(kFrameSink2, kLocalFrame1);
296 278
297 // Removing non-existent reference should be ignored. 279 // Removing non-existent reference should be ignored.
298 manager().AddSurfaceReference(id1, id2); 280 manager().AddSurfaceReference(id1, id2);
299 manager().RemoveSurfaceReference(id2, id1); 281 manager().RemoveSurfaceReference(id2, id1);
300 EXPECT_EQ(manager().GetReferencedSurfaceCount(id1), 1u); 282 EXPECT_EQ(manager().GetReferencedSurfaceCount(id1), 1u);
301 EXPECT_EQ(manager().GetSurfaceReferenceCount(id2), 1u); 283 EXPECT_EQ(manager().GetSurfaceReferenceCount(id2), 1u);
302 } 284 }
303 285
286 // Temporary Reference Tests
287
288 TEST_F(SurfaceManagerRefTest, AddSurfaceThenReference) {
289 const SurfaceId surface_id = CreateSurface(2, 1, 1);
290
291 // Temporary reference must be added.
292 EXPECT_EQ(1u, tmp_refs().size());
293 EXPECT_EQ(std::vector<LocalFrameId>{surface_id.local_frame_id()},
294 tmp_refs()[surface_id.frame_sink_id()]);
295 EXPECT_EQ(1u, refs(manager().GetRootSurfaceId()).size());
296 EXPECT_EQ(1u, refs(manager().GetRootSurfaceId()).count(surface_id));
297
298 // Add a real reference to surface_id.
299 const SurfaceId parent_id = CreateSurface(1, 1, 1);
300 manager().AddSurfaceReference(parent_id, surface_id);
301
302 // Real reference is added and temporary reference to surface_id is removed.
303 EXPECT_EQ(1u, tmp_refs().size());
304 EXPECT_EQ(std::vector<LocalFrameId>{parent_id.local_frame_id()},
305 tmp_refs()[parent_id.frame_sink_id()]);
306 EXPECT_EQ(1u, refs(manager().GetRootSurfaceId()).size());
307 EXPECT_EQ(1u, refs(manager().GetRootSurfaceId()).count(parent_id));
308 EXPECT_EQ(1u, refs(parent_id).size());
309 EXPECT_EQ(1u, refs(parent_id).count(surface_id));
310 }
311
312 TEST_F(SurfaceManagerRefTest, AddSurfaceThenRootReference) {
313 const SurfaceId surface_id = CreateSurface(1, 1, 1);
314
315 // Temporary reference should be added.
316 EXPECT_EQ(1u, tmp_refs().size());
317 EXPECT_EQ(std::vector<LocalFrameId>{surface_id.local_frame_id()},
318 tmp_refs()[surface_id.frame_sink_id()]);
319 EXPECT_EQ(1u, refs(manager().GetRootSurfaceId()).size());
320 EXPECT_EQ(1u, refs(manager().GetRootSurfaceId()).count(surface_id));
321
322 // Add a real reference from root to surface_id.
323 manager().AddSurfaceReference(manager().GetRootSurfaceId(), surface_id);
324
325 // Adding real reference doesn't need to change anything in
326 // SurfaceReferenceManager does remove the temporary reference marker.
327 EXPECT_EQ(0u, tmp_refs().size());
328 EXPECT_EQ(1u, refs(manager().GetRootSurfaceId()).size());
329 EXPECT_EQ(1u, refs(manager().GetRootSurfaceId()).count(surface_id));
330 }
331
332 TEST_F(SurfaceManagerRefTest, AddTwoSurfacesThenOneReference) {
333 // Add two surfaces with different FrameSinkIds.
334 const SurfaceId surface_id1 = CreateSurface(2, 1, 1);
335 const SurfaceId surface_id2 = CreateSurface(3, 1, 1);
336
337 // Temporary reference should be added for both surfaces.
338 EXPECT_EQ(2u, tmp_refs().size());
339 EXPECT_EQ(std::vector<LocalFrameId>{surface_id1.local_frame_id()},
340 tmp_refs()[surface_id1.frame_sink_id()]);
341 EXPECT_EQ(std::vector<LocalFrameId>{surface_id2.local_frame_id()},
342 tmp_refs()[surface_id2.frame_sink_id()]);
343 EXPECT_EQ(2u, refs(manager().GetRootSurfaceId()).size());
344 EXPECT_EQ(1u, refs(manager().GetRootSurfaceId()).count(surface_id1));
345 EXPECT_EQ(1u, refs(manager().GetRootSurfaceId()).count(surface_id2));
346
347 // Add a real reference to surface_id1.
348 const SurfaceId parent_id = CreateSurface(1, 1, 1);
349 manager().AddSurfaceReference(parent_id, surface_id1);
350
351 // Real reference is added then temporary reference removed for 2:1:1. There
352 // should still be a temporary reference left to 3:1:1
353 EXPECT_EQ(2u, tmp_refs().size());
354 EXPECT_EQ(std::vector<LocalFrameId>{surface_id2.local_frame_id()},
355 tmp_refs()[surface_id2.frame_sink_id()]);
356 EXPECT_EQ(std::vector<LocalFrameId>{parent_id.local_frame_id()},
357 tmp_refs()[parent_id.frame_sink_id()]);
358 EXPECT_EQ(2u, refs(manager().GetRootSurfaceId()).size());
359 EXPECT_EQ(1u, refs(manager().GetRootSurfaceId()).count(parent_id));
360 EXPECT_EQ(1u, refs(manager().GetRootSurfaceId()).count(surface_id2));
361 EXPECT_EQ(1u, refs(parent_id).size());
362 EXPECT_EQ(1u, refs(parent_id).count(surface_id1));
363 }
364
365 TEST_F(SurfaceManagerRefTest, AddSurfacesSkipReference) {
366 // Add two surfaces that have the same FrameSinkId. This would happen when a
367 // client submits two CFs before parent submits a new CF.
368 const SurfaceId surface_id1 = CreateSurface(2, 1, 1);
369 const SurfaceId surface_id2 = CreateSurface(2, 1, 2);
370
371 // Temporary references should be added for both surfaces.
372 std::vector<LocalFrameId> expected_ids = {surface_id1.local_frame_id(),
373 surface_id2.local_frame_id()};
374 EXPECT_EQ(1u, tmp_refs().size());
375 EXPECT_EQ(expected_ids, tmp_refs()[surface_id1.frame_sink_id()]);
376 EXPECT_EQ(2u, refs(manager().GetRootSurfaceId()).size());
377 EXPECT_EQ(1u, refs(manager().GetRootSurfaceId()).count(surface_id1));
378 EXPECT_EQ(1u, refs(manager().GetRootSurfaceId()).count(surface_id2));
379
380 // Add a reference to the surface with the later LocalFrameId.
381 const SurfaceId parent_id = CreateSurface(1, 1, 1);
382 manager().AddSurfaceReference(parent_id, surface_id2);
383
384 // The real reference should be added for 2:1:2 and both temporary references
385 // should be removed.
386 EXPECT_EQ(1u, tmp_refs().size());
387 EXPECT_EQ(std::vector<LocalFrameId>{parent_id.local_frame_id()},
388 tmp_refs()[parent_id.frame_sink_id()]);
389 EXPECT_EQ(1u, refs(manager().GetRootSurfaceId()).size());
390 EXPECT_EQ(1u, refs(manager().GetRootSurfaceId()).count(parent_id));
391 EXPECT_EQ(1u, refs(parent_id).size());
392 EXPECT_EQ(1u, refs(parent_id).count(surface_id2));
393 }
394
395 TEST_F(SurfaceManagerRefTest, RemoveFirstTempRefOnly) {
396 // Add two surfaces that have the same FrameSinkId. This would happen when a
397 // client submits two CFs before parent submits a new CF.
398 const SurfaceId surface_id1 = CreateSurface(2, 1, 1);
399 const SurfaceId surface_id2 = CreateSurface(2, 1, 2);
400
401 // Temporary references should be added for both surfaces.
402 std::vector<LocalFrameId> expected_ids = {surface_id1.local_frame_id(),
403 surface_id2.local_frame_id()};
404 EXPECT_EQ(1u, tmp_refs().size());
405 EXPECT_EQ(expected_ids, tmp_refs()[surface_id1.frame_sink_id()]);
406 EXPECT_EQ(2u, refs(manager().GetRootSurfaceId()).size());
407 EXPECT_EQ(1u, refs(manager().GetRootSurfaceId()).count(surface_id1));
408 EXPECT_EQ(1u, refs(manager().GetRootSurfaceId()).count(surface_id2));
409
410 // Add a reference to the surface with the earlier LocalFrameId.
411 const SurfaceId parent_id = CreateSurface(1, 1, 1);
412 manager().AddSurfaceReference(parent_id, surface_id1);
413
414 // The real reference should be added for 2:1:1 and temporary reference
415 // should be removed. The temporary reference for 2:1:2 should remain.
416 EXPECT_EQ(2u, tmp_refs().size());
417 EXPECT_EQ(std::vector<LocalFrameId>{surface_id2.local_frame_id()},
418 tmp_refs()[surface_id2.frame_sink_id()]);
419 EXPECT_EQ(std::vector<LocalFrameId>{parent_id.local_frame_id()},
420 tmp_refs()[parent_id.frame_sink_id()]);
421 EXPECT_EQ(2u, refs(manager().GetRootSurfaceId()).size());
422 EXPECT_EQ(1u, refs(manager().GetRootSurfaceId()).count(surface_id2));
423 EXPECT_EQ(1u, refs(manager().GetRootSurfaceId()).count(parent_id));
424 EXPECT_EQ(1u, refs(parent_id).size());
425 EXPECT_EQ(1u, refs(parent_id).count(surface_id1));
426 }
427
304 } // namespace cc 428 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698