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