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 <algorithm> | 10 #include <algorithm> |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 32 : lifetime_type_(lifetime_type), | 32 : lifetime_type_(lifetime_type), |
| 33 root_surface_id_(FrameSinkId(0u, 0u), | 33 root_surface_id_(FrameSinkId(0u, 0u), |
| 34 LocalSurfaceId(1u, base::UnguessableToken::Create())), | 34 LocalSurfaceId(1u, base::UnguessableToken::Create())), |
| 35 weak_factory_(this) { | 35 weak_factory_(this) { |
| 36 thread_checker_.DetachFromThread(); | 36 thread_checker_.DetachFromThread(); |
| 37 reference_factory_ = | 37 reference_factory_ = |
| 38 new DirectSurfaceReferenceFactory(weak_factory_.GetWeakPtr()); | 38 new DirectSurfaceReferenceFactory(weak_factory_.GetWeakPtr()); |
| 39 } | 39 } |
| 40 | 40 |
| 41 SurfaceManager::~SurfaceManager() { | 41 SurfaceManager::~SurfaceManager() { |
| 42 DCHECK(thread_checker_.CalledOnValidThread()); | 42 DCHECK_EQ(surfaces_to_destroy_.size(), surface_map_.size()); |
|
danakj
2017/06/28 18:16:24
Can you leave a comment explaining what went wrong
| |
| 43 | |
| 44 // Remove all temporary references on shutdown. | |
| 45 temporary_references_.clear(); | |
| 46 temporary_reference_ranges_.clear(); | |
| 47 | |
| 48 GarbageCollectSurfaces(); | |
| 49 | |
| 50 for (SurfaceDestroyList::iterator it = surfaces_to_destroy_.begin(); | |
| 51 it != surfaces_to_destroy_.end(); | |
| 52 ++it) { | |
| 53 UnregisterSurface((*it)->surface_id()); | |
| 54 } | |
| 55 surfaces_to_destroy_.clear(); | |
| 56 } | 43 } |
| 57 | 44 |
| 58 #if DCHECK_IS_ON() | 45 #if DCHECK_IS_ON() |
| 59 std::string SurfaceManager::SurfaceReferencesToString() { | 46 std::string SurfaceManager::SurfaceReferencesToString() { |
| 60 std::stringstream str; | 47 std::stringstream str; |
| 61 SurfaceReferencesToStringImpl(root_surface_id_, "", &str); | 48 SurfaceReferencesToStringImpl(root_surface_id_, "", &str); |
| 62 // Temporary references will have an asterisk in front of them. | 49 // Temporary references will have an asterisk in front of them. |
| 63 for (auto& map_entry : temporary_references_) | 50 for (auto& map_entry : temporary_references_) |
| 64 SurfaceReferencesToStringImpl(map_entry.first, "* ", &str); | 51 SurfaceReferencesToStringImpl(map_entry.first, "* ", &str); |
| 65 | 52 |
| 66 return str.str(); | 53 return str.str(); |
| 67 } | 54 } |
| 68 #endif | 55 #endif |
| 69 | 56 |
| 70 void SurfaceManager::SetDependencyTracker( | 57 void SurfaceManager::SetDependencyTracker( |
| 71 SurfaceDependencyTracker* dependency_tracker) { | 58 SurfaceDependencyTracker* dependency_tracker) { |
| 72 dependency_tracker_ = dependency_tracker; | 59 dependency_tracker_ = dependency_tracker; |
| 73 } | 60 } |
| 74 | 61 |
| 75 void SurfaceManager::RequestSurfaceResolution(Surface* pending_surface) { | 62 void SurfaceManager::RequestSurfaceResolution(Surface* pending_surface) { |
| 76 if (dependency_tracker_) | 63 if (dependency_tracker_) |
| 77 dependency_tracker_->RequestSurfaceResolution(pending_surface); | 64 dependency_tracker_->RequestSurfaceResolution(pending_surface); |
| 78 } | 65 } |
| 79 | 66 |
| 80 std::unique_ptr<Surface> SurfaceManager::CreateSurface( | 67 Surface* SurfaceManager::CreateSurface( |
| 81 base::WeakPtr<CompositorFrameSinkSupport> compositor_frame_sink_support, | 68 base::WeakPtr<CompositorFrameSinkSupport> compositor_frame_sink_support, |
| 82 const SurfaceInfo& surface_info) { | 69 const SurfaceInfo& surface_info) { |
| 83 DCHECK(thread_checker_.CalledOnValidThread()); | 70 DCHECK(thread_checker_.CalledOnValidThread()); |
| 84 DCHECK(surface_info.is_valid()); | 71 DCHECK(surface_info.is_valid()); |
| 85 DCHECK(compositor_frame_sink_support); | 72 DCHECK(compositor_frame_sink_support); |
| 86 DCHECK_EQ(surface_info.id().frame_sink_id(), | 73 DCHECK_EQ(surface_info.id().frame_sink_id(), |
| 87 compositor_frame_sink_support->frame_sink_id()); | 74 compositor_frame_sink_support->frame_sink_id()); |
| 88 | 75 |
| 89 // If no surface with this SurfaceId exists, simply create the surface and | 76 // If no surface with this SurfaceId exists, simply create the surface and |
| 90 // return. | 77 // return. |
| 91 auto surface_iter = surface_map_.find(surface_info.id()); | 78 auto it = surface_map_.find(surface_info.id()); |
| 92 if (surface_iter == surface_map_.end()) { | 79 if (it == surface_map_.end()) { |
| 93 auto surface = | 80 surface_map_[surface_info.id()] = |
| 94 base::MakeUnique<Surface>(surface_info, compositor_frame_sink_support); | 81 base::MakeUnique<Surface>(surface_info, compositor_frame_sink_support); |
| 95 surface_map_[surface->surface_id()] = surface.get(); | 82 return surface_map_[surface_info.id()].get(); |
| 96 return surface; | |
| 97 } | 83 } |
| 98 | 84 |
| 99 // If a surface with this SurfaceId exists and it's not marked as destroyed, | 85 // If a surface with this SurfaceId exists, it must be marked as destroyed. |
| 100 // we should not receive a request to create a new surface with the same | 86 // Otherwise, we wouldn't receive a request to reuse the same SurfaceId. |
| 101 // SurfaceId. | 87 // Remove the surface out of the garbage collector's queue and reuse it. |
| 102 DCHECK(surface_iter->second->destroyed()); | 88 Surface* surface = it->second.get(); |
| 103 | 89 DCHECK(IsMarkedForDestruction(surface_info.id())); |
| 104 // If a surface with this SurfaceId exists and it's marked as destroyed, | 90 surfaces_to_destroy_.erase(surface_info.id()); |
| 105 // it means it's in the garbage collector's queue. We simply take it out of | |
| 106 // the queue and reuse it. | |
| 107 auto it = | |
| 108 std::find_if(surfaces_to_destroy_.begin(), surfaces_to_destroy_.end(), | |
| 109 [&surface_info](const std::unique_ptr<Surface>& surface) { | |
| 110 return surface->surface_id() == surface_info.id(); | |
| 111 }); | |
| 112 DCHECK(it != surfaces_to_destroy_.end()); | |
| 113 std::unique_ptr<Surface> surface = std::move(*it); | |
| 114 surfaces_to_destroy_.erase(it); | |
| 115 surface->set_destroyed(false); | |
| 116 DCHECK_EQ(compositor_frame_sink_support.get(), | 91 DCHECK_EQ(compositor_frame_sink_support.get(), |
| 117 surface->compositor_frame_sink_support().get()); | 92 surface->compositor_frame_sink_support().get()); |
| 118 return surface; | 93 return surface; |
| 119 } | 94 } |
| 120 | 95 |
| 121 void SurfaceManager::DestroySurface(std::unique_ptr<Surface> surface) { | 96 void SurfaceManager::DestroySurface(const SurfaceId& surface_id) { |
| 122 DCHECK(thread_checker_.CalledOnValidThread()); | 97 DCHECK(thread_checker_.CalledOnValidThread()); |
| 123 surface->set_destroyed(true); | 98 DCHECK(surface_map_.count(surface_id)); |
| 124 for (auto& observer : observer_list_) | 99 for (auto& observer : observer_list_) |
| 125 observer.OnSurfaceDestroyed(surface->surface_id()); | 100 observer.OnSurfaceDestroyed(surface_id); |
| 126 surfaces_to_destroy_.push_back(std::move(surface)); | 101 surfaces_to_destroy_.insert(surface_id); |
| 127 GarbageCollectSurfaces(); | 102 GarbageCollectSurfaces(); |
| 128 } | 103 } |
| 129 | 104 |
| 130 void SurfaceManager::SurfaceWillDraw(const SurfaceId& surface_id) { | 105 void SurfaceManager::SurfaceWillDraw(const SurfaceId& surface_id) { |
| 131 DCHECK(thread_checker_.CalledOnValidThread()); | 106 DCHECK(thread_checker_.CalledOnValidThread()); |
| 132 for (auto& observer : observer_list_) | 107 for (auto& observer : observer_list_) |
| 133 observer.OnSurfaceWillDraw(surface_id); | 108 observer.OnSurfaceWillDraw(surface_id); |
| 134 } | 109 } |
| 135 | 110 |
| 136 void SurfaceManager::RequireSequence(const SurfaceId& surface_id, | 111 void SurfaceManager::RequireSequence(const SurfaceId& surface_id, |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 231 } | 206 } |
| 232 | 207 |
| 233 void SurfaceManager::GarbageCollectSurfaces() { | 208 void SurfaceManager::GarbageCollectSurfaces() { |
| 234 if (surfaces_to_destroy_.empty()) | 209 if (surfaces_to_destroy_.empty()) |
| 235 return; | 210 return; |
| 236 | 211 |
| 237 SurfaceIdSet reachable_surfaces = using_surface_references() | 212 SurfaceIdSet reachable_surfaces = using_surface_references() |
| 238 ? GetLiveSurfacesForReferences() | 213 ? GetLiveSurfacesForReferences() |
| 239 : GetLiveSurfacesForSequences(); | 214 : GetLiveSurfacesForSequences(); |
| 240 | 215 |
| 241 std::vector<std::unique_ptr<Surface>> surfaces_to_delete; | 216 std::vector<SurfaceId> surfaces_to_delete; |
| 242 | 217 |
| 243 // Delete all destroyed and unreachable surfaces. | 218 // Delete all destroyed and unreachable surfaces. |
| 244 for (auto iter = surfaces_to_destroy_.begin(); | 219 for (auto iter = surfaces_to_destroy_.begin(); |
| 245 iter != surfaces_to_destroy_.end();) { | 220 iter != surfaces_to_destroy_.end();) { |
| 246 SurfaceId surface_id = (*iter)->surface_id(); | 221 if (reachable_surfaces.count(*iter) == 0) { |
| 247 if (reachable_surfaces.count(surface_id) == 0) { | 222 surfaces_to_delete.push_back(*iter); |
| 248 UnregisterSurface(surface_id); | |
| 249 surfaces_to_delete.push_back(std::move(*iter)); | |
| 250 iter = surfaces_to_destroy_.erase(iter); | 223 iter = surfaces_to_destroy_.erase(iter); |
| 251 } else { | 224 } else { |
| 252 ++iter; | 225 ++iter; |
| 253 } | 226 } |
| 254 } | 227 } |
| 255 | 228 |
| 256 // ~Surface() draw callback could modify |surfaces_to_destroy_|. | 229 // ~Surface() draw callback could modify |surfaces_to_destroy_|. |
| 257 surfaces_to_delete.clear(); | 230 for (const SurfaceId& surface_id : surfaces_to_delete) |
| 231 DestroySurfaceInternal(surface_id); | |
| 258 } | 232 } |
| 259 | 233 |
| 260 SurfaceManager::SurfaceIdSet SurfaceManager::GetLiveSurfacesForReferences() { | 234 SurfaceManager::SurfaceIdSet SurfaceManager::GetLiveSurfacesForReferences() { |
| 261 DCHECK(using_surface_references()); | 235 DCHECK(using_surface_references()); |
| 262 | 236 |
| 263 SurfaceIdSet reachable_surfaces; | 237 SurfaceIdSet reachable_surfaces; |
| 264 | 238 |
| 265 // Walk down from the root and mark each SurfaceId we encounter as reachable. | 239 // Walk down from the root and mark each SurfaceId we encounter as reachable. |
| 266 std::queue<SurfaceId> surface_queue; | 240 std::queue<SurfaceId> surface_queue; |
| 267 surface_queue.push(root_surface_id_); | 241 surface_queue.push(root_surface_id_); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 291 // Simple mark and sweep GC. | 265 // Simple mark and sweep GC. |
| 292 // TODO(jbauman): Reduce the amount of work when nothing needs to be | 266 // TODO(jbauman): Reduce the amount of work when nothing needs to be |
| 293 // destroyed. | 267 // destroyed. |
| 294 std::vector<SurfaceId> live_surfaces; | 268 std::vector<SurfaceId> live_surfaces; |
| 295 std::unordered_set<SurfaceId, SurfaceIdHash> live_surfaces_set; | 269 std::unordered_set<SurfaceId, SurfaceIdHash> live_surfaces_set; |
| 296 | 270 |
| 297 // GC roots are surfaces that have not been destroyed, or have not had all | 271 // GC roots are surfaces that have not been destroyed, or have not had all |
| 298 // their destruction dependencies satisfied. | 272 // their destruction dependencies satisfied. |
| 299 for (auto& map_entry : surface_map_) { | 273 for (auto& map_entry : surface_map_) { |
| 300 const SurfaceId& surface_id = map_entry.first; | 274 const SurfaceId& surface_id = map_entry.first; |
| 301 Surface* surface = map_entry.second; | 275 Surface* surface = map_entry.second.get(); |
| 302 surface->SatisfyDestructionDependencies(&satisfied_sequences_, | 276 surface->SatisfyDestructionDependencies(&satisfied_sequences_, |
| 303 framesink_manager_.GetValidFrameSinkIds()); | 277 framesink_manager_.GetValidFrameSinkIds()); |
| 304 | 278 |
| 305 if (!surface->destroyed() || surface->GetDestructionDependencyCount() > 0) { | 279 if (!IsMarkedForDestruction(surface_id) || |
| 280 surface->GetDestructionDependencyCount() > 0) { | |
| 306 live_surfaces_set.insert(surface_id); | 281 live_surfaces_set.insert(surface_id); |
| 307 live_surfaces.push_back(surface_id); | 282 live_surfaces.push_back(surface_id); |
| 308 } | 283 } |
| 309 } | 284 } |
| 310 | 285 |
| 311 // Mark all surfaces reachable from live surfaces by adding them to | 286 // Mark all surfaces reachable from live surfaces by adding them to |
| 312 // live_surfaces and live_surfaces_set. | 287 // live_surfaces and live_surfaces_set. |
| 313 for (size_t i = 0; i < live_surfaces.size(); i++) { | 288 for (size_t i = 0; i < live_surfaces.size(); i++) { |
| 314 Surface* surf = surface_map_[live_surfaces[i]]; | 289 Surface* surf = surface_map_[live_surfaces[i]].get(); |
| 315 DCHECK(surf); | 290 DCHECK(surf); |
| 316 | 291 |
| 317 const auto& children = GetSurfacesReferencedByParent(surf->surface_id()); | 292 const auto& children = GetSurfacesReferencedByParent(surf->surface_id()); |
| 318 for (const SurfaceId& id : children) { | 293 for (const SurfaceId& id : children) { |
| 319 if (live_surfaces_set.count(id)) | 294 if (live_surfaces_set.count(id)) |
| 320 continue; | 295 continue; |
| 321 | 296 |
| 322 Surface* surf2 = GetSurfaceForId(id); | 297 Surface* surf2 = GetSurfaceForId(id); |
| 323 if (surf2) { | 298 if (surf2) { |
| 324 live_surfaces.push_back(id); | 299 live_surfaces.push_back(id); |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 458 | 433 |
| 459 void SurfaceManager::UnregisterFrameSinkHierarchy( | 434 void SurfaceManager::UnregisterFrameSinkHierarchy( |
| 460 const FrameSinkId& parent_frame_sink_id, | 435 const FrameSinkId& parent_frame_sink_id, |
| 461 const FrameSinkId& child_frame_sink_id) { | 436 const FrameSinkId& child_frame_sink_id) { |
| 462 framesink_manager_.UnregisterFrameSinkHierarchy(parent_frame_sink_id, | 437 framesink_manager_.UnregisterFrameSinkHierarchy(parent_frame_sink_id, |
| 463 child_frame_sink_id); | 438 child_frame_sink_id); |
| 464 } | 439 } |
| 465 | 440 |
| 466 Surface* SurfaceManager::GetSurfaceForId(const SurfaceId& surface_id) { | 441 Surface* SurfaceManager::GetSurfaceForId(const SurfaceId& surface_id) { |
| 467 DCHECK(thread_checker_.CalledOnValidThread()); | 442 DCHECK(thread_checker_.CalledOnValidThread()); |
| 468 SurfaceMap::iterator it = surface_map_.find(surface_id); | 443 auto it = surface_map_.find(surface_id); |
| 469 if (it == surface_map_.end()) | 444 if (it == surface_map_.end()) |
| 470 return nullptr; | 445 return nullptr; |
| 471 return it->second; | 446 return it->second.get(); |
| 472 } | 447 } |
| 473 | 448 |
| 474 bool SurfaceManager::SurfaceModified(const SurfaceId& surface_id, | 449 bool SurfaceManager::SurfaceModified(const SurfaceId& surface_id, |
| 475 const BeginFrameAck& ack) { | 450 const BeginFrameAck& ack) { |
| 476 CHECK(thread_checker_.CalledOnValidThread()); | 451 CHECK(thread_checker_.CalledOnValidThread()); |
| 477 bool changed = false; | 452 bool changed = false; |
| 478 for (auto& observer : observer_list_) | 453 for (auto& observer : observer_list_) |
| 479 changed |= observer.OnSurfaceDamaged(surface_id, ack); | 454 changed |= observer.OnSurfaceDamaged(surface_id, ack); |
| 480 return changed; | 455 return changed; |
| 481 } | 456 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 519 dependency_tracker_->OnSurfaceDiscarded(surface); | 494 dependency_tracker_->OnSurfaceDiscarded(surface); |
| 520 } | 495 } |
| 521 | 496 |
| 522 void SurfaceManager::SurfaceDamageExpected(const SurfaceId& surface_id, | 497 void SurfaceManager::SurfaceDamageExpected(const SurfaceId& surface_id, |
| 523 const BeginFrameArgs& args) { | 498 const BeginFrameArgs& args) { |
| 524 DCHECK(thread_checker_.CalledOnValidThread()); | 499 DCHECK(thread_checker_.CalledOnValidThread()); |
| 525 for (auto& observer : observer_list_) | 500 for (auto& observer : observer_list_) |
| 526 observer.OnSurfaceDamageExpected(surface_id, args); | 501 observer.OnSurfaceDamageExpected(surface_id, args); |
| 527 } | 502 } |
| 528 | 503 |
| 529 void SurfaceManager::UnregisterSurface(const SurfaceId& surface_id) { | 504 void SurfaceManager::DestroySurfaceInternal(const SurfaceId& surface_id) { |
| 530 DCHECK(thread_checker_.CalledOnValidThread()); | 505 DCHECK(thread_checker_.CalledOnValidThread()); |
| 531 SurfaceMap::iterator it = surface_map_.find(surface_id); | 506 auto it = surface_map_.find(surface_id); |
| 532 DCHECK(it != surface_map_.end()); | 507 DCHECK(it != surface_map_.end()); |
| 508 // Make sure that the surface is removed from the map before being actually | |
| 509 // destroyed. An ack could be sent during the destruction of a surface which | |
| 510 // could trigger a synchronous frame submission to a half-destroyed surface | |
| 511 // and that's not desirable. | |
| 512 std::unique_ptr<Surface> doomed = std::move(it->second); | |
| 533 surface_map_.erase(it); | 513 surface_map_.erase(it); |
| 534 RemoveAllSurfaceReferences(surface_id); | 514 RemoveAllSurfaceReferences(surface_id); |
| 535 } | 515 } |
| 536 | 516 |
| 537 #if DCHECK_IS_ON() | 517 #if DCHECK_IS_ON() |
| 538 void SurfaceManager::SurfaceReferencesToStringImpl(const SurfaceId& surface_id, | 518 void SurfaceManager::SurfaceReferencesToStringImpl(const SurfaceId& surface_id, |
| 539 std::string indent, | 519 std::string indent, |
| 540 std::stringstream* str) { | 520 std::stringstream* str) { |
| 541 *str << indent; | 521 *str << indent; |
| 542 | 522 |
| 543 // Print the current line for |surface_id|. | 523 // Print the current line for |surface_id|. |
| 544 Surface* surface = GetSurfaceForId(surface_id); | 524 Surface* surface = GetSurfaceForId(surface_id); |
| 545 if (surface) { | 525 if (surface) { |
| 546 *str << surface->surface_id().ToString(); | 526 *str << surface->surface_id().ToString(); |
| 547 *str << (surface->destroyed() ? " destroyed" : " live"); | 527 *str << (IsMarkedForDestruction(surface_id) ? " destroyed" : " live"); |
| 548 | 528 |
| 549 if (surface->HasPendingFrame()) { | 529 if (surface->HasPendingFrame()) { |
| 550 // This provides the surface size from the root render pass. | 530 // This provides the surface size from the root render pass. |
| 551 const CompositorFrame& frame = surface->GetPendingFrame(); | 531 const CompositorFrame& frame = surface->GetPendingFrame(); |
| 552 *str << " pending " | 532 *str << " pending " |
| 553 << frame.render_pass_list.back()->output_rect.size().ToString(); | 533 << frame.render_pass_list.back()->output_rect.size().ToString(); |
| 554 } | 534 } |
| 555 | 535 |
| 556 if (surface->HasActiveFrame()) { | 536 if (surface->HasActiveFrame()) { |
| 557 // This provides the surface size from the root render pass. | 537 // This provides the surface size from the root render pass. |
| 558 const CompositorFrame& frame = surface->GetActiveFrame(); | 538 const CompositorFrame& frame = surface->GetActiveFrame(); |
| 559 *str << " active " | 539 *str << " active " |
| 560 << frame.render_pass_list.back()->output_rect.size().ToString(); | 540 << frame.render_pass_list.back()->output_rect.size().ToString(); |
| 561 } | 541 } |
| 562 } else { | 542 } else { |
| 563 *str << surface_id; | 543 *str << surface_id; |
| 564 } | 544 } |
| 565 *str << "\n"; | 545 *str << "\n"; |
| 566 | 546 |
| 567 // If the current surface has references to children, sort children and print | 547 // If the current surface has references to children, sort children and print |
| 568 // references for each child. | 548 // references for each child. |
| 569 for (const SurfaceId& child_id : GetSurfacesReferencedByParent(surface_id)) | 549 for (const SurfaceId& child_id : GetSurfacesReferencedByParent(surface_id)) |
| 570 SurfaceReferencesToStringImpl(child_id, indent + " ", str); | 550 SurfaceReferencesToStringImpl(child_id, indent + " ", str); |
| 571 } | 551 } |
| 572 #endif // DCHECK_IS_ON() | 552 #endif // DCHECK_IS_ON() |
| 573 | 553 |
| 554 bool SurfaceManager::IsMarkedForDestruction(const SurfaceId& surface_id) { | |
| 555 return surfaces_to_destroy_.count(surface_id) != 0; | |
| 556 } | |
| 557 | |
| 574 } // namespace cc | 558 } // namespace cc |
| OLD | NEW |