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