| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 #include "cc/tiles/software_image_decode_cache.h" | 5 #include "cc/tiles/software_image_decode_cache.h" |
| 6 | 6 |
| 7 #include <inttypes.h> | 7 #include <inttypes.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 using base::trace_event::MemoryAllocatorDump; | 31 using base::trace_event::MemoryAllocatorDump; |
| 32 using base::trace_event::MemoryDumpLevelOfDetail; | 32 using base::trace_event::MemoryDumpLevelOfDetail; |
| 33 | 33 |
| 34 namespace cc { | 34 namespace cc { |
| 35 namespace { | 35 namespace { |
| 36 | 36 |
| 37 // The number of entries to keep around in the cache. This limit can be breached | 37 // The number of entries to keep around in the cache. This limit can be breached |
| 38 // if more items are locked. That is, locked items ignore this limit. | 38 // if more items are locked. That is, locked items ignore this limit. |
| 39 // Depending on the memory state of the system, we limit the amount of items | 39 // Depending on the memory state of the system, we limit the amount of items |
| 40 // differently. | 40 // differently. |
| 41 const size_t kNormalMaxItemsInCache = 1000; | 41 const size_t kSIDNormalMaxItemsInCache = 1000; |
| 42 const size_t kThrottledMaxItemsInCache = 100; | 42 const size_t kSIDThrottledMaxItemsInCache = 100; |
| 43 const size_t kSuspendedMaxItemsInCache = 0; | 43 const size_t kSIDSuspendedMaxItemsInCache = 0; |
| 44 | 44 |
| 45 // If the size of the original sized image breaches kMemoryRatioToSubrect but we | 45 // If the size of the original sized image breaches kMemoryRatioToSubrect but we |
| 46 // don't need to scale the image, consider caching only the needed subrect. | 46 // don't need to scale the image, consider caching only the needed subrect. |
| 47 // The second part that much be true is that we cache only the needed subrect if | 47 // The second part that much be true is that we cache only the needed subrect if |
| 48 // the total size needed for the subrect is at most kMemoryRatioToSubrect * | 48 // the total size needed for the subrect is at most kMemoryRatioToSubrect * |
| 49 // (size needed for the full original image). | 49 // (size needed for the full original image). |
| 50 // Note that at least one of the dimensions has to be at least | 50 // Note that at least one of the dimensions has to be at least |
| 51 // kMinDimensionToSubrect before an image can breach the threshold. | 51 // kMinDimensionToSubrect before an image can breach the threshold. |
| 52 const size_t kMemoryThresholdToSubrect = 64 * 1024 * 1024; | 52 const size_t kMemoryThresholdToSubrect = 64 * 1024 * 1024; |
| 53 const int kMinDimensionToSubrect = 4 * 1024; | 53 const int kMinDimensionToSubrect = 4 * 1024; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 81 ~AutoDrawWithImageFinished() { | 81 ~AutoDrawWithImageFinished() { |
| 82 cache_->DrawWithImageFinished(draw_image_, decoded_draw_image_); | 82 cache_->DrawWithImageFinished(draw_image_, decoded_draw_image_); |
| 83 } | 83 } |
| 84 | 84 |
| 85 private: | 85 private: |
| 86 SoftwareImageDecodeCache* cache_; | 86 SoftwareImageDecodeCache* cache_; |
| 87 const DrawImage& draw_image_; | 87 const DrawImage& draw_image_; |
| 88 const DecodedDrawImage& decoded_draw_image_; | 88 const DecodedDrawImage& decoded_draw_image_; |
| 89 }; | 89 }; |
| 90 | 90 |
| 91 class ImageDecodeTaskImpl : public TileTask { | 91 class ImageDecodeTaskImpl2 : public TileTask { |
| 92 public: | 92 public: |
| 93 ImageDecodeTaskImpl(SoftwareImageDecodeCache* cache, | 93 ImageDecodeTaskImpl2(SoftwareImageDecodeCache* cache, |
| 94 const SoftwareImageDecodeCache::ImageKey& image_key, | 94 const SoftwareImageDecodeCache::ImageKey& image_key, |
| 95 const DrawImage& image, | 95 const DrawImage& image, |
| 96 SoftwareImageDecodeCache::DecodeTaskType task_type, | 96 SoftwareImageDecodeCache::DecodeTaskType task_type, |
| 97 const ImageDecodeCache::TracingInfo& tracing_info) | 97 const ImageDecodeCache::TracingInfo& tracing_info) |
| 98 : TileTask(true), | 98 : TileTask(true), |
| 99 cache_(cache), | 99 cache_(cache), |
| 100 image_key_(image_key), | 100 image_key_(image_key), |
| 101 image_(image), | 101 image_(image), |
| 102 task_type_(task_type), | 102 task_type_(task_type), |
| 103 tracing_info_(tracing_info) {} | 103 tracing_info_(tracing_info) {} |
| 104 | 104 |
| 105 // Overridden from Task: | 105 // Overridden from Task: |
| 106 void RunOnWorkerThread() override { | 106 void RunOnWorkerThread() override { |
| 107 TRACE_EVENT2("cc", "ImageDecodeTaskImpl::RunOnWorkerThread", "mode", | 107 TRACE_EVENT2("cc", "ImageDecodeTaskImpl2::RunOnWorkerThread", "mode", |
| 108 "software", "source_prepare_tiles_id", | 108 "software", "source_prepare_tiles_id", |
| 109 tracing_info_.prepare_tiles_id); | 109 tracing_info_.prepare_tiles_id); |
| 110 devtools_instrumentation::ScopedImageDecodeTask image_decode_task( | 110 devtools_instrumentation::ScopedImageDecodeTask image_decode_task( |
| 111 image_.image().get(), | 111 image_.image().get(), |
| 112 devtools_instrumentation::ScopedImageDecodeTask::kSoftware, | 112 devtools_instrumentation::ScopedImageDecodeTask::kSoftware, |
| 113 ImageDecodeCache::ToScopedTaskType(tracing_info_.task_type)); | 113 ImageDecodeCache::ToScopedTaskType(tracing_info_.task_type)); |
| 114 cache_->DecodeImage(image_key_, image_, task_type_); | 114 cache_->DecodeImage(image_key_, image_, task_type_); |
| 115 } | 115 } |
| 116 | 116 |
| 117 // Overridden from TileTask: | 117 // Overridden from TileTask: |
| 118 void OnTaskCompleted() override { | 118 void OnTaskCompleted() override { |
| 119 cache_->RemovePendingTask(image_key_, task_type_); | 119 cache_->RemovePendingTask(image_key_, task_type_); |
| 120 } | 120 } |
| 121 | 121 |
| 122 protected: | 122 protected: |
| 123 ~ImageDecodeTaskImpl() override {} | 123 ~ImageDecodeTaskImpl2() override {} |
| 124 | 124 |
| 125 private: | 125 private: |
| 126 SoftwareImageDecodeCache* cache_; | 126 SoftwareImageDecodeCache* cache_; |
| 127 SoftwareImageDecodeCache::ImageKey image_key_; | 127 SoftwareImageDecodeCache::ImageKey image_key_; |
| 128 DrawImage image_; | 128 DrawImage image_; |
| 129 SoftwareImageDecodeCache::DecodeTaskType task_type_; | 129 SoftwareImageDecodeCache::DecodeTaskType task_type_; |
| 130 const ImageDecodeCache::TracingInfo tracing_info_; | 130 const ImageDecodeCache::TracingInfo tracing_info_; |
| 131 | 131 |
| 132 DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl); | 132 DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl2); |
| 133 }; | 133 }; |
| 134 | 134 |
| 135 SkSize GetScaleAdjustment(const ImageDecodeCacheKey& key) { | 135 SkSize GetScaleAdjustment(const ImageDecodeCacheKey& key) { |
| 136 // If the requested filter quality did not require scale, then the adjustment | 136 // If the requested filter quality did not require scale, then the adjustment |
| 137 // is identity. | 137 // is identity. |
| 138 if (key.can_use_original_size_decode() || key.should_use_subrect()) { | 138 if (key.can_use_original_size_decode() || key.should_use_subrect()) { |
| 139 return SkSize::Make(1.f, 1.f); | 139 return SkSize::Make(1.f, 1.f); |
| 140 } else if (key.filter_quality() == kMedium_SkFilterQuality) { | 140 } else if (key.filter_quality() == kMedium_SkFilterQuality) { |
| 141 return MipMapUtil::GetScaleAdjustmentForSize(key.src_rect().size(), | 141 return MipMapUtil::GetScaleAdjustmentForSize(key.src_rect().size(), |
| 142 key.target_size()); | 142 key.target_size()); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 | 189 |
| 190 } // namespace | 190 } // namespace |
| 191 | 191 |
| 192 SoftwareImageDecodeCache::SoftwareImageDecodeCache( | 192 SoftwareImageDecodeCache::SoftwareImageDecodeCache( |
| 193 viz::ResourceFormat format, | 193 viz::ResourceFormat format, |
| 194 size_t locked_memory_limit_bytes) | 194 size_t locked_memory_limit_bytes) |
| 195 : decoded_images_(ImageMRUCache::NO_AUTO_EVICT), | 195 : decoded_images_(ImageMRUCache::NO_AUTO_EVICT), |
| 196 at_raster_decoded_images_(ImageMRUCache::NO_AUTO_EVICT), | 196 at_raster_decoded_images_(ImageMRUCache::NO_AUTO_EVICT), |
| 197 locked_images_budget_(locked_memory_limit_bytes), | 197 locked_images_budget_(locked_memory_limit_bytes), |
| 198 format_(format), | 198 format_(format), |
| 199 max_items_in_cache_(kNormalMaxItemsInCache) { | 199 max_items_in_cache_(kSIDNormalMaxItemsInCache) { |
| 200 // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview). | 200 // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview). |
| 201 // Don't register a dump provider in these cases. | 201 // Don't register a dump provider in these cases. |
| 202 if (base::ThreadTaskRunnerHandle::IsSet()) { | 202 if (base::ThreadTaskRunnerHandle::IsSet()) { |
| 203 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( | 203 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( |
| 204 this, "cc::SoftwareImageDecodeCache", | 204 this, "cc::SoftwareImageDecodeCache", |
| 205 base::ThreadTaskRunnerHandle::Get()); | 205 base::ThreadTaskRunnerHandle::Get()); |
| 206 } | 206 } |
| 207 // Register this component with base::MemoryCoordinatorClientRegistry. | 207 // Register this component with base::MemoryCoordinatorClientRegistry. |
| 208 base::MemoryCoordinatorClientRegistry::GetInstance()->Register(this); | 208 base::MemoryCoordinatorClientRegistry::GetInstance()->Register(this); |
| 209 } | 209 } |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 if (!new_image_fits_in_memory && (decoded_images_ref_counts_.find(key) == | 314 if (!new_image_fits_in_memory && (decoded_images_ref_counts_.find(key) == |
| 315 decoded_images_ref_counts_.end())) { | 315 decoded_images_ref_counts_.end())) { |
| 316 *task = nullptr; | 316 *task = nullptr; |
| 317 return false; | 317 return false; |
| 318 } | 318 } |
| 319 | 319 |
| 320 // Actually create the task. RefImage will account for memory on the first | 320 // Actually create the task. RefImage will account for memory on the first |
| 321 // ref. | 321 // ref. |
| 322 RefImage(key); | 322 RefImage(key); |
| 323 existing_task = make_scoped_refptr( | 323 existing_task = make_scoped_refptr( |
| 324 new ImageDecodeTaskImpl(this, key, image, task_type, tracing_info)); | 324 new ImageDecodeTaskImpl2(this, key, image, task_type, tracing_info)); |
| 325 *task = existing_task; | 325 *task = existing_task; |
| 326 return true; | 326 return true; |
| 327 } | 327 } |
| 328 | 328 |
| 329 void SoftwareImageDecodeCache::RefImage(const ImageKey& key) { | 329 void SoftwareImageDecodeCache::RefImage(const ImageKey& key) { |
| 330 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), | 330 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), |
| 331 "SoftwareImageDecodeCache::RefImage", "key", key.ToString()); | 331 "SoftwareImageDecodeCache::RefImage", "key", key.ToString()); |
| 332 lock_.AssertAcquired(); | 332 lock_.AssertAcquired(); |
| 333 int ref = ++decoded_images_ref_counts_[key]; | 333 int ref = ++decoded_images_ref_counts_[key]; |
| 334 if (ref == 1) { | 334 if (ref == 1) { |
| (...skipping 831 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1166 | 1166 |
| 1167 size_t SoftwareImageDecodeCache::MemoryBudget::GetCurrentUsageSafe() const { | 1167 size_t SoftwareImageDecodeCache::MemoryBudget::GetCurrentUsageSafe() const { |
| 1168 return current_usage_bytes_.ValueOrDie(); | 1168 return current_usage_bytes_.ValueOrDie(); |
| 1169 } | 1169 } |
| 1170 | 1170 |
| 1171 void SoftwareImageDecodeCache::OnMemoryStateChange(base::MemoryState state) { | 1171 void SoftwareImageDecodeCache::OnMemoryStateChange(base::MemoryState state) { |
| 1172 { | 1172 { |
| 1173 base::AutoLock hold(lock_); | 1173 base::AutoLock hold(lock_); |
| 1174 switch (state) { | 1174 switch (state) { |
| 1175 case base::MemoryState::NORMAL: | 1175 case base::MemoryState::NORMAL: |
| 1176 max_items_in_cache_ = kNormalMaxItemsInCache; | 1176 max_items_in_cache_ = kSIDNormalMaxItemsInCache; |
| 1177 break; | 1177 break; |
| 1178 case base::MemoryState::THROTTLED: | 1178 case base::MemoryState::THROTTLED: |
| 1179 max_items_in_cache_ = kThrottledMaxItemsInCache; | 1179 max_items_in_cache_ = kSIDThrottledMaxItemsInCache; |
| 1180 break; | 1180 break; |
| 1181 case base::MemoryState::SUSPENDED: | 1181 case base::MemoryState::SUSPENDED: |
| 1182 max_items_in_cache_ = kSuspendedMaxItemsInCache; | 1182 max_items_in_cache_ = kSIDSuspendedMaxItemsInCache; |
| 1183 break; | 1183 break; |
| 1184 case base::MemoryState::UNKNOWN: | 1184 case base::MemoryState::UNKNOWN: |
| 1185 NOTREACHED(); | 1185 NOTREACHED(); |
| 1186 return; | 1186 return; |
| 1187 } | 1187 } |
| 1188 } | 1188 } |
| 1189 } | 1189 } |
| 1190 | 1190 |
| 1191 void SoftwareImageDecodeCache::OnPurgeMemory() { | 1191 void SoftwareImageDecodeCache::OnPurgeMemory() { |
| 1192 base::AutoLock lock(lock_); | 1192 base::AutoLock lock(lock_); |
| 1193 ReduceCacheUsageUntilWithinLimit(0); | 1193 ReduceCacheUsageUntilWithinLimit(0); |
| 1194 } | 1194 } |
| 1195 | 1195 |
| 1196 } // namespace cc | 1196 } // namespace cc |
| OLD | NEW |