Chromium Code Reviews| Index: cc/surfaces/surface_manager.cc |
| diff --git a/cc/surfaces/surface_manager.cc b/cc/surfaces/surface_manager.cc |
| index b95954aab2659af9264ca1d6977304f64427dfd8..7e4229f58ef12f0e1dbcf70728e547ac90fa4a83 100644 |
| --- a/cc/surfaces/surface_manager.cc |
| +++ b/cc/surfaces/surface_manager.cc |
| @@ -7,6 +7,7 @@ |
| #include <stddef.h> |
| #include <stdint.h> |
| +#include <queue> |
| #include <utility> |
| #include "base/logging.h" |
| @@ -27,9 +28,10 @@ SurfaceManager::FrameSinkSourceMapping::~FrameSinkSourceMapping() { |
| << ", children: " << children.size(); |
| } |
| -SurfaceManager::SurfaceManager() |
| - : kRootSurfaceId(FrameSinkId(0u, 0u), |
| - LocalFrameId(0u, base::UnguessableToken::Create())) { |
| +SurfaceManager::SurfaceManager(bool use_references) |
| + : use_references_(use_references), |
| + root_surface_id_(FrameSinkId(0u, 0u), |
| + LocalFrameId(1u, base::UnguessableToken::Create())) { |
|
vmpstr
2016/12/01 21:04:02
Why 1u change?
kylechar
2016/12/01 22:49:58
The LocalFrameId will be a valid value (local_fram
|
| thread_checker_.DetachFromThread(); |
| } |
| @@ -74,6 +76,7 @@ void SurfaceManager::Destroy(std::unique_ptr<Surface> surface) { |
| void SurfaceManager::DidSatisfySequences(const FrameSinkId& frame_sink_id, |
| std::vector<uint32_t>* sequence) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| + DCHECK(!use_references_); |
| for (uint32_t value : *sequence) |
| satisfied_sequences_.insert(SurfaceSequence(frame_sink_id, value)); |
| sequence->clear(); |
| @@ -91,7 +94,7 @@ void SurfaceManager::InvalidateFrameSinkId(const FrameSinkId& frame_sink_id) { |
| } |
| const SurfaceId& SurfaceManager::GetRootSurfaceId() const { |
| - return kRootSurfaceId; |
| + return root_surface_id_; |
| } |
| void SurfaceManager::AddSurfaceReference(const SurfaceId& parent_id, |
| @@ -104,7 +107,7 @@ void SurfaceManager::AddSurfaceReference(const SurfaceId& parent_id, |
| LOG(ERROR) << "Cannot add self reference for " << parent_id.ToString(); |
| return; |
| } |
| - if (parent_id != kRootSurfaceId && surface_map_.count(parent_id) == 0) { |
| + if (parent_id != root_surface_id_ && surface_map_.count(parent_id) == 0) { |
| LOG(ERROR) << "No surface in map for " << parent_id.ToString(); |
| return; |
| } |
| @@ -150,7 +153,54 @@ size_t SurfaceManager::GetReferencedSurfaceCount( |
| return iter->second.size(); |
| } |
| +void SurfaceManager::GarbageCollectSurfacesFromRoot() { |
| + DCHECK(use_references_); |
| + |
| + if (surfaces_to_destroy_.empty()) |
| + return; |
| + |
| + std::unordered_set<SurfaceId, SurfaceIdHash> reachable_surfaces; |
| + |
| + // Walk down from the root and mark each SurfaceId we encounter as reachable. |
| + std::queue<SurfaceId> surface_queue({root_surface_id_}); |
|
vmpstr
2016/12/01 21:04:02
surface_queue{root_surface_id_}?
Can you also ver
kylechar
2016/12/01 22:49:58
std::initializer_list are allowed now and I can't
|
| + while (!surface_queue.empty()) { |
| + const SurfaceId& surface_id = surface_queue.front(); |
| + auto iter = parent_to_child_refs_.find(surface_id); |
| + if (iter != parent_to_child_refs_.end()) { |
| + for (const SurfaceId& child_id : iter->second) { |
| + // Check for cycles when inserting into |reachable_surfaces|. |
| + if (reachable_surfaces.insert(child_id).second) |
| + surface_queue.push(child_id); |
| + } |
| + } |
| + surface_queue.pop(); |
| + } |
| + |
| + std::vector<std::unique_ptr<Surface>> surfaces_to_delete; |
| + |
| + // Delete all destroyed and unreachable surfaces. |
| + for (auto iter = surfaces_to_destroy_.begin(); |
| + iter != surfaces_to_destroy_.end();) { |
| + SurfaceId surface_id = (*iter)->surface_id(); |
| + if (reachable_surfaces.count(surface_id) == 0) { |
| + DeregisterSurface(surface_id); |
| + surfaces_to_delete.push_back(std::move(*iter)); |
| + iter = surfaces_to_destroy_.erase(iter); |
| + } else { |
| + ++iter; |
| + } |
| + } |
| + |
| + // ~Surface() draw callback could modify |surfaces_to_destroy_|. |
| + surfaces_to_delete.clear(); |
| +} |
| + |
| void SurfaceManager::GarbageCollectSurfaces() { |
| + if (use_references_) { |
| + GarbageCollectSurfacesFromRoot(); |
| + return; |
| + } |
| + |
| // Simple mark and sweep GC. |
| // TODO(jbauman): Reduce the amount of work when nothing needs to be |
| // destroyed. |