summaryrefslogtreecommitdiffstats
path: root/chromium/cc/tiles/software_image_decode_cache.cc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-09-18 14:34:04 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-10-04 11:15:27 +0000
commite6430e577f105ad8813c92e75c54660c4985026e (patch)
tree88115e5d1fb471fea807111924dcccbeadbf9e4f /chromium/cc/tiles/software_image_decode_cache.cc
parent53d399fe6415a96ea6986ec0d402a9c07da72453 (diff)
BASELINE: Update Chromium to 61.0.3163.99
Change-Id: I8452f34574d88ca2b27af9bd56fc9ff3f16b1367 Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/cc/tiles/software_image_decode_cache.cc')
-rw-r--r--chromium/cc/tiles/software_image_decode_cache.cc153
1 files changed, 77 insertions, 76 deletions
diff --git a/chromium/cc/tiles/software_image_decode_cache.cc b/chromium/cc/tiles/software_image_decode_cache.cc
index c3b6eb7d4f0..5486a718d7d 100644
--- a/chromium/cc/tiles/software_image_decode_cache.cc
+++ b/chromium/cc/tiles/software_image_decode_cache.cc
@@ -21,8 +21,8 @@
#include "base/trace_event/memory_dump_manager.h"
#include "cc/base/devtools_instrumentation.h"
#include "cc/raster/tile_task.h"
-#include "cc/resources/resource_format_utils.h"
#include "cc/tiles/mipmap_util.h"
+#include "components/viz/common/resources/resource_format_utils.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkPixmap.h"
@@ -34,10 +34,6 @@ using base::trace_event::MemoryDumpLevelOfDetail;
namespace cc {
namespace {
-// The largest single high quality image to try and process. Images above this
-// size will drop down to medium quality.
-const size_t kMaxHighQualityImageSizeBytes = 64 * 1024 * 1024;
-
// 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.
// Depending on the memory state of the system, we limit the amount of items
@@ -113,7 +109,8 @@ class ImageDecodeTaskImpl : public TileTask {
tracing_info_.prepare_tiles_id);
devtools_instrumentation::ScopedImageDecodeTask image_decode_task(
image_.image().get(),
- devtools_instrumentation::ScopedImageDecodeTask::SOFTWARE);
+ devtools_instrumentation::ScopedImageDecodeTask::kSoftware,
+ ImageDecodeCache::ToScopedTaskType(tracing_info_.task_type));
cache_->DecodeImage(image_key_, image_, task_type_);
}
@@ -158,9 +155,9 @@ SkFilterQuality GetDecodedFilterQuality(const ImageDecodeCacheKey& key) {
SkImageInfo CreateImageInfo(size_t width,
size_t height,
- ResourceFormat format) {
+ viz::ResourceFormat format) {
return SkImageInfo::Make(width, height,
- ResourceFormatToClosestSkColorType(format),
+ viz::ResourceFormatToClosestSkColorType(format),
kPremul_SkAlphaType);
}
@@ -193,7 +190,7 @@ gfx::Rect GetSrcRect(const DrawImage& image) {
} // namespace
SoftwareImageDecodeCache::SoftwareImageDecodeCache(
- ResourceFormat format,
+ viz::ResourceFormat format,
size_t locked_memory_limit_bytes)
: decoded_images_(ImageMRUCache::NO_AUTO_EVICT),
at_raster_decoded_images_(ImageMRUCache::NO_AUTO_EVICT),
@@ -227,6 +224,7 @@ bool SoftwareImageDecodeCache::GetTaskForImageAndRef(
const DrawImage& image,
const TracingInfo& tracing_info,
scoped_refptr<TileTask>* task) {
+ DCHECK_EQ(tracing_info.task_type, TaskType::kInRaster);
return GetTaskForImageAndRefInternal(
image, tracing_info, DecodeTaskType::USE_IN_RASTER_TASKS, task);
}
@@ -235,7 +233,8 @@ bool SoftwareImageDecodeCache::GetOutOfRasterDecodeTaskForImageAndRef(
const DrawImage& image,
scoped_refptr<TileTask>* task) {
return GetTaskForImageAndRefInternal(
- image, TracingInfo(), DecodeTaskType::USE_OUT_OF_RASTER_TASKS, task);
+ image, TracingInfo(0, TilePriority::NOW, TaskType::kOutOfRaster),
+ DecodeTaskType::USE_OUT_OF_RASTER_TASKS, task);
}
bool SoftwareImageDecodeCache::GetTaskForImageAndRefInternal(
@@ -428,6 +427,12 @@ void SoftwareImageDecodeCache::DecodeImage(const ImageKey& key,
decoded_image->Unlock();
}
+ if (task_type == DecodeTaskType::USE_OUT_OF_RASTER_TASKS)
+ decoded_image->mark_out_of_raster();
+
+ RecordImageMipLevelUMA(
+ MipMapUtil::GetLevelForSize(key.src_rect().size(), key.target_size()));
+
decoded_images_.Put(key, std::move(decoded_image));
}
@@ -448,8 +453,8 @@ SoftwareImageDecodeCache::DecodeImageInternal(const ImageKey& key,
return GetSubrectImageDecode(key, draw_image.paint_image());
return GetOriginalSizeImageDecode(key, std::move(image));
case kMedium_SkFilterQuality:
- case kHigh_SkFilterQuality:
return GetScaledImageDecode(key, draw_image.paint_image());
+ case kHigh_SkFilterQuality:
default:
NOTREACHED();
return nullptr;
@@ -587,7 +592,12 @@ SoftwareImageDecodeCache::GetOriginalSizeImageDecode(
"color conversion");
image = image->makeColorSpace(target_color_space,
SkTransferFunctionBehavior::kIgnore);
- DCHECK(image);
+ // Because image is a lazy-decode image, the call to makeColorSpace will
+ // fail if image decode fails.
+ if (!image) {
+ decoded_pixels->Unlock();
+ return nullptr;
+ }
}
{
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
@@ -725,8 +735,7 @@ SoftwareImageDecodeCache::GetScaledImageDecode(const ImageKey& key,
}
SkPixmap scaled_pixmap(scaled_info, scaled_pixels->data(),
scaled_info.minRowBytes());
- DCHECK(key.filter_quality() == kHigh_SkFilterQuality ||
- key.filter_quality() == kMedium_SkFilterQuality);
+ DCHECK(key.filter_quality() == kMedium_SkFilterQuality);
{
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
"SoftwareImageDecodeCache::ScaleImage - scale pixels");
@@ -845,6 +854,10 @@ size_t SoftwareImageDecodeCache::GetMaximumMemoryLimitBytes() const {
return locked_images_budget_.total_limit_bytes();
}
+void SoftwareImageDecodeCache::NotifyImageUnused(uint32_t skimage_id) {
+ // TODO(sohanjg) :Implement it, crbug.com/734982.
+}
+
void SoftwareImageDecodeCache::RemovePendingTask(const ImageKey& key,
DecodeTaskType task_type) {
base::AutoLock lock(lock_);
@@ -904,69 +917,66 @@ void SoftwareImageDecodeCache::DumpImageMemoryForCache(
}
// SoftwareImageDecodeCacheKey
-ImageDecodeCacheKey ImageDecodeCacheKey::FromDrawImage(const DrawImage& image,
- ResourceFormat format) {
+ImageDecodeCacheKey ImageDecodeCacheKey::FromDrawImage(
+ const DrawImage& image,
+ viz::ResourceFormat format) {
const SkSize& scale = image.scale();
// If the src_rect falls outside of the image, we need to clip it since
// otherwise we might end up with uninitialized memory in the decode process.
// Note that the scale is still unchanged and the target size is now a
// function of the new src_rect.
const gfx::Rect& src_rect = GetSrcRect(image);
+
+ // Start with the exact target size. However, this will be adjusted below to
+ // be either a mip level, the original size, or a subrect size. This is done
+ // to keep memory accounting correct.
gfx::Size target_size(
SkScalarRoundToInt(std::abs(src_rect.width() * scale.width())),
SkScalarRoundToInt(std::abs(src_rect.height() * scale.height())));
- // Start with the quality that was requested.
+ // If the target size is empty, then we'll be skipping the decode anyway, so
+ // the filter quality doesn't matter. Early out instead.
+ if (target_size.IsEmpty()) {
+ return ImageDecodeCacheKey(image.image()->uniqueID(), src_rect, target_size,
+ image.target_color_space(), kLow_SkFilterQuality,
+ true /* can_use_original_decode */,
+ false /* should_use_subrect */);
+ }
+
+ // Start with the given filter quality.
SkFilterQuality quality = image.filter_quality();
- // If we're not going to do a scale, we can use low filter quality. Note that
- // checking if the sizes are the same is better than checking if scale is 1.f,
- // because even non-1 scale can result in the same (rounded) width/height.
- // If either dimension is a downscale, and the quality is not None (in which
- // case we need to preserve the pixelated scale), then use mipmaps (medium
- // filter quality).
- if (target_size.width() == src_rect.width() &&
- target_size.height() == src_rect.height()) {
+ int mip_level = MipMapUtil::GetLevelForSize(src_rect.size(), target_size);
+ // If any of the following conditions hold, then use at most low filter
+ // quality and adjust the target size to match the original image:
+ // - Quality is none: We need a pixelated image, so we can't upgrade it.
+ // - Format is RGBA_4444: Skia doesn't support scaling these, so use low
+ // filter quality.
+ // - Mip level is 0: The required mip is the original image, so just use low
+ // filter quality.
+ // - Matrix is not decomposable: There's perspective on this image and we
+ // can't determine the size, so use the original.
+ if (quality == kNone_SkFilterQuality || format == viz::RGBA_4444 ||
+ mip_level == 0 || !image.matrix_is_decomposable()) {
quality = std::min(quality, kLow_SkFilterQuality);
- } else if (quality != kNone_SkFilterQuality &&
- (target_size.width() < src_rect.width() ||
- target_size.height() < src_rect.height())) {
+ // Update the size to be the original image size.
+ target_size = gfx::Size(image.image()->width(), image.image()->height());
+ } else {
quality = kMedium_SkFilterQuality;
+ // Update the target size to be a mip level size.
+ SkSize mip_scale_adjustment =
+ MipMapUtil::GetScaleAdjustmentForLevel(src_rect.size(), mip_level);
+ target_size.set_width(src_rect.width() * mip_scale_adjustment.width());
+ target_size.set_height(src_rect.height() * mip_scale_adjustment.height());
}
- // Skia doesn't scale an RGBA_4444 format, so always use the original decode.
- if (format == RGBA_4444)
- quality = std::min(quality, kLow_SkFilterQuality);
-
- // Drop from high to medium if the the matrix we applied wasn't decomposable,
- // or if the scaled image will be too large.
- if (quality == kHigh_SkFilterQuality) {
- if (!image.matrix_is_decomposable()) {
- quality = kMedium_SkFilterQuality;
- } else {
- base::CheckedNumeric<size_t> size = 4u;
- size *= target_size.width();
- size *= target_size.height();
- if (size.ValueOrDefault(std::numeric_limits<size_t>::max()) >
- kMaxHighQualityImageSizeBytes) {
- quality = kMedium_SkFilterQuality;
- }
- }
- }
-
- // Drop from medium to low if the matrix we applied wasn't decomposable or if
- // we're enlarging the image in both dimensions.
- if (quality == kMedium_SkFilterQuality) {
- if (!image.matrix_is_decomposable() ||
- (scale.width() >= 1.f && scale.height() >= 1.f)) {
- quality = kLow_SkFilterQuality;
- }
- }
-
+ // Now the quality is fixed, determine the other parameters we need.
bool can_use_original_size_decode =
quality == kLow_SkFilterQuality || quality == kNone_SkFilterQuality;
-
bool should_use_subrect = false;
+
+ // If the original image is large, we might want to do a subrect instead if
+ // the subrect would be kMemoryRatioToSubrect times smaller.
if (can_use_original_size_decode &&
(image.image()->width() >= kMinDimensionToSubrect ||
image.image()->height() >= kMinDimensionToSubrect)) {
@@ -981,29 +991,16 @@ ImageDecodeCacheKey ImageDecodeCacheKey::FromDrawImage(const DrawImage& image,
checked_src_rect_size *= src_rect.height();
size_t src_rect_size = checked_src_rect_size.ValueOrDefault(
std::numeric_limits<size_t>::max());
+
+ // If the sizes are such that we get good savings by subrecting, then do
+ // that. Also update the target size to be the src rect size since that's
+ // the rect we want to use.
if (original_size > kMemoryThresholdToSubrect &&
src_rect_size <= original_size * kMemoryRatioToSubrect) {
should_use_subrect = true;
can_use_original_size_decode = false;
- }
- }
-
- // If we're going to use the original decode, then the target size should be
- // the full image size, since that will allow for proper memory accounting.
- // Note we skip the decode if the target size is empty altogether, so don't
- // update the target size in that case.
- if (!target_size.IsEmpty()) {
- if (should_use_subrect)
target_size = src_rect.size();
- else if (can_use_original_size_decode)
- target_size = gfx::Size(image.image()->width(), image.image()->height());
- }
-
- if (quality == kMedium_SkFilterQuality && !target_size.IsEmpty()) {
- SkSize mip_target_size =
- MipMapUtil::GetScaleAdjustmentForSize(src_rect.size(), target_size);
- target_size.set_width(src_rect.width() * mip_target_size.width());
- target_size.set_height(src_rect.height() * mip_target_size.height());
+ }
}
return ImageDecodeCacheKey(image.image()->uniqueID(), src_rect, target_size,
@@ -1119,6 +1116,10 @@ SoftwareImageDecodeCache::DecodedImage::~DecodedImage() {
DECODED_IMAGE_STATE_COUNT);
UMA_HISTOGRAM_BOOLEAN("Renderer4.SoftwareImageDecodeState.FirstLockWasted",
usage_stats_.first_lock_wasted);
+ if (usage_stats_.first_lock_out_of_raster)
+ UMA_HISTOGRAM_BOOLEAN(
+ "Renderer4.SoftwareImageDecodeState.FirstLockWasted.OutOfRaster",
+ usage_stats_.first_lock_wasted);
}
bool SoftwareImageDecodeCache::DecodedImage::Lock() {