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