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