Chromium Code Reviews| 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 |