Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(21)

Side by Side Diff: cc/tiles/software_image_decode_cache.cc

Issue 2797583002: cc: Add color space to image decode caches (Closed)
Patch Set: Review feedback, except the sk_sp bit... Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698