// 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 #include #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) { 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* sequence) { DCHECK(thread_checker_.CalledOnValidThread()); for (std::vector::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 live_surfaces; std::set 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 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