OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "cc/surfaces/surface_manager.h" | 5 #include "cc/surfaces/surface_manager.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <queue> | 10 #include <queue> |
11 #include <utility> | 11 #include <utility> |
12 | 12 |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "cc/surfaces/direct_surface_reference_factory.h" | 14 #include "cc/surfaces/direct_surface_reference_factory.h" |
15 #include "cc/surfaces/surface.h" | 15 #include "cc/surfaces/surface.h" |
16 #include "cc/surfaces/surface_factory_client.h" | 16 #include "cc/surfaces/surface_factory_client.h" |
17 #include "cc/surfaces/surface_id_allocator.h" | 17 #include "cc/surfaces/surface_id_allocator.h" |
18 #include "cc/surfaces/surface_info.h" | 18 #include "cc/surfaces/surface_info.h" |
19 | 19 |
20 #if DCHECK_IS_ON() | 20 #if DCHECK_IS_ON() |
21 #include <sstream> | 21 #include <sstream> |
22 #endif | 22 #endif |
23 | 23 |
24 namespace cc { | 24 namespace cc { |
25 | 25 |
26 SurfaceManager::FrameSinkSourceMapping::FrameSinkSourceMapping() | |
27 : client(nullptr), source(nullptr) {} | |
28 | |
29 SurfaceManager::FrameSinkSourceMapping::FrameSinkSourceMapping( | |
30 const FrameSinkSourceMapping& other) = default; | |
31 | |
32 SurfaceManager::FrameSinkSourceMapping::~FrameSinkSourceMapping() { | |
33 DCHECK(is_empty()) << "client: " << client | |
34 << ", children: " << children.size(); | |
35 } | |
36 | |
37 SurfaceManager::SurfaceManager(LifetimeType lifetime_type) | 26 SurfaceManager::SurfaceManager(LifetimeType lifetime_type) |
38 : lifetime_type_(lifetime_type), | 27 : lifetime_type_(lifetime_type), |
39 root_surface_id_(FrameSinkId(0u, 0u), | 28 root_surface_id_(FrameSinkId(0u, 0u), |
40 LocalSurfaceId(1u, base::UnguessableToken::Create())), | 29 LocalSurfaceId(1u, base::UnguessableToken::Create())), |
41 weak_factory_(this) { | 30 weak_factory_(this) { |
42 thread_checker_.DetachFromThread(); | 31 thread_checker_.DetachFromThread(); |
43 reference_factory_ = | 32 reference_factory_ = |
44 new DirectSurfaceReferenceFactory(weak_factory_.GetWeakPtr()); | 33 new DirectSurfaceReferenceFactory(weak_factory_.GetWeakPtr()); |
45 } | 34 } |
46 | 35 |
(...skipping 11 matching lines...) Expand all Loading... | |
58 } | 47 } |
59 GarbageCollectSurfaces(); | 48 GarbageCollectSurfaces(); |
60 } | 49 } |
61 | 50 |
62 for (SurfaceDestroyList::iterator it = surfaces_to_destroy_.begin(); | 51 for (SurfaceDestroyList::iterator it = surfaces_to_destroy_.begin(); |
63 it != surfaces_to_destroy_.end(); | 52 it != surfaces_to_destroy_.end(); |
64 ++it) { | 53 ++it) { |
65 DeregisterSurface((*it)->surface_id()); | 54 DeregisterSurface((*it)->surface_id()); |
66 } | 55 } |
67 surfaces_to_destroy_.clear(); | 56 surfaces_to_destroy_.clear(); |
68 | |
69 // All hierarchies, sources, and surface factory clients should be | |
70 // unregistered prior to SurfaceManager destruction. | |
71 DCHECK_EQ(frame_sink_source_map_.size(), 0u); | |
72 DCHECK_EQ(registered_sources_.size(), 0u); | |
73 } | 57 } |
74 | 58 |
75 #if DCHECK_IS_ON() | 59 #if DCHECK_IS_ON() |
76 std::string SurfaceManager::SurfaceReferencesToString() { | 60 std::string SurfaceManager::SurfaceReferencesToString() { |
77 std::stringstream str; | 61 std::stringstream str; |
78 SurfaceReferencesToStringImpl(root_surface_id_, "", &str); | 62 SurfaceReferencesToStringImpl(root_surface_id_, "", &str); |
79 return str.str(); | 63 return str.str(); |
80 } | 64 } |
81 #endif | 65 #endif |
82 | 66 |
(...skipping 29 matching lines...) Expand all Loading... | |
112 surface->AddDestructionDependency(sequence); | 96 surface->AddDestructionDependency(sequence); |
113 } | 97 } |
114 | 98 |
115 void SurfaceManager::SatisfySequence(const SurfaceSequence& sequence) { | 99 void SurfaceManager::SatisfySequence(const SurfaceSequence& sequence) { |
116 DCHECK(thread_checker_.CalledOnValidThread()); | 100 DCHECK(thread_checker_.CalledOnValidThread()); |
117 DCHECK_EQ(lifetime_type_, LifetimeType::SEQUENCES); | 101 DCHECK_EQ(lifetime_type_, LifetimeType::SEQUENCES); |
118 satisfied_sequences_.insert(sequence); | 102 satisfied_sequences_.insert(sequence); |
119 GarbageCollectSurfaces(); | 103 GarbageCollectSurfaces(); |
120 } | 104 } |
121 | 105 |
122 void SurfaceManager::RegisterFrameSinkId(const FrameSinkId& frame_sink_id) { | |
123 bool inserted = valid_frame_sink_ids_.insert(frame_sink_id).second; | |
124 DCHECK(inserted); | |
125 } | |
126 | |
127 void SurfaceManager::InvalidateFrameSinkId(const FrameSinkId& frame_sink_id) { | |
128 valid_frame_sink_ids_.erase(frame_sink_id); | |
129 GarbageCollectSurfaces(); | |
130 } | |
131 | |
132 const SurfaceId& SurfaceManager::GetRootSurfaceId() const { | 106 const SurfaceId& SurfaceManager::GetRootSurfaceId() const { |
133 return root_surface_id_; | 107 return root_surface_id_; |
134 } | 108 } |
135 | 109 |
136 void SurfaceManager::AddSurfaceReference(const SurfaceId& parent_id, | 110 void SurfaceManager::AddSurfaceReference(const SurfaceId& parent_id, |
137 const SurfaceId& child_id) { | 111 const SurfaceId& child_id) { |
138 DCHECK(thread_checker_.CalledOnValidThread()); | 112 DCHECK(thread_checker_.CalledOnValidThread()); |
139 DCHECK_EQ(lifetime_type_, LifetimeType::REFERENCES); | 113 DCHECK_EQ(lifetime_type_, LifetimeType::REFERENCES); |
140 | 114 |
141 // Check some conditions that should never happen. We don't want to crash on | 115 // Check some conditions that should never happen. We don't want to crash on |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
295 // TODO(jbauman): Reduce the amount of work when nothing needs to be | 269 // TODO(jbauman): Reduce the amount of work when nothing needs to be |
296 // destroyed. | 270 // destroyed. |
297 std::vector<SurfaceId> live_surfaces; | 271 std::vector<SurfaceId> live_surfaces; |
298 std::unordered_set<SurfaceId, SurfaceIdHash> live_surfaces_set; | 272 std::unordered_set<SurfaceId, SurfaceIdHash> live_surfaces_set; |
299 | 273 |
300 // GC roots are surfaces that have not been destroyed, or have not had all | 274 // GC roots are surfaces that have not been destroyed, or have not had all |
301 // their destruction dependencies satisfied. | 275 // their destruction dependencies satisfied. |
302 for (auto& map_entry : surface_map_) { | 276 for (auto& map_entry : surface_map_) { |
303 const SurfaceId& surface_id = map_entry.first; | 277 const SurfaceId& surface_id = map_entry.first; |
304 Surface* surface = map_entry.second; | 278 Surface* surface = map_entry.second; |
305 surface->SatisfyDestructionDependencies(&satisfied_sequences_, | 279 // TODO(kavithadevara): commented out following bcz of moving frame_sink_ids |
Fady Samuel
2017/02/12 19:04:07
Can you restore this change?
k.devara
2017/02/13 07:00:52
I was trying to avoid having to expose valid_frame
| |
306 &valid_frame_sink_ids_); | 280 // management to framesink_manager.cc - this whole function should go away |
281 // when Sequences are removed | |
282 // surface->SatisfyDestructionDependencies(&satisfied_sequences_, | |
283 // &valid_frame_sink_ids_); | |
307 | 284 |
308 if (!surface->destroyed() || surface->GetDestructionDependencyCount() > 0) { | 285 if (!surface->destroyed() || surface->GetDestructionDependencyCount() > 0) { |
309 live_surfaces_set.insert(surface_id); | 286 live_surfaces_set.insert(surface_id); |
310 live_surfaces.push_back(surface_id); | 287 live_surfaces.push_back(surface_id); |
311 } | 288 } |
312 } | 289 } |
313 | 290 |
314 // Mark all surfaces reachable from live surfaces by adding them to | 291 // Mark all surfaces reachable from live surfaces by adding them to |
315 // live_surfaces and live_surfaces_set. | 292 // live_surfaces and live_surfaces_set. |
316 for (size_t i = 0; i < live_surfaces.size(); i++) { | 293 for (size_t i = 0; i < live_surfaces.size(); i++) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
355 | 332 |
356 // Remove all reference from parent surface to |surface_id|. | 333 // Remove all reference from parent surface to |surface_id|. |
357 iter = child_to_parent_refs_.find(surface_id); | 334 iter = child_to_parent_refs_.find(surface_id); |
358 if (iter != child_to_parent_refs_.end()) { | 335 if (iter != child_to_parent_refs_.end()) { |
359 for (const SurfaceId& parent_id : iter->second) | 336 for (const SurfaceId& parent_id : iter->second) |
360 parent_to_child_refs_[parent_id].erase(surface_id); | 337 parent_to_child_refs_[parent_id].erase(surface_id); |
361 child_to_parent_refs_.erase(iter); | 338 child_to_parent_refs_.erase(iter); |
362 } | 339 } |
363 } | 340 } |
364 | 341 |
365 void SurfaceManager::RegisterSurfaceFactoryClient( | |
366 const FrameSinkId& frame_sink_id, | |
367 SurfaceFactoryClient* client) { | |
368 DCHECK(client); | |
369 DCHECK_EQ(valid_frame_sink_ids_.count(frame_sink_id), 1u); | |
370 | |
371 // Will create a new FrameSinkSourceMapping for |frame_sink_id| if necessary. | |
372 FrameSinkSourceMapping& frame_sink_source = | |
373 frame_sink_source_map_[frame_sink_id]; | |
374 DCHECK(!frame_sink_source.client); | |
375 frame_sink_source.client = client; | |
376 | |
377 // Propagate any previously set sources to the new client. | |
378 if (frame_sink_source.source) | |
379 client->SetBeginFrameSource(frame_sink_source.source); | |
380 } | |
381 | |
382 void SurfaceManager::UnregisterSurfaceFactoryClient( | |
383 const FrameSinkId& frame_sink_id) { | |
384 DCHECK_EQ(valid_frame_sink_ids_.count(frame_sink_id), 1u); | |
385 DCHECK_EQ(frame_sink_source_map_.count(frame_sink_id), 1u); | |
386 | |
387 auto iter = frame_sink_source_map_.find(frame_sink_id); | |
388 if (iter->second.source) | |
389 iter->second.client->SetBeginFrameSource(nullptr); | |
390 iter->second.client = nullptr; | |
391 | |
392 // The SurfaceFactoryClient and hierarchy can be registered/unregistered | |
393 // in either order, so empty namespace_client_map entries need to be | |
394 // checked when removing either clients or relationships. | |
395 if (iter->second.is_empty()) | |
396 frame_sink_source_map_.erase(iter); | |
397 } | |
398 | |
399 void SurfaceManager::RegisterBeginFrameSource( | |
400 BeginFrameSource* source, | |
401 const FrameSinkId& frame_sink_id) { | |
402 DCHECK(source); | |
403 DCHECK_EQ(registered_sources_.count(source), 0u); | |
404 DCHECK_EQ(valid_frame_sink_ids_.count(frame_sink_id), 1u); | |
405 | |
406 registered_sources_[source] = frame_sink_id; | |
407 RecursivelyAttachBeginFrameSource(frame_sink_id, source); | |
408 } | |
409 | |
410 void SurfaceManager::UnregisterBeginFrameSource(BeginFrameSource* source) { | |
411 DCHECK(source); | |
412 DCHECK_EQ(registered_sources_.count(source), 1u); | |
413 | |
414 FrameSinkId frame_sink_id = registered_sources_[source]; | |
415 registered_sources_.erase(source); | |
416 | |
417 if (frame_sink_source_map_.count(frame_sink_id) == 0u) | |
418 return; | |
419 | |
420 // TODO(enne): these walks could be done in one step. | |
421 // Remove this begin frame source from its subtree. | |
422 RecursivelyDetachBeginFrameSource(frame_sink_id, source); | |
423 // Then flush every remaining registered source to fix any sources that | |
424 // became null because of the previous step but that have an alternative. | |
425 for (auto source_iter : registered_sources_) | |
426 RecursivelyAttachBeginFrameSource(source_iter.second, source_iter.first); | |
427 } | |
428 | |
429 void SurfaceManager::RecursivelyAttachBeginFrameSource( | |
430 const FrameSinkId& frame_sink_id, | |
431 BeginFrameSource* source) { | |
432 FrameSinkSourceMapping& mapping = frame_sink_source_map_[frame_sink_id]; | |
433 if (!mapping.source) { | |
434 mapping.source = source; | |
435 if (mapping.client) | |
436 mapping.client->SetBeginFrameSource(source); | |
437 } | |
438 for (size_t i = 0; i < mapping.children.size(); ++i) | |
439 RecursivelyAttachBeginFrameSource(mapping.children[i], source); | |
440 } | |
441 | |
442 void SurfaceManager::RecursivelyDetachBeginFrameSource( | |
443 const FrameSinkId& frame_sink_id, | |
444 BeginFrameSource* source) { | |
445 auto iter = frame_sink_source_map_.find(frame_sink_id); | |
446 if (iter == frame_sink_source_map_.end()) | |
447 return; | |
448 if (iter->second.source == source) { | |
449 iter->second.source = nullptr; | |
450 if (iter->second.client) | |
451 iter->second.client->SetBeginFrameSource(nullptr); | |
452 } | |
453 | |
454 if (iter->second.is_empty()) { | |
455 frame_sink_source_map_.erase(iter); | |
456 return; | |
457 } | |
458 | |
459 std::vector<FrameSinkId>& children = iter->second.children; | |
460 for (size_t i = 0; i < children.size(); ++i) { | |
461 RecursivelyDetachBeginFrameSource(children[i], source); | |
462 } | |
463 } | |
464 | |
465 bool SurfaceManager::ChildContains( | |
466 const FrameSinkId& child_frame_sink_id, | |
467 const FrameSinkId& search_frame_sink_id) const { | |
468 auto iter = frame_sink_source_map_.find(child_frame_sink_id); | |
469 if (iter == frame_sink_source_map_.end()) | |
470 return false; | |
471 | |
472 const std::vector<FrameSinkId>& children = iter->second.children; | |
473 for (size_t i = 0; i < children.size(); ++i) { | |
474 if (children[i] == search_frame_sink_id) | |
475 return true; | |
476 if (ChildContains(children[i], search_frame_sink_id)) | |
477 return true; | |
478 } | |
479 return false; | |
480 } | |
481 | |
482 void SurfaceManager::RegisterFrameSinkHierarchy( | |
483 const FrameSinkId& parent_frame_sink_id, | |
484 const FrameSinkId& child_frame_sink_id) { | |
485 DCHECK_EQ(valid_frame_sink_ids_.count(parent_frame_sink_id), 1u); | |
486 DCHECK_EQ(valid_frame_sink_ids_.count(child_frame_sink_id), 1u); | |
487 | |
488 // If it's possible to reach the parent through the child's descendant chain, | |
489 // then this will create an infinite loop. Might as well just crash here. | |
490 CHECK(!ChildContains(child_frame_sink_id, parent_frame_sink_id)); | |
491 | |
492 std::vector<FrameSinkId>& children = | |
493 frame_sink_source_map_[parent_frame_sink_id].children; | |
494 for (size_t i = 0; i < children.size(); ++i) | |
495 DCHECK(children[i] != child_frame_sink_id); | |
496 children.push_back(child_frame_sink_id); | |
497 | |
498 // If the parent has no source, then attaching it to this child will | |
499 // not change any downstream sources. | |
500 BeginFrameSource* parent_source = | |
501 frame_sink_source_map_[parent_frame_sink_id].source; | |
502 if (!parent_source) | |
503 return; | |
504 | |
505 DCHECK_EQ(registered_sources_.count(parent_source), 1u); | |
506 RecursivelyAttachBeginFrameSource(child_frame_sink_id, parent_source); | |
507 } | |
508 | |
509 void SurfaceManager::UnregisterFrameSinkHierarchy( | |
510 const FrameSinkId& parent_frame_sink_id, | |
511 const FrameSinkId& child_frame_sink_id) { | |
512 // Deliberately do not check validity of either parent or child namespace | |
513 // here. They were valid during the registration, so were valid at some | |
514 // point in time. This makes it possible to invalidate parent and child | |
515 // namespaces independently of each other and not have an ordering dependency | |
516 // of unregistering the hierarchy first before either of them. | |
517 DCHECK_EQ(frame_sink_source_map_.count(parent_frame_sink_id), 1u); | |
518 | |
519 auto iter = frame_sink_source_map_.find(parent_frame_sink_id); | |
520 | |
521 std::vector<FrameSinkId>& children = iter->second.children; | |
522 bool found_child = false; | |
523 for (size_t i = 0; i < children.size(); ++i) { | |
524 if (children[i] == child_frame_sink_id) { | |
525 found_child = true; | |
526 children[i] = children.back(); | |
527 children.resize(children.size() - 1); | |
528 break; | |
529 } | |
530 } | |
531 DCHECK(found_child); | |
532 | |
533 // The SurfaceFactoryClient and hierarchy can be registered/unregistered | |
534 // in either order, so empty namespace_client_map entries need to be | |
535 // checked when removing either clients or relationships. | |
536 if (iter->second.is_empty()) { | |
537 frame_sink_source_map_.erase(iter); | |
538 return; | |
539 } | |
540 | |
541 // If the parent does not have a begin frame source, then disconnecting it | |
542 // will not change any of its children. | |
543 BeginFrameSource* parent_source = iter->second.source; | |
544 if (!parent_source) | |
545 return; | |
546 | |
547 // TODO(enne): these walks could be done in one step. | |
548 RecursivelyDetachBeginFrameSource(child_frame_sink_id, parent_source); | |
549 for (auto source_iter : registered_sources_) | |
550 RecursivelyAttachBeginFrameSource(source_iter.second, source_iter.first); | |
551 } | |
552 | |
553 Surface* SurfaceManager::GetSurfaceForId(const SurfaceId& surface_id) { | 342 Surface* SurfaceManager::GetSurfaceForId(const SurfaceId& surface_id) { |
554 DCHECK(thread_checker_.CalledOnValidThread()); | 343 DCHECK(thread_checker_.CalledOnValidThread()); |
555 SurfaceMap::iterator it = surface_map_.find(surface_id); | 344 SurfaceMap::iterator it = surface_map_.find(surface_id); |
556 if (it == surface_map_.end()) | 345 if (it == surface_map_.end()) |
557 return nullptr; | 346 return nullptr; |
558 return it->second; | 347 return it->second; |
559 } | 348 } |
560 | 349 |
561 bool SurfaceManager::SurfaceModified(const SurfaceId& surface_id) { | 350 bool SurfaceManager::SurfaceModified(const SurfaceId& surface_id) { |
562 CHECK(thread_checker_.CalledOnValidThread()); | 351 CHECK(thread_checker_.CalledOnValidThread()); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
614 std::vector<SurfaceId> children(iter->second.begin(), iter->second.end()); | 403 std::vector<SurfaceId> children(iter->second.begin(), iter->second.end()); |
615 std::sort(children.begin(), children.end()); | 404 std::sort(children.begin(), children.end()); |
616 | 405 |
617 for (const SurfaceId& child_id : children) | 406 for (const SurfaceId& child_id : children) |
618 SurfaceReferencesToStringImpl(child_id, indent + " ", str); | 407 SurfaceReferencesToStringImpl(child_id, indent + " ", str); |
619 } | 408 } |
620 } | 409 } |
621 #endif // DCHECK_IS_ON() | 410 #endif // DCHECK_IS_ON() |
622 | 411 |
623 } // namespace cc | 412 } // namespace cc |
OLD | NEW |