| 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 19 matching lines...) Expand all Loading... |
| 30 using base::trace_event::MemoryAllocatorDump; | 30 using base::trace_event::MemoryAllocatorDump; |
| 31 using base::trace_event::MemoryDumpLevelOfDetail; | 31 using base::trace_event::MemoryDumpLevelOfDetail; |
| 32 | 32 |
| 33 namespace cc { | 33 namespace cc { |
| 34 namespace { | 34 namespace { |
| 35 | 35 |
| 36 // The number of entries to keep around in the cache. This limit can be breached | 36 // The number of entries to keep around in the cache. This limit can be breached |
| 37 // if more items are locked. That is, locked items ignore this limit. | 37 // if more items are locked. That is, locked items ignore this limit. |
| 38 // Depending on the memory state of the system, we limit the amount of items | 38 // Depending on the memory state of the system, we limit the amount of items |
| 39 // differently. | 39 // differently. |
| 40 const size_t kNormalMaxItemsInCache = 1000; | 40 const size_t kSIDNormalMaxItemsInCache = 1000; |
| 41 const size_t kThrottledMaxItemsInCache = 100; | 41 const size_t kSIDThrottledMaxItemsInCache = 100; |
| 42 const size_t kSuspendedMaxItemsInCache = 0; | 42 const size_t kSIDSuspendedMaxItemsInCache = 0; |
| 43 | 43 |
| 44 // If the size of the original sized image breaches kMemoryRatioToSubrect but we | 44 // If the size of the original sized image breaches kMemoryRatioToSubrect but we |
| 45 // don't need to scale the image, consider caching only the needed subrect. | 45 // don't need to scale the image, consider caching only the needed subrect. |
| 46 // The second part that much be true is that we cache only the needed subrect if | 46 // The second part that much be true is that we cache only the needed subrect if |
| 47 // the total size needed for the subrect is at most kMemoryRatioToSubrect * | 47 // the total size needed for the subrect is at most kMemoryRatioToSubrect * |
| 48 // (size needed for the full original image). | 48 // (size needed for the full original image). |
| 49 // Note that at least one of the dimensions has to be at least | 49 // Note that at least one of the dimensions has to be at least |
| 50 // kMinDimensionToSubrect before an image can breach the threshold. | 50 // kMinDimensionToSubrect before an image can breach the threshold. |
| 51 const size_t kMemoryThresholdToSubrect = 64 * 1024 * 1024; | 51 const size_t kMemoryThresholdToSubrect = 64 * 1024 * 1024; |
| 52 const int kMinDimensionToSubrect = 4 * 1024; | 52 const int kMinDimensionToSubrect = 4 * 1024; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 80 ~AutoDrawWithImageFinished() { | 80 ~AutoDrawWithImageFinished() { |
| 81 cache_->DrawWithImageFinished(draw_image_, decoded_draw_image_); | 81 cache_->DrawWithImageFinished(draw_image_, decoded_draw_image_); |
| 82 } | 82 } |
| 83 | 83 |
| 84 private: | 84 private: |
| 85 SoftwareImageDecodeCache* cache_; | 85 SoftwareImageDecodeCache* cache_; |
| 86 const DrawImage& draw_image_; | 86 const DrawImage& draw_image_; |
| 87 const DecodedDrawImage& decoded_draw_image_; | 87 const DecodedDrawImage& decoded_draw_image_; |
| 88 }; | 88 }; |
| 89 | 89 |
| 90 class ImageDecodeTaskImpl : public TileTask { | 90 class ImageDecodeTaskImpl2 : public TileTask { |
| 91 public: | 91 public: |
| 92 ImageDecodeTaskImpl(SoftwareImageDecodeCache* cache, | 92 ImageDecodeTaskImpl2(SoftwareImageDecodeCache* cache, |
| 93 const SoftwareImageDecodeCache::ImageKey& image_key, | 93 const SoftwareImageDecodeCache::ImageKey& image_key, |
| 94 const DrawImage& image, | 94 const DrawImage& image, |
| 95 SoftwareImageDecodeCache::DecodeTaskType task_type, | 95 SoftwareImageDecodeCache::DecodeTaskType task_type, |
| 96 const ImageDecodeCache::TracingInfo& tracing_info) | 96 const ImageDecodeCache::TracingInfo& tracing_info) |
| 97 : TileTask(true), | 97 : TileTask(true), |
| 98 cache_(cache), | 98 cache_(cache), |
| 99 image_key_(image_key), | 99 image_key_(image_key), |
| 100 image_(image), | 100 image_(image), |
| 101 task_type_(task_type), | 101 task_type_(task_type), |
| 102 tracing_info_(tracing_info) {} | 102 tracing_info_(tracing_info) {} |
| 103 | 103 |
| 104 // Overridden from Task: | 104 // Overridden from Task: |
| 105 void RunOnWorkerThread() override { | 105 void RunOnWorkerThread() override { |
| 106 TRACE_EVENT2("cc", "ImageDecodeTaskImpl::RunOnWorkerThread", "mode", | 106 TRACE_EVENT2("cc", "ImageDecodeTaskImpl2::RunOnWorkerThread", "mode", |
| 107 "software", "source_prepare_tiles_id", | 107 "software", "source_prepare_tiles_id", |
| 108 tracing_info_.prepare_tiles_id); | 108 tracing_info_.prepare_tiles_id); |
| 109 devtools_instrumentation::ScopedImageDecodeTask image_decode_task( | 109 devtools_instrumentation::ScopedImageDecodeTask image_decode_task( |
| 110 image_.paint_image().GetSkImage().get(), | 110 image_.paint_image().GetSkImage().get(), |
| 111 devtools_instrumentation::ScopedImageDecodeTask::kSoftware, | 111 devtools_instrumentation::ScopedImageDecodeTask::kSoftware, |
| 112 ImageDecodeCache::ToScopedTaskType(tracing_info_.task_type)); | 112 ImageDecodeCache::ToScopedTaskType(tracing_info_.task_type)); |
| 113 cache_->DecodeImage(image_key_, image_, task_type_); | 113 cache_->DecodeImage(image_key_, image_, task_type_); |
| 114 } | 114 } |
| 115 | 115 |
| 116 // Overridden from TileTask: | 116 // Overridden from TileTask: |
| 117 void OnTaskCompleted() override { | 117 void OnTaskCompleted() override { |
| 118 cache_->RemovePendingTask(image_key_, task_type_); | 118 cache_->RemovePendingTask(image_key_, task_type_); |
| 119 } | 119 } |
| 120 | 120 |
| 121 protected: | 121 protected: |
| 122 ~ImageDecodeTaskImpl() override {} | 122 ~ImageDecodeTaskImpl2() override {} |
| 123 | 123 |
| 124 private: | 124 private: |
| 125 SoftwareImageDecodeCache* cache_; | 125 SoftwareImageDecodeCache* cache_; |
| 126 SoftwareImageDecodeCache::ImageKey image_key_; | 126 SoftwareImageDecodeCache::ImageKey image_key_; |
| 127 DrawImage image_; | 127 DrawImage image_; |
| 128 SoftwareImageDecodeCache::DecodeTaskType task_type_; | 128 SoftwareImageDecodeCache::DecodeTaskType task_type_; |
| 129 const ImageDecodeCache::TracingInfo tracing_info_; | 129 const ImageDecodeCache::TracingInfo tracing_info_; |
| 130 | 130 |
| 131 DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl); | 131 DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl2); |
| 132 }; | 132 }; |
| 133 | 133 |
| 134 SkSize GetScaleAdjustment(const ImageDecodeCacheKey& key) { | 134 SkSize GetScaleAdjustment(const ImageDecodeCacheKey& key) { |
| 135 // If the requested filter quality did not require scale, then the adjustment | 135 // If the requested filter quality did not require scale, then the adjustment |
| 136 // is identity. | 136 // is identity. |
| 137 if (key.can_use_original_size_decode() || key.should_use_subrect()) { | 137 if (key.can_use_original_size_decode() || key.should_use_subrect()) { |
| 138 return SkSize::Make(1.f, 1.f); | 138 return SkSize::Make(1.f, 1.f); |
| 139 } else if (key.filter_quality() == kMedium_SkFilterQuality) { | 139 } else if (key.filter_quality() == kMedium_SkFilterQuality) { |
| 140 return MipMapUtil::GetScaleAdjustmentForSize(key.src_rect().size(), | 140 return MipMapUtil::GetScaleAdjustmentForSize(key.src_rect().size(), |
| 141 key.target_size()); | 141 key.target_size()); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 | 186 |
| 187 } // namespace | 187 } // namespace |
| 188 | 188 |
| 189 SoftwareImageDecodeCache::SoftwareImageDecodeCache( | 189 SoftwareImageDecodeCache::SoftwareImageDecodeCache( |
| 190 SkColorType color_type, | 190 SkColorType color_type, |
| 191 size_t locked_memory_limit_bytes) | 191 size_t locked_memory_limit_bytes) |
| 192 : decoded_images_(ImageMRUCache::NO_AUTO_EVICT), | 192 : decoded_images_(ImageMRUCache::NO_AUTO_EVICT), |
| 193 at_raster_decoded_images_(ImageMRUCache::NO_AUTO_EVICT), | 193 at_raster_decoded_images_(ImageMRUCache::NO_AUTO_EVICT), |
| 194 locked_images_budget_(locked_memory_limit_bytes), | 194 locked_images_budget_(locked_memory_limit_bytes), |
| 195 color_type_(color_type), | 195 color_type_(color_type), |
| 196 max_items_in_cache_(kNormalMaxItemsInCache) { | 196 max_items_in_cache_(kSIDNormalMaxItemsInCache) { |
| 197 // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview). | 197 // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview). |
| 198 // Don't register a dump provider in these cases. | 198 // Don't register a dump provider in these cases. |
| 199 if (base::ThreadTaskRunnerHandle::IsSet()) { | 199 if (base::ThreadTaskRunnerHandle::IsSet()) { |
| 200 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( | 200 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( |
| 201 this, "cc::SoftwareImageDecodeCache", | 201 this, "cc::SoftwareImageDecodeCache", |
| 202 base::ThreadTaskRunnerHandle::Get()); | 202 base::ThreadTaskRunnerHandle::Get()); |
| 203 } | 203 } |
| 204 // Register this component with base::MemoryCoordinatorClientRegistry. | 204 // Register this component with base::MemoryCoordinatorClientRegistry. |
| 205 base::MemoryCoordinatorClientRegistry::GetInstance()->Register(this); | 205 base::MemoryCoordinatorClientRegistry::GetInstance()->Register(this); |
| 206 } | 206 } |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 if (!new_image_fits_in_memory && (decoded_images_ref_counts_.find(key) == | 311 if (!new_image_fits_in_memory && (decoded_images_ref_counts_.find(key) == |
| 312 decoded_images_ref_counts_.end())) { | 312 decoded_images_ref_counts_.end())) { |
| 313 *task = nullptr; | 313 *task = nullptr; |
| 314 return false; | 314 return false; |
| 315 } | 315 } |
| 316 | 316 |
| 317 // Actually create the task. RefImage will account for memory on the first | 317 // Actually create the task. RefImage will account for memory on the first |
| 318 // ref. | 318 // ref. |
| 319 RefImage(key); | 319 RefImage(key); |
| 320 existing_task = make_scoped_refptr( | 320 existing_task = make_scoped_refptr( |
| 321 new ImageDecodeTaskImpl(this, key, image, task_type, tracing_info)); | 321 new ImageDecodeTaskImpl2(this, key, image, task_type, tracing_info)); |
| 322 *task = existing_task; | 322 *task = existing_task; |
| 323 return true; | 323 return true; |
| 324 } | 324 } |
| 325 | 325 |
| 326 void SoftwareImageDecodeCache::RefImage(const ImageKey& key) { | 326 void SoftwareImageDecodeCache::RefImage(const ImageKey& key) { |
| 327 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), | 327 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), |
| 328 "SoftwareImageDecodeCache::RefImage", "key", key.ToString()); | 328 "SoftwareImageDecodeCache::RefImage", "key", key.ToString()); |
| 329 lock_.AssertAcquired(); | 329 lock_.AssertAcquired(); |
| 330 int ref = ++decoded_images_ref_counts_[key]; | 330 int ref = ++decoded_images_ref_counts_[key]; |
| 331 if (ref == 1) { | 331 if (ref == 1) { |
| (...skipping 871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1203 | 1203 |
| 1204 size_t SoftwareImageDecodeCache::MemoryBudget::GetCurrentUsageSafe() const { | 1204 size_t SoftwareImageDecodeCache::MemoryBudget::GetCurrentUsageSafe() const { |
| 1205 return current_usage_bytes_.ValueOrDie(); | 1205 return current_usage_bytes_.ValueOrDie(); |
| 1206 } | 1206 } |
| 1207 | 1207 |
| 1208 void SoftwareImageDecodeCache::OnMemoryStateChange(base::MemoryState state) { | 1208 void SoftwareImageDecodeCache::OnMemoryStateChange(base::MemoryState state) { |
| 1209 { | 1209 { |
| 1210 base::AutoLock hold(lock_); | 1210 base::AutoLock hold(lock_); |
| 1211 switch (state) { | 1211 switch (state) { |
| 1212 case base::MemoryState::NORMAL: | 1212 case base::MemoryState::NORMAL: |
| 1213 max_items_in_cache_ = kNormalMaxItemsInCache; | 1213 max_items_in_cache_ = kSIDNormalMaxItemsInCache; |
| 1214 break; | 1214 break; |
| 1215 case base::MemoryState::THROTTLED: | 1215 case base::MemoryState::THROTTLED: |
| 1216 max_items_in_cache_ = kThrottledMaxItemsInCache; | 1216 max_items_in_cache_ = kSIDThrottledMaxItemsInCache; |
| 1217 break; | 1217 break; |
| 1218 case base::MemoryState::SUSPENDED: | 1218 case base::MemoryState::SUSPENDED: |
| 1219 max_items_in_cache_ = kSuspendedMaxItemsInCache; | 1219 max_items_in_cache_ = kSIDSuspendedMaxItemsInCache; |
| 1220 break; | 1220 break; |
| 1221 case base::MemoryState::UNKNOWN: | 1221 case base::MemoryState::UNKNOWN: |
| 1222 NOTREACHED(); | 1222 NOTREACHED(); |
| 1223 return; | 1223 return; |
| 1224 } | 1224 } |
| 1225 } | 1225 } |
| 1226 } | 1226 } |
| 1227 | 1227 |
| 1228 void SoftwareImageDecodeCache::OnPurgeMemory() { | 1228 void SoftwareImageDecodeCache::OnPurgeMemory() { |
| 1229 base::AutoLock lock(lock_); | 1229 base::AutoLock lock(lock_); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1251 | 1251 |
| 1252 void SoftwareImageDecodeCache::CacheDecodedImages( | 1252 void SoftwareImageDecodeCache::CacheDecodedImages( |
| 1253 const ImageKey& key, | 1253 const ImageKey& key, |
| 1254 std::unique_ptr<DecodedImage> decoded_image) { | 1254 std::unique_ptr<DecodedImage> decoded_image) { |
| 1255 lock_.AssertAcquired(); | 1255 lock_.AssertAcquired(); |
| 1256 frame_key_to_image_keys_[key.frame_key()].push_back(key); | 1256 frame_key_to_image_keys_[key.frame_key()].push_back(key); |
| 1257 decoded_images_.Put(key, std::move(decoded_image)); | 1257 decoded_images_.Put(key, std::move(decoded_image)); |
| 1258 } | 1258 } |
| 1259 | 1259 |
| 1260 } // namespace cc | 1260 } // namespace cc |
| OLD | NEW |