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

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

Issue 2797583002: cc: Add color space to image decode caches (Closed)
Patch Set: Remove dead code 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 441 matching lines...) Expand 10 before | Expand all | Expand 10 after
593 "read pixels"); 593 "read pixels");
594 bool result = image->readPixels(decoded_info, decoded_pixels->data(), 594 bool result = image->readPixels(decoded_info, decoded_pixels->data(),
595 decoded_info.minRowBytes(), 0, 0, 595 decoded_info.minRowBytes(), 0, 0,
596 SkImage::kDisallow_CachingHint); 596 SkImage::kDisallow_CachingHint);
597 597
598 if (!result) { 598 if (!result) {
599 decoded_pixels->Unlock(); 599 decoded_pixels->Unlock();
600 return nullptr; 600 return nullptr;
601 } 601 }
602 } 602 }
603
604 // TODO(ccameron,msarett): Convert image to target color space.
605 // http://crbug.com/706613
606
603 return base::MakeUnique<DecodedImage>(decoded_info, std::move(decoded_pixels), 607 return base::MakeUnique<DecodedImage>(decoded_info, std::move(decoded_pixels),
604 SkSize::Make(0, 0), 608 SkSize::Make(0, 0),
605 next_tracing_id_.GetNext()); 609 next_tracing_id_.GetNext());
606 } 610 }
607 611
608 std::unique_ptr<SoftwareImageDecodeCache::DecodedImage> 612 std::unique_ptr<SoftwareImageDecodeCache::DecodedImage>
609 SoftwareImageDecodeCache::GetSubrectImageDecode(const ImageKey& key, 613 SoftwareImageDecodeCache::GetSubrectImageDecode(const ImageKey& key,
610 sk_sp<const SkImage> image) { 614 sk_sp<const SkImage> image) {
611 // Construct a key to use in GetDecodedImageForDrawInternal(). 615 // Construct a key to use in GetDecodedImageForDrawInternal().
612 // This allows us to reuse an image in any cache if available. 616 // This allows us to reuse an image in any cache if available.
613 gfx::Rect full_image_rect(image->width(), image->height()); 617 gfx::Rect full_image_rect(image->width(), image->height());
614 DrawImage original_size_draw_image(std::move(image), 618 DrawImage original_size_draw_image(
615 gfx::RectToSkIRect(full_image_rect), 619 std::move(image), gfx::RectToSkIRect(full_image_rect),
616 kNone_SkFilterQuality, SkMatrix::I()); 620 kNone_SkFilterQuality, SkMatrix::I(), key.target_color_space());
617 ImageKey original_size_key = 621 ImageKey original_size_key =
618 ImageKey::FromDrawImage(original_size_draw_image); 622 ImageKey::FromDrawImage(original_size_draw_image);
619 // Sanity checks. 623 // Sanity checks.
620 DCHECK(original_size_key.can_use_original_decode()) 624 DCHECK(original_size_key.can_use_original_size_decode())
621 << original_size_key.ToString(); 625 << original_size_key.ToString();
622 DCHECK(full_image_rect.size() == original_size_key.target_size()); 626 DCHECK(full_image_rect.size() == original_size_key.target_size());
623 627
624 auto decoded_draw_image = GetDecodedImageForDrawInternal( 628 auto decoded_draw_image = GetDecodedImageForDrawInternal(
625 original_size_key, original_size_draw_image); 629 original_size_key, original_size_draw_image);
626 AutoDrawWithImageFinished auto_finish_draw(this, original_size_draw_image, 630 AutoDrawWithImageFinished auto_finish_draw(this, original_size_draw_image,
627 decoded_draw_image); 631 decoded_draw_image);
628 if (!decoded_draw_image.image()) 632 if (!decoded_draw_image.image())
629 return nullptr; 633 return nullptr;
630 634
(...skipping 17 matching lines...) Expand all
648 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), 652 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
649 "SoftwareImageDecodeCache::GetSubrectImageDecode - " 653 "SoftwareImageDecodeCache::GetSubrectImageDecode - "
650 "read pixels"); 654 "read pixels");
651 bool result = decoded_draw_image.image()->readPixels( 655 bool result = decoded_draw_image.image()->readPixels(
652 subrect_info, subrect_pixels->data(), subrect_info.minRowBytes(), 656 subrect_info, subrect_pixels->data(), subrect_info.minRowBytes(),
653 key.src_rect().x(), key.src_rect().y(), SkImage::kDisallow_CachingHint); 657 key.src_rect().x(), key.src_rect().y(), SkImage::kDisallow_CachingHint);
654 // We have a decoded image, and we're reading into already allocated memory. 658 // We have a decoded image, and we're reading into already allocated memory.
655 // This should never fail. 659 // This should never fail.
656 DCHECK(result); 660 DCHECK(result);
657 } 661 }
662
663 // TODO(ccameron,msarett): Convert image to target color space.
664 // http://crbug.com/706613
665
658 return base::WrapUnique( 666 return base::WrapUnique(
659 new DecodedImage(subrect_info, std::move(subrect_pixels), 667 new DecodedImage(subrect_info, std::move(subrect_pixels),
660 SkSize::Make(-key.src_rect().x(), -key.src_rect().y()), 668 SkSize::Make(-key.src_rect().x(), -key.src_rect().y()),
661 next_tracing_id_.GetNext())); 669 next_tracing_id_.GetNext()));
662 } 670 }
663 671
664 std::unique_ptr<SoftwareImageDecodeCache::DecodedImage> 672 std::unique_ptr<SoftwareImageDecodeCache::DecodedImage>
665 SoftwareImageDecodeCache::GetScaledImageDecode(const ImageKey& key, 673 SoftwareImageDecodeCache::GetScaledImageDecode(const ImageKey& key,
666 sk_sp<const SkImage> image) { 674 sk_sp<const SkImage> image) {
667 // Construct a key to use in GetDecodedImageForDrawInternal(). 675 // Construct a key to use in GetDecodedImageForDrawInternal().
668 // This allows us to reuse an image in any cache if available. 676 // This allows us to reuse an image in any cache if available.
669 gfx::Rect full_image_rect(image->width(), image->height()); 677 gfx::Rect full_image_rect(image->width(), image->height());
670 DrawImage original_size_draw_image(std::move(image), 678 DrawImage original_size_draw_image(
671 gfx::RectToSkIRect(full_image_rect), 679 std::move(image), gfx::RectToSkIRect(full_image_rect),
672 kNone_SkFilterQuality, SkMatrix::I()); 680 kNone_SkFilterQuality, SkMatrix::I(), key.target_color_space());
673 ImageKey original_size_key = 681 ImageKey original_size_key =
674 ImageKey::FromDrawImage(original_size_draw_image); 682 ImageKey::FromDrawImage(original_size_draw_image);
675 // Sanity checks. 683 // Sanity checks.
676 DCHECK(original_size_key.can_use_original_decode()) 684 DCHECK(original_size_key.can_use_original_size_decode())
677 << original_size_key.ToString(); 685 << original_size_key.ToString();
678 DCHECK(full_image_rect.size() == original_size_key.target_size()); 686 DCHECK(full_image_rect.size() == original_size_key.target_size());
679 687
680 auto decoded_draw_image = GetDecodedImageForDrawInternal( 688 auto decoded_draw_image = GetDecodedImageForDrawInternal(
681 original_size_key, original_size_draw_image); 689 original_size_key, original_size_draw_image);
682 AutoDrawWithImageFinished auto_finish_draw(this, original_size_draw_image, 690 AutoDrawWithImageFinished auto_finish_draw(this, original_size_draw_image,
683 decoded_draw_image); 691 decoded_draw_image);
684 if (!decoded_draw_image.image()) 692 if (!decoded_draw_image.image())
685 return nullptr; 693 return nullptr;
686 694
(...skipping 23 matching lines...) Expand all
710 DCHECK(key.filter_quality() == kHigh_SkFilterQuality || 718 DCHECK(key.filter_quality() == kHigh_SkFilterQuality ||
711 key.filter_quality() == kMedium_SkFilterQuality); 719 key.filter_quality() == kMedium_SkFilterQuality);
712 { 720 {
713 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), 721 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
714 "SoftwareImageDecodeCache::ScaleImage - scale pixels"); 722 "SoftwareImageDecodeCache::ScaleImage - scale pixels");
715 bool result = 723 bool result =
716 decoded_pixmap.scalePixels(scaled_pixmap, key.filter_quality()); 724 decoded_pixmap.scalePixels(scaled_pixmap, key.filter_quality());
717 DCHECK(result) << key.ToString(); 725 DCHECK(result) << key.ToString();
718 } 726 }
719 727
728 // TODO(ccameron,msarett): Convert image to target color space.
729 // http://crbug.com/706613
730
720 return base::MakeUnique<DecodedImage>( 731 return base::MakeUnique<DecodedImage>(
721 scaled_info, std::move(scaled_pixels), 732 scaled_info, std::move(scaled_pixels),
722 SkSize::Make(-key.src_rect().x(), -key.src_rect().y()), 733 SkSize::Make(-key.src_rect().x(), -key.src_rect().y()),
723 next_tracing_id_.GetNext()); 734 next_tracing_id_.GetNext());
724 } 735 }
725 736
726 void SoftwareImageDecodeCache::DrawWithImageFinished( 737 void SoftwareImageDecodeCache::DrawWithImageFinished(
727 const DrawImage& image, 738 const DrawImage& image,
728 const DecodedDrawImage& decoded_image) { 739 const DecodedDrawImage& decoded_image) {
729 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), 740 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
959 970
960 // Drop from medium to low if the matrix we applied wasn't decomposable or if 971 // Drop from medium to low if the matrix we applied wasn't decomposable or if
961 // we're enlarging the image in both dimensions. 972 // we're enlarging the image in both dimensions.
962 if (quality == kMedium_SkFilterQuality) { 973 if (quality == kMedium_SkFilterQuality) {
963 if (!image.matrix_is_decomposable() || 974 if (!image.matrix_is_decomposable() ||
964 (scale.width() >= 1.f && scale.height() >= 1.f)) { 975 (scale.width() >= 1.f && scale.height() >= 1.f)) {
965 quality = kLow_SkFilterQuality; 976 quality = kLow_SkFilterQuality;
966 } 977 }
967 } 978 }
968 979
969 bool can_use_original_decode = 980 bool can_use_original_size_decode =
970 quality == kLow_SkFilterQuality || quality == kNone_SkFilterQuality; 981 quality == kLow_SkFilterQuality || quality == kNone_SkFilterQuality;
982
971 bool should_use_subrect = false; 983 bool should_use_subrect = false;
972 if (can_use_original_decode && 984 if (can_use_original_size_decode &&
973 (image.image()->width() >= kMinDimensionToSubrect || 985 (image.image()->width() >= kMinDimensionToSubrect ||
974 image.image()->height() >= kMinDimensionToSubrect)) { 986 image.image()->height() >= kMinDimensionToSubrect)) {
975 base::CheckedNumeric<size_t> checked_original_size = 4u; 987 base::CheckedNumeric<size_t> checked_original_size = 4u;
976 checked_original_size *= image.image()->width(); 988 checked_original_size *= image.image()->width();
977 checked_original_size *= image.image()->height(); 989 checked_original_size *= image.image()->height();
978 size_t original_size = checked_original_size.ValueOrDefault( 990 size_t original_size = checked_original_size.ValueOrDefault(
979 std::numeric_limits<size_t>::max()); 991 std::numeric_limits<size_t>::max());
980 992
981 base::CheckedNumeric<size_t> checked_src_rect_size = 4u; 993 base::CheckedNumeric<size_t> checked_src_rect_size = 4u;
982 checked_src_rect_size *= src_rect.width(); 994 checked_src_rect_size *= src_rect.width();
983 checked_src_rect_size *= src_rect.height(); 995 checked_src_rect_size *= src_rect.height();
984 size_t src_rect_size = checked_src_rect_size.ValueOrDefault( 996 size_t src_rect_size = checked_src_rect_size.ValueOrDefault(
985 std::numeric_limits<size_t>::max()); 997 std::numeric_limits<size_t>::max());
986 if (original_size > kMemoryThresholdToSubrect && 998 if (original_size > kMemoryThresholdToSubrect &&
987 src_rect_size <= original_size * kMemoryRatioToSubrect) { 999 src_rect_size <= original_size * kMemoryRatioToSubrect) {
988 should_use_subrect = true; 1000 should_use_subrect = true;
989 can_use_original_decode = false; 1001 can_use_original_size_decode = false;
990 } 1002 }
991 } 1003 }
992 1004
993 // If we're going to use the original decode, then the target size should be 1005 // If we're going to use the original decode, then the target size should be
994 // the full image size, since that will allow for proper memory accounting. 1006 // the full image size, since that will allow for proper memory accounting.
995 // Note we skip the decode if the target size is empty altogether, so don't 1007 // Note we skip the decode if the target size is empty altogether, so don't
996 // update the target size in that case. 1008 // update the target size in that case.
997 if (!target_size.IsEmpty()) { 1009 if (!target_size.IsEmpty()) {
998 if (should_use_subrect) 1010 if (should_use_subrect)
999 target_size = src_rect.size(); 1011 target_size = src_rect.size();
1000 else if (can_use_original_decode) 1012 else if (can_use_original_size_decode)
1001 target_size = gfx::Size(image.image()->width(), image.image()->height()); 1013 target_size = gfx::Size(image.image()->width(), image.image()->height());
1002 } 1014 }
1003 1015
1004 if (quality == kMedium_SkFilterQuality && !target_size.IsEmpty()) { 1016 if (quality == kMedium_SkFilterQuality && !target_size.IsEmpty()) {
1005 SkSize mip_target_size = 1017 SkSize mip_target_size =
1006 MipMapUtil::GetScaleAdjustmentForSize(src_rect.size(), target_size); 1018 MipMapUtil::GetScaleAdjustmentForSize(src_rect.size(), target_size);
1007 target_size.set_width(src_rect.width() * mip_target_size.width()); 1019 target_size.set_width(src_rect.width() * mip_target_size.width());
1008 target_size.set_height(src_rect.height() * mip_target_size.height()); 1020 target_size.set_height(src_rect.height() * mip_target_size.height());
1009 } 1021 }
1010 1022
1011 return ImageDecodeCacheKey(image.image()->uniqueID(), src_rect, target_size, 1023 return ImageDecodeCacheKey(image.image()->uniqueID(), src_rect, target_size,
1012 quality, can_use_original_decode, 1024 image.target_color_space(), quality,
1013 should_use_subrect); 1025 can_use_original_size_decode, should_use_subrect);
1014 } 1026 }
1015 1027
1016 ImageDecodeCacheKey::ImageDecodeCacheKey(uint32_t image_id, 1028 ImageDecodeCacheKey::ImageDecodeCacheKey(
1017 const gfx::Rect& src_rect, 1029 uint32_t image_id,
1018 const gfx::Size& target_size, 1030 const gfx::Rect& src_rect,
1019 SkFilterQuality filter_quality, 1031 const gfx::Size& target_size,
1020 bool can_use_original_decode, 1032 const gfx::ColorSpace& target_color_space,
1021 bool should_use_subrect) 1033 SkFilterQuality filter_quality,
1034 bool can_use_original_size_decode,
1035 bool should_use_subrect)
1022 : image_id_(image_id), 1036 : image_id_(image_id),
1023 src_rect_(src_rect), 1037 src_rect_(src_rect),
1024 target_size_(target_size), 1038 target_size_(target_size),
1039 target_color_space_(target_color_space),
1025 filter_quality_(filter_quality), 1040 filter_quality_(filter_quality),
1026 can_use_original_decode_(can_use_original_decode), 1041 can_use_original_size_decode_(can_use_original_size_decode),
1027 should_use_subrect_(should_use_subrect) { 1042 should_use_subrect_(should_use_subrect) {
1028 if (can_use_original_decode_) { 1043 if (can_use_original_size_decode_) {
1029 hash_ = std::hash<uint32_t>()(image_id_); 1044 hash_ = std::hash<uint32_t>()(image_id_);
1030 } else { 1045 } else {
1031 // TODO(vmpstr): This is a mess. Maybe it's faster to just search the vector 1046 // TODO(vmpstr): This is a mess. Maybe it's faster to just search the vector
1032 // always (forwards or backwards to account for LRU). 1047 // always (forwards or backwards to account for LRU).
1033 uint64_t src_rect_hash = base::HashInts( 1048 uint64_t src_rect_hash = base::HashInts(
1034 static_cast<uint64_t>(base::HashInts(src_rect_.x(), src_rect_.y())), 1049 static_cast<uint64_t>(base::HashInts(src_rect_.x(), src_rect_.y())),
1035 static_cast<uint64_t>( 1050 static_cast<uint64_t>(
1036 base::HashInts(src_rect_.width(), src_rect_.height()))); 1051 base::HashInts(src_rect_.width(), src_rect_.height())));
1037 1052
1038 uint64_t target_size_hash = 1053 uint64_t target_size_hash =
1039 base::HashInts(target_size_.width(), target_size_.height()); 1054 base::HashInts(target_size_.width(), target_size_.height());
1040 1055
1041 hash_ = base::HashInts(base::HashInts(src_rect_hash, target_size_hash), 1056 hash_ = base::HashInts(base::HashInts(src_rect_hash, target_size_hash),
1042 base::HashInts(image_id_, filter_quality_)); 1057 base::HashInts(image_id_, filter_quality_));
1043 } 1058 }
1059 // Include the target color space in the hash regardless of scaling.
1060 hash_ = base::HashInts(hash_, target_color_space.GetHash());
1044 } 1061 }
1045 1062
1046 ImageDecodeCacheKey::ImageDecodeCacheKey(const ImageDecodeCacheKey& other) = 1063 ImageDecodeCacheKey::ImageDecodeCacheKey(const ImageDecodeCacheKey& other) =
1047 default; 1064 default;
1048 1065
1049 std::string ImageDecodeCacheKey::ToString() const { 1066 std::string ImageDecodeCacheKey::ToString() const {
1050 std::ostringstream str; 1067 std::ostringstream str;
1051 str << "id[" << image_id_ << "] src_rect[" << src_rect_.x() << "," 1068 str << "id[" << image_id_ << "] src_rect[" << src_rect_.x() << ","
1052 << src_rect_.y() << " " << src_rect_.width() << "x" << src_rect_.height() 1069 << src_rect_.y() << " " << src_rect_.width() << "x" << src_rect_.height()
1053 << "] target_size[" << target_size_.width() << "x" 1070 << "] target_size[" << target_size_.width() << "x"
1054 << target_size_.height() << "] filter_quality[" << filter_quality_ 1071 << target_size_.height() << "] target_color_space"
1055 << "] can_use_original_decode [" << can_use_original_decode_ 1072 << target_color_space_.ToString() << " filter_quality[" << filter_quality_
1073 << "] can_use_original_size_decode [" << can_use_original_size_decode_
1056 << "] should_use_subrect [" << should_use_subrect_ << "] hash [" << hash_ 1074 << "] should_use_subrect [" << should_use_subrect_ << "] hash [" << hash_
1057 << "]"; 1075 << "]";
1058 return str.str(); 1076 return str.str();
1059 } 1077 }
1060 1078
1061 // DecodedImage 1079 // DecodedImage
1062 SoftwareImageDecodeCache::DecodedImage::DecodedImage( 1080 SoftwareImageDecodeCache::DecodedImage::DecodedImage(
1063 const SkImageInfo& info, 1081 const SkImageInfo& info,
1064 std::unique_ptr<base::DiscardableMemory> memory, 1082 std::unique_ptr<base::DiscardableMemory> memory,
1065 const SkSize& src_rect_offset, 1083 const SkSize& src_rect_offset,
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
1182 } 1200 }
1183 } 1201 }
1184 } 1202 }
1185 1203
1186 void SoftwareImageDecodeCache::OnPurgeMemory() { 1204 void SoftwareImageDecodeCache::OnPurgeMemory() {
1187 base::AutoLock lock(lock_); 1205 base::AutoLock lock(lock_);
1188 ReduceCacheUsageUntilWithinLimit(0); 1206 ReduceCacheUsageUntilWithinLimit(0);
1189 } 1207 }
1190 1208
1191 } // namespace cc 1209 } // namespace cc
OLDNEW
« no previous file with comments | « cc/tiles/software_image_decode_cache.h ('k') | cc/tiles/software_image_decode_cache_perftest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698