| 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 |