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/local_surface_id_allocator.h" | 15 #include "cc/surfaces/local_surface_id_allocator.h" |
16 #include "cc/surfaces/surface.h" | 16 #include "cc/surfaces/surface.h" |
17 #include "cc/surfaces/surface_factory_client.h" | 17 #include "cc/surfaces/surface_factory_client.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 : source(nullptr) {} | |
28 | |
29 SurfaceManager::FrameSinkSourceMapping::FrameSinkSourceMapping( | |
30 const FrameSinkSourceMapping& other) = default; | |
31 | |
32 SurfaceManager::FrameSinkSourceMapping::~FrameSinkSourceMapping() { | |
33 } | |
34 | |
35 SurfaceManager::SurfaceManager(LifetimeType lifetime_type) | 26 SurfaceManager::SurfaceManager(LifetimeType lifetime_type) |
36 : lifetime_type_(lifetime_type), | 27 : lifetime_type_(lifetime_type), |
37 root_surface_id_(FrameSinkId(0u, 0u), | 28 root_surface_id_(FrameSinkId(0u, 0u), |
38 LocalSurfaceId(1u, base::UnguessableToken::Create())), | 29 LocalSurfaceId(1u, base::UnguessableToken::Create())), |
39 weak_factory_(this) { | 30 weak_factory_(this) { |
40 thread_checker_.DetachFromThread(); | 31 thread_checker_.DetachFromThread(); |
| 32 framesink_manager_ = new FrameSinkManager(); |
41 reference_factory_ = | 33 reference_factory_ = |
42 new DirectSurfaceReferenceFactory(weak_factory_.GetWeakPtr()); | 34 new DirectSurfaceReferenceFactory(weak_factory_.GetWeakPtr()); |
43 } | 35 } |
44 | 36 |
45 SurfaceManager::~SurfaceManager() { | 37 SurfaceManager::~SurfaceManager() { |
46 DCHECK(thread_checker_.CalledOnValidThread()); | 38 DCHECK(thread_checker_.CalledOnValidThread()); |
47 | 39 |
48 if (using_surface_references()) { | 40 if (using_surface_references()) { |
49 // Remove all temporary references on shutdown. | 41 // Remove all temporary references on shutdown. |
50 temporary_references_.clear(); | 42 temporary_references_.clear(); |
51 temporary_reference_ranges_.clear(); | 43 temporary_reference_ranges_.clear(); |
52 | 44 |
53 GarbageCollectSurfaces(); | 45 GarbageCollectSurfaces(); |
54 } | 46 } |
55 | 47 |
56 for (SurfaceDestroyList::iterator it = surfaces_to_destroy_.begin(); | 48 for (SurfaceDestroyList::iterator it = surfaces_to_destroy_.begin(); |
57 it != surfaces_to_destroy_.end(); | 49 it != surfaces_to_destroy_.end(); |
58 ++it) { | 50 ++it) { |
59 UnregisterSurface((*it)->surface_id()); | 51 UnregisterSurface((*it)->surface_id()); |
60 } | 52 } |
61 surfaces_to_destroy_.clear(); | 53 surfaces_to_destroy_.clear(); |
62 | |
63 // All surface factory clients should be unregistered prior to SurfaceManager | |
64 // destruction. | |
65 DCHECK_EQ(clients_.size(), 0u); | |
66 DCHECK_EQ(registered_sources_.size(), 0u); | |
67 } | 54 } |
68 | 55 |
69 #if DCHECK_IS_ON() | 56 #if DCHECK_IS_ON() |
70 std::string SurfaceManager::SurfaceReferencesToString() { | 57 std::string SurfaceManager::SurfaceReferencesToString() { |
71 std::stringstream str; | 58 std::stringstream str; |
72 SurfaceReferencesToStringImpl(root_surface_id_, "", &str); | 59 SurfaceReferencesToStringImpl(root_surface_id_, "", &str); |
73 // Temporary references will have an asterisk in front of them. | 60 // Temporary references will have an asterisk in front of them. |
74 for (auto& map_entry : temporary_references_) | 61 for (auto& map_entry : temporary_references_) |
75 SurfaceReferencesToStringImpl(map_entry.first, "* ", &str); | 62 SurfaceReferencesToStringImpl(map_entry.first, "* ", &str); |
76 | 63 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 } | 131 } |
145 | 132 |
146 void SurfaceManager::SatisfySequence(const SurfaceSequence& sequence) { | 133 void SurfaceManager::SatisfySequence(const SurfaceSequence& sequence) { |
147 DCHECK(thread_checker_.CalledOnValidThread()); | 134 DCHECK(thread_checker_.CalledOnValidThread()); |
148 DCHECK_EQ(lifetime_type_, LifetimeType::SEQUENCES); | 135 DCHECK_EQ(lifetime_type_, LifetimeType::SEQUENCES); |
149 satisfied_sequences_.insert(sequence); | 136 satisfied_sequences_.insert(sequence); |
150 GarbageCollectSurfaces(); | 137 GarbageCollectSurfaces(); |
151 } | 138 } |
152 | 139 |
153 void SurfaceManager::RegisterFrameSinkId(const FrameSinkId& frame_sink_id) { | 140 void SurfaceManager::RegisterFrameSinkId(const FrameSinkId& frame_sink_id) { |
154 bool inserted = valid_frame_sink_ids_.insert(frame_sink_id).second; | 141 framesink_manager_->RegisterFrameSinkId(frame_sink_id); |
155 DCHECK(inserted); | |
156 } | 142 } |
157 | 143 |
158 void SurfaceManager::InvalidateFrameSinkId(const FrameSinkId& frame_sink_id) { | 144 void SurfaceManager::InvalidateFrameSinkId(const FrameSinkId& frame_sink_id) { |
159 valid_frame_sink_ids_.erase(frame_sink_id); | 145 framesink_manager_->InvalidateFrameSinkId(frame_sink_id); |
160 | 146 |
161 if (using_surface_references()) { | 147 if (using_surface_references()) { |
162 // Remove any temporary references owned by |frame_sink_id|. | 148 // Remove any temporary references owned by |frame_sink_id|. |
163 std::vector<SurfaceId> temp_refs_to_clear; | 149 std::vector<SurfaceId> temp_refs_to_clear; |
164 for (auto& map_entry : temporary_references_) { | 150 for (auto& map_entry : temporary_references_) { |
165 base::Optional<FrameSinkId>& owner = map_entry.second; | 151 base::Optional<FrameSinkId>& owner = map_entry.second; |
166 if (owner.has_value() && owner.value() == frame_sink_id) | 152 if (owner.has_value() && owner.value() == frame_sink_id) |
167 temp_refs_to_clear.push_back(map_entry.first); | 153 temp_refs_to_clear.push_back(map_entry.first); |
168 } | 154 } |
169 | 155 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 // destroyed. | 271 // destroyed. |
286 std::vector<SurfaceId> live_surfaces; | 272 std::vector<SurfaceId> live_surfaces; |
287 std::unordered_set<SurfaceId, SurfaceIdHash> live_surfaces_set; | 273 std::unordered_set<SurfaceId, SurfaceIdHash> live_surfaces_set; |
288 | 274 |
289 // GC roots are surfaces that have not been destroyed, or have not had all | 275 // GC roots are surfaces that have not been destroyed, or have not had all |
290 // their destruction dependencies satisfied. | 276 // their destruction dependencies satisfied. |
291 for (auto& map_entry : surface_map_) { | 277 for (auto& map_entry : surface_map_) { |
292 const SurfaceId& surface_id = map_entry.first; | 278 const SurfaceId& surface_id = map_entry.first; |
293 Surface* surface = map_entry.second; | 279 Surface* surface = map_entry.second; |
294 surface->SatisfyDestructionDependencies(&satisfied_sequences_, | 280 surface->SatisfyDestructionDependencies(&satisfied_sequences_, |
295 &valid_frame_sink_ids_); | 281 framesink_manager_->GetValidFrameSinkIds()); |
296 | 282 |
297 if (!surface->destroyed() || surface->GetDestructionDependencyCount() > 0) { | 283 if (!surface->destroyed() || surface->GetDestructionDependencyCount() > 0) { |
298 live_surfaces_set.insert(surface_id); | 284 live_surfaces_set.insert(surface_id); |
299 live_surfaces.push_back(surface_id); | 285 live_surfaces.push_back(surface_id); |
300 } | 286 } |
301 } | 287 } |
302 | 288 |
303 // Mark all surfaces reachable from live surfaces by adding them to | 289 // Mark all surfaces reachable from live surfaces by adding them to |
304 // live_surfaces and live_surfaces_set. | 290 // live_surfaces and live_surfaces_set. |
305 for (size_t i = 0; i < live_surfaces.size(); i++) { | 291 for (size_t i = 0; i < live_surfaces.size(); i++) { |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
411 | 397 |
412 // If last temporary reference is removed for |frame_sink_id| then cleanup | 398 // If last temporary reference is removed for |frame_sink_id| then cleanup |
413 // range tracking map entry. | 399 // range tracking map entry. |
414 if (frame_sink_temp_refs.empty()) | 400 if (frame_sink_temp_refs.empty()) |
415 temporary_reference_ranges_.erase(frame_sink_id); | 401 temporary_reference_ranges_.erase(frame_sink_id); |
416 } | 402 } |
417 | 403 |
418 void SurfaceManager::RegisterSurfaceFactoryClient( | 404 void SurfaceManager::RegisterSurfaceFactoryClient( |
419 const FrameSinkId& frame_sink_id, | 405 const FrameSinkId& frame_sink_id, |
420 SurfaceFactoryClient* client) { | 406 SurfaceFactoryClient* client) { |
421 DCHECK(client); | 407 framesink_manager_->RegisterSurfaceFactoryClient(frame_sink_id, client); |
422 DCHECK_EQ(valid_frame_sink_ids_.count(frame_sink_id), 1u); | |
423 | |
424 clients_[frame_sink_id] = client; | |
425 | |
426 auto it = frame_sink_source_map_.find(frame_sink_id); | |
427 if (it != frame_sink_source_map_.end()) { | |
428 if (it->second.source) | |
429 client->SetBeginFrameSource(it->second.source); | |
430 } | |
431 } | 408 } |
432 | 409 |
433 void SurfaceManager::UnregisterSurfaceFactoryClient( | 410 void SurfaceManager::UnregisterSurfaceFactoryClient( |
434 const FrameSinkId& frame_sink_id) { | 411 const FrameSinkId& frame_sink_id) { |
435 DCHECK_EQ(valid_frame_sink_ids_.count(frame_sink_id), 1u); | 412 framesink_manager_->UnregisterSurfaceFactoryClient(frame_sink_id); |
436 auto client_iter = clients_.find(frame_sink_id); | |
437 DCHECK(client_iter != clients_.end()); | |
438 | |
439 auto source_iter = frame_sink_source_map_.find(frame_sink_id); | |
440 if (source_iter != frame_sink_source_map_.end()) { | |
441 if (source_iter->second.source) | |
442 client_iter->second->SetBeginFrameSource(nullptr); | |
443 if (!source_iter->second.has_children()) | |
444 frame_sink_source_map_.erase(source_iter); | |
445 } | |
446 clients_.erase(client_iter); | |
447 } | 413 } |
448 | 414 |
449 void SurfaceManager::RegisterBeginFrameSource( | 415 void SurfaceManager::RegisterBeginFrameSource( |
450 BeginFrameSource* source, | 416 BeginFrameSource* source, |
451 const FrameSinkId& frame_sink_id) { | 417 const FrameSinkId& frame_sink_id) { |
452 DCHECK(source); | 418 framesink_manager_->RegisterBeginFrameSource(source, frame_sink_id); |
453 DCHECK_EQ(registered_sources_.count(source), 0u); | |
454 DCHECK_EQ(valid_frame_sink_ids_.count(frame_sink_id), 1u); | |
455 | |
456 registered_sources_[source] = frame_sink_id; | |
457 RecursivelyAttachBeginFrameSource(frame_sink_id, source); | |
458 } | 419 } |
459 | 420 |
460 void SurfaceManager::UnregisterBeginFrameSource(BeginFrameSource* source) { | 421 void SurfaceManager::UnregisterBeginFrameSource(BeginFrameSource* source) { |
461 DCHECK(source); | 422 framesink_manager_->UnregisterBeginFrameSource(source); |
462 DCHECK_EQ(registered_sources_.count(source), 1u); | |
463 | |
464 FrameSinkId frame_sink_id = registered_sources_[source]; | |
465 registered_sources_.erase(source); | |
466 | |
467 if (frame_sink_source_map_.count(frame_sink_id) == 0u) | |
468 return; | |
469 | |
470 // TODO(enne): these walks could be done in one step. | |
471 // Remove this begin frame source from its subtree. | |
472 RecursivelyDetachBeginFrameSource(frame_sink_id, source); | |
473 // Then flush every remaining registered source to fix any sources that | |
474 // became null because of the previous step but that have an alternative. | |
475 for (auto source_iter : registered_sources_) | |
476 RecursivelyAttachBeginFrameSource(source_iter.second, source_iter.first); | |
477 } | |
478 | |
479 void SurfaceManager::RecursivelyAttachBeginFrameSource( | |
480 const FrameSinkId& frame_sink_id, | |
481 BeginFrameSource* source) { | |
482 FrameSinkSourceMapping& mapping = frame_sink_source_map_[frame_sink_id]; | |
483 if (!mapping.source) { | |
484 mapping.source = source; | |
485 auto client_iter = clients_.find(frame_sink_id); | |
486 if (client_iter != clients_.end()) | |
487 client_iter->second->SetBeginFrameSource(source); | |
488 } | |
489 for (size_t i = 0; i < mapping.children.size(); ++i) | |
490 RecursivelyAttachBeginFrameSource(mapping.children[i], source); | |
491 } | |
492 | |
493 void SurfaceManager::RecursivelyDetachBeginFrameSource( | |
494 const FrameSinkId& frame_sink_id, | |
495 BeginFrameSource* source) { | |
496 auto iter = frame_sink_source_map_.find(frame_sink_id); | |
497 if (iter == frame_sink_source_map_.end()) | |
498 return; | |
499 if (iter->second.source == source) { | |
500 iter->second.source = nullptr; | |
501 auto client_iter = clients_.find(frame_sink_id); | |
502 if (client_iter != clients_.end()) | |
503 client_iter->second->SetBeginFrameSource(nullptr); | |
504 } | |
505 | |
506 if (!iter->second.has_children() && !clients_.count(frame_sink_id)) { | |
507 frame_sink_source_map_.erase(iter); | |
508 return; | |
509 } | |
510 | |
511 std::vector<FrameSinkId>& children = iter->second.children; | |
512 for (size_t i = 0; i < children.size(); ++i) { | |
513 RecursivelyDetachBeginFrameSource(children[i], source); | |
514 } | |
515 } | |
516 | |
517 bool SurfaceManager::ChildContains( | |
518 const FrameSinkId& child_frame_sink_id, | |
519 const FrameSinkId& search_frame_sink_id) const { | |
520 auto iter = frame_sink_source_map_.find(child_frame_sink_id); | |
521 if (iter == frame_sink_source_map_.end()) | |
522 return false; | |
523 | |
524 const std::vector<FrameSinkId>& children = iter->second.children; | |
525 for (size_t i = 0; i < children.size(); ++i) { | |
526 if (children[i] == search_frame_sink_id) | |
527 return true; | |
528 if (ChildContains(children[i], search_frame_sink_id)) | |
529 return true; | |
530 } | |
531 return false; | |
532 } | 423 } |
533 | 424 |
534 void SurfaceManager::RegisterFrameSinkHierarchy( | 425 void SurfaceManager::RegisterFrameSinkHierarchy( |
535 const FrameSinkId& parent_frame_sink_id, | 426 const FrameSinkId& parent_frame_sink_id, |
536 const FrameSinkId& child_frame_sink_id) { | 427 const FrameSinkId& child_frame_sink_id) { |
537 // If it's possible to reach the parent through the child's descendant chain, | 428 framesink_manager_->RegisterFrameSinkHierarchy(parent_frame_sink_id, |
538 // then this will create an infinite loop. Might as well just crash here. | 429 child_frame_sink_id); |
539 CHECK(!ChildContains(child_frame_sink_id, parent_frame_sink_id)); | |
540 | |
541 std::vector<FrameSinkId>& children = | |
542 frame_sink_source_map_[parent_frame_sink_id].children; | |
543 for (size_t i = 0; i < children.size(); ++i) | |
544 DCHECK(children[i] != child_frame_sink_id); | |
545 children.push_back(child_frame_sink_id); | |
546 | |
547 // If the parent has no source, then attaching it to this child will | |
548 // not change any downstream sources. | |
549 BeginFrameSource* parent_source = | |
550 frame_sink_source_map_[parent_frame_sink_id].source; | |
551 if (!parent_source) | |
552 return; | |
553 | |
554 DCHECK_EQ(registered_sources_.count(parent_source), 1u); | |
555 RecursivelyAttachBeginFrameSource(child_frame_sink_id, parent_source); | |
556 } | 430 } |
557 | 431 |
558 void SurfaceManager::UnregisterFrameSinkHierarchy( | 432 void SurfaceManager::UnregisterFrameSinkHierarchy( |
559 const FrameSinkId& parent_frame_sink_id, | 433 const FrameSinkId& parent_frame_sink_id, |
560 const FrameSinkId& child_frame_sink_id) { | 434 const FrameSinkId& child_frame_sink_id) { |
561 // Deliberately do not check validity of either parent or child FrameSinkId | 435 framesink_manager_->UnregisterFrameSinkHierarchy(parent_frame_sink_id, |
562 // here. They were valid during the registration, so were valid at some | 436 child_frame_sink_id); |
563 // point in time. This makes it possible to invalidate parent and child | |
564 // FrameSinkIds independently of each other and not have an ordering | |
565 // dependency of unregistering the hierarchy first before either of them. | |
566 DCHECK_EQ(frame_sink_source_map_.count(parent_frame_sink_id), 1u); | |
567 | |
568 auto iter = frame_sink_source_map_.find(parent_frame_sink_id); | |
569 | |
570 std::vector<FrameSinkId>& children = iter->second.children; | |
571 bool found_child = false; | |
572 for (size_t i = 0; i < children.size(); ++i) { | |
573 if (children[i] == child_frame_sink_id) { | |
574 found_child = true; | |
575 children[i] = children.back(); | |
576 children.resize(children.size() - 1); | |
577 break; | |
578 } | |
579 } | |
580 DCHECK(found_child); | |
581 | |
582 // The SurfaceFactoryClient and hierarchy can be registered/unregistered | |
583 // in either order, so empty frame_sink_source_map entries need to be | |
584 // checked when removing either clients or relationships. | |
585 if (!iter->second.has_children() && !clients_.count(parent_frame_sink_id)) { | |
586 frame_sink_source_map_.erase(iter); | |
587 return; | |
588 } | |
589 | |
590 // If the parent does not have a begin frame source, then disconnecting it | |
591 // will not change any of its children. | |
592 BeginFrameSource* parent_source = iter->second.source; | |
593 if (!parent_source) | |
594 return; | |
595 | |
596 // TODO(enne): these walks could be done in one step. | |
597 RecursivelyDetachBeginFrameSource(child_frame_sink_id, parent_source); | |
598 for (auto source_iter : registered_sources_) | |
599 RecursivelyAttachBeginFrameSource(source_iter.second, source_iter.first); | |
600 } | 437 } |
601 | 438 |
602 Surface* SurfaceManager::GetSurfaceForId(const SurfaceId& surface_id) { | 439 Surface* SurfaceManager::GetSurfaceForId(const SurfaceId& surface_id) { |
603 DCHECK(thread_checker_.CalledOnValidThread()); | 440 DCHECK(thread_checker_.CalledOnValidThread()); |
604 SurfaceMap::iterator it = surface_map_.find(surface_id); | 441 SurfaceMap::iterator it = surface_map_.find(surface_id); |
605 if (it == surface_map_.end()) | 442 if (it == surface_map_.end()) |
606 return nullptr; | 443 return nullptr; |
607 return it->second; | 444 return it->second; |
608 } | 445 } |
609 | 446 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
688 std::vector<SurfaceId> children(iter->second.begin(), iter->second.end()); | 525 std::vector<SurfaceId> children(iter->second.begin(), iter->second.end()); |
689 std::sort(children.begin(), children.end()); | 526 std::sort(children.begin(), children.end()); |
690 | 527 |
691 for (const SurfaceId& child_id : children) | 528 for (const SurfaceId& child_id : children) |
692 SurfaceReferencesToStringImpl(child_id, indent + " ", str); | 529 SurfaceReferencesToStringImpl(child_id, indent + " ", str); |
693 } | 530 } |
694 } | 531 } |
695 #endif // DCHECK_IS_ON() | 532 #endif // DCHECK_IS_ON() |
696 | 533 |
697 } // namespace cc | 534 } // namespace cc |
OLD | NEW |