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