Commit 353ed830 authored by sohan's avatar sohan Committed by Commit Bot

cc: Implement eviction from SW image decode cache.

This implements logic to evict from SW image decode cache
in cc, based on skia unique image id. We add a auxiliary
map of image id and key, and use it for optimizing search
and access. New api's to handle cache addition and deletion
is also added.

BUG=734982
CQ_INCLUDE_TRYBOTS=master.tryserver.blink:linux_trusty_blink_rel

patch from issue 2951093002 at patchset 80001 (http://crrev.com/2951093002#ps80001)

Change-Id: Iab533d140802a0308bf2143765708257a465bd31
Reviewed-on: https://chromium-review.googlesource.com/571459Reviewed-by: default avatarEric Karl <ericrk@chromium.org>
Reviewed-by: default avatarVladimir Levin <vmpstr@chromium.org>
Reviewed-by: default avatarSohan Jyoti Ghosh <sohan.jyoti@huawei.com>
Commit-Queue: Sohan Jyoti Ghosh <sohan.jyoti@huawei.com>
Cr-Commit-Position: refs/heads/master@{#488829}
parent fe41133f
......@@ -287,7 +287,7 @@ bool SoftwareImageDecodeCache::GetTaskForImageAndRefInternal(
if (new_image_fits_in_memory) {
RecordLockExistingCachedImageHistogram(tracing_info.requesting_tile_bin,
false);
decoded_images_.Erase(decoded_it);
CleanupDecodedImagesCache(key, decoded_it);
}
}
......@@ -392,7 +392,7 @@ void SoftwareImageDecodeCache::DecodeImage(const ImageKey& key,
if (image_it != decoded_images_.end()) {
if (image_it->second->is_locked() || image_it->second->Lock())
return;
decoded_images_.Erase(image_it);
CleanupDecodedImagesCache(key, image_it);
}
std::unique_ptr<DecodedImage> decoded_image;
......@@ -416,7 +416,7 @@ void SoftwareImageDecodeCache::DecodeImage(const ImageKey& key,
decoded_image->Unlock();
return;
}
decoded_images_.Erase(image_it);
CleanupDecodedImagesCache(key, image_it);
}
// We could have finished all of the raster tasks (cancelled) while this image
......@@ -433,7 +433,7 @@ void SoftwareImageDecodeCache::DecodeImage(const ImageKey& key,
RecordImageMipLevelUMA(
MipMapUtil::GetLevelForSize(key.src_rect().size(), key.target_size()));
decoded_images_.Put(key, std::move(decoded_image));
CacheDecodedImages(key, std::move(decoded_image));
}
std::unique_ptr<SoftwareImageDecodeCache::DecodedImage>
......@@ -496,7 +496,7 @@ DecodedDrawImage SoftwareImageDecodeCache::GetDecodedImageForDrawInternal(
GetScaleAdjustment(key), GetDecodedFilterQuality(key));
} else {
scoped_decoded_image = std::move(decoded_images_it->second);
decoded_images_.Erase(decoded_images_it);
CleanupDecodedImagesCache(key, decoded_images_it);
}
}
......@@ -810,13 +810,15 @@ void SoftwareImageDecodeCache::UnrefAtRasterImage(const ImageKey& key) {
decoded_images_ref_counts_.end()) {
at_raster_image_it->second->Unlock();
}
decoded_images_.Put(key, std::move(at_raster_image_it->second));
CacheDecodedImages(key, std::move(at_raster_image_it->second));
} else if (image_it->second->is_locked()) {
at_raster_image_it->second->Unlock();
} else {
DCHECK(decoded_images_ref_counts_.find(key) ==
decoded_images_ref_counts_.end());
at_raster_image_it->second->Unlock();
// Access decoded_images_ directly here to avoid deletion and entry
// of same key in ImageKey vector of decoded_images_unique_ids_.
decoded_images_.Erase(image_it);
decoded_images_.Put(key, std::move(at_raster_image_it->second));
}
......@@ -855,7 +857,22 @@ size_t SoftwareImageDecodeCache::GetMaximumMemoryLimitBytes() const {
}
void SoftwareImageDecodeCache::NotifyImageUnused(uint32_t skimage_id) {
// TODO(sohanjg) :Implement it, crbug.com/734982.
base::AutoLock lock(lock_);
auto it = decoded_images_unique_ids_.find(skimage_id);
if (it == decoded_images_unique_ids_.end())
return;
for (auto key = it->second.begin(); key != it->second.end(); ++key) {
// This iterates over the ImageKey vector for the given skimage_id,
// and deletes all entries from decoded_images_ corresponding to the
// skimage_id.
auto image_it = decoded_images_.Peek(*key);
// TODO(sohanjg) :Find an optimized way to cleanup locked images.
if (image_it != decoded_images_.end() && !image_it->second->is_locked())
decoded_images_.Erase(image_it);
}
decoded_images_unique_ids_.erase(it);
}
void SoftwareImageDecodeCache::RemovePendingTask(const ImageKey& key,
......@@ -1193,4 +1210,31 @@ void SoftwareImageDecodeCache::OnPurgeMemory() {
ReduceCacheUsageUntilWithinLimit(0);
}
void SoftwareImageDecodeCache::CleanupDecodedImagesCache(
const ImageKey& key,
ImageMRUCache::iterator it) {
lock_.AssertAcquired();
auto vector_it = decoded_images_unique_ids_.find(key.image_id());
// TODO(sohanjg): Check if we can DCHECK here.
if (vector_it != decoded_images_unique_ids_.end()) {
auto iter =
std::find(vector_it->second.begin(), vector_it->second.end(), key);
DCHECK(iter != vector_it->second.end());
vector_it->second.erase(iter);
if (vector_it->second.empty())
decoded_images_unique_ids_.erase(vector_it);
}
decoded_images_.Erase(it);
}
void SoftwareImageDecodeCache::CacheDecodedImages(
const ImageKey& key,
std::unique_ptr<DecodedImage> decoded_image) {
lock_.AssertAcquired();
decoded_images_unique_ids_[key.image_id()].push_back(key);
decoded_images_.Put(key, std::move(decoded_image));
}
} // namespace cc
......@@ -302,6 +302,11 @@ class CC_EXPORT SoftwareImageDecodeCache
DecodeTaskType type,
scoped_refptr<TileTask>* task);
void CacheDecodedImages(const ImageKey& key,
std::unique_ptr<DecodedImage> decoded_image);
void CleanupDecodedImagesCache(const ImageKey& key,
ImageMRUCache::iterator it);
std::unordered_map<ImageKey, scoped_refptr<TileTask>, ImageKeyHash>
pending_in_raster_image_tasks_;
std::unordered_map<ImageKey, scoped_refptr<TileTask>, ImageKeyHash>
......@@ -317,6 +322,10 @@ class CC_EXPORT SoftwareImageDecodeCache
ImageMRUCache decoded_images_;
std::unordered_map<ImageKey, int, ImageKeyHash> decoded_images_ref_counts_;
// Decoded ImageKey vector and Skimage uniqueID.
std::unordered_map<uint32_t, std::vector<ImageKey>>
decoded_images_unique_ids_;
// Decoded image and ref counts (at-raster decode path).
ImageMRUCache at_raster_decoded_images_;
std::unordered_map<ImageKey, int, ImageKeyHash>
......
......@@ -1691,5 +1691,42 @@ TEST(SoftwareImageDecodeCacheTest, ClearCache) {
EXPECT_EQ(0u, cache.GetNumCacheEntriesForTesting());
}
TEST(SoftwareImageDecodeCacheTest, RemoveUnusedImage) {
TestSoftwareImageDecodeCache cache;
bool is_decomposable = true;
SkFilterQuality quality = kHigh_SkFilterQuality;
std::vector<uint32_t> unique_ids(10);
for (int i = 0; i < 10; ++i) {
sk_sp<SkImage> image = CreateImage(100, 100);
unique_ids[i] = image->uniqueID();
DrawImage draw_image(
CreatePaintImage(image),
SkIRect::MakeWH(image->width(), image->height()), quality,
CreateMatrix(SkSize::Make(1.0f, 1.0f), is_decomposable),
DefaultColorSpace());
DecodedDrawImage decoded_draw_image =
cache.GetDecodedImageForDraw(draw_image);
scoped_refptr<TileTask> task;
bool need_unref = cache.GetTaskForImageAndRef(
draw_image, ImageDecodeCache::TracingInfo(), &task);
EXPECT_TRUE(need_unref);
EXPECT_TRUE(task);
TestTileTaskRunner::ProcessTask(task.get());
cache.DrawWithImageFinished(draw_image, decoded_draw_image);
cache.UnrefImage(draw_image);
}
// We should now have data image in our cache.
EXPECT_EQ(cache.GetNumCacheEntriesForTesting(), 10u);
// Remove unused ids.
for (uint32_t i = 0; i < 10; ++i) {
cache.NotifyImageUnused(unique_ids[i]);
EXPECT_EQ(cache.GetNumCacheEntriesForTesting(), (10 - i - 1));
}
}
} // namespace
} // namespace cc
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment