Flutter Engine
raster_cache.h
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef FLUTTER_FLOW_RASTER_CACHE_H_
6 #define FLUTTER_FLOW_RASTER_CACHE_H_
7 
8 #include <memory>
9 #include <unordered_map>
10 
11 #include "flutter/flow/display_list.h"
12 #include "flutter/flow/raster_cache_key.h"
13 #include "flutter/fml/macros.h"
14 #include "flutter/fml/memory/weak_ptr.h"
15 #include "third_party/skia/include/core/SkImage.h"
16 #include "third_party/skia/include/core/SkSize.h"
17 
18 namespace flutter {
19 
21  public:
22  RasterCacheResult(sk_sp<SkImage> image, const SkRect& logical_rect);
23 
24  virtual ~RasterCacheResult() = default;
25 
26  virtual void draw(SkCanvas& canvas, const SkPaint* paint) const;
27 
28  virtual SkISize image_dimensions() const {
29  return image_ ? image_->dimensions() : SkISize::Make(0, 0);
30  };
31 
32  virtual int64_t image_bytes() const {
33  return image_ ? image_->imageInfo().computeMinByteSize() : 0;
34  };
35 
36  private:
37  sk_sp<SkImage> image_;
38  SkRect logical_rect_;
39 };
40 
41 struct PrerollContext;
42 
43 class RasterCache {
44  public:
45  // The default max number of picture and display list raster caches to be
46  // generated per frame. Generating too many caches in one frame may cause jank
47  // on that frame. This limit allows us to throttle the cache and distribute
48  // the work across multiple frames.
49  static constexpr int kDefaultPictureAndDispLayListCacheLimitPerFrame = 3;
50 
51  explicit RasterCache(size_t access_threshold = 3,
52  size_t picture_and_display_list_cache_limit_per_frame =
53  kDefaultPictureAndDispLayListCacheLimitPerFrame);
54 
55  virtual ~RasterCache() = default;
56 
57  /**
58  * @brief Rasterize a picture object and produce a RasterCacheResult
59  * to be stored in the cache.
60  *
61  * @param picture the SkPicture object to be cached.
62  * @param context the GrDirectContext used for rendering.
63  * @param ctm the transformation matrix used for rendering.
64  * @param dst_color_space the destination color space that the cached
65  * rendering will be drawn into
66  * @param checkerboard a flag indicating whether or not a checkerboard
67  * pattern should be rendered into the cached image for debug
68  * analysis
69  * @return a RasterCacheResult that can draw the rendered picture into
70  * the destination using a simple image blit
71  */
72  virtual std::unique_ptr<RasterCacheResult> RasterizePicture(
73  SkPicture* picture,
74  GrDirectContext* context,
75  const SkMatrix& ctm,
76  SkColorSpace* dst_color_space,
77  bool checkerboard) const;
78  virtual std::unique_ptr<RasterCacheResult> RasterizeDisplayList(
79  DisplayList* display_list,
80  GrDirectContext* context,
81  const SkMatrix& ctm,
82  SkColorSpace* dst_color_space,
83  bool checkerboard) const;
84 
85  /**
86  * @brief Rasterize an engine Layer and produce a RasterCacheResult
87  * to be stored in the cache.
88  *
89  * @param context the PrerollContext containing important information
90  * needed for rendering a layer.
91  * @param layer the Layer object to be cached.
92  * @param ctm the transformation matrix used for rendering.
93  * @param checkerboard a flag indicating whether or not a checkerboard
94  * pattern should be rendered into the cached image for debug
95  * analysis
96  * @return a RasterCacheResult that can draw the rendered layer into
97  * the destination using a simple image blit
98  */
99  virtual std::unique_ptr<RasterCacheResult> RasterizeLayer(
100  PrerollContext* context,
101  Layer* layer,
102  const SkMatrix& ctm,
103  bool checkerboard) const;
104 
105  static SkIRect GetDeviceBounds(const SkRect& rect, const SkMatrix& ctm) {
106  SkRect device_rect;
107  ctm.mapRect(&device_rect, rect);
108  SkIRect bounds;
109  device_rect.roundOut(&bounds);
110  return bounds;
111  }
112 
113  /**
114  * @brief Snap the translation components of the matrix to integers.
115  *
116  * The snapping will only happen if the matrix only has scale and translation
117  * transformations.
118  *
119  * @param ctm the current transformation matrix.
120  * @return SkMatrix the snapped transformation matrix.
121  */
122  static SkMatrix GetIntegralTransCTM(const SkMatrix& ctm) {
123  // Avoid integral snapping if the matrix has complex transformation to avoid
124  // the artifact observed in https://github.com/flutter/flutter/issues/41654.
125  if (!ctm.isScaleTranslate()) {
126  return ctm;
127  }
128  SkMatrix result = ctm;
129  result[SkMatrix::kMTransX] = SkScalarRoundToScalar(ctm.getTranslateX());
130  result[SkMatrix::kMTransY] = SkScalarRoundToScalar(ctm.getTranslateY());
131  return result;
132  }
133 
134  // Return true if the cache is generated.
135  //
136  // We may return false and not generate the cache if
137  // 1. There are too many pictures to be cached in the current frame.
138  // (See also kDefaultPictureAndDispLayListCacheLimitPerFrame.)
139  // 2. The picture is not worth rasterizing
140  // 3. The matrix is singular
141  // 4. The picture is accessed too few times
142  bool Prepare(PrerollContext* context,
143  SkPicture* picture,
144  bool is_complex,
145  bool will_change,
146  const SkMatrix& untranslated_matrix,
147  const SkPoint& offset = SkPoint());
148  bool Prepare(PrerollContext* context,
149  DisplayList* display_list,
150  bool is_complex,
151  bool will_change,
152  const SkMatrix& untranslated_matrix,
153  const SkPoint& offset = SkPoint());
154 
155  void Prepare(PrerollContext* context, Layer* layer, const SkMatrix& ctm);
156 
157  // Find the raster cache for the picture and draw it to the canvas.
158  //
159  // Return true if it's found and drawn.
160  bool Draw(const SkPicture& picture, SkCanvas& canvas) const;
161 
162  // Find the raster cache for the display list and draw it to the canvas.
163  //
164  // Return true if it's found and drawn.
165  bool Draw(const DisplayList& display_list, SkCanvas& canvas) const;
166 
167  // Find the raster cache for the layer and draw it to the canvas.
168  //
169  // Additional paint can be given to change how the raster cache is drawn
170  // (e.g., draw the raster cache with some opacity).
171  //
172  // Return true if the layer raster cache is found and drawn.
173  bool Draw(const Layer* layer,
174  SkCanvas& canvas,
175  SkPaint* paint = nullptr) const;
176 
177  void SweepAfterFrame();
178 
179  void Clear();
180 
181  void SetCheckboardCacheImages(bool checkerboard);
182 
183  size_t GetCachedEntriesCount() const;
184 
185  size_t GetLayerCachedEntriesCount() const;
186 
187  size_t GetPictureCachedEntriesCount() const;
188 
189  /**
190  * @brief Estimate how much memory is used by picture raster cache entries in
191  * bytes, including cache entries in the SkPicture cache and the DisplayList
192  * cache.
193  *
194  * Only SkImage's memory usage is counted as other objects are often much
195  * smaller compared to SkImage. SkImageInfo::computeMinByteSize is used to
196  * estimate the SkImage memory usage.
197  */
198  size_t EstimatePictureCacheByteSize() const;
199 
200  /**
201  * @brief Estimate how much memory is used by layer raster cache entries in
202  * bytes.
203  *
204  * Only SkImage's memory usage is counted as other objects are often much
205  * smaller compared to SkImage. SkImageInfo::computeMinByteSize is used to
206  * estimate the SkImage memory usage.
207  */
208  size_t EstimateLayerCacheByteSize() const;
209 
210  /**
211  * @brief Return the count of cache sweeps that have occured.
212  *
213  * The sweep count will help to determine if a sweep of the cache may have
214  * removed expired entries since the last time the method was called.
215  * The count will increment even if the sweep performs no evictions.
216  */
217  int sweep_count() const { return sweep_count_; }
218 
219  /**
220  * @brief Return the number of frames that a picture must be prepared
221  * before it will be cached. If the number is 0, then no picture will
222  * ever be cached.
223  *
224  * If the number is one, then it must be prepared and drawn on 1 frame
225  * and it will then be cached on the next frame if it is prepared.
226  */
227  int access_threshold() const { return access_threshold_; }
228 
229  private:
230  struct Entry {
231  bool used_this_frame = false;
232  size_t access_count = 0;
233  std::unique_ptr<RasterCacheResult> image;
234  };
235 
236  template <class Cache>
237  static void SweepOneCacheAfterFrame(Cache& cache) {
238  std::vector<typename Cache::iterator> dead;
239 
240  for (auto it = cache.begin(); it != cache.end(); ++it) {
241  Entry& entry = it->second;
242  if (!entry.used_this_frame) {
243  dead.push_back(it);
244  }
245  entry.used_this_frame = false;
246  }
247 
248  for (auto it : dead) {
249  cache.erase(it);
250  }
251  }
252 
253  bool GenerateNewCacheInThisFrame() const {
254  // Disabling caching when access_threshold is zero is historic behavior.
255  return access_threshold_ != 0 &&
256  picture_cached_this_frame_ + display_list_cached_this_frame_ <
257  picture_and_display_list_cache_limit_per_frame_;
258  }
259 
260  const size_t access_threshold_;
261  const size_t picture_and_display_list_cache_limit_per_frame_;
262  size_t picture_cached_this_frame_ = 0;
263  size_t display_list_cached_this_frame_ = 0;
264  int sweep_count_ = 0;
265  mutable PictureRasterCacheKey::Map<Entry> picture_cache_;
266  mutable DisplayListRasterCacheKey::Map<Entry> display_list_cache_;
267  mutable LayerRasterCacheKey::Map<Entry> layer_cache_;
268  bool checkerboard_images_;
269 
270  void TraceStatsToTimeline() const;
271 
273 };
274 
275 } // namespace flutter
276 
277 #endif // FLUTTER_FLOW_RASTER_CACHE_H_
static SkIRect GetDeviceBounds(const SkRect &rect, const SkMatrix &ctm)
Definition: raster_cache.h:105
RasterCacheResult(sk_sp< SkImage > image, const SkRect &logical_rect)
Definition: raster_cache.cc:22
GAsyncResult * result
std::unordered_map< RasterCacheKey, Value, Hash, Equal > Map
int access_threshold() const
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.
Definition: raster_cache.h:227
virtual int64_t image_bytes() const
Definition: raster_cache.h:32
int sweep_count() const
Return the count of cache sweeps that have occured.
Definition: raster_cache.h:217
virtual ~RasterCacheResult()=default
virtual SkISize image_dimensions() const
Definition: raster_cache.h:28
static SkMatrix GetIntegralTransCTM(const SkMatrix &ctm)
Snap the translation components of the matrix to integers.
Definition: raster_cache.h:122
virtual void draw(SkCanvas &canvas, const SkPaint *paint) const
Definition: raster_cache.cc:26
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: macros.h:27