Chromium Code Reviews| 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> |
| 11 | 11 |
| 12 #include "base/containers/mru_cache.h" | 12 #include "base/containers/mru_cache.h" |
| 13 #include "base/memory/discardable_memory.h" | 13 #include "base/memory/discardable_memory.h" |
| 14 #include "base/synchronization/lock.h" | 14 #include "base/synchronization/lock.h" |
| 15 #include "base/trace_event/memory_dump_provider.h" | 15 #include "base/trace_event/memory_dump_provider.h" |
| 16 #include "cc/base/cc_export.h" | 16 #include "cc/base/cc_export.h" |
| 17 #include "cc/resources/resource_format.h" | 17 #include "cc/resources/resource_format.h" |
| 18 #include "cc/tiles/image_decode_controller.h" | 18 #include "cc/tiles/image_decode_controller.h" |
| 19 #include "third_party/skia/include/core/SkRefCnt.h" | 19 #include "third_party/skia/include/core/SkRefCnt.h" |
| 20 | 20 |
| 21 class SkImageTextureData; | 21 class SkImageTextureData; |
| 22 | 22 |
| 23 namespace cc { | 23 namespace cc { |
| 24 | 24 |
| 25 class ContextProvider; | 25 class ContextProvider; |
| 26 | 26 |
| 27 // OVERVIEW: | |
| 28 // | |
| 27 // GpuImageDecodeController handles the decode and upload of images that will | 29 // GpuImageDecodeController handles the decode and upload of images that will |
| 28 // be used by Skia's GPU raster path. It also maintains a cache of these | 30 // be used by Skia's GPU raster path. It also maintains a cache of these |
| 29 // decoded/uploaded images for later re-use. | 31 // decoded/uploaded images for later re-use. |
| 30 // | 32 // |
| 31 // Generally, when an image is required for raster, GpuImageDecodeController | 33 // Generally, when an image is required for raster, GpuImageDecodeController |
| 32 // creates two tasks, one to decode the image, and one to upload the image to | 34 // creates two tasks, one to decode the image, and one to upload the image to |
| 33 // the GPU. These tasks are completed before the raster task which depends on | 35 // the GPU. These tasks are completed before the raster task which depends on |
| 34 // the image. We need to seperate decode and upload tasks, as decode can occur | 36 // the image. We need to seperate decode and upload tasks, as decode can occur |
| 35 // simultaneously on multiple threads, while upload requires the GL context | 37 // simultaneously on multiple threads, while upload requires the GL context |
| 36 // lock must happen on our non-concurrent raster thread. | 38 // lock must happen on our non-concurrent raster thread. |
| 37 // | 39 // |
| 38 // Decoded and Uploaded image data share a single cache entry. Depending on how | 40 // Decoded and Uploaded image data share a single cache entry. Depending on how |
| 39 // far we've progressed, this cache entry may contain CPU-side decoded data, | 41 // far we've progressed, this cache entry may contain CPU-side decoded data, |
| 40 // GPU-side uploaded data, or both. Because CPU-side decoded data is stored in | 42 // GPU-side uploaded data, or both. Because CPU-side decoded data is stored in |
| 41 // discardable memory, and is only locked for short periods of time (until the | 43 // discardable memory, and is only locked for short periods of time (until the |
| 42 // upload completes), this memory is not counted against our sized cache | 44 // upload completes), this memory is not counted against our sized cache |
| 43 // limits. Uploaded GPU memory, being non-discardable, always counts against | 45 // limits. Uploaded GPU memory, being non-discardable, always counts against |
| 44 // our limits. | 46 // our limits. |
| 45 // | 47 // |
| 46 // In cases where the number of images needed exceeds our cache limits, we | 48 // 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 | 49 // 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 | 50 // 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 | 51 // 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 | 52 // prevents future tasks from taking a dependency on them and extending their |
| 51 // lifetime longer than is necessary. | 53 // lifetime longer than is necessary. |
| 54 // | |
| 55 // RASTER-SCALE CACHING: | |
|
vmpstr
2016/06/21 20:07:08
Can you move this to a doc? Can you add a section
ericrk
2016/06/22 18:56:38
Added a ref-counting section. Will move to a doc o
| |
| 56 // | |
| 57 // In order to save memory, images which are going to be scaled may be uploaded | |
| 58 // at lower than original resolution. In these cases, we may later need to | |
| 59 // re-upload the image at a higher resolution. To handle multiple images of | |
| 60 // different scales being in use at the same time, we have a two-part caching | |
| 61 // system. | |
| 62 // | |
| 63 // The first cache, |persistent_cache_|, stores one ImageData per image id. | |
| 64 // These ImageDatas are not necessarily associated with a given DrawImage, and | |
| 65 // are saved (persisted) even when their ref-count reaches zero (assuming they | |
| 66 // fit in the current memory budget). This allows for future re-use of image | |
| 67 // resources. | |
| 68 // | |
| 69 // The second cache, |in_use_cache_|, stores one image data per DrawImage - | |
| 70 // this may be the same ImageData that is in the persistent_cache_. These | |
| 71 // cache entries are more transient and are deleted as soon as all refs to the | |
| 72 // given DrawImage are released (the image is no longer in-use). | |
| 73 // | |
| 74 // Consider the following two cases, which show the cache-usage patterns. | |
| 75 // | |
| 76 // Case 1: Larger (1x) scale used before smaller (0.5x) scale. | |
| 77 // | |
| 78 // Step 1: Create/Find Tasks and ImageData for 1x Scale (GetTaskForImageAndRef) | |
| 79 // 1a: No existing cache data exists, 1x ImageData created | |
| 80 // 1b: 1x ImageData cached in |persistent_cache_| with image's unique ID as | |
| 81 // key. | |
| 82 // 1c: 1x ImageData cached in |in_use_cache_| with 1x Scale key. | |
| 83 // 1d: 1x Decode task created, cached in 1x ImageData. | |
| 84 // 1e: 1x Upload task created, cached in 1x ImageData. | |
| 85 // | |
| 86 // ╔═══════════════════╗ ╔══════════════════════╗ | |
| 87 // ║ Persistent Cache ║ ║ In-Use Cache ║ | |
| 88 // ╟───────┬───────────╢ ╟───────────┬──────────╢ | |
| 89 // ║ image │ 1x ║ ║ 1x Scale │ 1x ║ | |
| 90 // ║ ID Key│ ImageData ║ ║ Key │ ImageData║ | |
| 91 // ╚═══════╧═══════════╝ ╚═══════════╧══════════╝ | |
| 92 // | |
| 93 // Step 2: Create/Find Tasks and ImageData for 0.5x Scale | |
| 94 // 2a: Find 1x ImageData in |persistent_cache_|. 0.5x scale can use this. | |
| 95 // 2b: 1x ImageData cached in |in_use_cache_| with 0.5x scale key. | |
| 96 // | |
| 97 // ╔═══════════════════╗ ╔══════════════════════╗ | |
| 98 // ║ Persistent Cache ║ ║ In-Use Cache ║ | |
| 99 // ╟───────┬───────────╢ ╟───────────┬──────────╢ | |
| 100 // ║ image │ 1x ║ ║ 1x Scale │ 1x ║ | |
| 101 // ║ ID Key│ ImageData ║ ║ Key │ ImageData║ | |
| 102 // ╚═══════╧═══════════╝ ╟───────────┼──────────╢ | |
| 103 // ║ 0.5x Scale│ 1x ║ | |
| 104 // ║ Key │ ImageData║ | |
| 105 // ╚═══════════╧══════════╝ | |
| 106 // | |
| 107 // Step 4: Draw 1x Scale | |
| 108 // 1x scale looked up in |in_use_cache_| via 1x key. | |
| 109 // | |
| 110 // Step 5: Draw 0.5x Scale | |
| 111 // 1x scale looked up in |in_use_cache_| via 0.5x key. | |
| 112 // | |
| 113 // Step 6: Finished, refs released | |
| 114 // Tasks are deleted from ImageData. | |
| 115 // Entries are deleted from |in_use_cache_|. | |
| 116 // 1x scale preserved in |persistent_cache_|. | |
| 117 // | |
| 118 // ╔═══════════════════╗ ╔════════════════════╗ | |
| 119 // ║ Persistent Cache ║ ║ In-Use Cache ║ | |
| 120 // ╟───────┬───────────╢ ╚════════════════════╝ | |
| 121 // ║ image │ 1x ║ | |
| 122 // ║ ID Key│ ImageData ║ | |
| 123 // ╚═══════╧═══════════╝ | |
| 124 // | |
| 125 // Case 2: Smaller (0.5x) scale used before larger (1x) scale. | |
| 126 // | |
| 127 // Step 1: Create/Find Tasks and ImageData for 0.5x Scale | |
| 128 // (GetTaskForImageAndRef) | |
| 129 // 1a: No existing cache data exists, 0.5x ImageData created | |
| 130 // 1b: 0.5x ImageData cached in |persistent_cache_| with image's unique ID | |
| 131 // as key. | |
| 132 // 1c: 0.5x ImageData cached in |in_use_cache_| with 0.5x Scale key. | |
| 133 // 1d: 0.5x Decode task created, cached in 0.5x ImageData. | |
| 134 // 1e: 0.5x Upload task created, cached in 0.5x ImageData. | |
| 135 // | |
| 136 // ╔═══════════════════╗ ╔══════════════════════╗ | |
| 137 // ║ Persistent Cache ║ ║ In-Use Cache ║ | |
| 138 // ╟───────┬───────────╢ ╟───────────┬──────────╢ | |
| 139 // ║ image │ 0.5 ║ ║ 0.5x Scale│ 0.5x ║ | |
| 140 // ║ ID Key│ ImageData ║ ║ Key │ ImageData║ | |
| 141 // ╚═══════╧═══════════╝ ╚═══════════╧══════════╝ | |
| 142 // | |
| 143 // Step 2: Create/Find Tasks and ImageData for 1x Scale | |
| 144 // 2a: Find 0.5x ImageData in |persistent_cache_|. 1x scale can't use this. | |
| 145 // 2b: 0.5x scale is about to be replaced by 1x scale, remove it from the | |
|
vmpstr
2016/06/21 20:07:08
When does this happen? What about the case where t
ericrk
2016/06/22 18:56:38
The 0.5x scale is only removed from the persistent
| |
| 146 // persistent_cache_. | |
| 147 // 2c: 1x ImageData created | |
| 148 // 2d: 1x ImageData cached in |persistent_cache_| with image's unique ID as | |
| 149 // key. | |
| 150 // 2e: 1x ImageData cached in |in_use_cache_| with 1x Scale key. | |
| 151 // 2f: 1x Decode task created, cached in 1x ImageData. | |
| 152 // 2g: 1x Upload task created, cached in 1x ImageData. | |
| 153 // | |
| 154 // ╔═══════════════════╗ ╔══════════════════════╗ | |
| 155 // ║ Persistent Cache ║ ║ In-Use Cache ║ | |
| 156 // ╟───────┬───────────╢ ╟───────────┬──────────╢ | |
| 157 // ║ image │ 1x ║ ║ 1x Scale │ 1x ║ | |
| 158 // ║ ID Key│ ImageData ║ ║ Key │ ImageData║ | |
| 159 // ╚═══════╧═══════════╝ ╟───────────┼──────────╢ | |
| 160 // ║ 0.5x Scale│ 0.5x ║ | |
| 161 // ║ Key │ ImageData║ | |
| 162 // ╚═══════════╧══════════╝ | |
| 163 // | |
| 164 // Step 4: Draw 0.5x Scale | |
| 165 // 0.5x scale looked up in |in_use_cache_| via 0.5x key. | |
| 166 // | |
| 167 // Step 5: Draw 1x Scale | |
| 168 // 1x scale looked up in |in_use_cache_| via 1x key. | |
| 169 // | |
| 170 // Step 6: Finished, refs released | |
| 171 // Tasks are deleted from ImageDatas. | |
| 172 // Entries are deleted from |in_use_cache_|. | |
| 173 // 1x scale preserved in |persistent_cache_|. | |
| 174 // | |
| 175 // ╔═══════════════════╗ ╔════════════════════╗ | |
| 176 // ║ Persistent Cache ║ ║ In-Use Cache ║ | |
| 177 // ╟───────┬───────────╢ ╚════════════════════╝ | |
| 178 // ║ image │ 1x ║ | |
| 179 // ║ ID Key│ ImageData ║ | |
| 180 // ╚═══════╧═══════════╝ | |
| 181 // | |
| 52 class CC_EXPORT GpuImageDecodeController | 182 class CC_EXPORT GpuImageDecodeController |
| 53 : public ImageDecodeController, | 183 : public ImageDecodeController, |
| 54 public base::trace_event::MemoryDumpProvider { | 184 public base::trace_event::MemoryDumpProvider { |
| 55 public: | 185 public: |
| 56 explicit GpuImageDecodeController(ContextProvider* context, | 186 explicit GpuImageDecodeController(ContextProvider* context, |
| 57 ResourceFormat decode_format, | 187 ResourceFormat decode_format, |
| 58 size_t max_gpu_image_bytes); | 188 size_t max_gpu_image_bytes); |
| 59 ~GpuImageDecodeController() override; | 189 ~GpuImageDecodeController() override; |
| 60 | 190 |
| 61 // ImageDecodeController overrides. | 191 // ImageDecodeController overrides. |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 86 void OnImageUploadTaskCompleted(const DrawImage& image); | 216 void OnImageUploadTaskCompleted(const DrawImage& image); |
| 87 | 217 |
| 88 // For testing only. | 218 // For testing only. |
| 89 void SetCachedItemLimitForTesting(size_t limit) { | 219 void SetCachedItemLimitForTesting(size_t limit) { |
| 90 cached_items_limit_ = limit; | 220 cached_items_limit_ = limit; |
| 91 } | 221 } |
| 92 void SetCachedBytesLimitForTesting(size_t limit) { | 222 void SetCachedBytesLimitForTesting(size_t limit) { |
| 93 cached_bytes_limit_ = limit; | 223 cached_bytes_limit_ = limit; |
| 94 } | 224 } |
| 95 size_t GetBytesUsedForTesting() const { return bytes_used_; } | 225 size_t GetBytesUsedForTesting() const { return bytes_used_; } |
| 226 size_t GetDrawImageSizeForTesting(const DrawImage& image); | |
| 96 void SetImageDecodingFailedForTesting(const DrawImage& image); | 227 void SetImageDecodingFailedForTesting(const DrawImage& image); |
| 97 bool DiscardableIsLockedForTesting(const DrawImage& image); | 228 bool DiscardableIsLockedForTesting(const DrawImage& image); |
| 98 | 229 |
| 99 private: | 230 private: |
| 100 enum class DecodedDataMode { GPU, CPU }; | 231 enum class DecodedDataMode { GPU, CPU }; |
| 101 | 232 |
| 102 // Stores the CPU-side decoded bits of an image and supporting fields. | 233 // Stores the CPU-side decoded bits of an image and supporting fields. |
| 103 struct DecodedImageData { | 234 struct DecodedImageData { |
| 104 DecodedImageData(); | 235 DecodedImageData(); |
| 105 ~DecodedImageData(); | 236 ~DecodedImageData(); |
| 106 | 237 |
| 107 bool is_locked() const { return is_locked_; } | 238 bool is_locked() const { return is_locked_; } |
| 108 bool Lock(); | 239 bool Lock(); |
| 109 void Unlock(); | 240 void Unlock(); |
| 110 void SetLockedData(std::unique_ptr<base::DiscardableMemory> data); | 241 void SetLockedData(std::unique_ptr<base::DiscardableMemory> data); |
| 111 void ResetData(); | 242 void ResetData(); |
| 112 base::DiscardableMemory* data() const { return data_.get(); } | 243 base::DiscardableMemory* data() const { return data_.get(); } |
| 113 | |
| 114 void mark_used() { usage_stats_.used = true; } | 244 void mark_used() { usage_stats_.used = true; } |
| 115 | 245 |
| 116 // May be null if image not yet decoded. | |
| 117 uint32_t ref_count = 0; | 246 uint32_t ref_count = 0; |
| 118 // Set to true if the image was corrupt and could not be decoded. | 247 // Set to true if the image was corrupt and could not be decoded. |
| 119 bool decode_failure = false; | 248 bool decode_failure = false; |
| 249 // If non-null, this is the pending decode task for this image. | |
| 250 scoped_refptr<TileTask> task; | |
| 120 | 251 |
| 121 private: | 252 private: |
| 122 struct UsageStats { | 253 struct UsageStats { |
| 123 int lock_count = 1; | 254 int lock_count = 1; |
| 124 bool used = false; | 255 bool used = false; |
| 125 bool first_lock_wasted = false; | 256 bool first_lock_wasted = false; |
| 126 }; | 257 }; |
| 127 | 258 |
| 128 void ReportUsageStats() const; | 259 void ReportUsageStats() const; |
| 129 | 260 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 142 | 273 |
| 143 void mark_used() { usage_stats_.used = true; } | 274 void mark_used() { usage_stats_.used = true; } |
| 144 void notify_ref_reached_zero() { | 275 void notify_ref_reached_zero() { |
| 145 if (++usage_stats_.ref_reached_zero_count == 1) | 276 if (++usage_stats_.ref_reached_zero_count == 1) |
| 146 usage_stats_.first_ref_wasted = !usage_stats_.used; | 277 usage_stats_.first_ref_wasted = !usage_stats_.used; |
| 147 } | 278 } |
| 148 | 279 |
| 149 // True if the image is counting against our memory limits. | 280 // True if the image is counting against our memory limits. |
| 150 bool budgeted = false; | 281 bool budgeted = false; |
| 151 uint32_t ref_count = 0; | 282 uint32_t ref_count = 0; |
| 283 // If non-null, this is the pending upload task for this image. | |
| 284 scoped_refptr<TileTask> task; | |
| 152 | 285 |
| 153 private: | 286 private: |
| 154 struct UsageStats { | 287 struct UsageStats { |
| 155 bool used = false; | 288 bool used = false; |
| 156 bool first_ref_wasted = false; | 289 bool first_ref_wasted = false; |
| 157 int ref_reached_zero_count = 0; | 290 int ref_reached_zero_count = 0; |
| 158 }; | 291 }; |
| 159 | 292 |
| 160 void ReportUsageStats() const; | 293 void ReportUsageStats() const; |
| 161 | 294 |
| 162 // May be null if image not yet uploaded / prepared. | 295 // May be null if image not yet uploaded / prepared. |
| 163 sk_sp<SkImage> image_; | 296 sk_sp<SkImage> image_; |
| 164 UsageStats usage_stats_; | 297 UsageStats usage_stats_; |
| 165 }; | 298 }; |
| 166 | 299 |
| 167 struct ImageData { | 300 struct ImageData : public base::RefCounted<ImageData> { |
| 168 ImageData(DecodedDataMode mode, size_t size); | 301 ImageData(DecodedDataMode mode, |
| 169 ~ImageData(); | 302 size_t size, |
| 303 int pre_scale_mip_level, | |
| 304 SkFilterQuality pre_scale_filter_quality); | |
| 170 | 305 |
| 171 const DecodedDataMode mode; | 306 const DecodedDataMode mode; |
| 172 const size_t size; | 307 const size_t size; |
| 173 bool is_at_raster = false; | 308 bool is_at_raster = false; |
| 174 | 309 |
| 310 // Variables used to identify/track multiple scale levels of a single image. | |
| 311 int pre_scale_mip_level; | |
| 312 SkFilterQuality pre_scale_filter_quality; | |
| 313 bool is_orphaned = false; | |
|
vmpstr
2016/06/21 20:07:08
Set the above variables as well (even though they'
ericrk
2016/06/22 18:56:38
Done.
| |
| 314 | |
| 175 DecodedImageData decode; | 315 DecodedImageData decode; |
| 176 UploadedImageData upload; | 316 UploadedImageData upload; |
| 317 | |
| 318 private: | |
| 319 friend class base::RefCounted<ImageData>; | |
| 320 ~ImageData(); | |
| 177 }; | 321 }; |
| 178 | 322 |
| 179 using ImageDataMRUCache = | 323 // A ref-count and ImageData, used to associate the ImageData with a specific |
| 180 base::MRUCache<uint32_t, std::unique_ptr<ImageData>>; | 324 // DrawImage in the |in_use_cache_|. |
| 325 struct InUseCacheEntry { | |
| 326 explicit InUseCacheEntry(scoped_refptr<ImageData> image_data); | |
| 327 InUseCacheEntry(const InUseCacheEntry& other); | |
| 328 InUseCacheEntry(InUseCacheEntry&& other); | |
| 329 ~InUseCacheEntry(); | |
| 330 | |
| 331 uint32_t ref_count = 0; | |
| 332 scoped_refptr<ImageData> image_data; | |
| 333 }; | |
| 334 | |
| 335 // Uniquely identifies (without collisions) a specific DrawImage for use in | |
| 336 // the |in_use_cache_|. | |
| 337 using InUseCacheKey = uint64_t; | |
| 181 | 338 |
| 182 // All private functions should only be called while holding |lock_|. Some | 339 // All private functions should only be called while holding |lock_|. Some |
| 183 // functions also require the |context_| lock. These are indicated by | 340 // functions also require the |context_| lock. These are indicated by |
| 184 // additional comments. | 341 // additional comments. |
| 185 | 342 |
| 186 // Similar to GetTaskForImageAndRef, but gets the dependent decode task | 343 // Similar to GetTaskForImageAndRef, but gets the dependent decode task |
| 187 // rather than the upload task, if necessary. | 344 // rather than the upload task, if necessary. |
| 188 scoped_refptr<TileTask> GetImageDecodeTaskAndRef( | 345 scoped_refptr<TileTask> GetImageDecodeTaskAndRef( |
| 189 const DrawImage& image, | 346 const DrawImage& image, |
| 190 const TracingInfo& tracing_info); | 347 const TracingInfo& tracing_info); |
| 191 | 348 |
| 192 void RefImageDecode(const DrawImage& draw_image); | 349 void RefImageDecode(const DrawImage& draw_image); |
| 193 void UnrefImageDecode(const DrawImage& draw_image); | 350 void UnrefImageDecode(const DrawImage& draw_image); |
| 194 void RefImage(const DrawImage& draw_image); | 351 void RefImage(const DrawImage& draw_image); |
| 195 void UnrefImageInternal(const DrawImage& draw_image); | 352 void UnrefImageInternal(const DrawImage& draw_image); |
| 196 void RefCountChanged(ImageData* image_data); | 353 void RefCountChanged(ImageData* image_data); |
| 197 | 354 |
| 198 // Ensures that the cache can hold an element of |required_size|, freeing | 355 // Ensures that the cache can hold an element of |required_size|, freeing |
| 199 // unreferenced cache entries if necessary to make room. | 356 // unreferenced cache entries if necessary to make room. |
| 200 bool EnsureCapacity(size_t required_size); | 357 bool EnsureCapacity(size_t required_size); |
| 201 bool CanFitSize(size_t size) const; | 358 bool CanFitSize(size_t size) const; |
| 202 bool ExceedsPreferredCount() const; | 359 bool ExceedsPreferredCount() const; |
| 203 | 360 |
| 204 void DecodeImageIfNecessary(const DrawImage& draw_image, | 361 void DecodeImageIfNecessary(const DrawImage& draw_image, |
| 205 ImageData* image_data); | 362 ImageData* image_data); |
| 206 | 363 |
| 207 std::unique_ptr<GpuImageDecodeController::ImageData> CreateImageData( | 364 scoped_refptr<GpuImageDecodeController::ImageData> CreateImageData( |
| 208 const DrawImage& image); | 365 const DrawImage& image); |
| 209 SkImageInfo CreateImageInfoForDrawImage(const DrawImage& draw_image) const; | 366 SkImageInfo CreateImageInfoForDrawImage(const DrawImage& draw_image, |
| 367 int pre_scale_mip_level) const; | |
| 368 | |
| 369 // Finds the ImageData that should be used for the given DrawImage. Looks | |
| 370 // first in the |in_use_cache_|, and then in the |persistent_cache_|. | |
|
vmpstr
2016/06/21 20:07:08
When would it check the persistent_cache? From you
ericrk
2016/06/22 18:56:38
If the image has previously been used, but is not
| |
| 371 ImageData* GetImageDataForDrawImage(const DrawImage& image); | |
| 372 | |
| 373 // Returns true if the given ImageData can be used to draw the specified | |
| 374 // DrawImage. | |
| 375 bool IsCompatibleWithDrawImage(const ImageData* image_data, | |
| 376 const DrawImage& draw_image) const; | |
| 210 | 377 |
| 211 // The following two functions also require the |context_| lock to be held. | 378 // The following two functions also require the |context_| lock to be held. |
| 212 void UploadImageIfNecessary(const DrawImage& draw_image, | 379 void UploadImageIfNecessary(const DrawImage& draw_image, |
| 213 ImageData* image_data); | 380 ImageData* image_data); |
| 214 void DeletePendingImages(); | 381 void DeletePendingImages(); |
| 215 | 382 |
| 216 const ResourceFormat format_; | 383 const ResourceFormat format_; |
| 217 ContextProvider* context_; | 384 ContextProvider* context_; |
| 218 sk_sp<GrContextThreadSafeProxy> context_threadsafe_proxy_; | 385 sk_sp<GrContextThreadSafeProxy> context_threadsafe_proxy_; |
| 219 | 386 |
| 220 // All members below this point must only be accessed while holding |lock_|. | 387 // All members below this point must only be accessed while holding |lock_|. |
| 221 base::Lock lock_; | 388 base::Lock lock_; |
| 222 | 389 |
| 223 std::unordered_map<uint32_t, scoped_refptr<TileTask>> | 390 // |persistent_cache_| represents the long-lived cache, keeping a certain |
| 224 pending_image_upload_tasks_; | 391 // budget of ImageDatas alive even when their ref count reaches zero. |
| 225 std::unordered_map<uint32_t, scoped_refptr<TileTask>> | 392 using ImageDataMRUCache = base::MRUCache<uint32_t, scoped_refptr<ImageData>>; |
| 226 pending_image_decode_tasks_; | 393 ImageDataMRUCache persistent_cache_; |
| 227 | 394 |
| 228 ImageDataMRUCache image_data_; | 395 // |in_use_cache_| represents the in-use (short-lived) cache. Entries are |
| 396 // cleaned up as soon as their ref count reaches zero. | |
| 397 std::unordered_map<InUseCacheKey, InUseCacheEntry> in_use_cache_; | |
| 229 | 398 |
| 230 size_t cached_items_limit_; | 399 size_t cached_items_limit_; |
| 231 size_t cached_bytes_limit_; | 400 size_t cached_bytes_limit_; |
| 232 size_t bytes_used_; | 401 size_t bytes_used_; |
| 233 const size_t max_gpu_image_bytes_; | 402 const size_t max_gpu_image_bytes_; |
| 234 | 403 |
| 235 // We can't release GPU backed SkImages without holding the context lock, | 404 // 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 | 405 // so we add them to this list and defer deletion until the next time the lock |
| 237 // is held. | 406 // is held. |
| 238 std::vector<sk_sp<SkImage>> images_pending_deletion_; | 407 std::vector<sk_sp<SkImage>> images_pending_deletion_; |
| 239 }; | 408 }; |
| 240 | 409 |
| 241 } // namespace cc | 410 } // namespace cc |
| 242 | 411 |
| 243 #endif // CC_TILES_GPU_IMAGE_DECODE_CONTROLLER_H_ | 412 #endif // CC_TILES_GPU_IMAGE_DECODE_CONTROLLER_H_ |
| OLD | NEW |