|  | // 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_(nullptr), 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, | 
|  | const ReturnedResourceArray& returned, | 
|  | BlockingTaskRunner* main_thread_task_runner) { | 
|  | main_thread_task_runner->PostTask( | 
|  | FROM_HERE, | 
|  | base::Bind( | 
|  | &DelegatedFrameResourceCollection::UnrefResources, self, returned)); | 
|  | } | 
|  |  | 
|  | ReturnCallback | 
|  | DelegatedFrameResourceCollection::GetReturnResourcesCallbackForImplThread() { | 
|  | return base::Bind(&UnrefResourcesOnImplThread, | 
|  | weak_ptr_factory_.GetWeakPtr()); | 
|  | } | 
|  |  | 
|  | }  // namespace cc |