1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
|
// Copyright 2012 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.
#ifndef CC_RESOURCES_RESOURCE_POOL_H_
#define CC_RESOURCES_RESOURCE_POOL_H_
#include <stddef.h>
#include <stdint.h>
#include <deque>
#include <map>
#include <memory>
#include "base/macros.h"
#include "base/memory/memory_coordinator_client.h"
#include "base/memory/ptr_util.h"
#include "base/trace_event/memory_dump_provider.h"
#include "cc/base/cc_export.h"
#include "cc/resources/resource.h"
#include "cc/resources/resource_format.h"
#include "cc/resources/scoped_resource.h"
namespace cc {
class CC_EXPORT ResourcePool : public base::trace_event::MemoryDumpProvider,
public base::MemoryCoordinatorClient {
public:
// Delay before a resource is considered expired.
static base::TimeDelta kDefaultExpirationDelay;
static std::unique_ptr<ResourcePool> CreateForGpuMemoryBufferResources(
ResourceProvider* resource_provider,
base::SingleThreadTaskRunner* task_runner,
gfx::BufferUsage usage,
const base::TimeDelta& expiration_delay) {
return base::WrapUnique(new ResourcePool(resource_provider, task_runner,
usage, expiration_delay));
}
static std::unique_ptr<ResourcePool> Create(
ResourceProvider* resource_provider,
base::SingleThreadTaskRunner* task_runner,
ResourceProvider::TextureHint hint,
const base::TimeDelta& expiration_delay) {
return base::WrapUnique(new ResourcePool(resource_provider, task_runner,
hint, expiration_delay));
}
~ResourcePool() override;
// Tries to reuse a resource. If none are available, makes a new one.
Resource* AcquireResource(const gfx::Size& size,
ResourceFormat format,
const gfx::ColorSpace& color_space);
// Tries to acquire the resource with |previous_content_id| for us in partial
// raster. If successful, this function will retun the invalidated rect which
// must be re-rastered in |total_invalidated_rect|.
Resource* TryAcquireResourceForPartialRaster(
uint64_t new_content_id,
const gfx::Rect& new_invalidated_rect,
uint64_t previous_content_id,
gfx::Rect* total_invalidated_rect);
// Called when a resource's content has been fully replaced (and is completely
// valid). Updates the resource's content ID to its new value.
void OnContentReplaced(ResourceId resource_id, uint64_t content_id);
void ReleaseResource(Resource* resource);
void SetResourceUsageLimits(size_t max_memory_usage_bytes,
size_t max_resource_count);
void ReduceResourceUsage();
bool ResourceUsageTooHigh();
// Must be called regularly to move resources from the busy pool to the unused
// pool.
void CheckBusyResources();
size_t memory_usage_bytes() const { return in_use_memory_usage_bytes_; }
size_t resource_count() const { return in_use_resources_.size(); }
// Overridden from base::trace_event::MemoryDumpProvider:
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) override;
// Overriden from base::MemoryCoordinatorClient.
void OnPurgeMemory() override;
size_t GetTotalMemoryUsageForTesting() const {
return total_memory_usage_bytes_;
}
size_t GetTotalResourceCountForTesting() const {
return total_resource_count_;
}
size_t GetBusyResourceCountForTesting() const {
return busy_resources_.size();
}
protected:
// Constructor for creating GPU memory buffer resources.
ResourcePool(ResourceProvider* resource_provider,
base::SingleThreadTaskRunner* task_runner,
gfx::BufferUsage usage,
const base::TimeDelta& expiration_delay);
// Constructor for creating standard resources.
ResourcePool(ResourceProvider* resource_provider,
base::SingleThreadTaskRunner* task_runner,
ResourceProvider::TextureHint hint,
const base::TimeDelta& expiration_delay);
private:
FRIEND_TEST_ALL_PREFIXES(ResourcePoolTest, ReuseResource);
class PoolResource : public ScopedResource {
public:
static std::unique_ptr<PoolResource> Create(
ResourceProvider* resource_provider) {
return base::WrapUnique(new PoolResource(resource_provider));
}
void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd,
const ResourceProvider* resource_provider,
bool is_free) const;
uint64_t content_id() const { return content_id_; }
void set_content_id(uint64_t content_id) { content_id_ = content_id; }
base::TimeTicks last_usage() const { return last_usage_; }
void set_last_usage(base::TimeTicks time) { last_usage_ = time; }
gfx::Rect invalidated_rect() const { return invalidated_rect_; }
void set_invalidated_rect(const gfx::Rect& invalidated_rect) {
invalidated_rect_ = invalidated_rect;
}
private:
explicit PoolResource(ResourceProvider* resource_provider)
: ScopedResource(resource_provider), content_id_(0) {}
uint64_t content_id_;
base::TimeTicks last_usage_;
gfx::Rect invalidated_rect_;
};
// Tries to reuse a resource. Returns |nullptr| if none are available.
Resource* ReuseResource(const gfx::Size& size,
ResourceFormat format,
const gfx::ColorSpace& color_space);
// Creates a new resource without trying to reuse an old one.
Resource* CreateResource(const gfx::Size& size,
ResourceFormat format,
const gfx::ColorSpace& color_space);
void DidFinishUsingResource(std::unique_ptr<PoolResource> resource);
void DeleteResource(std::unique_ptr<PoolResource> resource);
static void UpdateResourceContentIdAndInvalidation(
PoolResource* resource,
uint64_t new_content_id,
const gfx::Rect& new_invalidated_rect);
// Functions which manage periodic eviction of expired resources.
void ScheduleEvictExpiredResourcesIn(base::TimeDelta time_from_now);
void EvictExpiredResources();
void EvictResourcesNotUsedSince(base::TimeTicks time_limit);
bool HasEvictableResources() const;
base::TimeTicks GetUsageTimeForLRUResource() const;
ResourceProvider* resource_provider_ = nullptr;
bool use_gpu_memory_buffers_ = false;
gfx::BufferUsage usage_ = gfx::BufferUsage::GPU_READ_CPU_READ_WRITE;
ResourceProvider::TextureHint hint_ = ResourceProvider::TEXTURE_HINT_DEFAULT;
size_t max_memory_usage_bytes_ = 0;
size_t max_resource_count_ = 0;
size_t in_use_memory_usage_bytes_ = 0;
size_t total_memory_usage_bytes_ = 0;
size_t total_resource_count_ = 0;
// Holds most recently used resources at the front of the queue.
using ResourceDeque = std::deque<std::unique_ptr<PoolResource>>;
ResourceDeque unused_resources_;
ResourceDeque busy_resources_;
using InUseResourceMap = std::map<ResourceId, std::unique_ptr<PoolResource>>;
InUseResourceMap in_use_resources_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
bool evict_expired_resources_pending_ = false;
const base::TimeDelta resource_expiration_delay_;
base::WeakPtrFactory<ResourcePool> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ResourcePool);
};
} // namespace cc
#endif // CC_RESOURCES_RESOURCE_POOL_H_
|