Chromium Code Reviews| 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 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |