| // 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 entris as | 
 |  *         encountered by the current frame. | 
 |  * - Paint stage | 
 |  *   - RasterCache::EvictUnusedCacheEntries | 
 |  *       Evit 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_ |