| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "cc/surfaces/surface_manager.h" |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| #include "base/logging.h" |
| #include "cc/surfaces/surface.h" |
| #include "cc/surfaces/surface_id_allocator.h" |
| |
| namespace cc { |
| |
| SurfaceManager::SurfaceManager() { |
| thread_checker_.DetachFromThread(); |
| } |
| |
| SurfaceManager::~SurfaceManager() { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| for (SurfaceDestroyList::iterator it = surfaces_to_destroy_.begin(); |
| it != surfaces_to_destroy_.end(); |
| ++it) { |
| DeregisterSurface((*it)->surface_id()); |
| delete *it; |
| } |
| } |
| |
| void SurfaceManager::RegisterSurface(Surface* surface) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| DCHECK(surface); |
| DCHECK(!surface_map_.count(surface->surface_id())); |
| surface_map_[surface->surface_id()] = surface; |
| } |
| |
| void SurfaceManager::DeregisterSurface(SurfaceId surface_id) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| SurfaceMap::iterator it = surface_map_.find(surface_id); |
| DCHECK(it != surface_map_.end()); |
| surface_map_.erase(it); |
| } |
| |
| void SurfaceManager::Destroy(scoped_ptr<Surface> surface) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| surface->set_destroyed(true); |
| surfaces_to_destroy_.push_back(surface.release()); |
| GarbageCollectSurfaces(); |
| } |
| |
| void SurfaceManager::DidSatisfySequences(uint32_t id_namespace, |
| std::vector<uint32_t>* sequence) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| for (std::vector<uint32_t>::iterator it = sequence->begin(); |
| it != sequence->end(); |
| ++it) { |
| satisfied_sequences_.insert(SurfaceSequence(id_namespace, *it)); |
| } |
| sequence->clear(); |
| GarbageCollectSurfaces(); |
| } |
| |
| void SurfaceManager::RegisterSurfaceIdNamespace(uint32_t id_namespace) { |
| bool inserted = valid_surface_id_namespaces_.insert(id_namespace).second; |
| DCHECK(inserted); |
| } |
| |
| void SurfaceManager::InvalidateSurfaceIdNamespace(uint32_t id_namespace) { |
| valid_surface_id_namespaces_.erase(id_namespace); |
| GarbageCollectSurfaces(); |
| } |
| |
| void SurfaceManager::GarbageCollectSurfaces() { |
| // Simple mark and sweep GC. |
| // TODO(jbauman): Reduce the amount of work when nothing needs to be |
| // destroyed. |
| std::vector<SurfaceId> live_surfaces; |
| std::set<SurfaceId> live_surfaces_set; |
| |
| // GC roots are surfaces that have not been destroyed, or have not had all |
| // their destruction dependencies satisfied. |
| for (auto& map_entry : surface_map_) { |
| map_entry.second->SatisfyDestructionDependencies( |
| &satisfied_sequences_, &valid_surface_id_namespaces_); |
| if (!map_entry.second->destroyed() || |
| map_entry.second->GetDestructionDependencyCount()) { |
| live_surfaces_set.insert(map_entry.first); |
| live_surfaces.push_back(map_entry.first); |
| } |
| } |
| |
| // Mark all surfaces reachable from live surfaces by adding them to |
| // live_surfaces and live_surfaces_set. |
| for (size_t i = 0; i < live_surfaces.size(); i++) { |
| Surface* surf = surface_map_[live_surfaces[i]]; |
| DCHECK(surf); |
| |
| for (SurfaceId id : surf->referenced_surfaces()) { |
| if (live_surfaces_set.count(id)) |
| continue; |
| |
| Surface* surf2 = GetSurfaceForId(id); |
| if (surf2) { |
| live_surfaces.push_back(id); |
| live_surfaces_set.insert(id); |
| } |
| } |
| } |
| |
| // Destroy all remaining unreachable surfaces. |
| for (SurfaceDestroyList::iterator dest_it = surfaces_to_destroy_.begin(); |
| dest_it != surfaces_to_destroy_.end();) { |
| if (!live_surfaces_set.count((*dest_it)->surface_id())) { |
| scoped_ptr<Surface> surf(*dest_it); |
| DeregisterSurface(surf->surface_id()); |
| dest_it = surfaces_to_destroy_.erase(dest_it); |
| } else { |
| ++dest_it; |
| } |
| } |
| } |
| |
| Surface* SurfaceManager::GetSurfaceForId(SurfaceId surface_id) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| SurfaceMap::iterator it = surface_map_.find(surface_id); |
| if (it == surface_map_.end()) |
| return NULL; |
| return it->second; |
| } |
| |
| bool SurfaceManager::SurfaceModified(SurfaceId surface_id) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| bool changed = false; |
| FOR_EACH_OBSERVER(SurfaceDamageObserver, observer_list_, |
| OnSurfaceDamaged(surface_id, &changed)); |
| return changed; |
| } |
| |
| } // namespace cc |