| 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_controller.h" | 5 #include "cc/tiles/software_image_decode_controller.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <functional> | 9 #include <functional> |
| 10 | 10 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 template <typename Type> | 76 template <typename Type> |
| 77 typename std::deque<Type>::iterator FindImage( | 77 typename std::deque<Type>::iterator FindImage( |
| 78 std::deque<Type>* collection, | 78 std::deque<Type>* collection, |
| 79 const ImageDecodeControllerKey& key) { | 79 const ImageDecodeControllerKey& key) { |
| 80 return std::find_if(collection->begin(), collection->end(), | 80 return std::find_if(collection->begin(), collection->end(), |
| 81 [key](const Type& image) { return image.first == key; }); | 81 [key](const Type& image) { return image.first == key; }); |
| 82 } | 82 } |
| 83 | 83 |
| 84 SkSize GetScaleAdjustment(const ImageDecodeControllerKey& key) { | 84 SkSize GetScaleAdjustment(const ImageDecodeControllerKey& key) { |
| 85 // If the requested filter quality did not require scale, then the adjustment | 85 // If the requested filter quality did not require scale, then the adjustment |
| 86 // is identity. Note that we still might have extracted a subrect, so | 86 // is identity. |
| 87 // can_use_original_decode is not a sufficient check. | 87 if (key.can_use_original_decode()) |
| 88 if (key.filter_quality() == kLow_SkFilterQuality || | |
| 89 key.filter_quality() == kNone_SkFilterQuality) { | |
| 90 return SkSize::Make(1.f, 1.f); | 88 return SkSize::Make(1.f, 1.f); |
| 91 } | |
| 92 | 89 |
| 93 float x_scale = | 90 float x_scale = |
| 94 key.target_size().width() / static_cast<float>(key.src_rect().width()); | 91 key.target_size().width() / static_cast<float>(key.src_rect().width()); |
| 95 float y_scale = | 92 float y_scale = |
| 96 key.target_size().height() / static_cast<float>(key.src_rect().height()); | 93 key.target_size().height() / static_cast<float>(key.src_rect().height()); |
| 97 return SkSize::Make(x_scale, y_scale); | 94 return SkSize::Make(x_scale, y_scale); |
| 98 } | 95 } |
| 99 | 96 |
| 100 SkFilterQuality GetDecodedFilterQuality(const ImageDecodeControllerKey& key) { | 97 SkFilterQuality GetDecodedFilterQuality(const ImageDecodeControllerKey& key) { |
| 101 return std::min(key.filter_quality(), kLow_SkFilterQuality); | 98 return std::min(key.filter_quality(), kLow_SkFilterQuality); |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 if (!decoded_draw_image.image()) { | 390 if (!decoded_draw_image.image()) { |
| 394 DrawWithImageFinished(original_size_draw_image, decoded_draw_image); | 391 DrawWithImageFinished(original_size_draw_image, decoded_draw_image); |
| 395 return nullptr; | 392 return nullptr; |
| 396 } | 393 } |
| 397 | 394 |
| 398 scoped_ptr<uint8_t[]> decoded_subrect_pixels; | 395 scoped_ptr<uint8_t[]> decoded_subrect_pixels; |
| 399 SkPixmap decoded_pixmap; | 396 SkPixmap decoded_pixmap; |
| 400 bool result; | 397 bool result; |
| 401 if (key.src_rect() == full_image_rect) { | 398 if (key.src_rect() == full_image_rect) { |
| 402 result = decoded_draw_image.image()->peekPixels(&decoded_pixmap); | 399 result = decoded_draw_image.image()->peekPixels(&decoded_pixmap); |
| 403 } else if (key.filter_quality() != kNone_SkFilterQuality && | 400 } else { |
| 404 key.filter_quality() != kLow_SkFilterQuality) { | 401 // TODO(vmpstr): We don't need to allocate memory here, we can use some |
| 402 // pointer math to get the subrect from the original. This is possible |
| 403 // because we know the original can peek pixels. |
| 405 SkImageInfo decoded_info = SkImageInfo::MakeN32Premul( | 404 SkImageInfo decoded_info = SkImageInfo::MakeN32Premul( |
| 406 key.src_rect().width(), key.src_rect().height()); | 405 key.src_rect().width(), key.src_rect().height()); |
| 407 { | 406 { |
| 408 TRACE_EVENT0( | 407 TRACE_EVENT0( |
| 409 "disabled-by-default-cc.debug", | 408 "disabled-by-default-cc.debug", |
| 410 "SoftwareImageDecodeController::DecodeImageInternal - allocate " | 409 "SoftwareImageDecodeController::DecodeImageInternal - allocate " |
| 411 "decoded pixels"); | 410 "decoded pixels"); |
| 412 decoded_subrect_pixels.reset( | 411 decoded_subrect_pixels.reset( |
| 413 new uint8_t[decoded_info.minRowBytes() * decoded_info.height()]); | 412 new uint8_t[decoded_info.minRowBytes() * decoded_info.height()]); |
| 414 } | 413 } |
| 415 { | 414 { |
| 416 TRACE_EVENT0( | 415 TRACE_EVENT0( |
| 417 "disabled-by-default-cc.debug", | 416 "disabled-by-default-cc.debug", |
| 418 "SoftwareImageDecodeController::DecodeImageInternal - read pixels"); | 417 "SoftwareImageDecodeController::DecodeImageInternal - read pixels"); |
| 419 result = | 418 result = |
| 420 image->readPixels(decoded_info, decoded_subrect_pixels.get(), | 419 image->readPixels(decoded_info, decoded_subrect_pixels.get(), |
| 421 decoded_info.minRowBytes(), key.src_rect().x(), | 420 decoded_info.minRowBytes(), key.src_rect().x(), |
| 422 key.src_rect().y(), SkImage::kDisallow_CachingHint); | 421 key.src_rect().y(), SkImage::kDisallow_CachingHint); |
| 423 } | 422 } |
| 424 decoded_pixmap = SkPixmap(decoded_info, decoded_subrect_pixels.get(), | 423 decoded_pixmap = SkPixmap(decoded_info, decoded_subrect_pixels.get(), |
| 425 decoded_info.minRowBytes()); | 424 decoded_info.minRowBytes()); |
| 426 } else { | |
| 427 // In a low and none filter quality cases if we need a subrect, we need to | |
| 428 // extract it but then we don't need to scale it. | |
| 429 SkImageInfo decoded_info = SkImageInfo::MakeN32Premul( | |
| 430 key.src_rect().width(), key.src_rect().height()); | |
| 431 scoped_ptr<base::DiscardableMemory> discardable_subrect_pixels; | |
| 432 { | |
| 433 TRACE_EVENT0( | |
| 434 "disabled-by-default-cc.debug", | |
| 435 "SoftwareImageDecodeController::DecodeImageInternal - allocate " | |
| 436 "discardable subrect pixels"); | |
| 437 discardable_subrect_pixels = | |
| 438 base::DiscardableMemoryAllocator::GetInstance() | |
| 439 ->AllocateLockedDiscardableMemory(decoded_info.minRowBytes() * | |
| 440 decoded_info.height()); | |
| 441 } | |
| 442 { | |
| 443 TRACE_EVENT0("disabled-by-default-cc.debug", | |
| 444 "SoftwareImageDecodeController::DecodeImageInternal - read " | |
| 445 "subrect pixels"); | |
| 446 result = | |
| 447 image->readPixels(decoded_info, discardable_subrect_pixels->data(), | |
| 448 decoded_info.minRowBytes(), key.src_rect().x(), | |
| 449 key.src_rect().y(), SkImage::kDisallow_CachingHint); | |
| 450 } | |
| 451 DCHECK(result); | |
| 452 DrawWithImageFinished(original_size_draw_image, decoded_draw_image); | |
| 453 return make_scoped_refptr(new DecodedImage( | |
| 454 decoded_info, std::move(discardable_subrect_pixels), | |
| 455 SkSize::Make(-key.src_rect().x(), -key.src_rect().y()))); | |
| 456 } | 425 } |
| 457 | 426 |
| 458 // Since the decoded_draw_image has locked memory, it should always succeed on | 427 // Since the decoded_draw_image has locked memory, it should always succeed on |
| 459 // both peekPixels and readPixels. | 428 // both peekPixels and readPixels. |
| 460 DCHECK(result); | 429 DCHECK(result); |
| 461 | 430 |
| 462 // Now we have a decoded_pixmap which represents the src_rect at the | 431 // Now we have a decoded_pixmap which represents the src_rect at the |
| 463 // original | 432 // original |
| 464 // scale. All we need to do is scale it. | 433 // scale. All we need to do is scale it. |
| 465 DCHECK(!key.target_size().IsEmpty()); | 434 DCHECK(!key.target_size().IsEmpty()); |
| (...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 788 | 757 |
| 789 // Drop from medium to low if the matrix we applied wasn't decomposable or if | 758 // Drop from medium to low if the matrix we applied wasn't decomposable or if |
| 790 // we're enlarging the image in both dimensions. | 759 // we're enlarging the image in both dimensions. |
| 791 if (quality == kMedium_SkFilterQuality) { | 760 if (quality == kMedium_SkFilterQuality) { |
| 792 if (!image.matrix_is_decomposable() || | 761 if (!image.matrix_is_decomposable() || |
| 793 (scale.width() >= 1.f && scale.height() >= 1.f)) { | 762 (scale.width() >= 1.f && scale.height() >= 1.f)) { |
| 794 quality = kLow_SkFilterQuality; | 763 quality = kLow_SkFilterQuality; |
| 795 } | 764 } |
| 796 } | 765 } |
| 797 | 766 |
| 798 gfx::Size full_image_size(image.image()->width(), image.image()->height()); | |
| 799 gfx::Rect full_image_rect(full_image_size); | |
| 800 bool scale_needs_caching = | |
| 801 quality != kLow_SkFilterQuality && quality != kNone_SkFilterQuality; | |
| 802 bool is_full_image_rect = full_image_rect == src_rect; | |
| 803 bool scale_is_required = src_rect.width() != target_size.width() || | |
| 804 src_rect.height() != target_size.height(); | |
| 805 bool can_use_original_decode = | 767 bool can_use_original_decode = |
| 806 !scale_needs_caching && (is_full_image_rect || !scale_is_required); | 768 quality == kLow_SkFilterQuality || quality == kNone_SkFilterQuality; |
| 769 |
| 807 // If we're going to use the original decode, then the target size should be | 770 // If we're going to use the original decode, then the target size should be |
| 808 // the full image size, since that will allow for proper memory accounting. | 771 // the full image size, since that will allow for proper memory accounting. |
| 809 // Note we skip the decode if the target size is empty altogether, so don't | 772 // Note we skip the decode if the target size is empty altogether, so don't |
| 810 // update the target size in that case. | 773 // update the target size in that case. |
| 811 if (can_use_original_decode && !target_size.IsEmpty()) | 774 if (can_use_original_decode && !target_size.IsEmpty()) |
| 812 target_size = full_image_size; | 775 target_size = gfx::Size(image.image()->width(), image.image()->height()); |
| 813 | 776 |
| 814 return ImageDecodeControllerKey(image.image()->uniqueID(), src_rect, | 777 return ImageDecodeControllerKey(image.image()->uniqueID(), src_rect, |
| 815 target_size, quality, | 778 target_size, quality, |
| 816 can_use_original_decode); | 779 can_use_original_decode); |
| 817 } | 780 } |
| 818 | 781 |
| 819 ImageDecodeControllerKey::ImageDecodeControllerKey( | 782 ImageDecodeControllerKey::ImageDecodeControllerKey( |
| 820 uint32_t image_id, | 783 uint32_t image_id, |
| 821 const gfx::Rect& src_rect, | 784 const gfx::Rect& src_rect, |
| 822 const gfx::Size& target_size, | 785 const gfx::Size& target_size, |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 911 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() { | 874 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() { |
| 912 current_usage_bytes_ = 0; | 875 current_usage_bytes_ = 0; |
| 913 } | 876 } |
| 914 | 877 |
| 915 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe() | 878 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe() |
| 916 const { | 879 const { |
| 917 return current_usage_bytes_.ValueOrDie(); | 880 return current_usage_bytes_.ValueOrDie(); |
| 918 } | 881 } |
| 919 | 882 |
| 920 } // namespace cc | 883 } // namespace cc |
| OLD | NEW |