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

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

Issue 2042133002: Add display-resolution caching to GPU IDC (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@drt
Patch Set: comments Created 4 years, 6 months 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/playback/draw_image.h ('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
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef CC_TILES_GPU_IMAGE_DECODE_CONTROLLER_H_ 5 #ifndef CC_TILES_GPU_IMAGE_DECODE_CONTROLLER_H_
6 #define CC_TILES_GPU_IMAGE_DECODE_CONTROLLER_H_ 6 #define CC_TILES_GPU_IMAGE_DECODE_CONTROLLER_H_
7 7
8 #include <memory> 8 #include <memory>
9 #include <unordered_map> 9 #include <unordered_map>
10 #include <vector> 10 #include <vector>
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 // upload completes), this memory is not counted against our sized cache 42 // upload completes), this memory is not counted against our sized cache
43 // limits. Uploaded GPU memory, being non-discardable, always counts against 43 // limits. Uploaded GPU memory, being non-discardable, always counts against
44 // our limits. 44 // our limits.
45 // 45 //
46 // In cases where the number of images needed exceeds our cache limits, we 46 // In cases where the number of images needed exceeds our cache limits, we
47 // operate in an "at-raster" mode. In this mode, there are no decode/upload 47 // operate in an "at-raster" mode. In this mode, there are no decode/upload
48 // tasks, and images are decoded/uploaded as needed, immediately before being 48 // tasks, and images are decoded/uploaded as needed, immediately before being
49 // used in raster. Cache entries for at-raster tasks are marked as such, which 49 // used in raster. Cache entries for at-raster tasks are marked as such, which
50 // prevents future tasks from taking a dependency on them and extending their 50 // prevents future tasks from taking a dependency on them and extending their
51 // lifetime longer than is necessary. 51 // lifetime longer than is necessary.
52 //
53 // In order to save memory, images which are going to be scaled may be uploaded
54 // at lower than original resolution. In these cases, we may later need to
55 // re-upload the image at a higher resolution, to accomodate a new use case. In
56 // dealing with multiple scales of the same image, we take the following
57 // approach:
58 // 1) If an image is already uploaded at a larger resolution than is needed,
59 // use that upload directly.
60 // 2) If an image is already uploaded at a lower resolution than is needed,
61 // orphan the existing upload (removing it from the main cache) and start
62 // uploading the larger version.
63 // 2a) Orphaned images will be deleted as soon as all existing references
64 // to them are removed.
65 //
66 // In order to accomodate orphaned tasks, we have a two-part caching system. The
67 // primary cache, |image_data_|, stores one ImageData per image id. These
68 // ImageDatas are not necessarily associated with a given DrawImage, and are
69 // saved even when their ref-count reaches zero to allow for future re-use.
vmpstr 2016/06/14 21:35:27 It would be good to mention that it's kept there a
ericrk 2016/06/16 23:03:33 Done.
70 //
71 // The second cache, |image_data_for_draw_image_|, stores one image data per
72 // DrawImage - this may be the same ImageData that is in the primary cache.
73 // These cache entries are more transient than the primary cache and are deleted
74 // as soon as all refs to the given DrawImage are released.
75 //
76 // We consider an ImageData "orphaned" if it is in the secondary cache, but not
77 // the primary. This typically happens when we need a higher-quality/larger
78 // version of an image than what is in the primary cache, so we replace the
79 // primary cache entry. Orphaned ImageDatas still count against our budgets,
80 // but are cleaned up as soon as their ref count reaches zero.
52 class CC_EXPORT GpuImageDecodeController 81 class CC_EXPORT GpuImageDecodeController
53 : public ImageDecodeController, 82 : public ImageDecodeController,
54 public base::trace_event::MemoryDumpProvider { 83 public base::trace_event::MemoryDumpProvider {
55 public: 84 public:
56 explicit GpuImageDecodeController(ContextProvider* context, 85 explicit GpuImageDecodeController(ContextProvider* context,
57 ResourceFormat decode_format, 86 ResourceFormat decode_format,
58 size_t max_gpu_image_bytes); 87 size_t max_gpu_image_bytes);
59 ~GpuImageDecodeController() override; 88 ~GpuImageDecodeController() override;
60 89
61 // ImageDecodeController overrides. 90 // ImageDecodeController overrides.
(...skipping 24 matching lines...) Expand all
86 void OnImageUploadTaskCompleted(const DrawImage& image); 115 void OnImageUploadTaskCompleted(const DrawImage& image);
87 116
88 // For testing only. 117 // For testing only.
89 void SetCachedItemLimitForTesting(size_t limit) { 118 void SetCachedItemLimitForTesting(size_t limit) {
90 cached_items_limit_ = limit; 119 cached_items_limit_ = limit;
91 } 120 }
92 void SetCachedBytesLimitForTesting(size_t limit) { 121 void SetCachedBytesLimitForTesting(size_t limit) {
93 cached_bytes_limit_ = limit; 122 cached_bytes_limit_ = limit;
94 } 123 }
95 size_t GetBytesUsedForTesting() const { return bytes_used_; } 124 size_t GetBytesUsedForTesting() const { return bytes_used_; }
125 size_t GetDrawImageSizeForTesting(const DrawImage& image);
96 void SetImageDecodingFailedForTesting(const DrawImage& image); 126 void SetImageDecodingFailedForTesting(const DrawImage& image);
97 bool DiscardableIsLockedForTesting(const DrawImage& image); 127 bool DiscardableIsLockedForTesting(const DrawImage& image);
98 128
99 private: 129 private:
100 enum class DecodedDataMode { GPU, CPU }; 130 enum class DecodedDataMode { GPU, CPU };
101 131
102 // Stores the CPU-side decoded bits of an image and supporting fields. 132 // Stores the CPU-side decoded bits of an image and supporting fields.
103 struct DecodedImageData { 133 struct DecodedImageData {
104 DecodedImageData(); 134 DecodedImageData();
105 ~DecodedImageData(); 135 ~DecodedImageData();
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 int ref_reached_zero_count = 0; 187 int ref_reached_zero_count = 0;
158 }; 188 };
159 189
160 void ReportUsageStats() const; 190 void ReportUsageStats() const;
161 191
162 // May be null if image not yet uploaded / prepared. 192 // May be null if image not yet uploaded / prepared.
163 sk_sp<SkImage> image_; 193 sk_sp<SkImage> image_;
164 UsageStats usage_stats_; 194 UsageStats usage_stats_;
165 }; 195 };
166 196
167 struct ImageData { 197 struct ImageData : public base::RefCounted<ImageData> {
168 ImageData(DecodedDataMode mode, size_t size); 198 ImageData(DecodedDataMode mode,
169 ~ImageData(); 199 size_t size,
200 int pre_scale_mip_level,
201 SkFilterQuality pre_scale_filter_quality);
170 202
171 const DecodedDataMode mode; 203 const DecodedDataMode mode;
172 const size_t size; 204 const size_t size;
173 bool is_at_raster = false; 205 bool is_at_raster = false;
206 int pre_scale_mip_level;
207 SkFilterQuality pre_scale_filter_quality;
208 bool is_orphaned = false;
174 209
175 DecodedImageData decode; 210 DecodedImageData decode;
176 UploadedImageData upload; 211 UploadedImageData upload;
212
213 private:
214 friend class base::RefCounted<ImageData>;
215 ~ImageData();
177 }; 216 };
178 217
179 using ImageDataMRUCache = 218 // A ref-count and ImageData, used to associate the ImageData with a specific
180 base::MRUCache<uint32_t, std::unique_ptr<ImageData>>; 219 // DrawImage in the secondary |image_data_for_draw_image_| cache.
220 struct ImageDataForDrawImageEntry {
221 explicit ImageDataForDrawImageEntry(
222 const scoped_refptr<ImageData>& image_data);
vmpstr 2016/06/14 21:35:27 Pass by value, move into place?
ericrk 2016/06/16 23:03:33 Done.
223 ImageDataForDrawImageEntry(const ImageDataForDrawImageEntry&);
vmpstr 2016/06/14 21:35:27 nit: can you name the parameters? "other"? Also,
ericrk 2016/06/16 23:03:33 sadness: error: [chromium-style] Complex construc
224 ImageDataForDrawImageEntry(ImageDataForDrawImageEntry&&);
225 ~ImageDataForDrawImageEntry();
226
227 uint32_t ref_count = 0;
228 scoped_refptr<ImageData> image_data;
229 };
230
231 // A key used to identify a DrawImage in the |image_data_for_draw_image_|
232 // cache, as well as the pending task maps.
233 struct DrawImageKey {
234 uint32_t image_id;
vmpstr 2016/06/14 21:35:27 = 0 here and below
ericrk 2016/06/16 23:03:33 Done.
235 int mip_level;
236 SkFilterQuality quality;
237
238 bool operator==(const DrawImageKey& other) const {
239 return other.image_id == image_id && other.mip_level == mip_level &&
240 other.quality == quality;
241 }
242 };
243
244 struct DrawImageKeyHash {
245 std::size_t operator()(const DrawImageKey& key) const {
246 return base::HashInts(key.image_id,
247 base::HashInts(key.mip_level, key.quality));
vmpstr 2016/06/14 21:35:27 I wonder if you can do something smarter than Hash
ericrk 2016/06/16 23:03:33 Sure, I'll make a better hash :P
248 }
249 };
181 250
182 // All private functions should only be called while holding |lock_|. Some 251 // All private functions should only be called while holding |lock_|. Some
183 // functions also require the |context_| lock. These are indicated by 252 // functions also require the |context_| lock. These are indicated by
184 // additional comments. 253 // additional comments.
185 254
186 // Similar to GetTaskForImageAndRef, but gets the dependent decode task 255 // Similar to GetTaskForImageAndRef, but gets the dependent decode task
187 // rather than the upload task, if necessary. 256 // rather than the upload task, if necessary.
188 scoped_refptr<TileTask> GetImageDecodeTaskAndRef( 257 scoped_refptr<TileTask> GetImageDecodeTaskAndRef(
189 const DrawImage& image, 258 const DrawImage& image,
190 const TracingInfo& tracing_info); 259 const TracingInfo& tracing_info);
191 260
192 void RefImageDecode(const DrawImage& draw_image); 261 void RefImageDecode(const DrawImage& draw_image);
193 void UnrefImageDecode(const DrawImage& draw_image); 262 void UnrefImageDecode(const DrawImage& draw_image);
194 void RefImage(const DrawImage& draw_image); 263 void RefImage(const DrawImage& draw_image);
195 void UnrefImageInternal(const DrawImage& draw_image); 264 void UnrefImageInternal(const DrawImage& draw_image);
196 void RefCountChanged(ImageData* image_data); 265 void RefCountChanged(ImageData* image_data);
197 266
198 // Ensures that the cache can hold an element of |required_size|, freeing 267 // Ensures that the cache can hold an element of |required_size|, freeing
199 // unreferenced cache entries if necessary to make room. 268 // unreferenced cache entries if necessary to make room.
200 bool EnsureCapacity(size_t required_size); 269 bool EnsureCapacity(size_t required_size);
201 bool CanFitSize(size_t size) const; 270 bool CanFitSize(size_t size) const;
202 bool ExceedsPreferredCount() const; 271 bool ExceedsPreferredCount() const;
203 272
204 void DecodeImageIfNecessary(const DrawImage& draw_image, 273 void DecodeImageIfNecessary(const DrawImage& draw_image,
205 ImageData* image_data); 274 ImageData* image_data);
206 275
207 std::unique_ptr<GpuImageDecodeController::ImageData> CreateImageData( 276 scoped_refptr<GpuImageDecodeController::ImageData> CreateImageData(
208 const DrawImage& image); 277 const DrawImage& image);
209 SkImageInfo CreateImageInfoForDrawImage(const DrawImage& draw_image) const; 278 SkImageInfo CreateImageInfoForDrawImage(const DrawImage& draw_image) const;
279 ImageData* GetImageDataForDrawImage(const DrawImage& image);
280
281 // Returns true if the given ImageData is as large or larger than the
vmpstr 2016/06/14 21:35:28 This comment reads like like this could be an out
ericrk 2016/06/16 23:03:33 Now that the key is a uint64_t, moved this out-of-
282 // DrawImage.
283 bool IsCompatibleWithDrawImage(const ImageData* image_data,
284 const DrawImage& draw_image) const;
285
286 // Generates a key which can be used to look up the provided |draw_image| in
287 // the |image_data_for_draw_image_| map.
288 DrawImageKey GenerateDrawImageKey(const DrawImage& draw_image) const;
vmpstr 2016/06/14 21:35:27 This needs a better comment; specifically, can you
ericrk 2016/06/16 23:03:33 Removed the second fn and cleaned this up.
289
290 // Generates a key which can be used to look up the task for the provided
291 // |draw_image| in the task maps.
292 DrawImageKey GenerateTaskKeyForDrawImage(const DrawImage& draw_image);
210 293
211 // The following two functions also require the |context_| lock to be held. 294 // The following two functions also require the |context_| lock to be held.
212 void UploadImageIfNecessary(const DrawImage& draw_image, 295 void UploadImageIfNecessary(const DrawImage& draw_image,
213 ImageData* image_data); 296 ImageData* image_data);
214 void DeletePendingImages(); 297 void DeletePendingImages();
215 298
216 const ResourceFormat format_; 299 const ResourceFormat format_;
217 ContextProvider* context_; 300 ContextProvider* context_;
218 sk_sp<GrContextThreadSafeProxy> context_threadsafe_proxy_; 301 sk_sp<GrContextThreadSafeProxy> context_threadsafe_proxy_;
219 302
220 // All members below this point must only be accessed while holding |lock_|. 303 // All members below this point must only be accessed while holding |lock_|.
221 base::Lock lock_; 304 base::Lock lock_;
222 305
223 std::unordered_map<uint32_t, scoped_refptr<TileTask>> 306 using ImageDataMRUCache = base::MRUCache<uint32_t, scoped_refptr<ImageData>>;
224 pending_image_upload_tasks_; 307 // |image_data_| represents the primary (long-lived) cache.
225 std::unordered_map<uint32_t, scoped_refptr<TileTask>> 308 ImageDataMRUCache image_data_;
226 pending_image_decode_tasks_;
227 309
228 ImageDataMRUCache image_data_; 310 template <typename T>
311 using DrawImageMap = std::unordered_map<DrawImageKey, T, DrawImageKeyHash>;
312 // |image_data_for_draw_image_| represents the secondary (short-lived) cache.
313 DrawImageMap<ImageDataForDrawImageEntry> image_data_for_draw_image_;
vmpstr 2016/06/14 21:35:27 I'd find better names for these caches, maybe some
ericrk 2016/06/16 23:03:33 Renamed to |persistent_cache_| and |in_use_cache_|
314
315 // Upload and decode tasks are keyed on the exact DrawImage they are decoding.
316 DrawImageMap<scoped_refptr<TileTask>> pending_image_upload_tasks_;
317 DrawImageMap<scoped_refptr<TileTask>> pending_image_decode_tasks_;
229 318
230 size_t cached_items_limit_; 319 size_t cached_items_limit_;
231 size_t cached_bytes_limit_; 320 size_t cached_bytes_limit_;
232 size_t bytes_used_; 321 size_t bytes_used_;
233 const size_t max_gpu_image_bytes_; 322 const size_t max_gpu_image_bytes_;
234 323
235 // We can't release GPU backed SkImages without holding the context lock, 324 // We can't release GPU backed SkImages without holding the context lock,
236 // so we add them to this list and defer deletion until the next time the lock 325 // so we add them to this list and defer deletion until the next time the lock
237 // is held. 326 // is held.
238 std::vector<sk_sp<SkImage>> images_pending_deletion_; 327 std::vector<sk_sp<SkImage>> images_pending_deletion_;
239 }; 328 };
240 329
241 } // namespace cc 330 } // namespace cc
242 331
243 #endif // CC_TILES_GPU_IMAGE_DECODE_CONTROLLER_H_ 332 #endif // CC_TILES_GPU_IMAGE_DECODE_CONTROLLER_H_
OLDNEW
« no previous file with comments | « cc/playback/draw_image.h ('k') | cc/tiles/gpu_image_decode_controller.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698