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

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

Issue 2801413002: color: Enable color conversion in image decoder caches (Closed)
Patch Set: Rebase 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
« no previous file with comments | « cc/tiles/software_image_decode_cache.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 return SkSize::Make(x_scale, y_scale); 151 return SkSize::Make(x_scale, y_scale);
152 } 152 }
153 } 153 }
154 154
155 SkFilterQuality GetDecodedFilterQuality(const ImageDecodeCacheKey& key) { 155 SkFilterQuality GetDecodedFilterQuality(const ImageDecodeCacheKey& key) {
156 return std::min(key.filter_quality(), kLow_SkFilterQuality); 156 return std::min(key.filter_quality(), kLow_SkFilterQuality);
157 } 157 }
158 158
159 SkImageInfo CreateImageInfo(size_t width, 159 SkImageInfo CreateImageInfo(size_t width,
160 size_t height, 160 size_t height,
161 ResourceFormat format) { 161 ResourceFormat format,
162 sk_sp<SkColorSpace> color_space) {
162 return SkImageInfo::Make(width, height, 163 return SkImageInfo::Make(width, height,
163 ResourceFormatToClosestSkColorType(format), 164 ResourceFormatToClosestSkColorType(format),
164 kPremul_SkAlphaType); 165 kPremul_SkAlphaType, color_space);
msarett1 2017/04/10 21:02:53 Ignorable nit/question not related to this CL: Is
ccameron 2017/04/10 23:18:30 I'm not sure ... vmpstr may know. I believe that w
msarett1 2017/04/12 12:59:17 Marking as opaque would definitely improve the per
165 } 166 }
166 167
167 void RecordLockExistingCachedImageHistogram(TilePriority::PriorityBin bin, 168 void RecordLockExistingCachedImageHistogram(TilePriority::PriorityBin bin,
168 bool success) { 169 bool success) {
169 switch (bin) { 170 switch (bin) {
170 case TilePriority::NOW: 171 case TilePriority::NOW:
171 UMA_HISTOGRAM_BOOLEAN("Renderer4.LockExistingCachedImage.Software.NOW", 172 UMA_HISTOGRAM_BOOLEAN("Renderer4.LockExistingCachedImage.Software.NOW",
172 success); 173 success);
173 case TilePriority::SOON: 174 case TilePriority::SOON:
174 UMA_HISTOGRAM_BOOLEAN("Renderer4.LockExistingCachedImage.Software.SOON", 175 UMA_HISTOGRAM_BOOLEAN("Renderer4.LockExistingCachedImage.Software.SOON",
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 key.ToString()); 448 key.ToString());
448 sk_sp<const SkImage> image = draw_image.image(); 449 sk_sp<const SkImage> image = draw_image.image();
449 if (!image) 450 if (!image)
450 return nullptr; 451 return nullptr;
451 452
452 switch (key.filter_quality()) { 453 switch (key.filter_quality()) {
453 case kNone_SkFilterQuality: 454 case kNone_SkFilterQuality:
454 case kLow_SkFilterQuality: 455 case kLow_SkFilterQuality:
455 if (key.should_use_subrect()) 456 if (key.should_use_subrect())
456 return GetSubrectImageDecode(key, std::move(image)); 457 return GetSubrectImageDecode(key, std::move(image));
457 return GetOriginalImageDecode(std::move(image)); 458 return GetOriginalSizeImageDecode(key, std::move(image));
458 case kMedium_SkFilterQuality: 459 case kMedium_SkFilterQuality:
459 case kHigh_SkFilterQuality: 460 case kHigh_SkFilterQuality:
460 return GetScaledImageDecode(key, std::move(image)); 461 return GetScaledImageDecode(key, std::move(image));
461 default: 462 default:
462 NOTREACHED(); 463 NOTREACHED();
463 return nullptr; 464 return nullptr;
464 } 465 }
465 } 466 }
466 467
467 DecodedDrawImage SoftwareImageDecodeCache::GetDecodedImageForDraw( 468 DecodedDrawImage SoftwareImageDecodeCache::GetDecodedImageForDraw(
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 SanityCheckState(__LINE__, true); 568 SanityCheckState(__LINE__, true);
568 decoded_image->mark_used(); 569 decoded_image->mark_used();
569 auto decoded_draw_image = 570 auto decoded_draw_image =
570 DecodedDrawImage(decoded_image->image(), decoded_image->src_rect_offset(), 571 DecodedDrawImage(decoded_image->image(), decoded_image->src_rect_offset(),
571 GetScaleAdjustment(key), GetDecodedFilterQuality(key)); 572 GetScaleAdjustment(key), GetDecodedFilterQuality(key));
572 decoded_draw_image.set_at_raster_decode(true); 573 decoded_draw_image.set_at_raster_decode(true);
573 return decoded_draw_image; 574 return decoded_draw_image;
574 } 575 }
575 576
576 std::unique_ptr<SoftwareImageDecodeCache::DecodedImage> 577 std::unique_ptr<SoftwareImageDecodeCache::DecodedImage>
577 SoftwareImageDecodeCache::GetOriginalImageDecode(sk_sp<const SkImage> image) { 578 SoftwareImageDecodeCache::GetOriginalSizeImageDecode(
579 const ImageKey& key,
580 sk_sp<const SkImage> image) {
578 SkImageInfo decoded_info = 581 SkImageInfo decoded_info =
579 CreateImageInfo(image->width(), image->height(), format_); 582 CreateImageInfo(image->width(), image->height(), format_,
583 key.target_color_space().ToSkColorSpace());
584
580 std::unique_ptr<base::DiscardableMemory> decoded_pixels; 585 std::unique_ptr<base::DiscardableMemory> decoded_pixels;
581 { 586 {
582 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), 587 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
583 "SoftwareImageDecodeCache::GetOriginalImageDecode - " 588 "SoftwareImageDecodeCache::GetOriginalSizeImageDecode - "
584 "allocate decoded pixels"); 589 "allocate decoded pixels");
585 decoded_pixels = 590 decoded_pixels =
586 base::DiscardableMemoryAllocator::GetInstance() 591 base::DiscardableMemoryAllocator::GetInstance()
587 ->AllocateLockedDiscardableMemory(decoded_info.minRowBytes() * 592 ->AllocateLockedDiscardableMemory(decoded_info.minRowBytes() *
588 decoded_info.height()); 593 decoded_info.height());
589 } 594 }
590 { 595 {
591 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), 596 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
592 "SoftwareImageDecodeCache::GetOriginalImageDecode - " 597 "SoftwareImageDecodeCache::GetOriginalSizeImageDecode - "
593 "read pixels"); 598 "read pixels");
594 bool result = image->readPixels(decoded_info, decoded_pixels->data(), 599 bool result = image->readPixels(decoded_info, decoded_pixels->data(),
ccameron 2017/04/10 23:18:29 Yes, I was hoping to just call readPixels here...
msarett1 2017/04/12 12:59:17 Acknowledged.
595 decoded_info.minRowBytes(), 0, 0, 600 decoded_info.minRowBytes(), 0, 0,
596 SkImage::kDisallow_CachingHint); 601 SkImage::kDisallow_CachingHint);
597 602
598 if (!result) { 603 if (!result) {
599 decoded_pixels->Unlock(); 604 decoded_pixels->Unlock();
600 return nullptr; 605 return nullptr;
601 } 606 }
602 } 607 }
603 608
604 // TODO(ccameron,msarett): Convert image to target color space.
605 // http://crbug.com/706613
606
607 return base::MakeUnique<DecodedImage>(decoded_info, std::move(decoded_pixels), 609 return base::MakeUnique<DecodedImage>(decoded_info, std::move(decoded_pixels),
608 SkSize::Make(0, 0), 610 SkSize::Make(0, 0),
609 next_tracing_id_.GetNext()); 611 next_tracing_id_.GetNext());
610 } 612 }
611 613
612 std::unique_ptr<SoftwareImageDecodeCache::DecodedImage> 614 std::unique_ptr<SoftwareImageDecodeCache::DecodedImage>
613 SoftwareImageDecodeCache::GetSubrectImageDecode(const ImageKey& key, 615 SoftwareImageDecodeCache::GetSubrectImageDecode(const ImageKey& key,
614 sk_sp<const SkImage> image) { 616 sk_sp<const SkImage> image) {
615 // Construct a key to use in GetDecodedImageForDrawInternal(). 617 // Construct a key to use in GetDecodedImageForDrawInternal().
616 // This allows us to reuse an image in any cache if available. 618 // This allows us to reuse an image in any cache if available.
617 gfx::Rect full_image_rect(image->width(), image->height()); 619 gfx::Rect full_image_rect(image->width(), image->height());
618 DrawImage original_size_draw_image( 620 DrawImage original_size_draw_image(
619 std::move(image), gfx::RectToSkIRect(full_image_rect), 621 std::move(image), gfx::RectToSkIRect(full_image_rect),
620 kNone_SkFilterQuality, SkMatrix::I(), key.target_color_space()); 622 kNone_SkFilterQuality, SkMatrix::I(), key.target_color_space());
621 ImageKey original_size_key = 623 ImageKey original_size_key =
622 ImageKey::FromDrawImage(original_size_draw_image); 624 ImageKey::FromDrawImage(original_size_draw_image);
623 // Sanity checks. 625 // Sanity checks.
624 DCHECK(original_size_key.can_use_original_size_decode()) 626 DCHECK(original_size_key.can_use_original_size_decode())
625 << original_size_key.ToString(); 627 << original_size_key.ToString();
626 DCHECK(full_image_rect.size() == original_size_key.target_size()); 628 DCHECK(full_image_rect.size() == original_size_key.target_size());
627 629
628 auto decoded_draw_image = GetDecodedImageForDrawInternal( 630 auto decoded_draw_image = GetDecodedImageForDrawInternal(
629 original_size_key, original_size_draw_image); 631 original_size_key, original_size_draw_image);
630 AutoDrawWithImageFinished auto_finish_draw(this, original_size_draw_image, 632 AutoDrawWithImageFinished auto_finish_draw(this, original_size_draw_image,
631 decoded_draw_image); 633 decoded_draw_image);
632 if (!decoded_draw_image.image()) 634 if (!decoded_draw_image.image())
633 return nullptr; 635 return nullptr;
634 636
635 SkImageInfo subrect_info = CreateImageInfo( 637 DCHECK(SkColorSpace::Equals(decoded_draw_image.image()->colorSpace(),
636 key.target_size().width(), key.target_size().height(), format_); 638 key.target_color_space().ToSkColorSpace().get()));
639 SkImageInfo subrect_info =
640 CreateImageInfo(key.target_size().width(), key.target_size().height(),
641 format_, decoded_draw_image.image()->refColorSpace());
637 std::unique_ptr<base::DiscardableMemory> subrect_pixels; 642 std::unique_ptr<base::DiscardableMemory> subrect_pixels;
638 { 643 {
639 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), 644 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
640 "SoftwareImageDecodeCache::GetSubrectImageDecode - " 645 "SoftwareImageDecodeCache::GetSubrectImageDecode - "
641 "allocate subrect pixels"); 646 "allocate subrect pixels");
642 // TODO(vmpstr): This is using checked math to diagnose a problem reported 647 // TODO(vmpstr): This is using checked math to diagnose a problem reported
643 // in crbug.com/662217. If this is causing crashes, then it should be fixed 648 // in crbug.com/662217. If this is causing crashes, then it should be fixed
644 // elsewhere by skipping images that are too large. 649 // elsewhere by skipping images that are too large.
645 base::CheckedNumeric<size_t> byte_size = subrect_info.minRowBytes(); 650 base::CheckedNumeric<size_t> byte_size = subrect_info.minRowBytes();
646 byte_size *= subrect_info.height(); 651 byte_size *= subrect_info.height();
647 subrect_pixels = 652 subrect_pixels =
648 base::DiscardableMemoryAllocator::GetInstance() 653 base::DiscardableMemoryAllocator::GetInstance()
649 ->AllocateLockedDiscardableMemory(byte_size.ValueOrDie()); 654 ->AllocateLockedDiscardableMemory(byte_size.ValueOrDie());
650 } 655 }
651 { 656 {
652 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), 657 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
653 "SoftwareImageDecodeCache::GetSubrectImageDecode - " 658 "SoftwareImageDecodeCache::GetSubrectImageDecode - "
654 "read pixels"); 659 "read pixels");
655 bool result = decoded_draw_image.image()->readPixels( 660 bool result = decoded_draw_image.image()->readPixels(
656 subrect_info, subrect_pixels->data(), subrect_info.minRowBytes(), 661 subrect_info, subrect_pixels->data(), subrect_info.minRowBytes(),
657 key.src_rect().x(), key.src_rect().y(), SkImage::kDisallow_CachingHint); 662 key.src_rect().x(), key.src_rect().y(), SkImage::kDisallow_CachingHint);
658 // We have a decoded image, and we're reading into already allocated memory. 663 // We have a decoded image, and we're reading into already allocated memory.
659 // This should never fail. 664 // This should never fail.
660 DCHECK(result); 665 DCHECK(result);
661 } 666 }
662 667
663 // TODO(ccameron,msarett): Convert image to target color space.
664 // http://crbug.com/706613
665
666 return base::WrapUnique( 668 return base::WrapUnique(
667 new DecodedImage(subrect_info, std::move(subrect_pixels), 669 new DecodedImage(subrect_info, std::move(subrect_pixels),
668 SkSize::Make(-key.src_rect().x(), -key.src_rect().y()), 670 SkSize::Make(-key.src_rect().x(), -key.src_rect().y()),
669 next_tracing_id_.GetNext())); 671 next_tracing_id_.GetNext()));
670 } 672 }
671 673
672 std::unique_ptr<SoftwareImageDecodeCache::DecodedImage> 674 std::unique_ptr<SoftwareImageDecodeCache::DecodedImage>
673 SoftwareImageDecodeCache::GetScaledImageDecode(const ImageKey& key, 675 SoftwareImageDecodeCache::GetScaledImageDecode(const ImageKey& key,
674 sk_sp<const SkImage> image) { 676 sk_sp<const SkImage> image) {
675 // Construct a key to use in GetDecodedImageForDrawInternal(). 677 // Construct a key to use in GetDecodedImageForDrawInternal().
(...skipping 19 matching lines...) Expand all
695 SkPixmap decoded_pixmap; 697 SkPixmap decoded_pixmap;
696 bool result = decoded_draw_image.image()->peekPixels(&decoded_pixmap); 698 bool result = decoded_draw_image.image()->peekPixels(&decoded_pixmap);
697 DCHECK(result) << key.ToString(); 699 DCHECK(result) << key.ToString();
698 if (key.src_rect() != full_image_rect) { 700 if (key.src_rect() != full_image_rect) {
699 result = decoded_pixmap.extractSubset(&decoded_pixmap, 701 result = decoded_pixmap.extractSubset(&decoded_pixmap,
700 gfx::RectToSkIRect(key.src_rect())); 702 gfx::RectToSkIRect(key.src_rect()));
701 DCHECK(result) << key.ToString(); 703 DCHECK(result) << key.ToString();
702 } 704 }
703 705
704 DCHECK(!key.target_size().IsEmpty()); 706 DCHECK(!key.target_size().IsEmpty());
707
708 // We cannot specify the color space for the scalePixels call, because the
709 // color space may not be renderable. Just declare that that the pixels had
710 // been in the target color space the whole time when we create the image at
711 // the very end.
712 DCHECK(SkColorSpace::Equals(decoded_draw_image.image()->colorSpace(),
713 key.target_color_space().ToSkColorSpace().get()));
705 SkImageInfo scaled_info = CreateImageInfo( 714 SkImageInfo scaled_info = CreateImageInfo(
706 key.target_size().width(), key.target_size().height(), format_); 715 key.target_size().width(), key.target_size().height(), format_, nullptr);
716 SkImageInfo scaled_info_with_color_space =
717 scaled_info.makeColorSpace(decoded_draw_image.image()->refColorSpace());
707 std::unique_ptr<base::DiscardableMemory> scaled_pixels; 718 std::unique_ptr<base::DiscardableMemory> scaled_pixels;
708 { 719 {
709 TRACE_EVENT0( 720 TRACE_EVENT0(
710 TRACE_DISABLED_BY_DEFAULT("cc.debug"), 721 TRACE_DISABLED_BY_DEFAULT("cc.debug"),
711 "SoftwareImageDecodeCache::ScaleImage - allocate scaled pixels"); 722 "SoftwareImageDecodeCache::ScaleImage - allocate scaled pixels");
712 scaled_pixels = base::DiscardableMemoryAllocator::GetInstance() 723 scaled_pixels = base::DiscardableMemoryAllocator::GetInstance()
713 ->AllocateLockedDiscardableMemory( 724 ->AllocateLockedDiscardableMemory(
714 scaled_info.minRowBytes() * scaled_info.height()); 725 scaled_info.minRowBytes() * scaled_info.height());
715 } 726 }
716 SkPixmap scaled_pixmap(scaled_info, scaled_pixels->data(), 727 SkPixmap scaled_pixmap(scaled_info, scaled_pixels->data(),
717 scaled_info.minRowBytes()); 728 scaled_info.minRowBytes());
718 DCHECK(key.filter_quality() == kHigh_SkFilterQuality || 729 DCHECK(key.filter_quality() == kHigh_SkFilterQuality ||
719 key.filter_quality() == kMedium_SkFilterQuality); 730 key.filter_quality() == kMedium_SkFilterQuality);
720 { 731 {
721 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), 732 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
722 "SoftwareImageDecodeCache::ScaleImage - scale pixels"); 733 "SoftwareImageDecodeCache::ScaleImage - scale pixels");
723 bool result = 734 bool result =
724 decoded_pixmap.scalePixels(scaled_pixmap, key.filter_quality()); 735 decoded_pixmap.scalePixels(scaled_pixmap, key.filter_quality());
725 DCHECK(result) << key.ToString(); 736 DCHECK(result) << key.ToString();
726 } 737 }
727 738
728 // TODO(ccameron,msarett): Convert image to target color space.
729 // http://crbug.com/706613
730
731 return base::MakeUnique<DecodedImage>( 739 return base::MakeUnique<DecodedImage>(
732 scaled_info, std::move(scaled_pixels), 740 scaled_info_with_color_space, std::move(scaled_pixels),
733 SkSize::Make(-key.src_rect().x(), -key.src_rect().y()), 741 SkSize::Make(-key.src_rect().x(), -key.src_rect().y()),
734 next_tracing_id_.GetNext()); 742 next_tracing_id_.GetNext());
735 } 743 }
736 744
737 void SoftwareImageDecodeCache::DrawWithImageFinished( 745 void SoftwareImageDecodeCache::DrawWithImageFinished(
738 const DrawImage& image, 746 const DrawImage& image,
739 const DecodedDrawImage& decoded_image) { 747 const DecodedDrawImage& decoded_image) {
740 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), 748 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
741 "SoftwareImageDecodeCache::DrawWithImageFinished", "key", 749 "SoftwareImageDecodeCache::DrawWithImageFinished", "key",
742 ImageKey::FromDrawImage(image).ToString()); 750 ImageKey::FromDrawImage(image).ToString());
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after
1200 } 1208 }
1201 } 1209 }
1202 } 1210 }
1203 1211
1204 void SoftwareImageDecodeCache::OnPurgeMemory() { 1212 void SoftwareImageDecodeCache::OnPurgeMemory() {
1205 base::AutoLock lock(lock_); 1213 base::AutoLock lock(lock_);
1206 ReduceCacheUsageUntilWithinLimit(0); 1214 ReduceCacheUsageUntilWithinLimit(0);
1207 } 1215 }
1208 1216
1209 } // namespace cc 1217 } // namespace cc
OLDNEW
« no previous file with comments | « cc/tiles/software_image_decode_cache.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698