Index: cc/tiles/gpu_image_decode_cache.cc |
diff --git a/cc/tiles/gpu_image_decode_cache.cc b/cc/tiles/gpu_image_decode_cache.cc |
index 3ea22ba20faaea37deda12875dc380c9f21f948d..70216a376f1a91890b4520d57f45c9cc1697d844 100644 |
--- a/cc/tiles/gpu_image_decode_cache.cc |
+++ b/cc/tiles/gpu_image_decode_cache.cc |
@@ -342,11 +342,15 @@ GpuImageDecodeCache::ImageData::~ImageData() { |
GpuImageDecodeCache::GpuImageDecodeCache(ContextProvider* context, |
ResourceFormat decode_format, |
- size_t max_gpu_image_bytes) |
+ size_t max_working_set_bytes, |
+ size_t max_cache_bytes) |
: format_(decode_format), |
context_(context), |
persistent_cache_(PersistentCache::NO_AUTO_EVICT), |
- normal_max_gpu_image_bytes_(max_gpu_image_bytes) { |
+ max_working_set_bytes_(max_working_set_bytes), |
+ normal_max_cache_bytes_(max_cache_bytes) { |
+ DCHECK_GE(max_working_set_bytes_, normal_max_cache_bytes_); |
+ |
// Acquire the context_lock so that we can safely retrieve the |
// GrContextThreadSafeProxy. This proxy can then be used with no lock held. |
{ |
@@ -576,7 +580,7 @@ void GpuImageDecodeCache::SetShouldAggressivelyFreeResources( |
DeletePendingImages(); |
} else { |
base::AutoLock lock(lock_); |
- cached_bytes_limit_ = normal_max_gpu_image_bytes_; |
+ cached_bytes_limit_ = normal_max_cache_bytes_; |
} |
} |
@@ -862,7 +866,7 @@ void GpuImageDecodeCache::OwnershipChanged(const DrawImage& draw_image, |
if (image_data->is_at_raster && !has_any_refs) { |
// We have an at-raster image which has reached zero refs. If it won't fit |
// in our cache, delete the image to allow it to fit. |
- if (image_data->upload.image() && !CanFitSize(image_data->size)) { |
+ if (image_data->upload.image() && !CanFitInCache(image_data->size)) { |
images_pending_deletion_.push_back(image_data->upload.image()); |
image_data->upload.SetImage(nullptr); |
} |
@@ -881,7 +885,7 @@ void GpuImageDecodeCache::OwnershipChanged(const DrawImage& draw_image, |
if (image_data->upload.ref_count > 0 && !image_data->upload.budgeted && |
!image_data->is_at_raster) { |
// We should only be taking non-at-raster refs on images that fit in cache. |
- DCHECK(CanFitSize(image_data->size)); |
+ DCHECK(CanFitInWorkingSet(image_data->size)); |
bytes_used_ += image_data->size; |
image_data->upload.budgeted = true; |
@@ -911,6 +915,9 @@ void GpuImageDecodeCache::OwnershipChanged(const DrawImage& draw_image, |
image_data->decode.Unlock(); |
} |
+ // EnsureCapacity to make sure we are under our cache limits. |
+ EnsureCapacity(0); |
+ |
#if DCHECK_IS_ON() |
// Sanity check the above logic. |
if (image_data->upload.image()) { |
@@ -923,15 +930,19 @@ void GpuImageDecodeCache::OwnershipChanged(const DrawImage& draw_image, |
#endif |
} |
-// Ensures that we can fit a new image of size |required_size| in our cache. In |
-// doing so, this function will free unreferenced image data as necessary to |
-// create rooom. |
+// Ensures that we can fit a new image of size |required_size| in our working |
+// set. In doing so, this function will free unreferenced image data as |
+// necessary to create rooom. |
bool GpuImageDecodeCache::EnsureCapacity(size_t required_size) { |
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), |
"GpuImageDecodeCache::EnsureCapacity"); |
lock_.AssertAcquired(); |
- if (CanFitSize(required_size) && !ExceedsPreferredCount()) |
+ // While we only care whether |required_size| fits in our working set, we |
+ // also want to keep our cache under-budget if possible. Working set size |
+ // will always match or exceed cache size, so keeping the cache under budget |
+ // may be impossible. |
+ if (CanFitInCache(required_size) && !ExceedsPreferredCount()) |
return true; |
// While we are over memory or preferred item capacity, we iterate through |
@@ -970,16 +981,14 @@ bool GpuImageDecodeCache::EnsureCapacity(size_t required_size) { |
++it; |
} |
- if (CanFitSize(required_size) && !ExceedsPreferredCount()) |
+ if (CanFitInCache(required_size) && !ExceedsPreferredCount()) |
return true; |
} |
- // Preferred count is only used as a guideline when triming the cache. Allow |
- // new elements to be added as long as we are below our size limit. |
- return CanFitSize(required_size); |
+ return CanFitInWorkingSet(required_size); |
} |
-bool GpuImageDecodeCache::CanFitSize(size_t size) const { |
+bool GpuImageDecodeCache::CanFitInCache(size_t size) const { |
lock_.AssertAcquired(); |
size_t bytes_limit; |
@@ -997,6 +1006,14 @@ bool GpuImageDecodeCache::CanFitSize(size_t size) const { |
return new_size.IsValid() && new_size.ValueOrDie() <= bytes_limit; |
} |
+bool GpuImageDecodeCache::CanFitInWorkingSet(size_t size) const { |
+ lock_.AssertAcquired(); |
+ |
+ base::CheckedNumeric<uint32_t> new_size(bytes_used_); |
+ new_size += size; |
+ return new_size.IsValid() && new_size.ValueOrDie() <= max_working_set_bytes_; |
+} |
+ |
bool GpuImageDecodeCache::ExceedsPreferredCount() const { |
lock_.AssertAcquired(); |