| 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 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 SoftwareImageDecodeCache* cache_; | 87 SoftwareImageDecodeCache* cache_; |
| 88 const DrawImage& draw_image_; | 88 const DrawImage& draw_image_; |
| 89 const DecodedDrawImage& decoded_draw_image_; | 89 const DecodedDrawImage& decoded_draw_image_; |
| 90 }; | 90 }; |
| 91 | 91 |
| 92 class ImageDecodeTaskImpl : public TileTask { | 92 class ImageDecodeTaskImpl : public TileTask { |
| 93 public: | 93 public: |
| 94 ImageDecodeTaskImpl(SoftwareImageDecodeCache* cache, | 94 ImageDecodeTaskImpl(SoftwareImageDecodeCache* cache, |
| 95 const SoftwareImageDecodeCache::ImageKey& image_key, | 95 const SoftwareImageDecodeCache::ImageKey& image_key, |
| 96 const DrawImage& image, | 96 const DrawImage& image, |
| 97 const SoftwareImageDecodeCache::DecodeTaskType task_type, |
| 97 const ImageDecodeCache::TracingInfo& tracing_info) | 98 const ImageDecodeCache::TracingInfo& tracing_info) |
| 98 : TileTask(true), | 99 : TileTask(true), |
| 99 cache_(cache), | 100 cache_(cache), |
| 100 image_key_(image_key), | 101 image_key_(image_key), |
| 101 image_(image), | 102 image_(image), |
| 103 task_type_(task_type), |
| 102 tracing_info_(tracing_info) {} | 104 tracing_info_(tracing_info) {} |
| 103 | 105 |
| 104 // Overridden from Task: | 106 // Overridden from Task: |
| 105 void RunOnWorkerThread() override { | 107 void RunOnWorkerThread() override { |
| 106 TRACE_EVENT2("cc", "ImageDecodeTaskImpl::RunOnWorkerThread", "mode", | 108 TRACE_EVENT2("cc", "ImageDecodeTaskImpl::RunOnWorkerThread", "mode", |
| 107 "software", "source_prepare_tiles_id", | 109 "software", "source_prepare_tiles_id", |
| 108 tracing_info_.prepare_tiles_id); | 110 tracing_info_.prepare_tiles_id); |
| 109 devtools_instrumentation::ScopedImageDecodeTask image_decode_task( | 111 devtools_instrumentation::ScopedImageDecodeTask image_decode_task( |
| 110 image_.image().get(), | 112 image_.image().get(), |
| 111 devtools_instrumentation::ScopedImageDecodeTask::SOFTWARE); | 113 devtools_instrumentation::ScopedImageDecodeTask::SOFTWARE); |
| 112 cache_->DecodeImage(image_key_, image_); | 114 cache_->DecodeImage(image_key_, image_, task_type_); |
| 113 } | 115 } |
| 114 | 116 |
| 115 // Overridden from TileTask: | 117 // Overridden from TileTask: |
| 116 void OnTaskCompleted() override { cache_->RemovePendingTask(image_key_); } | 118 void OnTaskCompleted() override { |
| 119 cache_->RemovePendingTask(image_key_, task_type_); |
| 120 } |
| 117 | 121 |
| 118 protected: | 122 protected: |
| 119 ~ImageDecodeTaskImpl() override {} | 123 ~ImageDecodeTaskImpl() override {} |
| 120 | 124 |
| 121 private: | 125 private: |
| 122 SoftwareImageDecodeCache* cache_; | 126 SoftwareImageDecodeCache* cache_; |
| 123 SoftwareImageDecodeCache::ImageKey image_key_; | 127 SoftwareImageDecodeCache::ImageKey image_key_; |
| 124 DrawImage image_; | 128 DrawImage image_; |
| 129 SoftwareImageDecodeCache::DecodeTaskType task_type_; |
| 125 const ImageDecodeCache::TracingInfo tracing_info_; | 130 const ImageDecodeCache::TracingInfo tracing_info_; |
| 126 | 131 |
| 127 DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl); | 132 DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl); |
| 128 }; | 133 }; |
| 129 | 134 |
| 130 SkSize GetScaleAdjustment(const ImageDecodeCacheKey& key) { | 135 SkSize GetScaleAdjustment(const ImageDecodeCacheKey& key) { |
| 131 // 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 |
| 132 // is identity. | 137 // is identity. |
| 133 if (key.can_use_original_decode() || key.should_use_subrect()) { | 138 if (key.can_use_original_decode() || key.should_use_subrect()) { |
| 134 return SkSize::Make(1.f, 1.f); | 139 return SkSize::Make(1.f, 1.f); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( | 205 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( |
| 201 this); | 206 this); |
| 202 // Unregister this component with memory_coordinator::ClientRegistry. | 207 // Unregister this component with memory_coordinator::ClientRegistry. |
| 203 base::MemoryCoordinatorClientRegistry::GetInstance()->Unregister(this); | 208 base::MemoryCoordinatorClientRegistry::GetInstance()->Unregister(this); |
| 204 } | 209 } |
| 205 | 210 |
| 206 bool SoftwareImageDecodeCache::GetTaskForImageAndRef( | 211 bool SoftwareImageDecodeCache::GetTaskForImageAndRef( |
| 207 const DrawImage& image, | 212 const DrawImage& image, |
| 208 const TracingInfo& tracing_info, | 213 const TracingInfo& tracing_info, |
| 209 scoped_refptr<TileTask>* task) { | 214 scoped_refptr<TileTask>* task) { |
| 215 return GetTaskForImageAndRefInternal(image, tracing_info, USE_IN_RASTER_TASKS, |
| 216 task); |
| 217 } |
| 218 |
| 219 bool SoftwareImageDecodeCache::GetOutOfRasterDecodeTaskForImageAndRef( |
| 220 const DrawImage& image, |
| 221 scoped_refptr<TileTask>* task) { |
| 222 return GetTaskForImageAndRefInternal(image, TracingInfo(), |
| 223 USE_OUT_OF_RASTER_TASKS, task); |
| 224 } |
| 225 |
| 226 bool SoftwareImageDecodeCache::GetTaskForImageAndRefInternal( |
| 227 const DrawImage& image, |
| 228 const TracingInfo& tracing_info, |
| 229 DecodeTaskType task_type, |
| 230 scoped_refptr<TileTask>* task) { |
| 210 // If the image already exists or if we're going to create a task for it, then | 231 // If the image already exists or if we're going to create a task for it, then |
| 211 // we'll likely need to ref this image (the exception is if we're prerolling | 232 // we'll likely need to ref this image (the exception is if we're prerolling |
| 212 // the image only). That means the image is or will be in the cache. When the | 233 // the image only). That means the image is or will be in the cache. When the |
| 213 // ref goes to 0, it will be unpinned but will remain in the cache. If the | 234 // ref goes to 0, it will be unpinned but will remain in the cache. If the |
| 214 // image does not fit into the budget, then we don't ref this image, since it | 235 // image does not fit into the budget, then we don't ref this image, since it |
| 215 // will be decoded at raster time which is when it will be temporarily put in | 236 // will be decoded at raster time which is when it will be temporarily put in |
| 216 // the cache. | 237 // the cache. |
| 217 ImageKey key = ImageKey::FromDrawImage(image); | 238 ImageKey key = ImageKey::FromDrawImage(image); |
| 218 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), | 239 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), |
| 219 "SoftwareImageDecodeCache::GetTaskForImageAndRef", "key", | 240 "SoftwareImageDecodeCache::GetTaskForImageAndRef", "key", |
| (...skipping 30 matching lines...) Expand all Loading... |
| 250 | 271 |
| 251 // If the image fits in memory, then we at least tried to lock it and | 272 // If the image fits in memory, then we at least tried to lock it and |
| 252 // failed. This means that it's not valid anymore. | 273 // failed. This means that it's not valid anymore. |
| 253 if (new_image_fits_in_memory) { | 274 if (new_image_fits_in_memory) { |
| 254 RecordLockExistingCachedImageHistogram(tracing_info.requesting_tile_bin, | 275 RecordLockExistingCachedImageHistogram(tracing_info.requesting_tile_bin, |
| 255 false); | 276 false); |
| 256 decoded_images_.Erase(decoded_it); | 277 decoded_images_.Erase(decoded_it); |
| 257 } | 278 } |
| 258 } | 279 } |
| 259 | 280 |
| 260 // If the task exists, return it. | 281 DCHECK(task_type == USE_IN_RASTER_TASKS || |
| 261 scoped_refptr<TileTask>& existing_task = pending_image_tasks_[key]; | 282 task_type == USE_OUT_OF_RASTER_TASKS); |
| 283 // If the task exists, return it. Note that if we always need to create a new |
| 284 // task, then just set |existing_task| to reference the passed in task (which |
| 285 // is set to nullptr above). |
| 286 scoped_refptr<TileTask>& existing_task = |
| 287 (task_type == USE_IN_RASTER_TASKS) |
| 288 ? pending_in_raster_image_tasks_[key] |
| 289 : pending_out_of_raster_image_tasks_[key]; |
| 262 if (existing_task) { | 290 if (existing_task) { |
| 263 RefImage(key); | 291 RefImage(key); |
| 264 *task = existing_task; | 292 *task = existing_task; |
| 265 SanityCheckState(__LINE__, true); | 293 SanityCheckState(__LINE__, true); |
| 266 return true; | 294 return true; |
| 267 } | 295 } |
| 268 | 296 |
| 269 // At this point, we have to create a new image/task, so we need to abort if | 297 // At this point, we have to create a new image/task, so we need to abort if |
| 270 // it doesn't fit into memory and there are currently no raster tasks that | 298 // it doesn't fit into memory and there are currently no raster tasks that |
| 271 // would have already accounted for memory. The latter part is possible if | 299 // would have already accounted for memory. The latter part is possible if |
| 272 // there's a running raster task that could not be canceled, and still has a | 300 // there's a running raster task that could not be canceled, and still has a |
| 273 // ref to the image that is now being reffed for the new schedule. | 301 // ref to the image that is now being reffed for the new schedule. |
| 274 if (!new_image_fits_in_memory && (decoded_images_ref_counts_.find(key) == | 302 if (!new_image_fits_in_memory && (decoded_images_ref_counts_.find(key) == |
| 275 decoded_images_ref_counts_.end())) { | 303 decoded_images_ref_counts_.end())) { |
| 276 *task = nullptr; | 304 *task = nullptr; |
| 277 SanityCheckState(__LINE__, true); | 305 SanityCheckState(__LINE__, true); |
| 278 return false; | 306 return false; |
| 279 } | 307 } |
| 280 | 308 |
| 281 // Actually create the task. RefImage will account for memory on the first | 309 // Actually create the task. RefImage will account for memory on the first |
| 282 // ref. | 310 // ref. |
| 283 RefImage(key); | 311 RefImage(key); |
| 284 existing_task = make_scoped_refptr( | 312 existing_task = make_scoped_refptr( |
| 285 new ImageDecodeTaskImpl(this, key, image, tracing_info)); | 313 new ImageDecodeTaskImpl(this, key, image, task_type, tracing_info)); |
| 286 *task = existing_task; | 314 *task = existing_task; |
| 287 SanityCheckState(__LINE__, true); | 315 SanityCheckState(__LINE__, true); |
| 288 return true; | 316 return true; |
| 289 } | 317 } |
| 290 | 318 |
| 291 void SoftwareImageDecodeCache::RefImage(const ImageKey& key) { | 319 void SoftwareImageDecodeCache::RefImage(const ImageKey& key) { |
| 292 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), | 320 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), |
| 293 "SoftwareImageDecodeCache::RefImage", "key", key.ToString()); | 321 "SoftwareImageDecodeCache::RefImage", "key", key.ToString()); |
| 294 lock_.AssertAcquired(); | 322 lock_.AssertAcquired(); |
| 295 int ref = ++decoded_images_ref_counts_[key]; | 323 int ref = ++decoded_images_ref_counts_[key]; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 326 SanityCheckState(__LINE__, true); | 354 SanityCheckState(__LINE__, true); |
| 327 return; | 355 return; |
| 328 } | 356 } |
| 329 DCHECK(decoded_image_it->second->is_locked()); | 357 DCHECK(decoded_image_it->second->is_locked()); |
| 330 decoded_image_it->second->Unlock(); | 358 decoded_image_it->second->Unlock(); |
| 331 } | 359 } |
| 332 SanityCheckState(__LINE__, true); | 360 SanityCheckState(__LINE__, true); |
| 333 } | 361 } |
| 334 | 362 |
| 335 void SoftwareImageDecodeCache::DecodeImage(const ImageKey& key, | 363 void SoftwareImageDecodeCache::DecodeImage(const ImageKey& key, |
| 336 const DrawImage& image) { | 364 const DrawImage& image, |
| 365 DecodeTaskType task_type) { |
| 337 TRACE_EVENT1("cc", "SoftwareImageDecodeCache::DecodeImage", "key", | 366 TRACE_EVENT1("cc", "SoftwareImageDecodeCache::DecodeImage", "key", |
| 338 key.ToString()); | 367 key.ToString()); |
| 339 base::AutoLock lock(lock_); | 368 base::AutoLock lock(lock_); |
| 340 AutoRemoveKeyFromTaskMap remove_key_from_task_map(&pending_image_tasks_, key); | 369 AutoRemoveKeyFromTaskMap remove_key_from_task_map( |
| 370 (task_type == USE_IN_RASTER_TASKS) ? &pending_in_raster_image_tasks_ |
| 371 : &pending_out_of_raster_image_tasks_, |
| 372 key); |
| 341 | 373 |
| 342 // We could have finished all of the raster tasks (cancelled) while the task | 374 // We could have finished all of the raster tasks (cancelled) while the task |
| 343 // was just starting to run. Since this task already started running, it | 375 // was just starting to run. Since this task already started running, it |
| 344 // wasn't cancelled. So, if the ref count for the image is 0 then we can just | 376 // wasn't cancelled. So, if the ref count for the image is 0 then we can just |
| 345 // abort. | 377 // abort. |
| 346 if (decoded_images_ref_counts_.find(key) == | 378 if (decoded_images_ref_counts_.find(key) == |
| 347 decoded_images_ref_counts_.end()) { | 379 decoded_images_ref_counts_.end()) { |
| 348 return; | 380 return; |
| 349 } | 381 } |
| 350 | 382 |
| (...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 760 if (it->second->is_locked()) { | 792 if (it->second->is_locked()) { |
| 761 ++it; | 793 ++it; |
| 762 continue; | 794 continue; |
| 763 } | 795 } |
| 764 | 796 |
| 765 it = decoded_images_.Erase(it); | 797 it = decoded_images_.Erase(it); |
| 766 --num_to_remove; | 798 --num_to_remove; |
| 767 } | 799 } |
| 768 } | 800 } |
| 769 | 801 |
| 770 void SoftwareImageDecodeCache::RemovePendingTask(const ImageKey& key) { | 802 void SoftwareImageDecodeCache::RemovePendingTask(const ImageKey& key, |
| 803 DecodeTaskType task_type) { |
| 771 base::AutoLock lock(lock_); | 804 base::AutoLock lock(lock_); |
| 772 pending_image_tasks_.erase(key); | 805 switch (task_type) { |
| 806 case USE_IN_RASTER_TASKS: |
| 807 pending_in_raster_image_tasks_.erase(key); |
| 808 break; |
| 809 case USE_OUT_OF_RASTER_TASKS: |
| 810 pending_out_of_raster_image_tasks_.erase(key); |
| 811 break; |
| 812 } |
| 773 } | 813 } |
| 774 | 814 |
| 775 bool SoftwareImageDecodeCache::OnMemoryDump( | 815 bool SoftwareImageDecodeCache::OnMemoryDump( |
| 776 const base::trace_event::MemoryDumpArgs& args, | 816 const base::trace_event::MemoryDumpArgs& args, |
| 777 base::trace_event::ProcessMemoryDump* pmd) { | 817 base::trace_event::ProcessMemoryDump* pmd) { |
| 778 base::AutoLock lock(lock_); | 818 base::AutoLock lock(lock_); |
| 779 | 819 |
| 780 if (args.level_of_detail == MemoryDumpLevelOfDetail::BACKGROUND) { | 820 if (args.level_of_detail == MemoryDumpLevelOfDetail::BACKGROUND) { |
| 781 std::string dump_name = base::StringPrintf( | 821 std::string dump_name = base::StringPrintf( |
| 782 "cc/image_memory/cache_0x%" PRIXPTR, reinterpret_cast<uintptr_t>(this)); | 822 "cc/image_memory/cache_0x%" PRIXPTR, reinterpret_cast<uintptr_t>(this)); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 829 for (const auto& image_pair : decoded_images_) { | 869 for (const auto& image_pair : decoded_images_) { |
| 830 const auto& key = image_pair.first; | 870 const auto& key = image_pair.first; |
| 831 const auto& image = image_pair.second; | 871 const auto& image = image_pair.second; |
| 832 | 872 |
| 833 auto ref_it = decoded_images_ref_counts_.find(key); | 873 auto ref_it = decoded_images_ref_counts_.find(key); |
| 834 if (image->is_locked()) { | 874 if (image->is_locked()) { |
| 835 budget.AddUsage(key.locked_bytes()); | 875 budget.AddUsage(key.locked_bytes()); |
| 836 DCHECK(ref_it != decoded_images_ref_counts_.end()) << line; | 876 DCHECK(ref_it != decoded_images_ref_counts_.end()) << line; |
| 837 } else { | 877 } else { |
| 838 DCHECK(ref_it == decoded_images_ref_counts_.end() || | 878 DCHECK(ref_it == decoded_images_ref_counts_.end() || |
| 839 pending_image_tasks_.find(key) != pending_image_tasks_.end()) | 879 pending_in_raster_image_tasks_.find(key) != |
| 880 pending_in_raster_image_tasks_.end() || |
| 881 pending_out_of_raster_image_tasks_.find(key) != |
| 882 pending_out_of_raster_image_tasks_.end()) |
| 840 << line; | 883 << line; |
| 841 } | 884 } |
| 842 } | 885 } |
| 843 DCHECK_GE(budget.AvailableMemoryBytes(), | 886 DCHECK_GE(budget.AvailableMemoryBytes(), |
| 844 locked_images_budget_.AvailableMemoryBytes()) | 887 locked_images_budget_.AvailableMemoryBytes()) |
| 845 << line; | 888 << line; |
| 846 #endif // DCHECK_IS_ON() | 889 #endif // DCHECK_IS_ON() |
| 847 } | 890 } |
| 848 | 891 |
| 849 // SoftwareImageDecodeCacheKey | 892 // SoftwareImageDecodeCacheKey |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1112 break; | 1155 break; |
| 1113 case base::MemoryState::UNKNOWN: | 1156 case base::MemoryState::UNKNOWN: |
| 1114 NOTREACHED(); | 1157 NOTREACHED(); |
| 1115 return; | 1158 return; |
| 1116 } | 1159 } |
| 1117 } | 1160 } |
| 1118 ReduceCacheUsage(); | 1161 ReduceCacheUsage(); |
| 1119 } | 1162 } |
| 1120 | 1163 |
| 1121 } // namespace cc | 1164 } // namespace cc |
| OLD | NEW |