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 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 // If we already have the image in cache, then we can return it. | 267 // If we already have the image in cache, then we can return it. |
268 auto decoded_it = decoded_images_.Get(key); | 268 auto decoded_it = decoded_images_.Get(key); |
269 bool new_image_fits_in_memory = | 269 bool new_image_fits_in_memory = |
270 locked_images_budget_.AvailableMemoryBytes() >= key.locked_bytes(); | 270 locked_images_budget_.AvailableMemoryBytes() >= key.locked_bytes(); |
271 if (decoded_it != decoded_images_.end()) { | 271 if (decoded_it != decoded_images_.end()) { |
272 bool image_was_locked = decoded_it->second->is_locked(); | 272 bool image_was_locked = decoded_it->second->is_locked(); |
273 if (image_was_locked || | 273 if (image_was_locked || |
274 (new_image_fits_in_memory && decoded_it->second->Lock())) { | 274 (new_image_fits_in_memory && decoded_it->second->Lock())) { |
275 RefImage(key); | 275 RefImage(key); |
276 *task = nullptr; | 276 *task = nullptr; |
277 SanityCheckState(__LINE__, true); | |
278 | 277 |
279 // If the image wasn't locked, then we just succeeded in locking it. | 278 // If the image wasn't locked, then we just succeeded in locking it. |
280 if (!image_was_locked) { | 279 if (!image_was_locked) { |
281 RecordLockExistingCachedImageHistogram(tracing_info.requesting_tile_bin, | 280 RecordLockExistingCachedImageHistogram(tracing_info.requesting_tile_bin, |
282 true); | 281 true); |
283 } | 282 } |
284 return true; | 283 return true; |
285 } | 284 } |
286 | 285 |
287 // If the image fits in memory, then we at least tried to lock it and | 286 // If the image fits in memory, then we at least tried to lock it and |
(...skipping 10 matching lines...) Expand all Loading... |
298 // If the task exists, return it. Note that if we always need to create a new | 297 // If the task exists, return it. Note that if we always need to create a new |
299 // task, then just set |existing_task| to reference the passed in task (which | 298 // task, then just set |existing_task| to reference the passed in task (which |
300 // is set to nullptr above). | 299 // is set to nullptr above). |
301 scoped_refptr<TileTask>& existing_task = | 300 scoped_refptr<TileTask>& existing_task = |
302 (task_type == DecodeTaskType::USE_IN_RASTER_TASKS) | 301 (task_type == DecodeTaskType::USE_IN_RASTER_TASKS) |
303 ? pending_in_raster_image_tasks_[key] | 302 ? pending_in_raster_image_tasks_[key] |
304 : pending_out_of_raster_image_tasks_[key]; | 303 : pending_out_of_raster_image_tasks_[key]; |
305 if (existing_task) { | 304 if (existing_task) { |
306 RefImage(key); | 305 RefImage(key); |
307 *task = existing_task; | 306 *task = existing_task; |
308 SanityCheckState(__LINE__, true); | |
309 return true; | 307 return true; |
310 } | 308 } |
311 | 309 |
312 // At this point, we have to create a new image/task, so we need to abort if | 310 // At this point, we have to create a new image/task, so we need to abort if |
313 // it doesn't fit into memory and there are currently no raster tasks that | 311 // it doesn't fit into memory and there are currently no raster tasks that |
314 // would have already accounted for memory. The latter part is possible if | 312 // would have already accounted for memory. The latter part is possible if |
315 // there's a running raster task that could not be canceled, and still has a | 313 // there's a running raster task that could not be canceled, and still has a |
316 // ref to the image that is now being reffed for the new schedule. | 314 // ref to the image that is now being reffed for the new schedule. |
317 if (!new_image_fits_in_memory && (decoded_images_ref_counts_.find(key) == | 315 if (!new_image_fits_in_memory && (decoded_images_ref_counts_.find(key) == |
318 decoded_images_ref_counts_.end())) { | 316 decoded_images_ref_counts_.end())) { |
319 *task = nullptr; | 317 *task = nullptr; |
320 SanityCheckState(__LINE__, true); | |
321 return false; | 318 return false; |
322 } | 319 } |
323 | 320 |
324 // Actually create the task. RefImage will account for memory on the first | 321 // Actually create the task. RefImage will account for memory on the first |
325 // ref. | 322 // ref. |
326 RefImage(key); | 323 RefImage(key); |
327 existing_task = make_scoped_refptr( | 324 existing_task = make_scoped_refptr( |
328 new ImageDecodeTaskImpl(this, key, image, task_type, tracing_info)); | 325 new ImageDecodeTaskImpl(this, key, image, task_type, tracing_info)); |
329 *task = existing_task; | 326 *task = existing_task; |
330 SanityCheckState(__LINE__, true); | |
331 return true; | 327 return true; |
332 } | 328 } |
333 | 329 |
334 void SoftwareImageDecodeCache::RefImage(const ImageKey& key) { | 330 void SoftwareImageDecodeCache::RefImage(const ImageKey& key) { |
335 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), | 331 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), |
336 "SoftwareImageDecodeCache::RefImage", "key", key.ToString()); | 332 "SoftwareImageDecodeCache::RefImage", "key", key.ToString()); |
337 lock_.AssertAcquired(); | 333 lock_.AssertAcquired(); |
338 int ref = ++decoded_images_ref_counts_[key]; | 334 int ref = ++decoded_images_ref_counts_[key]; |
339 if (ref == 1) { | 335 if (ref == 1) { |
340 DCHECK_GE(locked_images_budget_.AvailableMemoryBytes(), key.locked_bytes()); | 336 DCHECK_GE(locked_images_budget_.AvailableMemoryBytes(), key.locked_bytes()); |
(...skipping 17 matching lines...) Expand all Loading... |
358 DCHECK(ref_count_it != decoded_images_ref_counts_.end()); | 354 DCHECK(ref_count_it != decoded_images_ref_counts_.end()); |
359 | 355 |
360 --ref_count_it->second; | 356 --ref_count_it->second; |
361 if (ref_count_it->second == 0) { | 357 if (ref_count_it->second == 0) { |
362 decoded_images_ref_counts_.erase(ref_count_it); | 358 decoded_images_ref_counts_.erase(ref_count_it); |
363 locked_images_budget_.SubtractUsage(key.locked_bytes()); | 359 locked_images_budget_.SubtractUsage(key.locked_bytes()); |
364 | 360 |
365 auto decoded_image_it = decoded_images_.Peek(key); | 361 auto decoded_image_it = decoded_images_.Peek(key); |
366 // If we've never decoded the image before ref reached 0, then we wouldn't | 362 // If we've never decoded the image before ref reached 0, then we wouldn't |
367 // have it in our cache. This would happen if we canceled tasks. | 363 // have it in our cache. This would happen if we canceled tasks. |
368 if (decoded_image_it == decoded_images_.end()) { | 364 if (decoded_image_it == decoded_images_.end()) |
369 SanityCheckState(__LINE__, true); | |
370 return; | 365 return; |
371 } | |
372 DCHECK(decoded_image_it->second->is_locked()); | 366 DCHECK(decoded_image_it->second->is_locked()); |
373 decoded_image_it->second->Unlock(); | 367 decoded_image_it->second->Unlock(); |
374 } | 368 } |
375 SanityCheckState(__LINE__, true); | |
376 } | 369 } |
377 | 370 |
378 void SoftwareImageDecodeCache::DecodeImage(const ImageKey& key, | 371 void SoftwareImageDecodeCache::DecodeImage(const ImageKey& key, |
379 const DrawImage& image, | 372 const DrawImage& image, |
380 DecodeTaskType task_type) { | 373 DecodeTaskType task_type) { |
381 TRACE_EVENT1("cc", "SoftwareImageDecodeCache::DecodeImage", "key", | 374 TRACE_EVENT1("cc", "SoftwareImageDecodeCache::DecodeImage", "key", |
382 key.ToString()); | 375 key.ToString()); |
383 base::AutoLock lock(lock_); | 376 base::AutoLock lock(lock_); |
384 AutoRemoveKeyFromTaskMap remove_key_from_task_map( | 377 AutoRemoveKeyFromTaskMap remove_key_from_task_map( |
385 (task_type == DecodeTaskType::USE_IN_RASTER_TASKS) | 378 (task_type == DecodeTaskType::USE_IN_RASTER_TASKS) |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 | 422 |
430 // We could have finished all of the raster tasks (cancelled) while this image | 423 // We could have finished all of the raster tasks (cancelled) while this image |
431 // decode task was running, which means that we now have a locked image but no | 424 // decode task was running, which means that we now have a locked image but no |
432 // ref counts. Unlock it immediately in this case. | 425 // ref counts. Unlock it immediately in this case. |
433 if (decoded_images_ref_counts_.find(key) == | 426 if (decoded_images_ref_counts_.find(key) == |
434 decoded_images_ref_counts_.end()) { | 427 decoded_images_ref_counts_.end()) { |
435 decoded_image->Unlock(); | 428 decoded_image->Unlock(); |
436 } | 429 } |
437 | 430 |
438 decoded_images_.Put(key, std::move(decoded_image)); | 431 decoded_images_.Put(key, std::move(decoded_image)); |
439 SanityCheckState(__LINE__, true); | |
440 } | 432 } |
441 | 433 |
442 std::unique_ptr<SoftwareImageDecodeCache::DecodedImage> | 434 std::unique_ptr<SoftwareImageDecodeCache::DecodedImage> |
443 SoftwareImageDecodeCache::DecodeImageInternal(const ImageKey& key, | 435 SoftwareImageDecodeCache::DecodeImageInternal(const ImageKey& key, |
444 const DrawImage& draw_image) { | 436 const DrawImage& draw_image) { |
445 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), | 437 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), |
446 "SoftwareImageDecodeCache::DecodeImageInternal", "key", | 438 "SoftwareImageDecodeCache::DecodeImageInternal", "key", |
447 key.ToString()); | 439 key.ToString()); |
448 sk_sp<const SkImage> image = draw_image.image(); | 440 sk_sp<const SkImage> image = draw_image.image(); |
449 if (!image) | 441 if (!image) |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
487 auto decoded_images_it = decoded_images_.Get(key); | 479 auto decoded_images_it = decoded_images_.Get(key); |
488 // If we found the image and it's locked, then return it. If it's not locked, | 480 // If we found the image and it's locked, then return it. If it's not locked, |
489 // erase it from the cache since it might be put into the at-raster cache. | 481 // erase it from the cache since it might be put into the at-raster cache. |
490 std::unique_ptr<DecodedImage> scoped_decoded_image; | 482 std::unique_ptr<DecodedImage> scoped_decoded_image; |
491 DecodedImage* decoded_image = nullptr; | 483 DecodedImage* decoded_image = nullptr; |
492 if (decoded_images_it != decoded_images_.end()) { | 484 if (decoded_images_it != decoded_images_.end()) { |
493 decoded_image = decoded_images_it->second.get(); | 485 decoded_image = decoded_images_it->second.get(); |
494 if (decoded_image->is_locked()) { | 486 if (decoded_image->is_locked()) { |
495 RefImage(key); | 487 RefImage(key); |
496 decoded_image->mark_used(); | 488 decoded_image->mark_used(); |
497 SanityCheckState(__LINE__, true); | |
498 return DecodedDrawImage( | 489 return DecodedDrawImage( |
499 decoded_image->image(), decoded_image->src_rect_offset(), | 490 decoded_image->image(), decoded_image->src_rect_offset(), |
500 GetScaleAdjustment(key), GetDecodedFilterQuality(key)); | 491 GetScaleAdjustment(key), GetDecodedFilterQuality(key)); |
501 } else { | 492 } else { |
502 scoped_decoded_image = std::move(decoded_images_it->second); | 493 scoped_decoded_image = std::move(decoded_images_it->second); |
503 decoded_images_.Erase(decoded_images_it); | 494 decoded_images_.Erase(decoded_images_it); |
504 } | 495 } |
505 } | 496 } |
506 | 497 |
507 // See if another thread already decoded this image at raster time. If so, we | 498 // See if another thread already decoded this image at raster time. If so, we |
508 // can just use that result directly. | 499 // can just use that result directly. |
509 auto at_raster_images_it = at_raster_decoded_images_.Get(key); | 500 auto at_raster_images_it = at_raster_decoded_images_.Get(key); |
510 if (at_raster_images_it != at_raster_decoded_images_.end()) { | 501 if (at_raster_images_it != at_raster_decoded_images_.end()) { |
511 DCHECK(at_raster_images_it->second->is_locked()); | 502 DCHECK(at_raster_images_it->second->is_locked()); |
512 RefAtRasterImage(key); | 503 RefAtRasterImage(key); |
513 SanityCheckState(__LINE__, true); | |
514 DecodedImage* at_raster_decoded_image = at_raster_images_it->second.get(); | 504 DecodedImage* at_raster_decoded_image = at_raster_images_it->second.get(); |
515 at_raster_decoded_image->mark_used(); | 505 at_raster_decoded_image->mark_used(); |
516 auto decoded_draw_image = | 506 auto decoded_draw_image = |
517 DecodedDrawImage(at_raster_decoded_image->image(), | 507 DecodedDrawImage(at_raster_decoded_image->image(), |
518 at_raster_decoded_image->src_rect_offset(), | 508 at_raster_decoded_image->src_rect_offset(), |
519 GetScaleAdjustment(key), GetDecodedFilterQuality(key)); | 509 GetScaleAdjustment(key), GetDecodedFilterQuality(key)); |
520 decoded_draw_image.set_at_raster_decode(true); | 510 decoded_draw_image.set_at_raster_decode(true); |
521 return decoded_draw_image; | 511 return decoded_draw_image; |
522 } | 512 } |
523 | 513 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
557 } | 547 } |
558 | 548 |
559 // If we really are the first ones, or if the other thread already unlocked | 549 // If we really are the first ones, or if the other thread already unlocked |
560 // the image, then put our work into at-raster time cache. | 550 // the image, then put our work into at-raster time cache. |
561 if (scoped_decoded_image) | 551 if (scoped_decoded_image) |
562 at_raster_decoded_images_.Put(key, std::move(scoped_decoded_image)); | 552 at_raster_decoded_images_.Put(key, std::move(scoped_decoded_image)); |
563 | 553 |
564 DCHECK(decoded_image); | 554 DCHECK(decoded_image); |
565 DCHECK(decoded_image->is_locked()); | 555 DCHECK(decoded_image->is_locked()); |
566 RefAtRasterImage(key); | 556 RefAtRasterImage(key); |
567 SanityCheckState(__LINE__, true); | |
568 decoded_image->mark_used(); | 557 decoded_image->mark_used(); |
569 auto decoded_draw_image = | 558 auto decoded_draw_image = |
570 DecodedDrawImage(decoded_image->image(), decoded_image->src_rect_offset(), | 559 DecodedDrawImage(decoded_image->image(), decoded_image->src_rect_offset(), |
571 GetScaleAdjustment(key), GetDecodedFilterQuality(key)); | 560 GetScaleAdjustment(key), GetDecodedFilterQuality(key)); |
572 decoded_draw_image.set_at_raster_decode(true); | 561 decoded_draw_image.set_at_raster_decode(true); |
573 return decoded_draw_image; | 562 return decoded_draw_image; |
574 } | 563 } |
575 | 564 |
576 std::unique_ptr<SoftwareImageDecodeCache::DecodedImage> | 565 std::unique_ptr<SoftwareImageDecodeCache::DecodedImage> |
577 SoftwareImageDecodeCache::GetOriginalImageDecode(sk_sp<const SkImage> image) { | 566 SoftwareImageDecodeCache::GetOriginalImageDecode(sk_sp<const SkImage> image) { |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
741 "SoftwareImageDecodeCache::DrawWithImageFinished", "key", | 730 "SoftwareImageDecodeCache::DrawWithImageFinished", "key", |
742 ImageKey::FromDrawImage(image).ToString()); | 731 ImageKey::FromDrawImage(image).ToString()); |
743 ImageKey key = ImageKey::FromDrawImage(image); | 732 ImageKey key = ImageKey::FromDrawImage(image); |
744 if (!decoded_image.image()) | 733 if (!decoded_image.image()) |
745 return; | 734 return; |
746 | 735 |
747 if (decoded_image.is_at_raster_decode()) | 736 if (decoded_image.is_at_raster_decode()) |
748 UnrefAtRasterImage(key); | 737 UnrefAtRasterImage(key); |
749 else | 738 else |
750 UnrefImage(image); | 739 UnrefImage(image); |
751 SanityCheckState(__LINE__, false); | |
752 } | 740 } |
753 | 741 |
754 void SoftwareImageDecodeCache::RefAtRasterImage(const ImageKey& key) { | 742 void SoftwareImageDecodeCache::RefAtRasterImage(const ImageKey& key) { |
755 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), | 743 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), |
756 "SoftwareImageDecodeCache::RefAtRasterImage", "key", | 744 "SoftwareImageDecodeCache::RefAtRasterImage", "key", |
757 key.ToString()); | 745 key.ToString()); |
758 DCHECK(at_raster_decoded_images_.Peek(key) != | 746 DCHECK(at_raster_decoded_images_.Peek(key) != |
759 at_raster_decoded_images_.end()); | 747 at_raster_decoded_images_.end()); |
760 ++at_raster_decoded_images_ref_counts_[key]; | 748 ++at_raster_decoded_images_ref_counts_[key]; |
761 } | 749 } |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
885 image_pair.second->memory()->CreateMemoryAllocatorDump( | 873 image_pair.second->memory()->CreateMemoryAllocatorDump( |
886 dump_name.c_str(), pmd); | 874 dump_name.c_str(), pmd); |
887 DCHECK(dump); | 875 DCHECK(dump); |
888 size_t locked_bytes = | 876 size_t locked_bytes = |
889 image_pair.second->is_locked() ? image_pair.first.locked_bytes() : 0u; | 877 image_pair.second->is_locked() ? image_pair.first.locked_bytes() : 0u; |
890 dump->AddScalar("locked_size", MemoryAllocatorDump::kUnitsBytes, | 878 dump->AddScalar("locked_size", MemoryAllocatorDump::kUnitsBytes, |
891 locked_bytes); | 879 locked_bytes); |
892 } | 880 } |
893 } | 881 } |
894 | 882 |
895 void SoftwareImageDecodeCache::SanityCheckState(int line, bool lock_acquired) { | |
896 #if DCHECK_IS_ON() | |
897 if (!lock_acquired) { | |
898 base::AutoLock lock(lock_); | |
899 SanityCheckState(line, true); | |
900 return; | |
901 } | |
902 | |
903 MemoryBudget budget(locked_images_budget_.total_limit_bytes()); | |
904 for (const auto& image_pair : decoded_images_) { | |
905 const auto& key = image_pair.first; | |
906 const auto& image = image_pair.second; | |
907 | |
908 auto ref_it = decoded_images_ref_counts_.find(key); | |
909 if (image->is_locked()) { | |
910 budget.AddUsage(key.locked_bytes()); | |
911 DCHECK(ref_it != decoded_images_ref_counts_.end()) << line; | |
912 } else { | |
913 DCHECK(ref_it == decoded_images_ref_counts_.end() || | |
914 pending_in_raster_image_tasks_.find(key) != | |
915 pending_in_raster_image_tasks_.end() || | |
916 pending_out_of_raster_image_tasks_.find(key) != | |
917 pending_out_of_raster_image_tasks_.end()) | |
918 << line; | |
919 } | |
920 } | |
921 DCHECK_GE(budget.AvailableMemoryBytes(), | |
922 locked_images_budget_.AvailableMemoryBytes()) | |
923 << line; | |
924 #endif // DCHECK_IS_ON() | |
925 } | |
926 | |
927 // SoftwareImageDecodeCacheKey | 883 // SoftwareImageDecodeCacheKey |
928 ImageDecodeCacheKey ImageDecodeCacheKey::FromDrawImage(const DrawImage& image) { | 884 ImageDecodeCacheKey ImageDecodeCacheKey::FromDrawImage(const DrawImage& image) { |
929 const SkSize& scale = image.scale(); | 885 const SkSize& scale = image.scale(); |
930 // If the src_rect falls outside of the image, we need to clip it since | 886 // If the src_rect falls outside of the image, we need to clip it since |
931 // otherwise we might end up with uninitialized memory in the decode process. | 887 // otherwise we might end up with uninitialized memory in the decode process. |
932 // Note that the scale is still unchanged and the target size is now a | 888 // Note that the scale is still unchanged and the target size is now a |
933 // function of the new src_rect. | 889 // function of the new src_rect. |
934 const gfx::Rect& src_rect = GetSrcRect(image); | 890 const gfx::Rect& src_rect = GetSrcRect(image); |
935 gfx::Size target_size( | 891 gfx::Size target_size( |
936 SkScalarRoundToInt(std::abs(src_rect.width() * scale.width())), | 892 SkScalarRoundToInt(std::abs(src_rect.width() * scale.width())), |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1200 } | 1156 } |
1201 } | 1157 } |
1202 } | 1158 } |
1203 | 1159 |
1204 void SoftwareImageDecodeCache::OnPurgeMemory() { | 1160 void SoftwareImageDecodeCache::OnPurgeMemory() { |
1205 base::AutoLock lock(lock_); | 1161 base::AutoLock lock(lock_); |
1206 ReduceCacheUsageUntilWithinLimit(0); | 1162 ReduceCacheUsageUntilWithinLimit(0); |
1207 } | 1163 } |
1208 | 1164 |
1209 } // namespace cc | 1165 } // namespace cc |
OLD | NEW |