// 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.h" #include "cc/output/compositor_frame.h" #include "cc/surfaces/surface_manager.h" namespace cc { Surface::Surface(SurfaceManager* manager, SurfaceClient* client, const gfx::Size& size) : manager_(manager), client_(client), size_(size) { surface_id_ = manager_->RegisterAndAllocateIdForSurface(this); } Surface::~Surface() { manager_->DeregisterSurface(surface_id_); } void Surface::QueueFrame(scoped_ptr<CompositorFrame> frame) { scoped_ptr<CompositorFrame> previous_frame = current_frame_.Pass(); current_frame_ = frame.Pass(); ReceiveResourcesFromClient( current_frame_->delegated_frame_data->resource_list); if (previous_frame) { ReturnedResourceArray previous_resources; TransferableResource::ReturnResources( previous_frame->delegated_frame_data->resource_list, &previous_resources); UnrefResources(previous_resources); } } CompositorFrame* Surface::GetEligibleFrame() { return current_frame_.get(); } void Surface::ReturnUnusedResourcesToClient() { client_->ReturnResources(resources_available_to_return_); resources_available_to_return_.clear(); } void Surface::RefCurrentFrameResources() { if (!current_frame_) return; const TransferableResourceArray& current_frame_resources = current_frame_->delegated_frame_data->resource_list; for (size_t i = 0; i < current_frame_resources.size(); ++i) { const TransferableResource& resource = current_frame_resources[i]; ResourceIdCountMap::iterator it = resource_id_use_count_map_.find(resource.id); DCHECK(it != resource_id_use_count_map_.end()); it->second.refs_holding_resource_alive++; } } Surface::ResourceRefs::ResourceRefs() : refs_received_from_child(0), refs_holding_resource_alive(0) { } void Surface::ReceiveResourcesFromClient( const TransferableResourceArray& resources) { for (TransferableResourceArray::const_iterator it = resources.begin(); it != resources.end(); ++it) { ResourceRefs& ref = resource_id_use_count_map_[it->id]; ref.refs_holding_resource_alive++; ref.refs_received_from_child++; } } void Surface::UnrefResources(const ReturnedResourceArray& resources) { for (ReturnedResourceArray::const_iterator it = resources.begin(); it != resources.end(); ++it) { ResourceProvider::ResourceId id = it->id; ResourceIdCountMap::iterator count_it = resource_id_use_count_map_.find(id); DCHECK(count_it != resource_id_use_count_map_.end()); count_it->second.refs_holding_resource_alive -= it->count; if (count_it->second.refs_holding_resource_alive == 0) { resources_available_to_return_.push_back(*it); resources_available_to_return_.back().count = count_it->second.refs_received_from_child; resource_id_use_count_map_.erase(count_it); } } } } // namespace cc