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 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
131 DrawImage image_; | 131 DrawImage image_; |
132 SoftwareImageDecodeCache::DecodeTaskType task_type_; | 132 SoftwareImageDecodeCache::DecodeTaskType task_type_; |
133 const ImageDecodeCache::TracingInfo tracing_info_; | 133 const ImageDecodeCache::TracingInfo tracing_info_; |
134 | 134 |
135 DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl); | 135 DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl); |
136 }; | 136 }; |
137 | 137 |
138 SkSize GetScaleAdjustment(const ImageDecodeCacheKey& key) { | 138 SkSize GetScaleAdjustment(const ImageDecodeCacheKey& key) { |
139 // If the requested filter quality did not require scale, then the adjustment | 139 // If the requested filter quality did not require scale, then the adjustment |
140 // is identity. | 140 // is identity. |
141 if (key.can_use_original_decode() || key.should_use_subrect()) { | 141 if (key.can_use_original_size_decode() || key.should_use_subrect()) { |
142 return SkSize::Make(1.f, 1.f); | 142 return SkSize::Make(1.f, 1.f); |
143 } else if (key.filter_quality() == kMedium_SkFilterQuality) { | 143 } else if (key.filter_quality() == kMedium_SkFilterQuality) { |
144 return MipMapUtil::GetScaleAdjustmentForSize(key.src_rect().size(), | 144 return MipMapUtil::GetScaleAdjustmentForSize(key.src_rect().size(), |
145 key.target_size()); | 145 key.target_size()); |
146 } else { | 146 } else { |
147 float x_scale = | 147 float x_scale = |
148 key.target_size().width() / static_cast<float>(key.src_rect().width()); | 148 key.target_size().width() / static_cast<float>(key.src_rect().width()); |
149 float y_scale = key.target_size().height() / | 149 float y_scale = key.target_size().height() / |
150 static_cast<float>(key.src_rect().height()); | 150 static_cast<float>(key.src_rect().height()); |
151 return SkSize::Make(x_scale, y_scale); | 151 return SkSize::Make(x_scale, y_scale); |
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
604 SkSize::Make(0, 0), | 604 SkSize::Make(0, 0), |
605 next_tracing_id_.GetNext()); | 605 next_tracing_id_.GetNext()); |
606 } | 606 } |
607 | 607 |
608 std::unique_ptr<SoftwareImageDecodeCache::DecodedImage> | 608 std::unique_ptr<SoftwareImageDecodeCache::DecodedImage> |
609 SoftwareImageDecodeCache::GetSubrectImageDecode(const ImageKey& key, | 609 SoftwareImageDecodeCache::GetSubrectImageDecode(const ImageKey& key, |
610 sk_sp<const SkImage> image) { | 610 sk_sp<const SkImage> image) { |
611 // Construct a key to use in GetDecodedImageForDrawInternal(). | 611 // Construct a key to use in GetDecodedImageForDrawInternal(). |
612 // This allows us to reuse an image in any cache if available. | 612 // This allows us to reuse an image in any cache if available. |
613 gfx::Rect full_image_rect(image->width(), image->height()); | 613 gfx::Rect full_image_rect(image->width(), image->height()); |
614 DrawImage original_size_draw_image(std::move(image), | 614 DrawImage original_size_draw_image( |
615 gfx::RectToSkIRect(full_image_rect), | 615 std::move(image), gfx::RectToSkIRect(full_image_rect), |
616 kNone_SkFilterQuality, SkMatrix::I()); | 616 kNone_SkFilterQuality, SkMatrix::I(), key.target_color_space()); |
617 ImageKey original_size_key = | 617 ImageKey original_size_key = |
618 ImageKey::FromDrawImage(original_size_draw_image); | 618 ImageKey::FromDrawImage(original_size_draw_image); |
619 // Sanity checks. | 619 // Sanity checks. |
620 DCHECK(original_size_key.can_use_original_decode()) | 620 DCHECK(original_size_key.can_use_original_size_decode()) |
621 << original_size_key.ToString(); | 621 << original_size_key.ToString(); |
622 DCHECK(full_image_rect.size() == original_size_key.target_size()); | 622 DCHECK(full_image_rect.size() == original_size_key.target_size()); |
623 | 623 |
624 auto decoded_draw_image = GetDecodedImageForDrawInternal( | 624 auto decoded_draw_image = GetDecodedImageForDrawInternal( |
625 original_size_key, original_size_draw_image); | 625 original_size_key, original_size_draw_image); |
626 AutoDrawWithImageFinished auto_finish_draw(this, original_size_draw_image, | 626 AutoDrawWithImageFinished auto_finish_draw(this, original_size_draw_image, |
627 decoded_draw_image); | 627 decoded_draw_image); |
628 if (!decoded_draw_image.image()) | 628 if (!decoded_draw_image.image()) |
629 return nullptr; | 629 return nullptr; |
630 | 630 |
(...skipping 29 matching lines...) Expand all Loading... | |
660 SkSize::Make(-key.src_rect().x(), -key.src_rect().y()), | 660 SkSize::Make(-key.src_rect().x(), -key.src_rect().y()), |
661 next_tracing_id_.GetNext())); | 661 next_tracing_id_.GetNext())); |
662 } | 662 } |
663 | 663 |
664 std::unique_ptr<SoftwareImageDecodeCache::DecodedImage> | 664 std::unique_ptr<SoftwareImageDecodeCache::DecodedImage> |
665 SoftwareImageDecodeCache::GetScaledImageDecode(const ImageKey& key, | 665 SoftwareImageDecodeCache::GetScaledImageDecode(const ImageKey& key, |
666 sk_sp<const SkImage> image) { | 666 sk_sp<const SkImage> image) { |
667 // Construct a key to use in GetDecodedImageForDrawInternal(). | 667 // Construct a key to use in GetDecodedImageForDrawInternal(). |
668 // This allows us to reuse an image in any cache if available. | 668 // This allows us to reuse an image in any cache if available. |
669 gfx::Rect full_image_rect(image->width(), image->height()); | 669 gfx::Rect full_image_rect(image->width(), image->height()); |
670 DrawImage original_size_draw_image(std::move(image), | 670 DrawImage original_size_draw_image( |
671 gfx::RectToSkIRect(full_image_rect), | 671 std::move(image), gfx::RectToSkIRect(full_image_rect), |
672 kNone_SkFilterQuality, SkMatrix::I()); | 672 kNone_SkFilterQuality, SkMatrix::I(), key.target_color_space()); |
673 ImageKey original_size_key = | 673 ImageKey original_size_key = |
674 ImageKey::FromDrawImage(original_size_draw_image); | 674 ImageKey::FromDrawImage(original_size_draw_image); |
675 // Sanity checks. | 675 // Sanity checks. |
676 DCHECK(original_size_key.can_use_original_decode()) | 676 DCHECK(original_size_key.can_use_original_size_decode()) |
677 << original_size_key.ToString(); | 677 << original_size_key.ToString(); |
678 DCHECK(full_image_rect.size() == original_size_key.target_size()); | 678 DCHECK(full_image_rect.size() == original_size_key.target_size()); |
679 | 679 |
680 auto decoded_draw_image = GetDecodedImageForDrawInternal( | 680 auto decoded_draw_image = GetDecodedImageForDrawInternal( |
681 original_size_key, original_size_draw_image); | 681 original_size_key, original_size_draw_image); |
682 AutoDrawWithImageFinished auto_finish_draw(this, original_size_draw_image, | 682 AutoDrawWithImageFinished auto_finish_draw(this, original_size_draw_image, |
683 decoded_draw_image); | 683 decoded_draw_image); |
684 if (!decoded_draw_image.image()) | 684 if (!decoded_draw_image.image()) |
685 return nullptr; | 685 return nullptr; |
686 | 686 |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
954 | 954 |
955 // Drop from medium to low if the matrix we applied wasn't decomposable or if | 955 // Drop from medium to low if the matrix we applied wasn't decomposable or if |
956 // we're enlarging the image in both dimensions. | 956 // we're enlarging the image in both dimensions. |
957 if (quality == kMedium_SkFilterQuality) { | 957 if (quality == kMedium_SkFilterQuality) { |
958 if (!image.matrix_is_decomposable() || | 958 if (!image.matrix_is_decomposable() || |
959 (scale.width() >= 1.f && scale.height() >= 1.f)) { | 959 (scale.width() >= 1.f && scale.height() >= 1.f)) { |
960 quality = kLow_SkFilterQuality; | 960 quality = kLow_SkFilterQuality; |
961 } | 961 } |
962 } | 962 } |
963 | 963 |
964 bool can_use_original_decode = | 964 bool can_use_original_size_decode = |
965 quality == kLow_SkFilterQuality || quality == kNone_SkFilterQuality; | 965 quality == kLow_SkFilterQuality || quality == kNone_SkFilterQuality; |
966 | |
966 bool should_use_subrect = false; | 967 bool should_use_subrect = false; |
967 if (can_use_original_decode && | 968 if (can_use_original_size_decode && |
968 (image.image()->width() >= kMinDimensionToSubrect || | 969 (image.image()->width() >= kMinDimensionToSubrect || |
969 image.image()->height() >= kMinDimensionToSubrect)) { | 970 image.image()->height() >= kMinDimensionToSubrect)) { |
970 base::CheckedNumeric<size_t> checked_original_size = 4u; | 971 base::CheckedNumeric<size_t> checked_original_size = 4u; |
971 checked_original_size *= image.image()->width(); | 972 checked_original_size *= image.image()->width(); |
972 checked_original_size *= image.image()->height(); | 973 checked_original_size *= image.image()->height(); |
973 size_t original_size = checked_original_size.ValueOrDefault( | 974 size_t original_size = checked_original_size.ValueOrDefault( |
974 std::numeric_limits<size_t>::max()); | 975 std::numeric_limits<size_t>::max()); |
975 | 976 |
976 base::CheckedNumeric<size_t> checked_src_rect_size = 4u; | 977 base::CheckedNumeric<size_t> checked_src_rect_size = 4u; |
977 checked_src_rect_size *= src_rect.width(); | 978 checked_src_rect_size *= src_rect.width(); |
978 checked_src_rect_size *= src_rect.height(); | 979 checked_src_rect_size *= src_rect.height(); |
979 size_t src_rect_size = checked_src_rect_size.ValueOrDefault( | 980 size_t src_rect_size = checked_src_rect_size.ValueOrDefault( |
980 std::numeric_limits<size_t>::max()); | 981 std::numeric_limits<size_t>::max()); |
981 if (original_size > kMemoryThresholdToSubrect && | 982 if (original_size > kMemoryThresholdToSubrect && |
982 src_rect_size <= original_size * kMemoryRatioToSubrect) { | 983 src_rect_size <= original_size * kMemoryRatioToSubrect) { |
983 should_use_subrect = true; | 984 should_use_subrect = true; |
984 can_use_original_decode = false; | 985 can_use_original_size_decode = false; |
985 } | 986 } |
986 } | 987 } |
987 | 988 |
988 // If we're going to use the original decode, then the target size should be | 989 // If we're going to use the original decode, then the target size should be |
989 // the full image size, since that will allow for proper memory accounting. | 990 // the full image size, since that will allow for proper memory accounting. |
990 // Note we skip the decode if the target size is empty altogether, so don't | 991 // Note we skip the decode if the target size is empty altogether, so don't |
991 // update the target size in that case. | 992 // update the target size in that case. |
992 if (!target_size.IsEmpty()) { | 993 if (!target_size.IsEmpty()) { |
993 if (should_use_subrect) | 994 if (should_use_subrect) |
994 target_size = src_rect.size(); | 995 target_size = src_rect.size(); |
995 else if (can_use_original_decode) | 996 else if (can_use_original_size_decode) |
996 target_size = gfx::Size(image.image()->width(), image.image()->height()); | 997 target_size = gfx::Size(image.image()->width(), image.image()->height()); |
997 } | 998 } |
998 | 999 |
999 if (quality == kMedium_SkFilterQuality && !target_size.IsEmpty()) { | 1000 if (quality == kMedium_SkFilterQuality && !target_size.IsEmpty()) { |
1000 SkSize mip_target_size = | 1001 SkSize mip_target_size = |
1001 MipMapUtil::GetScaleAdjustmentForSize(src_rect.size(), target_size); | 1002 MipMapUtil::GetScaleAdjustmentForSize(src_rect.size(), target_size); |
1002 target_size.set_width(src_rect.width() * mip_target_size.width()); | 1003 target_size.set_width(src_rect.width() * mip_target_size.width()); |
1003 target_size.set_height(src_rect.height() * mip_target_size.height()); | 1004 target_size.set_height(src_rect.height() * mip_target_size.height()); |
1004 } | 1005 } |
1005 | 1006 |
1006 return ImageDecodeCacheKey(image.image()->uniqueID(), src_rect, target_size, | 1007 return ImageDecodeCacheKey(image.image()->uniqueID(), src_rect, target_size, |
1007 quality, can_use_original_decode, | 1008 image.target_color_space(), quality, |
1008 should_use_subrect); | 1009 can_use_original_size_decode, should_use_subrect); |
1009 } | 1010 } |
1010 | 1011 |
1011 ImageDecodeCacheKey::ImageDecodeCacheKey(uint32_t image_id, | 1012 ImageDecodeCacheKey::ImageDecodeCacheKey( |
1012 const gfx::Rect& src_rect, | 1013 uint32_t image_id, |
1013 const gfx::Size& target_size, | 1014 const gfx::Rect& src_rect, |
1014 SkFilterQuality filter_quality, | 1015 const gfx::Size& target_size, |
1015 bool can_use_original_decode, | 1016 const gfx::ColorSpace& target_color_space, |
1016 bool should_use_subrect) | 1017 SkFilterQuality filter_quality, |
1018 bool can_use_original_size_decode, | |
1019 bool should_use_subrect) | |
1017 : image_id_(image_id), | 1020 : image_id_(image_id), |
1018 src_rect_(src_rect), | 1021 src_rect_(src_rect), |
1019 target_size_(target_size), | 1022 target_size_(target_size), |
1023 target_color_space_(target_color_space), | |
1020 filter_quality_(filter_quality), | 1024 filter_quality_(filter_quality), |
1021 can_use_original_decode_(can_use_original_decode), | 1025 can_use_original_size_decode_(can_use_original_size_decode), |
1022 should_use_subrect_(should_use_subrect) { | 1026 should_use_subrect_(should_use_subrect) { |
1023 if (can_use_original_decode_) { | 1027 if (can_use_original_size_decode_) { |
1024 hash_ = std::hash<uint32_t>()(image_id_); | 1028 hash_ = std::hash<uint32_t>()(image_id_); |
1025 } else { | 1029 } else { |
1026 // TODO(vmpstr): This is a mess. Maybe it's faster to just search the vector | 1030 // TODO(vmpstr): This is a mess. Maybe it's faster to just search the vector |
1027 // always (forwards or backwards to account for LRU). | 1031 // always (forwards or backwards to account for LRU). |
1028 uint64_t src_rect_hash = base::HashInts( | 1032 uint64_t src_rect_hash = base::HashInts( |
1029 static_cast<uint64_t>(base::HashInts(src_rect_.x(), src_rect_.y())), | 1033 static_cast<uint64_t>(base::HashInts(src_rect_.x(), src_rect_.y())), |
1030 static_cast<uint64_t>( | 1034 static_cast<uint64_t>( |
1031 base::HashInts(src_rect_.width(), src_rect_.height()))); | 1035 base::HashInts(src_rect_.width(), src_rect_.height()))); |
1032 | 1036 |
1033 uint64_t target_size_hash = | 1037 uint64_t target_size_hash = |
1034 base::HashInts(target_size_.width(), target_size_.height()); | 1038 base::HashInts(target_size_.width(), target_size_.height()); |
1035 | 1039 |
1036 hash_ = base::HashInts(base::HashInts(src_rect_hash, target_size_hash), | 1040 hash_ = base::HashInts(base::HashInts(src_rect_hash, target_size_hash), |
1037 base::HashInts(image_id_, filter_quality_)); | 1041 base::HashInts(image_id_, filter_quality_)); |
1038 } | 1042 } |
1043 hash_ = base::HashInts(hash_, target_color_space.GetHash()); | |
vmpstr
2017/04/04 17:30:08
leave a comment here please
ccameron
2017/04/04 17:42:03
Sure -- if I leave it in, that is...
If I make I'
| |
1039 } | 1044 } |
1040 | 1045 |
1041 ImageDecodeCacheKey::ImageDecodeCacheKey(const ImageDecodeCacheKey& other) = | 1046 ImageDecodeCacheKey::ImageDecodeCacheKey(const ImageDecodeCacheKey& other) = |
1042 default; | 1047 default; |
1043 | 1048 |
1044 std::string ImageDecodeCacheKey::ToString() const { | 1049 std::string ImageDecodeCacheKey::ToString() const { |
1045 std::ostringstream str; | 1050 std::ostringstream str; |
1046 str << "id[" << image_id_ << "] src_rect[" << src_rect_.x() << "," | 1051 str << "id[" << image_id_ << "] src_rect[" << src_rect_.x() << "," |
1047 << src_rect_.y() << " " << src_rect_.width() << "x" << src_rect_.height() | 1052 << src_rect_.y() << " " << src_rect_.width() << "x" << src_rect_.height() |
1048 << "] target_size[" << target_size_.width() << "x" | 1053 << "] target_size[" << target_size_.width() << "x" |
1049 << target_size_.height() << "] filter_quality[" << filter_quality_ | 1054 << target_size_.height() << "] target_color_space" |
1050 << "] can_use_original_decode [" << can_use_original_decode_ | 1055 << target_color_space_.ToString() << " filter_quality[" << filter_quality_ |
1056 << "] can_use_original_size_decode [" << can_use_original_size_decode_ | |
1051 << "] should_use_subrect [" << should_use_subrect_ << "] hash [" << hash_ | 1057 << "] should_use_subrect [" << should_use_subrect_ << "] hash [" << hash_ |
1052 << "]"; | 1058 << "]"; |
1053 return str.str(); | 1059 return str.str(); |
1054 } | 1060 } |
1055 | 1061 |
1056 // DecodedImage | 1062 // DecodedImage |
1057 SoftwareImageDecodeCache::DecodedImage::DecodedImage( | 1063 SoftwareImageDecodeCache::DecodedImage::DecodedImage( |
1058 const SkImageInfo& info, | 1064 const SkImageInfo& info, |
1059 std::unique_ptr<base::DiscardableMemory> memory, | 1065 std::unique_ptr<base::DiscardableMemory> memory, |
1060 const SkSize& src_rect_offset, | 1066 const SkSize& src_rect_offset, |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1177 } | 1183 } |
1178 } | 1184 } |
1179 } | 1185 } |
1180 | 1186 |
1181 void SoftwareImageDecodeCache::OnPurgeMemory() { | 1187 void SoftwareImageDecodeCache::OnPurgeMemory() { |
1182 base::AutoLock lock(lock_); | 1188 base::AutoLock lock(lock_); |
1183 ReduceCacheUsageUntilWithinLimit(0); | 1189 ReduceCacheUsageUntilWithinLimit(0); |
1184 } | 1190 } |
1185 | 1191 |
1186 } // namespace cc | 1192 } // namespace cc |
OLD | NEW |