| 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 |