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
gpu / command_buffer / service / service_transfer_cache.h [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef GPU_COMMAND_BUFFER_SERVICE_SERVICE_TRANSFER_CACHE_H_
#define GPU_COMMAND_BUFFER_SERVICE_SERVICE_TRANSFER_CACHE_H_
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <vector>
#include "base/containers/lru_cache.h"
#include "base/containers/span.h"
#include "base/functional/callback.h"
#include "base/functional/function_ref.h"
#include "base/gtest_prod_util.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "base/trace_event/memory_dump_provider.h"
#include "cc/paint/image_transfer_cache_entry.h"
#include "cc/paint/transfer_cache_entry.h"
#include "gpu/command_buffer/common/discardable_handle.h"
#include "gpu/command_buffer/service/context_group.h"
#include "gpu/gpu_gles2_export.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkYUVAInfo.h"
class GrDirectContext;
class SkImage;
namespace gpu {
// ServiceTransferCache is a GPU process interface for retrieving cached entries
// from the transfer cache. These entries are populated by client calls to the
// ClientTransferCache or by an image decode accelerator task in the GPU
// process.
//
// In addition to access, the ServiceTransferCache is also responsible for
// unlocking and deleting entries when no longer needed, as well as enforcing
// cache limits. If the cache exceeds its specified limits, unlocked transfer
// cache entries may be deleted.
class GPU_GLES2_EXPORT ServiceTransferCache
: public base::trace_event::MemoryDumpProvider {
public:
struct GPU_GLES2_EXPORT EntryKey {
EntryKey(int decoder_id,
cc::TransferCacheEntryType entry_type,
uint32_t entry_id);
int decoder_id;
cc::TransferCacheEntryType entry_type;
uint32_t entry_id;
};
ServiceTransferCache(const GpuPreferences& preferences,
base::RepeatingClosure flush_callback);
ServiceTransferCache(const ServiceTransferCache&) = delete;
ServiceTransferCache& operator=(const ServiceTransferCache&) = delete;
~ServiceTransferCache() override;
bool CreateLockedEntry(const EntryKey& key,
ServiceDiscardableHandle handle,
GrDirectContext* context,
skgpu::graphite::Recorder* graphite_recorder,
base::span<uint8_t> data);
void CreateLocalEntry(const EntryKey& key,
std::unique_ptr<cc::ServiceTransferCacheEntry> entry);
bool UnlockEntry(const EntryKey& key);
bool DeleteEntry(const EntryKey& key);
cc::ServiceTransferCacheEntry* GetEntry(const EntryKey& key);
void DeleteAllEntriesForDecoder(int decoder_id);
// Creates an image transfer cache entry using |plane_images| (refer to
// ServiceImageTransferCacheEntry::BuildFromHardwareDecodedImage() for
// details). |decoder_id| and |entry_id| are used for creating the
// ServiceTransferCache::EntryKey (assuming cc::TransferCacheEntryType:kImage
// for the type). Returns true if the entry could be created and inserted;
// false otherwise.
bool CreateLockedHardwareDecodedImageEntry(
int decoder_id,
uint32_t entry_id,
ServiceDiscardableHandle handle,
GrDirectContext* context,
std::vector<sk_sp<SkImage>> plane_images,
SkYUVAInfo::PlaneConfig plane_config,
SkYUVAInfo::Subsampling subsampling,
SkYUVColorSpace yuv_color_space,
size_t buffer_byte_size,
bool needs_mips);
void PurgeMemory(
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
// base::trace_event::MemoryDumpProvider implementation.
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) override;
// Test-only functions:
void SetCacheSizeLimitForTesting(size_t cache_size_limit) {
cache_size_limit_ = cache_size_limit;
EnforceLimits();
}
void SetMaxCacheEntriesForTesting(size_t max_cache_entries) {
max_cache_entries_ = max_cache_entries;
EnforceLimits();
}
size_t cache_size_for_testing() const { return total_size_; }
size_t entries_count_for_testing() const { return entries_.size(); }
private:
FRIEND_TEST_ALL_PREFIXES(ServiceTransferCacheTest, PurgeEntryOnTimer);
struct CacheEntryInternal {
CacheEntryInternal(std::optional<ServiceDiscardableHandle> handle,
std::unique_ptr<cc::ServiceTransferCacheEntry> entry);
CacheEntryInternal(CacheEntryInternal&& other);
CacheEntryInternal& operator=(CacheEntryInternal&& other);
~CacheEntryInternal();
std::optional<ServiceDiscardableHandle> handle;
std::unique_ptr<cc::ServiceTransferCacheEntry> entry;
base::TimeTicks last_use = base::TimeTicks::Now();
// For metrics.
uint32_t num_reuse = 0u;
base::TimeDelta max_last_use_delta;
};
struct EntryKeyComp {
bool operator()(const EntryKey& lhs, const EntryKey& rhs) const {
if (lhs.decoder_id != rhs.decoder_id)
return lhs.decoder_id < rhs.decoder_id;
if (lhs.entry_type != rhs.entry_type)
return lhs.entry_type < rhs.entry_type;
return lhs.entry_id < rhs.entry_id;
}
};
using EntryCache = base::LRUCache<EntryKey, CacheEntryInternal, EntryKeyComp>;
void EnforceLimits();
void MaybePostPruneOldEntries();
void PruneOldEntries();
// Helper to iterate through entries from least recently used to most
// recently used and erase them until `should_stop` returns true. Returns
// number of entries removed.
int RemoveOldEntriesUntil(
base::FunctionRef<bool(EntryCache::reverse_iterator)> should_stop);
template <typename Iterator>
Iterator ForceDeleteEntry(Iterator it);
const base::RepeatingClosure flush_callback_;
EntryCache entries_;
// Total size of all |entries_|. The same as summing
// GpuDiscardableEntry::size for each entry.
size_t total_size_ = 0;
// Total size of all |entries_| of TransferCacheEntryType::kImage.
size_t total_image_size_ = 0;
// Number of |entries_| of TransferCacheEntryType::kImage.
int total_image_count_ = 0;
// The limit above which the cache will start evicting resources.
size_t cache_size_limit_;
// The max number of entries we will hold in the cache.
size_t max_cache_entries_;
bool request_post_prune_old_entries_while_pending_ = false;
base::OneShotTimer prune_old_entries_timer_;
};
} // namespace gpu
#endif // GPU_COMMAND_BUFFER_SERVICE_SERVICE_TRANSFER_CACHE_H_