| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef FLUTTER_FLOW_RASTER_CACHE_H_ |
| #define FLUTTER_FLOW_RASTER_CACHE_H_ |
| |
| #include <memory> |
| #include <unordered_map> |
| |
| #include "flutter/display_list/display_list.h" |
| #include "flutter/display_list/display_list_complexity.h" |
| #include "flutter/flow/raster_cache_key.h" |
| #include "flutter/flow/raster_cache_util.h" |
| #include "flutter/fml/macros.h" |
| #include "flutter/fml/memory/weak_ptr.h" |
| #include "flutter/fml/trace_event.h" |
| #include "include/core/SkCanvas.h" |
| #include "include/core/SkMatrix.h" |
| #include "include/core/SkRect.h" |
| #include "third_party/skia/include/core/SkImage.h" |
| #include "third_party/skia/include/core/SkSize.h" |
| |
| class SkColorSpace; |
| |
| namespace flutter { |
| |
| enum class RasterCacheLayerStrategy { kLayer, kLayerChildren }; |
| |
| class RasterCacheResult { |
| public: |
| RasterCacheResult(sk_sp<SkImage> image, |
| const SkRect& logical_rect, |
| const char* type); |
| |
| virtual ~RasterCacheResult() = default; |
| |
| virtual void draw(SkCanvas& canvas, const SkPaint* paint) const; |
| |
| virtual SkISize image_dimensions() const { |
| return image_ ? image_->dimensions() : SkISize::Make(0, 0); |
| }; |
| |
| virtual int64_t image_bytes() const { |
| return image_ ? image_->imageInfo().computeMinByteSize() : 0; |
| }; |
| |
| private: |
| sk_sp<SkImage> image_; |
| SkRect logical_rect_; |
| fml::tracing::TraceFlow flow_; |
| }; |
| |
| class Layer; |
| class RasterCacheItem; |
| struct PrerollContext; |
| struct PaintContext; |
| |
| struct RasterCacheMetrics { |
| /** |
| * The number of cache entries with images evicted in this frame. |
| */ |
| size_t eviction_count = 0; |
| |
| /** |
| * The size of all of the images evicted in this frame. |
| */ |
| size_t eviction_bytes = 0; |
| |
| /** |
| * The number of cache entries with images used in this frame. |
| */ |
| size_t in_use_count = 0; |
| |
| /** |
| * The size of all of the images used in this frame. |
| */ |
| size_t in_use_bytes = 0; |
| |
| /** |
| * The total cache entries that had images during this frame. |
| */ |
| size_t total_count() const { return in_use_count; } |
| |
| /** |
| * The size of all of the cached images during this frame. |
| */ |
| size_t total_bytes() const { return in_use_bytes; } |
| }; |
| |
| /** |
| * RasterCache is used to cache rasterized layers or display lists to improve |
| * performance. |
| * |
| * Life cycle of RasterCache methods: |
| * - Preroll stage |
| * - LayerTree::Preroll - for each Layer in the tree: |
| * - RasterCacheItem::PrerollSetup |
| * At the start of each layer's preroll, add cache items to |
| * `PrerollContext::raster_cached_entries`. |
| * - RasterCacheItem::PrerollFinalize |
| * At the end of each layer's preroll, may mark cache entries as |
| * encountered by the current frame. |
| * - Paint stage |
| * - RasterCache::EvictUnusedCacheEntries |
| * Evict cached images that are no longer used. |
| * - LayerTree::TryToPrepareRasterCache |
| * Create cache image for each cache entry if it does not exist. |
| * - LayerTree::Paint - for each layer in the tree: |
| * If layers or display lists are cached as cached images, the method |
| * `RasterCache::Draw` will be used to draw those cache images. |
| * - RasterCache::EndFrame: |
| * Computes used counts and memory then reports cache metrics. |
| */ |
| class RasterCache { |
| public: |
| struct Context { |
| GrDirectContext* gr_context; |
| const SkColorSpace* dst_color_space; |
| const SkMatrix& matrix; |
| const SkRect& logical_rect; |
| const char* flow_type; |
| }; |
| |
| std::unique_ptr<RasterCacheResult> Rasterize( |
| const RasterCache::Context& context, |
| const std::function<void(SkCanvas*)>& draw_function, |
| const std::function<void(SkCanvas*, const SkRect& rect)>& |
| draw_checkerboard) const; |
| |
| explicit RasterCache( |
| size_t access_threshold = 3, |
| size_t picture_and_display_list_cache_limit_per_frame = |
| RasterCacheUtil::kDefaultPictureAndDispLayListCacheLimitPerFrame); |
| |
| virtual ~RasterCache() = default; |
| |
| // Draws this item if it should be rendered from the cache and returns |
| // true iff it was successfully drawn. Typically this should only fail |
| // if the item was disabled due to conditions discovered during |Preroll| |
| // or if the attempt to populate the entry failed due to bounds overflow |
| // conditions. |
| bool Draw(const RasterCacheKeyID& id, |
| SkCanvas& canvas, |
| const SkPaint* paint) const; |
| |
| bool HasEntry(const RasterCacheKeyID& id, const SkMatrix&) const; |
| |
| void BeginFrame(); |
| |
| void EvictUnusedCacheEntries(); |
| |
| void EndFrame(); |
| |
| void Clear(); |
| |
| void SetCheckboardCacheImages(bool checkerboard); |
| |
| const RasterCacheMetrics& picture_metrics() const { return picture_metrics_; } |
| const RasterCacheMetrics& layer_metrics() const { return layer_metrics_; } |
| |
| size_t GetCachedEntriesCount() const; |
| |
| /** |
| * Return the number of map entries in the layer cache regardless of whether |
| * the entries have been populated with an image. |
| */ |
| size_t GetLayerCachedEntriesCount() const; |
| |
| /** |
| * Return the number of map entries in the picture caches (SkPicture and |
| * DisplayList) regardless of whether the entries have been populated with |
| * an image. |
| */ |
| size_t GetPictureCachedEntriesCount() const; |
| |
| /** |
| * @brief Estimate how much memory is used by picture raster cache entries in |
| * bytes, including cache entries in the SkPicture cache and the DisplayList |
| * cache. |
| * |
| * Only SkImage's memory usage is counted as other objects are often much |
| * smaller compared to SkImage. SkImageInfo::computeMinByteSize is used to |
| * estimate the SkImage memory usage. |
| */ |
| size_t EstimatePictureCacheByteSize() const; |
| |
| /** |
| * @brief Estimate how much memory is used by layer raster cache entries in |
| * bytes. |
| * |
| * Only SkImage's memory usage is counted as other objects are often much |
| * smaller compared to SkImage. SkImageInfo::computeMinByteSize is used to |
| * estimate the SkImage memory usage. |
| */ |
| size_t EstimateLayerCacheByteSize() const; |
| |
| /** |
| * @brief Return the number of frames that a picture must be prepared |
| * before it will be cached. If the number is 0, then no picture will |
| * ever be cached. |
| * |
| * If the number is one, then it must be prepared and drawn on 1 frame |
| * and it will then be cached on the next frame if it is prepared. |
| */ |
| int access_threshold() const { return access_threshold_; } |
| |
| bool GenerateNewCacheInThisFrame() const { |
| // Disabling caching when access_threshold is zero is historic behavior. |
| return access_threshold_ != 0 && display_list_cached_this_frame_ < |
| display_list_cache_limit_per_frame_; |
| } |
| |
| /** |
| * @brief The entry whose RasterCacheKey is generated by RasterCacheKeyID |
| * and matrix is marked as encountered by the current frame. The entry |
| * will be created if it does not exist. Optionally the entry will be marked |
| * as visible in the current frame if the caller determines that it |
| * intersects the cull rect. The access_count of the entry will be |
| * increased if it is visible, or if it was ever visible. |
| * @return the number of times the entry has been hit since it was created. |
| * For a new entry that will be 1 if it is visible, or zero if non-visible. |
| */ |
| int MarkSeen(const RasterCacheKeyID& id, |
| const SkMatrix& matrix, |
| bool visible) const; |
| |
| /** |
| * Returns the access count (i.e. accesses_since_visible) for the given |
| * entry in the cache, or -1 if no such entry exists. |
| */ |
| int GetAccessCount(const RasterCacheKeyID& id, const SkMatrix& matrix) const; |
| |
| bool UpdateCacheEntry( |
| const RasterCacheKeyID& id, |
| const Context& raster_cache_context, |
| const std::function<void(SkCanvas*)>& render_function) const; |
| |
| private: |
| struct Entry { |
| bool encountered_this_frame = false; |
| bool visible_this_frame = false; |
| size_t accesses_since_visible = 0; |
| std::unique_ptr<RasterCacheResult> image; |
| }; |
| |
| void UpdateMetrics(); |
| |
| RasterCacheMetrics& GetMetricsForKind(RasterCacheKeyKind kind); |
| |
| const size_t access_threshold_; |
| const size_t display_list_cache_limit_per_frame_; |
| mutable size_t display_list_cached_this_frame_ = 0; |
| RasterCacheMetrics layer_metrics_; |
| RasterCacheMetrics picture_metrics_; |
| mutable RasterCacheKey::Map<Entry> cache_; |
| bool checkerboard_images_; |
| |
| void TraceStatsToTimeline() const; |
| |
| friend class RasterCacheItem; |
| friend class LayerRasterCacheItem; |
| |
| FML_DISALLOW_COPY_AND_ASSIGN(RasterCache); |
| }; |
| |
| } // namespace flutter |
| |
| #endif // FLUTTER_FLOW_RASTER_CACHE_H_ |