// 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