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/display_list/dl_canvas.h"
12#include "flutter/flow/raster_cache_key.h"
13#include "flutter/flow/raster_cache_util.h"
14#include "flutter/fml/macros.h"
15#include "flutter/fml/memory/weak_ptr.h"
16#include "flutter/fml/trace_event.h"
17#include "third_party/skia/include/core/SkMatrix.h"
18#include "third_party/skia/include/core/SkRect.h"
19
20class GrDirectContext;
21class SkColorSpace;
22
23namespace flutter {
24
25enum class RasterCacheLayerStrategy { kLayer, kLayerChildren };
26
27class RasterCacheResult {
28 public:
29 RasterCacheResult(sk_sp<DlImage> image,
30 const SkRect& logical_rect,
31 const char* type,
32 sk_sp<const DlRTree> rtree = nullptr);
33
34 virtual ~RasterCacheResult() = default;
35
36 virtual void draw(DlCanvas& canvas,
37 const DlPaint* paint,
38 bool preserve_rtree) const;
39
40 virtual SkISize image_dimensions() const {
41 return image_ ? image_->dimensions() : SkISize::Make(w: 0, h: 0);
42 };
43
44 virtual int64_t image_bytes() const {
45 return image_ ? image_->GetApproximateByteSize() : 0;
46 };
47
48 private:
49 sk_sp<DlImage> image_;
50 SkRect logical_rect_;
51 fml::tracing::TraceFlow flow_;
52 sk_sp<const DlRTree> rtree_;
53};
54
55class Layer;
56class RasterCacheItem;
57struct PrerollContext;
58struct PaintContext;
59
60struct RasterCacheMetrics {
61 /**
62 * The number of cache entries with images evicted in this frame.
63 */
64 size_t eviction_count = 0;
65
66 /**
67 * The size of all of the images evicted in this frame.
68 */
69 size_t eviction_bytes = 0;
70
71 /**
72 * The number of cache entries with images used in this frame.
73 */
74 size_t in_use_count = 0;
75
76 /**
77 * The size of all of the images used in this frame.
78 */
79 size_t in_use_bytes = 0;
80
81 /**
82 * The total cache entries that had images during this frame.
83 */
84 size_t total_count() const { return in_use_count; }
85
86 /**
87 * The size of all of the cached images during this frame.
88 */
89 size_t total_bytes() const { return in_use_bytes; }
90};
91
92/**
93 * RasterCache is used to cache rasterized layers or display lists to improve
94 * performance.
95 *
96 * Life cycle of RasterCache methods:
97 * - Preroll stage
98 * - LayerTree::Preroll - for each Layer in the tree:
99 * - RasterCacheItem::PrerollSetup
100 * At the start of each layer's preroll, add cache items to
101 * `PrerollContext::raster_cached_entries`.
102 * - RasterCacheItem::PrerollFinalize
103 * At the end of each layer's preroll, may mark cache entries as
104 * encountered by the current frame.
105 * - Paint stage
106 * - RasterCache::EvictUnusedCacheEntries
107 * Evict cached images that are no longer used.
108 * - LayerTree::TryToPrepareRasterCache
109 * Create cache image for each cache entry if it does not exist.
110 * - LayerTree::Paint - for each layer in the tree:
111 * If layers or display lists are cached as cached images, the method
112 * `RasterCache::Draw` will be used to draw those cache images.
113 * - RasterCache::EndFrame:
114 * Computes used counts and memory then reports cache metrics.
115 */
116class RasterCache {
117 public:
118 struct Context {
119 GrDirectContext* gr_context;
120 const SkColorSpace* dst_color_space;
121 const SkMatrix& matrix;
122 const SkRect& logical_rect;
123 const char* flow_type;
124 };
125 struct CacheInfo {
126 const size_t accesses_since_visible;
127 const bool has_image;
128 };
129
130 std::unique_ptr<RasterCacheResult> Rasterize(
131 const RasterCache::Context& context,
132 sk_sp<const DlRTree> rtree,
133 const std::function<void(DlCanvas*)>& draw_function,
134 const std::function<void(DlCanvas*, const SkRect& rect)>&
135 draw_checkerboard) const;
136
137 explicit RasterCache(
138 size_t access_threshold = 3,
139 size_t picture_and_display_list_cache_limit_per_frame =
140 RasterCacheUtil::kDefaultPictureAndDisplayListCacheLimitPerFrame);
141
142 virtual ~RasterCache() = default;
143
144 // Draws this item if it should be rendered from the cache and returns
145 // true iff it was successfully drawn. Typically this should only fail
146 // if the item was disabled due to conditions discovered during |Preroll|
147 // or if the attempt to populate the entry failed due to bounds overflow
148 // conditions.
149 // If |preserve_rtree| is true, the raster cache will preserve the original
150 // RTree of cached content by blitting individual rectangles from the cached
151 // image to the canvas according to the original layer R-Tree (if present).
152 // This is to ensure that the target surface R-Tree will not be clobbered with
153 // one large blit as it can affect platform view overlays and hit testing.
154 bool Draw(const RasterCacheKeyID& id,
155 DlCanvas& canvas,
156 const DlPaint* paint,
157 bool preserve_rtree = false) const;
158
159 bool HasEntry(const RasterCacheKeyID& id, const SkMatrix&) const;
160
161 void BeginFrame();
162
163 void EvictUnusedCacheEntries();
164
165 void EndFrame();
166
167 void Clear();
168
169 void SetCheckboardCacheImages(bool checkerboard);
170
171 const RasterCacheMetrics& picture_metrics() const { return picture_metrics_; }
172 const RasterCacheMetrics& layer_metrics() const { return layer_metrics_; }
173
174 size_t GetCachedEntriesCount() const;
175
176 /**
177 * Return the number of map entries in the layer cache regardless of whether
178 * the entries have been populated with an image.
179 */
180 size_t GetLayerCachedEntriesCount() const;
181
182 /**
183 * Return the number of map entries in the picture (DisplayList) cache
184 * regardless of whether the entries have been populated with an image.
185 */
186 size_t GetPictureCachedEntriesCount() const;
187
188 /**
189 * @brief Estimate how much memory is used by picture raster cache entries in
190 * bytes.
191 *
192 * Only SkImage's memory usage is counted as other objects are often much
193 * smaller compared to SkImage. SkImageInfo::computeMinByteSize is used to
194 * estimate the SkImage memory usage.
195 */
196 size_t EstimatePictureCacheByteSize() const;
197
198 /**
199 * @brief Estimate how much memory is used by layer raster cache entries in
200 * bytes.
201 *
202 * Only SkImage's memory usage is counted as other objects are often much
203 * smaller compared to SkImage. SkImageInfo::computeMinByteSize is used to
204 * estimate the SkImage memory usage.
205 */
206 size_t EstimateLayerCacheByteSize() const;
207
208 /**
209 * @brief Return the number of frames that a picture must be prepared
210 * before it will be cached. If the number is 0, then no picture will
211 * ever be cached.
212 *
213 * If the number is one, then it must be prepared and drawn on 1 frame
214 * and it will then be cached on the next frame if it is prepared.
215 */
216 size_t access_threshold() const { return access_threshold_; }
217
218 bool GenerateNewCacheInThisFrame() const {
219 // Disabling caching when access_threshold is zero is historic behavior.
220 return access_threshold_ != 0 && display_list_cached_this_frame_ <
221 display_list_cache_limit_per_frame_;
222 }
223
224 /**
225 * @brief The entry whose RasterCacheKey is generated by RasterCacheKeyID
226 * and matrix is marked as encountered by the current frame. The entry
227 * will be created if it does not exist. Optionally the entry will be marked
228 * as visible in the current frame if the caller determines that it
229 * intersects the cull rect. The access_count of the entry will be
230 * increased if it is visible, or if it was ever visible.
231 * @return the number of times the entry has been hit since it was created.
232 * For a new entry that will be 1 if it is visible, or zero if non-visible.
233 */
234 CacheInfo MarkSeen(const RasterCacheKeyID& id,
235 const SkMatrix& matrix,
236 bool visible) const;
237
238 /**
239 * Returns the access count (i.e. accesses_since_visible) for the given
240 * entry in the cache, or -1 if no such entry exists.
241 */
242 int GetAccessCount(const RasterCacheKeyID& id, const SkMatrix& matrix) const;
243
244 bool UpdateCacheEntry(const RasterCacheKeyID& id,
245 const Context& raster_cache_context,
246 const std::function<void(DlCanvas*)>& render_function,
247 sk_sp<const DlRTree> rtree = nullptr) const;
248
249 private:
250 struct Entry {
251 bool encountered_this_frame = false;
252 bool visible_this_frame = false;
253 size_t accesses_since_visible = 0;
254 std::unique_ptr<RasterCacheResult> image;
255 };
256
257 void UpdateMetrics();
258
259 RasterCacheMetrics& GetMetricsForKind(RasterCacheKeyKind kind);
260
261 const size_t access_threshold_;
262 const size_t display_list_cache_limit_per_frame_;
263 mutable size_t display_list_cached_this_frame_ = 0;
264 RasterCacheMetrics layer_metrics_;
265 RasterCacheMetrics picture_metrics_;
266 mutable RasterCacheKey::Map<Entry> cache_;
267 bool checkerboard_images_;
268
269 void TraceStatsToTimeline() const;
270
271 friend class RasterCacheItem;
272 friend class LayerRasterCacheItem;
273
274 FML_DISALLOW_COPY_AND_ASSIGN(RasterCache);
275};
276
277} // namespace flutter
278
279#endif // FLUTTER_FLOW_RASTER_CACHE_H_
280

source code of flutter_engine/flutter/flow/raster_cache.h