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/raster_cache_key.h"
12 #include "flutter/fml/macros.h"
13 #include "flutter/fml/memory/weak_ptr.h"
14 #include "third_party/skia/include/core/SkImage.h"
15 #include "third_party/skia/include/core/SkSize.h"
16 
17 namespace flutter {
18 
20  public:
21  RasterCacheResult(sk_sp<SkImage> image, const SkRect& logical_rect);
22 
23  virtual ~RasterCacheResult() = default;
24 
25  virtual void draw(SkCanvas& canvas, const SkPaint* paint) const;
26 
27  virtual SkISize image_dimensions() const {
28  return image_ ? image_->dimensions() : SkISize::Make(0, 0);
29  };
30 
31  virtual int64_t image_bytes() const {
32  return image_ ? image_->imageInfo().computeMinByteSize() : 0;
33  };
34 
35  private:
36  sk_sp<SkImage> image_;
37  SkRect logical_rect_;
38 };
39 
40 struct PrerollContext;
41 
42 class RasterCache {
43  public:
44  // The default max number of picture raster caches to be generated per frame.
45  // Generating too many caches in one frame may cause jank on that frame. This
46  // limit allows us to throttle the cache and distribute the work across
47  // multiple frames.
48  static constexpr int kDefaultPictureCacheLimitPerFrame = 3;
49 
50  explicit RasterCache(
51  size_t access_threshold = 3,
52  size_t picture_cache_limit_per_frame = kDefaultPictureCacheLimitPerFrame);
53 
54  virtual ~RasterCache() = default;
55 
56  /**
57  * @brief Rasterize a picture object and produce a RasterCacheResult
58  * to be stored in the cache.
59  *
60  * @param picture the SkPicture object to be cached.
61  * @param context the GrDirectContext used for rendering.
62  * @param ctm the transformation matrix used for rendering.
63  * @param dst_color_space the destination color space that the cached
64  * rendering will be drawn into
65  * @param checkerboard a flag indicating whether or not a checkerboard
66  * pattern should be rendered into the cached image for debug
67  * analysis
68  * @return a RasterCacheResult that can draw the rendered picture into
69  * the destination using a simple image blit
70  */
71  virtual std::unique_ptr<RasterCacheResult> RasterizePicture(
72  SkPicture* picture,
73  GrDirectContext* context,
74  const SkMatrix& ctm,
75  SkColorSpace* dst_color_space,
76  bool checkerboard) const;
77 
78  /**
79  * @brief Rasterize an engine Layer and produce a RasterCacheResult
80  * to be stored in the cache.
81  *
82  * @param context the PrerollContext containing important information
83  * needed for rendering a layer.
84  * @param layer the Layer object to be cached.
85  * @param ctm the transformation matrix used for rendering.
86  * @param checkerboard a flag indicating whether or not a checkerboard
87  * pattern should be rendered into the cached image for debug
88  * analysis
89  * @return a RasterCacheResult that can draw the rendered layer into
90  * the destination using a simple image blit
91  */
92  virtual std::unique_ptr<RasterCacheResult> RasterizeLayer(
93  PrerollContext* context,
94  Layer* layer,
95  const SkMatrix& ctm,
96  bool checkerboard) const;
97 
98  static SkIRect GetDeviceBounds(const SkRect& rect, const SkMatrix& ctm) {
99  SkRect device_rect;
100  ctm.mapRect(&device_rect, rect);
101  SkIRect bounds;
102  device_rect.roundOut(&bounds);
103  return bounds;
104  }
105 
106  /**
107  * @brief Snap the translation components of the matrix to integers.
108  *
109  * The snapping will only happen if the matrix only has scale and translation
110  * transformations.
111  *
112  * @param ctm the current transformation matrix.
113  * @return SkMatrix the snapped transformation matrix.
114  */
115  static SkMatrix GetIntegralTransCTM(const SkMatrix& ctm) {
116  // Avoid integral snapping if the matrix has complex transformation to avoid
117  // the artifact observed in https://github.com/flutter/flutter/issues/41654.
118  if (!ctm.isScaleTranslate()) {
119  return ctm;
120  }
121  SkMatrix result = ctm;
122  result[SkMatrix::kMTransX] = SkScalarRoundToScalar(ctm.getTranslateX());
123  result[SkMatrix::kMTransY] = SkScalarRoundToScalar(ctm.getTranslateY());
124  return result;
125  }
126 
127  // Return true if the cache is generated.
128  //
129  // We may return false and not generate the cache if
130  // 1. The picture is not worth rasterizing
131  // 2. The matrix is singular
132  // 3. The picture is accessed too few times
133  // 4. There are too many pictures to be cached in the current frame.
134  // (See also kDefaultPictureCacheLimitPerFrame.)
135  bool Prepare(GrDirectContext* context,
136  SkPicture* picture,
137  const SkMatrix& transformation_matrix,
138  SkColorSpace* dst_color_space,
139  bool is_complex,
140  bool will_change);
141 
142  void Prepare(PrerollContext* context, Layer* layer, const SkMatrix& ctm);
143 
144  // Find the raster cache for the picture and draw it to the canvas.
145  //
146  // Return true if it's found and drawn.
147  bool Draw(const SkPicture& picture, SkCanvas& canvas) const;
148 
149  // Find the raster cache for the layer and draw it to the canvas.
150  //
151  // Addional paint can be given to change how the raster cache is drawn (e.g.,
152  // draw the raster cache with some opacity).
153  //
154  // Return true if the layer raster cache is found and drawn.
155  bool Draw(const Layer* layer,
156  SkCanvas& canvas,
157  SkPaint* paint = nullptr) const;
158 
159  void SweepAfterFrame();
160 
161  void Clear();
162 
163  void SetCheckboardCacheImages(bool checkerboard);
164 
165  size_t GetCachedEntriesCount() const;
166 
167  size_t GetLayerCachedEntriesCount() const;
168 
169  size_t GetPictureCachedEntriesCount() const;
170 
171  /**
172  * @brief Estimate how much memory is used by picture raster cache entries in
173  * bytes.
174  *
175  * Only SkImage's memory usage is counted as other objects are often much
176  * smaller compared to SkImage. SkImageInfo::computeMinByteSize is used to
177  * estimate the SkImage memory usage.
178  */
179  size_t EstimatePictureCacheByteSize() const;
180 
181  /**
182  * @brief Estimate how much memory is used by layer raster cache entries in
183  * bytes.
184  *
185  * Only SkImage's memory usage is counted as other objects are often much
186  * smaller compared to SkImage. SkImageInfo::computeMinByteSize is used to
187  * estimate the SkImage memory usage.
188  */
189  size_t EstimateLayerCacheByteSize() const;
190 
191  private:
192  struct Entry {
193  bool used_this_frame = false;
194  size_t access_count = 0;
195  std::unique_ptr<RasterCacheResult> image;
196  };
197 
198  template <class Cache>
199  static void SweepOneCacheAfterFrame(Cache& cache) {
200  std::vector<typename Cache::iterator> dead;
201 
202  for (auto it = cache.begin(); it != cache.end(); ++it) {
203  Entry& entry = it->second;
204  if (!entry.used_this_frame) {
205  dead.push_back(it);
206  }
207  entry.used_this_frame = false;
208  }
209 
210  for (auto it : dead) {
211  cache.erase(it);
212  }
213  }
214 
215  const size_t access_threshold_;
216  const size_t picture_cache_limit_per_frame_;
217  size_t picture_cached_this_frame_ = 0;
218  mutable PictureRasterCacheKey::Map<Entry> picture_cache_;
219  mutable LayerRasterCacheKey::Map<Entry> layer_cache_;
220  bool checkerboard_images_;
221 
222  void TraceStatsToTimeline() const;
223 
225 };
226 
227 } // namespace flutter
228 
229 #endif // FLUTTER_FLOW_RASTER_CACHE_H_
static SkIRect GetDeviceBounds(const SkRect &rect, const SkMatrix &ctm)
Definition: raster_cache.h:98
RasterCacheResult(sk_sp< SkImage > image, const SkRect &logical_rect)
Definition: raster_cache.cc:22
std::unordered_map< RasterCacheKey, Value, Hash, Equal > Map
virtual int64_t image_bytes() const
Definition: raster_cache.h:31
virtual ~RasterCacheResult()=default
virtual SkISize image_dimensions() const
Definition: raster_cache.h:27
static SkMatrix GetIntegralTransCTM(const SkMatrix &ctm)
Snap the translation components of the matrix to integers.
Definition: raster_cache.h:115
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