// Copyright 2013 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/layers/delegated_frame_resource_collection.h"
#include "base/bind.h"
#include "cc/trees/blocking_task_runner.h"
namespace cc {
DelegatedFrameResourceCollection::DelegatedFrameResourceCollection()
: client_(NULL),
main_thread_runner_(BlockingTaskRunner::current()),
lost_all_resources_(false),
weak_ptr_factory_(this) {
DCHECK(main_thread_checker_.CalledOnValidThread());
}
DelegatedFrameResourceCollection::~DelegatedFrameResourceCollection() {
DCHECK(main_thread_checker_.CalledOnValidThread());
}
void DelegatedFrameResourceCollection::SetClient(
DelegatedFrameResourceCollectionClient* client) {
client_ = client;
}
void DelegatedFrameResourceCollection::TakeUnusedResourcesForChildCompositor(
ReturnedResourceArray* array) {
DCHECK(main_thread_checker_.CalledOnValidThread());
DCHECK(array->empty());
array->swap(returned_resources_for_child_compositor_);
}
bool DelegatedFrameResourceCollection::LoseAllResources() {
DCHECK(main_thread_checker_.CalledOnValidThread());
DCHECK(!lost_all_resources_);
lost_all_resources_ = true;
if (resource_id_ref_count_map_.empty())
return false;
ReturnedResourceArray to_return;
for (ResourceIdRefCountMap::iterator it = resource_id_ref_count_map_.begin();
it != resource_id_ref_count_map_.end();
++it) {
DCHECK_GE(it->second.refs_to_wait_for, 1);
ReturnedResource returned;
returned.id = it->first;
returned.count = it->second.refs_to_return;
returned.lost = true;
to_return.push_back(returned);
}
returned_resources_for_child_compositor_.insert(
returned_resources_for_child_compositor_.end(),
to_return.begin(),
to_return.end());
if (client_)
client_->UnusedResourcesAreAvailable();
return true;
}
void DelegatedFrameResourceCollection::ReceivedResources(
const TransferableResourceArray& resources) {
DCHECK(main_thread_checker_.CalledOnValidThread());
DCHECK(!lost_all_resources_);
for (size_t i = 0; i < resources.size(); ++i)
resource_id_ref_count_map_[resources[i].id].refs_to_return++;
}
void DelegatedFrameResourceCollection::UnrefResources(
const ReturnedResourceArray& returned) {
DCHECK(main_thread_checker_.CalledOnValidThread());
if (lost_all_resources_)
return;
ReturnedResourceArray to_return;
for (size_t i = 0; i < returned.size(); ++i) {
ResourceIdRefCountMap::iterator it =
resource_id_ref_count_map_.find(returned[i].id);
DCHECK(it != resource_id_ref_count_map_.end());
DCHECK_GE(it->second.refs_to_wait_for, returned[i].count);
it->second.refs_to_wait_for -= returned[i].count;
if (it->second.refs_to_wait_for == 0) {
to_return.push_back(returned[i]);
to_return.back().count = it->second.refs_to_return;
resource_id_ref_count_map_.erase(it);
}
}
if (to_return.empty())
return;
returned_resources_for_child_compositor_.insert(
returned_resources_for_child_compositor_.end(),
to_return.begin(),
to_return.end());
if (client_)
client_->UnusedResourcesAreAvailable();
}
void DelegatedFrameResourceCollection::RefResources(
const TransferableResourceArray& resources) {
DCHECK(main_thread_checker_.CalledOnValidThread());
for (size_t i = 0; i < resources.size(); ++i)
resource_id_ref_count_map_[resources[i].id].refs_to_wait_for++;
}
static void UnrefResourcesOnImplThread(
base::WeakPtr<DelegatedFrameResourceCollection> self,
scoped_refptr<BlockingTaskRunner> main_thread_runner,
const ReturnedResourceArray& returned) {
main_thread_runner->PostTask(
FROM_HERE,
base::Bind(
&DelegatedFrameResourceCollection::UnrefResources, self, returned));
}
ReturnCallback
DelegatedFrameResourceCollection::GetReturnResourcesCallbackForImplThread() {
return base::Bind(&UnrefResourcesOnImplThread,
weak_ptr_factory_.GetWeakPtr(),
main_thread_runner_);
}
} // namespace cc