Flutter Engine
The Flutter Engine
raster_cache.cc
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#if !SLIMPELLER
6
7#include "flutter/flow/raster_cache.h"
8
9#include <cstddef>
10#include <vector>
11
12#include "flutter/common/constants.h"
13#include "flutter/display_list/skia/dl_sk_dispatcher.h"
14#include "flutter/flow/layers/container_layer.h"
15#include "flutter/flow/layers/layer.h"
16#include "flutter/flow/paint_utils.h"
17#include "flutter/flow/raster_cache_util.h"
18#include "flutter/fml/logging.h"
19#include "flutter/fml/trace_event.h"
26
27namespace flutter {
28
30 const SkRect& logical_rect,
31 const char* type,
33 : image_(std::move(image)),
34 logical_rect_(logical_rect),
35 flow_(type),
36 rtree_(std::move(rtree)) {}
37
39 const DlPaint* paint,
40 bool preserve_rtree) const {
41 DlAutoCanvasRestore auto_restore(&canvas, true);
42
46 FML_DCHECK(std::abs(bounds.width() - image_->dimensions().width()) <= 1 &&
47 std::abs(bounds.height() - image_->dimensions().height()) <= 1);
48 canvas.TransformReset();
49 flow_.Step();
50 if (!preserve_rtree || !rtree_) {
51 canvas.DrawImage(image_, {bounds.fLeft, bounds.fTop},
53 } else {
54 // On some platforms RTree from overlay layers is used for unobstructed
55 // platform views and hit testing. To preserve the RTree raster cache must
56 // paint individual rects instead of the whole image.
57 auto rects = rtree_->region().getRects(true);
58
59 canvas.Translate(bounds.fLeft, bounds.fTop);
60
61 SkRect rtree_bounds =
63 for (auto rect : rects) {
66 device_rect.offset(-rtree_bounds.fLeft, -rtree_bounds.fTop);
67 canvas.DrawImageRect(image_, device_rect, device_rect,
69 }
70 }
71}
72
73RasterCache::RasterCache(size_t access_threshold,
74 size_t display_list_cache_limit_per_frame)
75 : access_threshold_(access_threshold),
76 display_list_cache_limit_per_frame_(display_list_cache_limit_per_frame) {}
77
78/// @note Procedure doesn't copy all closures.
79std::unique_ptr<RasterCacheResult> RasterCache::Rasterize(
80 const RasterCache::Context& context,
82 const std::function<void(DlCanvas*)>& draw_function,
83 const std::function<void(DlCanvas*, const SkRect& rect)>& draw_checkerboard)
84 const {
86 SkRect dest_rect =
88
89 const SkImageInfo image_info = SkImageInfo::MakeN32Premul(
90 dest_rect.width(), dest_rect.height(), context.dst_color_space);
91
93 context.gr_context
95 image_info)
96 : SkSurfaces::Raster(image_info);
97
98 if (!surface) {
99 return nullptr;
100 }
101
102 DlSkCanvasAdapter canvas(surface->getCanvas());
104
105 canvas.Translate(-dest_rect.left(), -dest_rect.top());
106 canvas.Transform(matrix);
107 draw_function(&canvas);
108
109 if (checkerboard_images_) {
110 draw_checkerboard(&canvas, context.logical_rect);
111 }
112
113 auto image = DlImage::Make(surface->makeImageSnapshot());
114 return std::make_unique<RasterCacheResult>(
115 image, context.logical_rect, context.flow_type, std::move(rtree));
116}
117
119 const RasterCacheKeyID& id,
120 const Context& raster_cache_context,
121 const std::function<void(DlCanvas*)>& render_function,
122 sk_sp<const DlRTree> rtree) const {
123 RasterCacheKey key = RasterCacheKey(id, raster_cache_context.matrix);
124 Entry& entry = cache_[key];
125 if (!entry.image) {
126 void (*func)(DlCanvas*, const SkRect& rect) = DrawCheckerboard;
127 entry.image = Rasterize(raster_cache_context, std::move(rtree),
128 render_function, func);
129 if (entry.image != nullptr) {
130 switch (id.type()) {
132 display_list_cached_this_frame_++;
133 break;
134 }
135 default:
136 break;
137 }
138 return true;
139 }
140 }
141 return entry.image != nullptr;
142}
143
145 const SkMatrix& matrix,
146 bool visible) const {
148 Entry& entry = cache_[key];
149 entry.encountered_this_frame = true;
150 entry.visible_this_frame = visible;
151 if (visible || entry.accesses_since_visible > 0) {
152 entry.accesses_since_visible++;
153 }
154 return {entry.accesses_since_visible, entry.image != nullptr};
155}
156
158 const SkMatrix& matrix) const {
160 auto entry = cache_.find(key);
161 if (entry != cache_.cend()) {
162 return entry->second.accesses_since_visible;
163 }
164 return -1;
165}
166
168 const SkMatrix& matrix) const {
170 if (cache_.find(key) != cache_.cend()) {
171 return true;
172 }
173 return false;
174}
175
177 DlCanvas& canvas,
178 const DlPaint* paint,
179 bool preserve_rtree) const {
180 auto it = cache_.find(RasterCacheKey(id, canvas.GetTransform()));
181 if (it == cache_.end()) {
182 return false;
183 }
184
185 Entry& entry = it->second;
186
187 if (entry.image) {
188 entry.image->draw(canvas, paint, preserve_rtree);
189 return true;
190 }
191
192 return false;
193}
194
196 display_list_cached_this_frame_ = 0;
197 picture_metrics_ = {};
198 layer_metrics_ = {};
199}
200
201void RasterCache::UpdateMetrics() {
202 for (auto it = cache_.begin(); it != cache_.end(); ++it) {
203 Entry& entry = it->second;
204 FML_DCHECK(entry.encountered_this_frame);
205 if (entry.image) {
206 RasterCacheMetrics& metrics = GetMetricsForKind(it->first.kind());
207 metrics.in_use_count++;
208 metrics.in_use_bytes += entry.image->image_bytes();
209 }
210 entry.encountered_this_frame = false;
211 }
212}
213
215 std::vector<RasterCacheKey::Map<Entry>::iterator> dead;
216
217 for (auto it = cache_.begin(); it != cache_.end(); ++it) {
218 Entry& entry = it->second;
219 if (!entry.encountered_this_frame) {
220 dead.push_back(it);
221 }
222 }
223
224 for (auto it : dead) {
225 if (it->second.image) {
226 RasterCacheMetrics& metrics = GetMetricsForKind(it->first.kind());
227 metrics.eviction_count++;
228 metrics.eviction_bytes += it->second.image->image_bytes();
229 }
230 cache_.erase(it);
231 }
232}
233
235 UpdateMetrics();
236 TraceStatsToTimeline();
237}
238
240 cache_.clear();
241 picture_metrics_ = {};
242 layer_metrics_ = {};
243}
244
246 return cache_.size();
247}
248
250 size_t layer_cached_entries_count = 0;
251 for (const auto& item : cache_) {
252 if (item.first.kind() == RasterCacheKeyKind::kLayerMetrics) {
253 layer_cached_entries_count++;
254 }
255 }
256 return layer_cached_entries_count;
257}
258
260 size_t display_list_cached_entries_count = 0;
261 for (const auto& item : cache_) {
262 if (item.first.kind() == RasterCacheKeyKind::kDisplayListMetrics) {
263 display_list_cached_entries_count++;
264 }
265 }
266 return display_list_cached_entries_count;
267}
268
269void RasterCache::TraceStatsToTimeline() const {
270#if !FLUTTER_RELEASE
272 "flutter", //
273 "RasterCache", reinterpret_cast<int64_t>(this), //
274 "LayerCount", layer_metrics_.total_count(), //
275 "LayerMBytes", layer_metrics_.total_bytes() / kMegaByteSizeInBytes, //
276 "PictureCount", picture_metrics_.total_count(), //
277 "PictureMBytes", picture_metrics_.total_bytes() / kMegaByteSizeInBytes);
278
279#endif // !FLUTTER_RELEASE
280}
281
283 size_t layer_cache_bytes = 0;
284 for (const auto& item : cache_) {
285 if (item.first.kind() == RasterCacheKeyKind::kLayerMetrics &&
286 item.second.image) {
287 layer_cache_bytes += item.second.image->image_bytes();
288 }
289 }
290 return layer_cache_bytes;
291}
292
294 size_t picture_cache_bytes = 0;
295 for (const auto& item : cache_) {
296 if (item.first.kind() == RasterCacheKeyKind::kDisplayListMetrics &&
297 item.second.image) {
298 picture_cache_bytes += item.second.image->image_bytes();
299 }
300 }
301 return picture_cache_bytes;
302}
303
304RasterCacheMetrics& RasterCache::GetMetricsForKind(RasterCacheKeyKind kind) {
305 switch (kind) {
307 return picture_metrics_;
309 return layer_metrics_;
310 }
311}
312
313} // namespace flutter
314
315#endif // !SLIMPELLER
GLenum type
Developer-facing API for rendering anything within the engine.
Definition: dl_canvas.h:38
virtual void TransformReset()=0
virtual void Translate(SkScalar tx, SkScalar ty)=0
void Clear(DlColor color)
Definition: dl_canvas.h:132
virtual void DrawImageRect(const sk_sp< DlImage > &image, const SkRect &src, const SkRect &dst, DlImageSampling sampling, const DlPaint *paint=nullptr, SrcRectConstraint constraint=SrcRectConstraint::kFast)=0
virtual SkMatrix GetTransform() const =0
virtual void DrawImage(const sk_sp< DlImage > &image, const SkPoint point, DlImageSampling sampling, const DlPaint *paint=nullptr)=0
static sk_sp< DlImage > Make(const SkImage *image)
Definition: dl_image.cc:11
Backend implementation of |DlCanvas| for |SkCanvas|.
Definition: dl_sk_canvas.h:20
void Transform(const SkMatrix *matrix) override
void Translate(SkScalar tx, SkScalar ty) override
Definition: dl_sk_canvas.cc:77
RasterCacheResult(sk_sp< DlImage > image, const SkRect &logical_rect, const char *type, sk_sp< const DlRTree > rtree=nullptr)
Definition: raster_cache.cc:29
virtual void draw(DlCanvas &canvas, const DlPaint *paint, bool preserve_rtree) const
Definition: raster_cache.cc:38
bool Draw(const RasterCacheKeyID &id, DlCanvas &canvas, const DlPaint *paint, bool preserve_rtree=false) const
CacheInfo MarkSeen(const RasterCacheKeyID &id, const SkMatrix &matrix, bool visible) const
The entry whose RasterCacheKey is generated by RasterCacheKeyID and matrix is marked as encountered b...
size_t EstimatePictureCacheByteSize() const
Estimate how much memory is used by picture raster cache entries in bytes.
bool HasEntry(const RasterCacheKeyID &id, const SkMatrix &) const
bool UpdateCacheEntry(const RasterCacheKeyID &id, const Context &raster_cache_context, const std::function< void(DlCanvas *)> &render_function, sk_sp< const DlRTree > rtree=nullptr) const
RasterCache(size_t access_threshold=3, size_t picture_and_display_list_cache_limit_per_frame=RasterCacheUtil::kDefaultPictureAndDisplayListCacheLimitPerFrame)
Definition: raster_cache.cc:73
int GetAccessCount(const RasterCacheKeyID &id, const SkMatrix &matrix) const
size_t GetCachedEntriesCount() const
size_t GetPictureCachedEntriesCount() const
size_t EstimateLayerCacheByteSize() const
Estimate how much memory is used by layer raster cache entries in bytes.
size_t GetLayerCachedEntriesCount() const
std::unique_ptr< RasterCacheResult > Rasterize(const RasterCache::Context &context, sk_sp< const DlRTree > rtree, const std::function< void(DlCanvas *)> &draw_function, const std::function< void(DlCanvas *, const SkRect &rect)> &draw_checkerboard) const
Definition: raster_cache.cc:79
void Step(const char *label=nullptr) const
Definition: trace_event.h:484
const Paint & paint
Definition: color_source.cc:38
VkSurfaceKHR surface
Definition: main.cc:49
#define FML_DCHECK(condition)
Definition: logging.h:103
Dart_NativeFunction function
Definition: fuchsia.cc:51
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258
Optional< SkRect > bounds
Definition: SkRecords.h:189
sk_sp< const SkImage > image
Definition: SkRecords.h:269
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)
void draw_checkerboard(SkCanvas *canvas, SkColor c1, SkColor c2, int size)
Definition: ToolUtils.cpp:174
constexpr double kMegaByteSizeInBytes
Definition: constants.h:9
void DrawCheckerboard(DlCanvas *canvas, const SkRect &rect)
Definition: paint_utils.cc:32
SIN Vec< N, float > abs(const Vec< N, float > &x)
Definition: SkVx.h:707
Definition: ref_ptr.h:256
static SkImageInfo MakeN32Premul(int width, int height)
static SkRect Make(const SkISize &size)
Definition: SkRect.h:669
constexpr float left() const
Definition: SkRect.h:734
constexpr float top() const
Definition: SkRect.h:741
SkScalar fLeft
smaller x-axis bounds
Definition: extension.cpp:14
void offset(float dx, float dy)
Definition: SkRect.h:1016
constexpr float height() const
Definition: SkRect.h:769
constexpr float width() const
Definition: SkRect.h:762
SkScalar fTop
smaller y-axis bounds
Definition: extension.cpp:15
static constexpr DlColor kTransparent()
Definition: dl_color.h:21
size_t total_count() const
Definition: raster_cache.h:86
size_t total_bytes() const
Definition: raster_cache.h:91
static SkMatrix GetIntegralTransCTM(const SkMatrix &ctm)
Snap the translation components of the matrix to integers.
static SkRect GetRoundedOutDeviceBounds(const SkRect &rect, const SkMatrix &ctm)
GrDirectContext * gr_context
Definition: raster_cache.h:121
const sk_sp< SkColorSpace > dst_color_space
Definition: raster_cache.h:122
#define FML_TRACE_COUNTER(category_group, name, counter_id, arg1,...)
Definition: trace_event.h:85