Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(237)

Side by Side Diff: cc/tiles/gpu_image_decode_controller.h

Issue 2541183002: cc: Rename ImageDecodeController to ImageDecodeCache. (Closed)
Patch Set: rename: update Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « cc/tiles/gpu_image_decode_cache_unittest.cc ('k') | cc/tiles/gpu_image_decode_controller.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 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 #ifndef CC_TILES_GPU_IMAGE_DECODE_CONTROLLER_H_
6 #define CC_TILES_GPU_IMAGE_DECODE_CONTROLLER_H_
7
8 #include <memory>
9 #include <unordered_map>
10 #include <vector>
11
12 #include "base/containers/mru_cache.h"
13 #include "base/memory/discardable_memory.h"
14 #include "base/memory/memory_coordinator_client.h"
15 #include "base/synchronization/lock.h"
16 #include "base/trace_event/memory_dump_provider.h"
17 #include "cc/base/cc_export.h"
18 #include "cc/resources/resource_format.h"
19 #include "cc/tiles/image_decode_controller.h"
20 #include "third_party/skia/include/core/SkRefCnt.h"
21
22 namespace cc {
23
24 class ContextProvider;
25
26 // OVERVIEW:
27 //
28 // GpuImageDecodeController handles the decode and upload of images that will
29 // be used by Skia's GPU raster path. It also maintains a cache of these
30 // decoded/uploaded images for later re-use.
31 //
32 // Generally, when an image is required for raster, GpuImageDecodeController
33 // creates two tasks, one to decode the image, and one to upload the image to
34 // the GPU. These tasks are completed before the raster task which depends on
35 // the image. We need to seperate decode and upload tasks, as decode can occur
36 // simultaneously on multiple threads, while upload requires the GL context
37 // lock must happen on our non-concurrent raster thread.
38 //
39 // Decoded and Uploaded image data share a single cache entry. Depending on how
40 // far we've progressed, this cache entry may contain CPU-side decoded data,
41 // GPU-side uploaded data, or both. Because CPU-side decoded data is stored in
42 // discardable memory, and is only locked for short periods of time (until the
43 // upload completes), this memory is not counted against our sized cache
44 // limits. Uploaded GPU memory, being non-discardable, always counts against
45 // our limits.
46 //
47 // In cases where the number of images needed exceeds our cache limits, we
48 // operate in an "at-raster" mode. In this mode, there are no decode/upload
49 // tasks, and images are decoded/uploaded as needed, immediately before being
50 // used in raster. Cache entries for at-raster tasks are marked as such, which
51 // prevents future tasks from taking a dependency on them and extending their
52 // lifetime longer than is necessary.
53 //
54 // RASTER-SCALE CACHING:
55 //
56 // In order to save memory, images which are going to be scaled may be uploaded
57 // at lower than original resolution. In these cases, we may later need to
58 // re-upload the image at a higher resolution. To handle multiple images of
59 // different scales being in use at the same time, we have a two-part caching
60 // system.
61 //
62 // The first cache, |persistent_cache_|, stores one ImageData per image id.
63 // These ImageDatas are not necessarily associated with a given DrawImage, and
64 // are saved (persisted) even when their ref-count reaches zero (assuming they
65 // fit in the current memory budget). This allows for future re-use of image
66 // resources.
67 //
68 // The second cache, |in_use_cache_|, stores one image data per DrawImage -
69 // this may be the same ImageData that is in the persistent_cache_. These
70 // cache entries are more transient and are deleted as soon as all refs to the
71 // given DrawImage are released (the image is no longer in-use).
72 //
73 // For examples of raster-scale caching, see https://goo.gl/0zCd9Z
74 //
75 // REF COUNTING:
76 //
77 // In dealing with the two caches in GpuImageDecodeController, there are three
78 // ref-counting concepts in use:
79 // 1) ImageData upload/decode ref-counts.
80 // These ref-counts represent the overall number of references to the
81 // upload or decode portion of an ImageData. These ref-counts control
82 // both whether the upload/decode data can be freed, as well as whether an
83 // ImageData can be removed from the |persistent_cache_|. ImageDatas are
84 // only removed from the |persistent_cache_| if their upload/decode
85 // ref-counts are zero or if they are orphaned and replaced by a new entry.
86 // 2) InUseCacheEntry ref-counts.
87 // These ref-counts represent the number of references to an
88 // InUseCacheEntry from a specific DrawImage. When the InUseCacheEntry's
89 // ref-count reaches 0 it will be deleted.
90 // 3) scoped_refptr ref-counts.
91 // Because both the persistent_cache_ and the in_use_cache_ point at the
92 // same ImageDatas (and may need to keep these ImageDatas alive independent
93 // of each other), they hold ImageDatas by scoped_refptr. The scoped_refptr
94 // keeps an ImageData alive while it is present in either the
95 // |persistent_cache_| or |in_use_cache_|.
96 //
97 class CC_EXPORT GpuImageDecodeController
98 : public ImageDecodeController,
99 public base::trace_event::MemoryDumpProvider,
100 public base::MemoryCoordinatorClient {
101 public:
102 explicit GpuImageDecodeController(ContextProvider* context,
103 ResourceFormat decode_format,
104 size_t max_gpu_image_bytes);
105 ~GpuImageDecodeController() override;
106
107 // ImageDecodeController overrides.
108
109 // Finds the existing uploaded image for the provided DrawImage. Creates an
110 // upload task to upload the image if an exsiting image does not exist.
111 bool GetTaskForImageAndRef(const DrawImage& image,
112 const TracingInfo& tracing_info,
113 scoped_refptr<TileTask>* task) override;
114 void UnrefImage(const DrawImage& image) override;
115 DecodedDrawImage GetDecodedImageForDraw(const DrawImage& draw_image) override;
116 void DrawWithImageFinished(const DrawImage& image,
117 const DecodedDrawImage& decoded_image) override;
118 void ReduceCacheUsage() override;
119 void SetShouldAggressivelyFreeResources(
120 bool aggressively_free_resources) override;
121
122 // MemoryDumpProvider overrides.
123 bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
124 base::trace_event::ProcessMemoryDump* pmd) override;
125
126 // base::MemoryCoordinatorClient overrides.
127 void OnMemoryStateChange(base::MemoryState state) override;
128
129 // Called by Decode / Upload tasks.
130 void DecodeImage(const DrawImage& image);
131 void UploadImage(const DrawImage& image);
132
133 // Called by Decode / Upload tasks when tasks are finished.
134 void OnImageDecodeTaskCompleted(const DrawImage& image);
135 void OnImageUploadTaskCompleted(const DrawImage& image);
136
137 // For testing only.
138 void SetCachedBytesLimitForTesting(size_t limit) {
139 cached_bytes_limit_ = limit;
140 }
141 size_t GetBytesUsedForTesting() const { return bytes_used_; }
142 size_t GetNumCacheEntriesForTesting() const {
143 return persistent_cache_.size();
144 }
145 size_t GetDrawImageSizeForTesting(const DrawImage& image);
146 void SetImageDecodingFailedForTesting(const DrawImage& image);
147 bool DiscardableIsLockedForTesting(const DrawImage& image);
148
149 private:
150 enum class DecodedDataMode { GPU, CPU };
151
152 // Stores the CPU-side decoded bits of an image and supporting fields.
153 struct DecodedImageData {
154 DecodedImageData();
155 ~DecodedImageData();
156
157 bool is_locked() const { return is_locked_; }
158 bool Lock();
159 void Unlock();
160 void SetLockedData(std::unique_ptr<base::DiscardableMemory> data);
161 void ResetData();
162 base::DiscardableMemory* data() const { return data_.get(); }
163 void mark_used() { usage_stats_.used = true; }
164
165 uint32_t ref_count = 0;
166 // Set to true if the image was corrupt and could not be decoded.
167 bool decode_failure = false;
168 // If non-null, this is the pending decode task for this image.
169 scoped_refptr<TileTask> task;
170
171 private:
172 struct UsageStats {
173 int lock_count = 1;
174 bool used = false;
175 bool first_lock_wasted = false;
176 };
177
178 void ReportUsageStats() const;
179
180 std::unique_ptr<base::DiscardableMemory> data_;
181 bool is_locked_ = false;
182 UsageStats usage_stats_;
183 };
184
185 // Stores the GPU-side image and supporting fields.
186 struct UploadedImageData {
187 UploadedImageData();
188 ~UploadedImageData();
189
190 void SetImage(sk_sp<SkImage> image);
191 const sk_sp<SkImage>& image() const { return image_; }
192
193 void mark_used() { usage_stats_.used = true; }
194 void notify_ref_reached_zero() {
195 if (++usage_stats_.ref_reached_zero_count == 1)
196 usage_stats_.first_ref_wasted = !usage_stats_.used;
197 }
198
199 // True if the image is counting against our memory limits.
200 bool budgeted = false;
201 uint32_t ref_count = 0;
202 // If non-null, this is the pending upload task for this image.
203 scoped_refptr<TileTask> task;
204
205 private:
206 struct UsageStats {
207 bool used = false;
208 bool first_ref_wasted = false;
209 int ref_reached_zero_count = 0;
210 };
211
212 void ReportUsageStats() const;
213
214 // May be null if image not yet uploaded / prepared.
215 sk_sp<SkImage> image_;
216 UsageStats usage_stats_;
217 };
218
219 struct ImageData : public base::RefCounted<ImageData> {
220 ImageData(DecodedDataMode mode,
221 size_t size,
222 const SkImage::DeferredTextureImageUsageParams& upload_params);
223
224 const DecodedDataMode mode;
225 const size_t size;
226 bool is_at_raster = false;
227 SkImage::DeferredTextureImageUsageParams upload_params;
228
229 // If true, this image is no longer in our |persistent_cache_| and will be
230 // deleted as soon as its ref count reaches zero.
231 bool is_orphaned = false;
232
233 DecodedImageData decode;
234 UploadedImageData upload;
235
236 private:
237 friend class base::RefCounted<ImageData>;
238 ~ImageData();
239 };
240
241 // A ref-count and ImageData, used to associate the ImageData with a specific
242 // DrawImage in the |in_use_cache_|.
243 struct InUseCacheEntry {
244 explicit InUseCacheEntry(scoped_refptr<ImageData> image_data);
245 InUseCacheEntry(const InUseCacheEntry& other);
246 InUseCacheEntry(InUseCacheEntry&& other);
247 ~InUseCacheEntry();
248
249 uint32_t ref_count = 0;
250 scoped_refptr<ImageData> image_data;
251 };
252
253 // Uniquely identifies (without collisions) a specific DrawImage for use in
254 // the |in_use_cache_|.
255 using InUseCacheKey = uint64_t;
256
257 // All private functions should only be called while holding |lock_|. Some
258 // functions also require the |context_| lock. These are indicated by
259 // additional comments.
260
261 // Similar to GetTaskForImageAndRef, but gets the dependent decode task
262 // rather than the upload task, if necessary.
263 scoped_refptr<TileTask> GetImageDecodeTaskAndRef(
264 const DrawImage& image,
265 const TracingInfo& tracing_info);
266
267 void RefImageDecode(const DrawImage& draw_image);
268 void UnrefImageDecode(const DrawImage& draw_image);
269 void RefImage(const DrawImage& draw_image);
270 void UnrefImageInternal(const DrawImage& draw_image);
271
272 // Called any time the ownership of an object changed. This includes changes
273 // to ref-count or to orphaned status.
274 void OwnershipChanged(const DrawImage& draw_image, ImageData* image_data);
275
276 // Ensures that the cache can hold an element of |required_size|, freeing
277 // unreferenced cache entries if necessary to make room.
278 bool EnsureCapacity(size_t required_size);
279 bool CanFitSize(size_t size) const;
280 bool ExceedsPreferredCount() const;
281
282 void DecodeImageIfNecessary(const DrawImage& draw_image,
283 ImageData* image_data);
284
285 scoped_refptr<GpuImageDecodeController::ImageData> CreateImageData(
286 const DrawImage& image);
287 SkImageInfo CreateImageInfoForDrawImage(const DrawImage& draw_image,
288 int upload_scale_mip_level) const;
289
290 // Finds the ImageData that should be used for the given DrawImage. Looks
291 // first in the |in_use_cache_|, and then in the |persistent_cache_|.
292 ImageData* GetImageDataForDrawImage(const DrawImage& image);
293
294 // Returns true if the given ImageData can be used to draw the specified
295 // DrawImage.
296 bool IsCompatible(const ImageData* image_data,
297 const DrawImage& draw_image) const;
298
299 // The following two functions also require the |context_| lock to be held.
300 void UploadImageIfNecessary(const DrawImage& draw_image,
301 ImageData* image_data);
302 void DeletePendingImages();
303
304 const ResourceFormat format_;
305 ContextProvider* context_;
306 sk_sp<GrContextThreadSafeProxy> context_threadsafe_proxy_;
307
308 // All members below this point must only be accessed while holding |lock_|.
309 base::Lock lock_;
310
311 // |persistent_cache_| represents the long-lived cache, keeping a certain
312 // budget of ImageDatas alive even when their ref count reaches zero.
313 using PersistentCache = base::MRUCache<uint32_t, scoped_refptr<ImageData>>;
314 PersistentCache persistent_cache_;
315
316 // |in_use_cache_| represents the in-use (short-lived) cache. Entries are
317 // cleaned up as soon as their ref count reaches zero.
318 using InUseCache = std::unordered_map<InUseCacheKey, InUseCacheEntry>;
319 InUseCache in_use_cache_;
320
321 const size_t normal_max_gpu_image_bytes_;
322 size_t cached_bytes_limit_ = normal_max_gpu_image_bytes_;
323 size_t bytes_used_ = 0;
324 base::MemoryState memory_state_ = base::MemoryState::NORMAL;
325
326 // We can't release GPU backed SkImages without holding the context lock,
327 // so we add them to this list and defer deletion until the next time the lock
328 // is held.
329 std::vector<sk_sp<SkImage>> images_pending_deletion_;
330 };
331
332 } // namespace cc
333
334 #endif // CC_TILES_GPU_IMAGE_DECODE_CONTROLLER_H_
OLDNEW
« no previous file with comments | « cc/tiles/gpu_image_decode_cache_unittest.cc ('k') | cc/tiles/gpu_image_decode_controller.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698