summaryrefslogtreecommitdiffstats
path: root/chromium/cc/tiles/software_image_decode_cache.cc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-28 15:28:34 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-28 13:54:51 +0000
commit2a19c63448c84c1805fb1a585c3651318bb86ca7 (patch)
treeeb17888e8531aa6ee5e85721bd553b832a7e5156 /chromium/cc/tiles/software_image_decode_cache.cc
parentb014812705fc80bff0a5c120dfcef88f349816dc (diff)
BASELINE: Update Chromium to 69.0.3497.70
Change-Id: I2b7b56e4e7a8b26656930def0d4575dc32b900a0 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/cc/tiles/software_image_decode_cache.cc')
-rw-r--r--chromium/cc/tiles/software_image_decode_cache.cc206
1 files changed, 127 insertions, 79 deletions
diff --git a/chromium/cc/tiles/software_image_decode_cache.cc b/chromium/cc/tiles/software_image_decode_cache.cc
index 6a52e91c066..05038746066 100644
--- a/chromium/cc/tiles/software_image_decode_cache.cc
+++ b/chromium/cc/tiles/software_image_decode_cache.cc
@@ -24,23 +24,6 @@ using base::trace_event::MemoryDumpLevelOfDetail;
namespace cc {
namespace {
-bool UseCacheForDrawImage(const DrawImage& draw_image) {
- // Lazy generated images are have their decode cached.
- sk_sp<SkImage> sk_image = draw_image.paint_image().GetSkImage();
- if (sk_image->isLazyGenerated())
- return true;
-
- // Cache images that need to be converted to a non-sRGB color space.
- // TODO(ccameron): Consider caching when any color conversion is required.
- // https://crbug.com/791828
- const gfx::ColorSpace& dst_color_space = draw_image.target_color_space();
- if (dst_color_space.IsValid() &&
- dst_color_space != gfx::ColorSpace::CreateSRGB()) {
- return true;
- }
-
- return false;
-}
// The number of entries to keep around in the cache. This limit can be breached
// if more items are locked. That is, locked items ignore this limit.
@@ -172,6 +155,9 @@ SoftwareImageDecodeCache::SoftwareImageDecodeCache(
}
// Register this component with base::MemoryCoordinatorClientRegistry.
base::MemoryCoordinatorClientRegistry::GetInstance()->Register(this);
+ memory_pressure_listener_.reset(new base::MemoryPressureListener(
+ base::BindRepeating(&SoftwareImageDecodeCache::OnMemoryPressure,
+ base::Unretained(this))));
}
SoftwareImageDecodeCache::~SoftwareImageDecodeCache() {
@@ -383,43 +369,37 @@ void SoftwareImageDecodeCache::DecodeImageIfNecessary(
base::AutoUnlock release(lock_);
local_cache_entry = Utils::DoDecodeImage(key, paint_image, color_type_);
} else {
- // Use the full image decode to generate a scaled/subrected decode.
- // TODO(vmpstr): This part needs to handle decode to scale.
- base::Optional<CacheKey> candidate_key;
- auto image_keys_it = frame_key_to_image_keys_.find(key.frame_key());
- // We know that we must have at least our own |entry| in this list, so it
- // won't be empty.
- DCHECK(image_keys_it != frame_key_to_image_keys_.end());
-
- auto& available_keys = image_keys_it->second;
- std::sort(available_keys.begin(), available_keys.end(),
- [](const CacheKey& one, const CacheKey& two) {
- // Return true if |one| scale is less than |two| scale.
- return one.target_size().width() < two.target_size().width() &&
- one.target_size().height() < two.target_size().height();
- });
-
- for (auto& available_key : available_keys) {
- // Only consider keys coming from the same src rect, since otherwise the
- // resulting image was extracted using a different src.
- if (available_key.src_rect() != key.src_rect())
- continue;
-
- // that are at least as big as the required |key|.
- if (available_key.target_size().width() < key.target_size().width() ||
- available_key.target_size().height() < key.target_size().height()) {
- continue;
- }
- auto image_it = decoded_images_.Peek(available_key);
- DCHECK(image_it != decoded_images_.end());
- auto* available_entry = image_it->second.get();
- if (available_entry->is_locked || available_entry->Lock()) {
- candidate_key.emplace(available_key);
- break;
- }
+ // Attempt to find a cached decode to generate a scaled/subrected decode
+ // from.
+ base::Optional<CacheKey> candidate_key = FindCachedCandidate(key);
+
+ SkISize desired_size = gfx::SizeToSkISize(key.target_size());
+ const bool should_decode_to_scale =
+ // Prefer scaling from a cached decode instead of performing another
+ // decode to the desired size.
+ !candidate_key &&
+ // We need the original decode to subrect before scaling, if a subrect
+ // is requested.
+ key.src_rect() ==
+ gfx::Rect(paint_image.width(), paint_image.height()) &&
+ // Note that in the case where we can't decode to the exact desired
+ // size, but a size lower than the original, it would be better to
+ // decode to that size and then scale to the desired size. But this
+ // should be rare in practice, since we only decode to mip levels.
+ paint_image.GetSupportedDecodeSize(desired_size) == desired_size;
+
+ // We don't scale and cache the result if nearest neighbor is requested,
+ // i.e., the processing type should be kOriginal or kSubrectOriginal. And
+ // requesting a subrect already vetoes decode to scale.
+ DCHECK(!should_decode_to_scale || !key.is_nearest_neighbor());
+ if (should_decode_to_scale) {
+ base::AutoUnlock release(lock_);
+ local_cache_entry = Utils::DoDecodeImage(key, paint_image, color_type_);
}
- if (!candidate_key) {
+ // Couldn't decode to scale or find a cached candidate. Create the
+ // intermediate candidate key required for this decode.
+ if (!should_decode_to_scale && !candidate_key) {
// IMPORTANT: There is a bit of a subtlety here. We would normally want to
// generate a new candidate with the key.src_rect() as the src_rect. This
// would ensure that when scaling we won't need to peek pixels, since it's
@@ -445,25 +425,27 @@ void SoftwareImageDecodeCache::DecodeImageIfNecessary(
candidate_key.emplace(
CacheKey::FromDrawImage(candidate_draw_image, color_type_));
}
- CHECK(*candidate_key != key) << key.ToString();
- auto decoded_draw_image =
- GetDecodedImageForDrawInternal(*candidate_key, paint_image);
- if (!decoded_draw_image.image()) {
- local_cache_entry = nullptr;
- } else {
- base::AutoUnlock release(lock_);
- // IMPORTANT: More subtleties:
- // If the candidate could have used the original decode, that means we
- // need to extractSubset from it. In all other cases, this would have
- // already been done to generate the candidate.
- local_cache_entry = Utils::GenerateCacheEntryFromCandidate(
- key, decoded_draw_image, candidate_key->type() == CacheKey::kOriginal,
- color_type_);
- }
+ if (candidate_key) {
+ CHECK(*candidate_key != key) << key.ToString();
+ auto decoded_draw_image =
+ GetDecodedImageForDrawInternal(*candidate_key, paint_image);
+ if (!decoded_draw_image.image()) {
+ local_cache_entry = nullptr;
+ } else {
+ base::AutoUnlock release(lock_);
+ // IMPORTANT: More subtleties:
+ // If the candidate could have used the original decode, that means we
+ // need to extractSubset from it. In all other cases, this would have
+ // already been done to generate the candidate.
+ local_cache_entry = Utils::GenerateCacheEntryFromCandidate(
+ key, decoded_draw_image,
+ candidate_key->type() == CacheKey::kOriginal, color_type_);
+ }
- // Unref to balance the GetDecodedImageForDrawInternal() call.
- UnrefImage(*candidate_key);
+ // Unref to balance the GetDecodedImageForDrawInternal() call.
+ UnrefImage(*candidate_key);
+ }
}
if (!local_cache_entry) {
@@ -488,15 +470,70 @@ void SoftwareImageDecodeCache::DecodeImageIfNecessary(
}
}
+base::Optional<SoftwareImageDecodeCache::CacheKey>
+SoftwareImageDecodeCache::FindCachedCandidate(const CacheKey& key) {
+ auto image_keys_it = frame_key_to_image_keys_.find(key.frame_key());
+ // We know that we must have at least our own |entry| in this list, so it
+ // won't be empty.
+ DCHECK(image_keys_it != frame_key_to_image_keys_.end());
+
+ auto& available_keys = image_keys_it->second;
+ std::sort(available_keys.begin(), available_keys.end(),
+ [](const CacheKey& one, const CacheKey& two) {
+ // Return true if |one| scale is less than |two| scale.
+ return one.target_size().width() < two.target_size().width() &&
+ one.target_size().height() < two.target_size().height();
+ });
+
+ for (auto& available_key : available_keys) {
+ // Only consider keys coming from the same src rect, since otherwise the
+ // resulting image was extracted using a different src.
+ if (available_key.src_rect() != key.src_rect())
+ continue;
+
+ // That are at least as big as the required |key|.
+ if (available_key.target_size().width() < key.target_size().width() ||
+ available_key.target_size().height() < key.target_size().height()) {
+ continue;
+ }
+ auto image_it = decoded_images_.Peek(available_key);
+ DCHECK(image_it != decoded_images_.end());
+ auto* available_entry = image_it->second.get();
+ if (available_entry->is_locked || available_entry->Lock()) {
+ return available_key;
+ }
+ }
+
+ return base::nullopt;
+}
+
+bool SoftwareImageDecodeCache::UseCacheForDrawImage(
+ const DrawImage& draw_image) const {
+ sk_sp<SkImage> sk_image = draw_image.paint_image().GetSkImage();
+
+ // Software cache doesn't support using texture backed images.
+ if (sk_image->isTextureBacked())
+ return false;
+
+ // Lazy generated images need to have their decode cached.
+ if (sk_image->isLazyGenerated())
+ return true;
+
+ // Cache images that need to be converted to a non-sRGB color space.
+ // TODO(ccameron): Consider caching when any color conversion is required.
+ // https://crbug.com/791828
+ const gfx::ColorSpace& dst_color_space = draw_image.target_color_space();
+ if (dst_color_space.IsValid() &&
+ dst_color_space != gfx::ColorSpace::CreateSRGB()) {
+ return true;
+ }
+
+ return false;
+}
+
DecodedDrawImage SoftwareImageDecodeCache::GetDecodedImageForDraw(
const DrawImage& draw_image) {
- // Non-cached images are be used for raster directly.
- if (!UseCacheForDrawImage(draw_image)) {
- return DecodedDrawImage(draw_image.paint_image().GetSkImage(),
- SkSize::Make(0, 0), SkSize::Make(1.f, 1.f),
- draw_image.filter_quality(),
- true /* is_budgeted */);
- }
+ DCHECK(UseCacheForDrawImage(draw_image));
base::AutoLock hold(lock_);
return GetDecodedImageForDrawInternal(
@@ -538,9 +575,7 @@ DecodedDrawImage SoftwareImageDecodeCache::GetDecodedImageForDrawInternal(
void SoftwareImageDecodeCache::DrawWithImageFinished(
const DrawImage& image,
const DecodedDrawImage& decoded_image) {
- if (!UseCacheForDrawImage(image))
- return;
-
+ DCHECK(UseCacheForDrawImage(image));
TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
"SoftwareImageDecodeCache::DrawWithImageFinished", "key",
CacheKey::FromDrawImage(image, color_type_).ToString());
@@ -670,6 +705,19 @@ void SoftwareImageDecodeCache::OnPurgeMemory() {
ReduceCacheUsageUntilWithinLimit(0);
}
+void SoftwareImageDecodeCache::OnMemoryPressure(
+ base::MemoryPressureListener::MemoryPressureLevel level) {
+ base::AutoLock lock(lock_);
+ switch (level) {
+ case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
+ case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
+ break;
+ case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
+ ReduceCacheUsageUntilWithinLimit(0);
+ break;
+ }
+}
+
SoftwareImageDecodeCache::CacheEntry* SoftwareImageDecodeCache::AddCacheEntry(
const CacheKey& key) {
lock_.AssertAcquired();