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      main_thread_runner_(BlockingTaskRunner::current()),
15      lost_all_resources_(false),
16      weak_ptr_factory_(this) {
17  DCHECK(main_thread_checker_.CalledOnValidThread());
18}
19
20DelegatedFrameResourceCollection::~DelegatedFrameResourceCollection() {
21  DCHECK(main_thread_checker_.CalledOnValidThread());
22}
23
24void DelegatedFrameResourceCollection::SetClient(
25    DelegatedFrameResourceCollectionClient* client) {
26  client_ = client;
27}
28
29void DelegatedFrameResourceCollection::TakeUnusedResourcesForChildCompositor(
30    ReturnedResourceArray* array) {
31  DCHECK(main_thread_checker_.CalledOnValidThread());
32  DCHECK(array->empty());
33  array->swap(returned_resources_for_child_compositor_);
34}
35
36bool DelegatedFrameResourceCollection::LoseAllResources() {
37  DCHECK(main_thread_checker_.CalledOnValidThread());
38  DCHECK(!lost_all_resources_);
39  lost_all_resources_ = true;
40
41  if (resource_id_ref_count_map_.empty())
42    return false;
43
44  ReturnedResourceArray to_return;
45
46  for (ResourceIdRefCountMap::iterator it = resource_id_ref_count_map_.begin();
47       it != resource_id_ref_count_map_.end();
48       ++it) {
49    DCHECK_GE(it->second.refs_to_wait_for, 1);
50
51    ReturnedResource returned;
52    returned.id = it->first;
53    returned.count = it->second.refs_to_return;
54    returned.lost = true;
55    to_return.push_back(returned);
56  }
57
58  returned_resources_for_child_compositor_.insert(
59      returned_resources_for_child_compositor_.end(),
60      to_return.begin(),
61      to_return.end());
62  if (client_)
63    client_->UnusedResourcesAreAvailable();
64  return true;
65}
66
67void DelegatedFrameResourceCollection::ReceivedResources(
68    const TransferableResourceArray& resources) {
69  DCHECK(main_thread_checker_.CalledOnValidThread());
70  DCHECK(!lost_all_resources_);
71
72  for (size_t i = 0; i < resources.size(); ++i)
73    resource_id_ref_count_map_[resources[i].id].refs_to_return++;
74}
75
76void DelegatedFrameResourceCollection::UnrefResources(
77    const ReturnedResourceArray& returned) {
78  DCHECK(main_thread_checker_.CalledOnValidThread());
79
80  if (lost_all_resources_)
81    return;
82
83  ReturnedResourceArray to_return;
84
85  for (size_t i = 0; i < returned.size(); ++i) {
86    ResourceIdRefCountMap::iterator it =
87        resource_id_ref_count_map_.find(returned[i].id);
88    DCHECK(it != resource_id_ref_count_map_.end());
89    DCHECK_GE(it->second.refs_to_wait_for, returned[i].count);
90    it->second.refs_to_wait_for -= returned[i].count;
91    if (it->second.refs_to_wait_for == 0) {
92      to_return.push_back(returned[i]);
93      to_return.back().count = it->second.refs_to_return;
94      resource_id_ref_count_map_.erase(it);
95    }
96  }
97
98  if (to_return.empty())
99    return;
100
101  returned_resources_for_child_compositor_.insert(
102      returned_resources_for_child_compositor_.end(),
103      to_return.begin(),
104      to_return.end());
105  if (client_)
106    client_->UnusedResourcesAreAvailable();
107}
108
109void DelegatedFrameResourceCollection::RefResources(
110    const TransferableResourceArray& resources) {
111  DCHECK(main_thread_checker_.CalledOnValidThread());
112  for (size_t i = 0; i < resources.size(); ++i)
113    resource_id_ref_count_map_[resources[i].id].refs_to_wait_for++;
114}
115
116static void UnrefResourcesOnImplThread(
117    base::WeakPtr<DelegatedFrameResourceCollection> self,
118    scoped_refptr<BlockingTaskRunner> main_thread_runner,
119    const ReturnedResourceArray& returned) {
120  main_thread_runner->PostTask(
121      FROM_HERE,
122      base::Bind(
123          &DelegatedFrameResourceCollection::UnrefResources, self, returned));
124}
125
126ReturnCallback
127DelegatedFrameResourceCollection::GetReturnResourcesCallbackForImplThread() {
128  return base::Bind(&UnrefResourcesOnImplThread,
129                    weak_ptr_factory_.GetWeakPtr(),
130                    main_thread_runner_);
131}
132
133}  // namespace cc
134