OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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_ |
OLD | NEW |