1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "cc/layers/delegated_frame_resource_collection.h"
6
7#include "base/bind.h"
8#include "cc/trees/blocking_task_runner.h"
9
10namespace cc {
11
12DelegatedFrameResourceCollection::DelegatedFrameResourceCollection()
13    : client_(NULL),
14      lost_all_resources_(false),
15      weak_ptr_factory_(this) {
16  DCHECK(main_thread_checker_.CalledOnValidThread());
17}
18
19DelegatedFrameResourceCollection::~DelegatedFrameResourceCollection() {
20  DCHECK(main_thread_checker_.CalledOnValidThread());
21}
22
23void DelegatedFrameResourceCollection::SetClient(
24    DelegatedFrameResourceCollectionClient* client) {
25  client_ = client;
26}
27
28void DelegatedFrameResourceCollection::TakeUnusedResourcesForChildCompositor(
29    ReturnedResourceArray* array) {
30  DCHECK(main_thread_checker_.CalledOnValidThread());
31  DCHECK(array->empty());
32  array->swap(returned_resources_for_child_compositor_);
33}
34
35bool DelegatedFrameResourceCollection::LoseAllResources() {
36  DCHECK(main_thread_checker_.CalledOnValidThread());
37  DCHECK(!lost_all_resources_);
38  lost_all_resources_ = true;
39
40  if (resource_id_ref_count_map_.empty())
41    return false;
42
43  ReturnedResourceArray to_return;
44
45  for (ResourceIdRefCountMap::iterator it = resource_id_ref_count_map_.begin();
46       it != resource_id_ref_count_map_.end();
47       ++it) {
48    DCHECK_GE(it->second.refs_to_wait_for, 1);
49
50    ReturnedResource returned;
51    returned.id = it->first;
52    returned.count = it->second.refs_to_return;
53    returned.lost = true;
54    to_return.push_back(returned);
55  }
56
57  returned_resources_for_child_compositor_.insert(
58      returned_resources_for_child_compositor_.end(),
59      to_return.begin(),
60      to_return.end());
61  if (client_)
62    client_->UnusedResourcesAreAvailable();
63  return true;
64}
65
66void DelegatedFrameResourceCollection::ReceivedResources(
67    const TransferableResourceArray& resources) {
68  DCHECK(main_thread_checker_.CalledOnValidThread());
69  DCHECK(!lost_all_resources_);
70
71  for (size_t i = 0; i < resources.size(); ++i)
72    resource_id_ref_count_map_[resources[i].id].refs_to_return++;
73}
74
75void DelegatedFrameResourceCollection::UnrefResources(
76    const ReturnedResourceArray& returned) {
77  DCHECK(main_thread_checker_.CalledOnValidThread());
78
79  if (lost_all_resources_)
80    return;
81
82  ReturnedResourceArray to_return;
83
84  for (size_t i = 0; i < returned.size(); ++i) {
85    ResourceIdRefCountMap::iterator it =
86        resource_id_ref_count_map_.find(returned[i].id);
87    DCHECK(it != resource_id_ref_count_map_.end());
88    DCHECK_GE(it->second.refs_to_wait_for, returned[i].count);
89    it->second.refs_to_wait_for -= returned[i].count;
90    if (it->second.refs_to_wait_for == 0) {
91      to_return.push_back(returned[i]);
92      to_return.back().count = it->second.refs_to_return;
93      resource_id_ref_count_map_.erase(it);
94    }
95  }
96
97  if (to_return.empty())
98    return;
99
100  returned_resources_for_child_compositor_.insert(
101      returned_resources_for_child_compositor_.end(),
102      to_return.begin(),
103      to_return.end());
104  if (client_)
105    client_->UnusedResourcesAreAvailable();
106}
107
108void DelegatedFrameResourceCollection::RefResources(
109    const TransferableResourceArray& resources) {
110  DCHECK(main_thread_checker_.CalledOnValidThread());
111  for (size_t i = 0; i < resources.size(); ++i)
112    resource_id_ref_count_map_[resources[i].id].refs_to_wait_for++;
113}
114
115static void UnrefResourcesOnImplThread(
116    base::WeakPtr<DelegatedFrameResourceCollection> self,
117    const ReturnedResourceArray& returned,
118    BlockingTaskRunner* main_thread_task_runner) {
119  main_thread_task_runner->PostTask(
120      FROM_HERE,
121      base::Bind(
122          &DelegatedFrameResourceCollection::UnrefResources, self, returned));
123}
124
125ReturnCallback
126DelegatedFrameResourceCollection::GetReturnResourcesCallbackForImplThread() {
127  return base::Bind(&UnrefResourcesOnImplThread,
128                    weak_ptr_factory_.GetWeakPtr());
129}
130
131}  // namespace cc
132