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