diff --git a/engine/src/flutter/flow/raster_cache.cc b/engine/src/flutter/flow/raster_cache.cc index 0827a2de405..fe42639fe78 100644 --- a/engine/src/flutter/flow/raster_cache.cc +++ b/engine/src/flutter/flow/raster_cache.cc @@ -36,8 +36,11 @@ void RasterCacheResult::draw(SkCanvas& canvas, const SkPaint* paint) const { canvas.drawImage(image_, bounds.fLeft, bounds.fTop, paint); } -RasterCache::RasterCache(size_t threshold) - : threshold_(threshold), checkerboard_images_(false), weak_factory_(this) {} +RasterCache::RasterCache(size_t threshold, size_t picture_cache_limit_per_frame) + : threshold_(threshold), + picture_cache_limit_per_frame_(picture_cache_limit_per_frame), + checkerboard_images_(false), + weak_factory_(this) {} RasterCache::~RasterCache() = default; @@ -182,6 +185,9 @@ bool RasterCache::Prepare(GrContext* context, SkColorSpace* dst_color_space, bool is_complex, bool will_change) { + if (picture_cached_this_frame_ >= picture_cache_limit_per_frame_) { + return false; + } if (!IsPictureWorthRasterizing(picture, will_change, is_complex)) { // We only deal with pictures that are worthy of rasterization. return false; @@ -211,6 +217,7 @@ bool RasterCache::Prepare(GrContext* context, entry.image = RasterizePicture(picture, context, transformation_matrix, dst_color_space, checkerboard_images_); } + picture_cached_this_frame_++; return true; } @@ -232,6 +239,7 @@ void RasterCache::SweepAfterFrame() { using LayerCache = LayerRasterCacheKey::Map; SweepOneCacheAfterFrame(picture_cache_); SweepOneCacheAfterFrame(layer_cache_); + picture_cached_this_frame_ = 0; } void RasterCache::Clear() { diff --git a/engine/src/flutter/flow/raster_cache.h b/engine/src/flutter/flow/raster_cache.h index cb4383f41fb..74ce010b07c 100644 --- a/engine/src/flutter/flow/raster_cache.h +++ b/engine/src/flutter/flow/raster_cache.h @@ -42,7 +42,15 @@ struct PrerollContext; class RasterCache { public: - explicit RasterCache(size_t threshold = 3); + // The default max number of picture raster caches to be generated per frame. + // Generating too many caches in one frame may cause jank on that frame. This + // limit allows us to throttle the cache and distribute the work across + // multiple frames. + static constexpr int kDefaultPictureCacheLimitPerFrame = 3; + + explicit RasterCache( + size_t threshold = 3, + size_t picture_cache_limit_per_frame = kDefaultPictureCacheLimitPerFrame); ~RasterCache(); @@ -67,6 +75,8 @@ class RasterCache { // 1. The picture is not worth rasterizing // 2. The matrix is singular // 3. The picture is accessed too few times + // 4. There are too many pictures to be cached in the current frame. + // (See also kDefaultPictureCacheLimitPerFrame.) bool Prepare(GrContext* context, SkPicture* picture, const SkMatrix& transformation_matrix, @@ -110,6 +120,8 @@ class RasterCache { } const size_t threshold_; + const size_t picture_cache_limit_per_frame_; + size_t picture_cached_this_frame_ = 0; PictureRasterCacheKey::Map picture_cache_; LayerRasterCacheKey::Map layer_cache_; bool checkerboard_images_;