Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
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
8
9#include <cstddef>
10#include <vector>
11
19#include "flutter/fml/logging.h"
21#include "third_party/skia/include/core/SkColorSpace.h"
22#include "third_party/skia/include/core/SkImage.h"
23#include "third_party/skia/include/core/SkSurface.h"
24#include "third_party/skia/include/gpu/ganesh/GrDirectContext.h"
25#include "third_party/skia/include/gpu/ganesh/SkSurfaceGanesh.h"
26
27namespace flutter {
28
30 const SkRect& logical_rect,
31 const char* type,
32 sk_sp<const DlRTree> rtree)
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
43 auto matrix =
45 SkRect bounds =
46 RasterCacheUtil::GetRoundedOutDeviceBounds(logical_rect_, matrix);
47 FML_DCHECK(std::abs(bounds.width() - image_->GetSize().width) <= 1 &&
48 std::abs(bounds.height() - image_->GetSize().height) <= 1);
49 canvas.TransformReset();
50 flow_.Step();
51 if (!preserve_rtree || !rtree_) {
52 canvas.DrawImage(image_, DlPoint(bounds.fLeft, bounds.fTop),
54 } else {
55 // On some platforms RTree from overlay layers is used for unobstructed
56 // platform views and hit testing. To preserve the RTree raster cache must
57 // paint individual rects instead of the whole image.
58 auto rects = rtree_->region().getRects(true);
59
60 canvas.Translate(bounds.fLeft, bounds.fTop);
61
63 ToSkRect(rtree_->bounds()), matrix);
64 for (auto rect : rects) {
66 SkRect::Make(ToSkIRect(rect)), matrix));
67 device_rect = device_rect.Shift(-rtree_bounds.fLeft, -rtree_bounds.fTop);
68 canvas.DrawImageRect(image_, device_rect, device_rect,
70 }
71 }
72}
73
74RasterCache::RasterCache(size_t access_threshold,
75 size_t display_list_cache_limit_per_frame)
76 : access_threshold_(access_threshold),
77 display_list_cache_limit_per_frame_(display_list_cache_limit_per_frame) {}
78
79/// @note Procedure doesn't copy all closures.
80std::unique_ptr<RasterCacheResult> RasterCache::Rasterize(
81 const RasterCache::Context& context,
82 sk_sp<const DlRTree> rtree,
83 const std::function<void(DlCanvas*)>& draw_function,
84 const std::function<void(DlCanvas*, const DlRect& rect)>& draw_checkerboard)
85 const {
86 auto matrix = RasterCacheUtil::GetIntegralTransCTM(context.matrix);
87 SkRect dest_rect =
89
90 const SkImageInfo image_info = SkImageInfo::MakeN32Premul(
91 dest_rect.width(), dest_rect.height(), context.dst_color_space);
92
93 sk_sp<SkSurface> surface =
94 context.gr_context
95 ? SkSurfaces::RenderTarget(context.gr_context, skgpu::Budgeted::kYes,
96 image_info)
97 : SkSurfaces::Raster(image_info);
98
99 if (!surface) {
100 return nullptr;
101 }
102
103 DlSkCanvasAdapter canvas(surface->getCanvas());
105
106 canvas.Translate(-dest_rect.left(), -dest_rect.top());
107 canvas.Transform(ToDlMatrix(matrix));
108 draw_function(&canvas);
109
110 if (checkerboard_images_) {
111 draw_checkerboard(&canvas, ToDlRect(context.logical_rect));
112 }
113
114 auto image = DlImageSkia::Make(surface->makeImageSnapshot());
115 return std::make_unique<RasterCacheResult>(
116 image, context.logical_rect, context.flow_type, std::move(rtree));
117}
118
120 const RasterCacheKeyID& id,
121 const Context& raster_cache_context,
122 const std::function<void(DlCanvas*)>& render_function,
123 sk_sp<const DlRTree> rtree) const {
124 RasterCacheKey key = RasterCacheKey(id, raster_cache_context.matrix);
125 Entry& entry = cache_[key];
126 if (!entry.image) {
127 void (*func)(DlCanvas*, const DlRect& rect) = DrawCheckerboard;
128 entry.image = Rasterize(raster_cache_context, std::move(rtree),
129 render_function, func);
130 if (entry.image != nullptr) {
131 switch (id.type()) {
133 display_list_cached_this_frame_++;
134 break;
135 }
136 default:
137 break;
138 }
139 return true;
140 }
141 }
142 return entry.image != nullptr;
143}
144
146 const SkMatrix& matrix,
147 bool visible) const {
148 RasterCacheKey key = RasterCacheKey(id, matrix);
149 Entry& entry = cache_[key];
150 entry.encountered_this_frame = true;
151 entry.visible_this_frame = visible;
152 if (visible || entry.accesses_since_visible > 0) {
153 entry.accesses_since_visible++;
154 }
155 return {entry.accesses_since_visible, entry.image != nullptr};
156}
157
159 const SkMatrix& matrix) const {
160 RasterCacheKey key = RasterCacheKey(id, matrix);
161 auto entry = cache_.find(key);
162 if (entry != cache_.cend()) {
163 return entry->second.accesses_since_visible;
164 }
165 return -1;
166}
167
169 const SkMatrix& matrix) const {
170 RasterCacheKey key = RasterCacheKey(id, matrix);
171 if (cache_.find(key) != cache_.cend()) {
172 return true;
173 }
174 return false;
175}
176
178 DlCanvas& canvas,
179 const DlPaint* paint,
180 bool preserve_rtree) const {
181 auto it = cache_.find(RasterCacheKey(id, ToSkMatrix(canvas.GetMatrix())));
182 if (it == cache_.end()) {
183 return false;
184 }
185
186 Entry& entry = it->second;
187
188 if (entry.image) {
189 entry.image->draw(canvas, paint, preserve_rtree);
190 return true;
191 }
192
193 return false;
194}
195
197 display_list_cached_this_frame_ = 0;
198 picture_metrics_ = {};
199 layer_metrics_ = {};
200}
201
202void RasterCache::UpdateMetrics() {
203 for (auto it = cache_.begin(); it != cache_.end(); ++it) {
204 Entry& entry = it->second;
205 FML_DCHECK(entry.encountered_this_frame);
206 if (entry.image) {
207 RasterCacheMetrics& metrics = GetMetricsForKind(it->first.kind());
208 metrics.in_use_count++;
209 metrics.in_use_bytes += entry.image->image_bytes();
210 }
211 entry.encountered_this_frame = false;
212 }
213}
214
216 std::vector<RasterCacheKey::Map<Entry>::iterator> dead;
217
218 for (auto it = cache_.begin(); it != cache_.end(); ++it) {
219 Entry& entry = it->second;
220 if (!entry.encountered_this_frame) {
221 dead.push_back(it);
222 }
223 }
224
225 for (auto it : dead) {
226 if (it->second.image) {
227 RasterCacheMetrics& metrics = GetMetricsForKind(it->first.kind());
228 metrics.eviction_count++;
229 metrics.eviction_bytes += it->second.image->image_bytes();
230 }
231 cache_.erase(it);
232 }
233}
234
236 UpdateMetrics();
237 TraceStatsToTimeline();
238}
239
241 cache_.clear();
242 picture_metrics_ = {};
243 layer_metrics_ = {};
244}
245
247 return cache_.size();
248}
249
251 size_t layer_cached_entries_count = 0;
252 for (const auto& item : cache_) {
253 if (item.first.kind() == RasterCacheKeyKind::kLayerMetrics) {
254 layer_cached_entries_count++;
255 }
256 }
257 return layer_cached_entries_count;
258}
259
261 size_t display_list_cached_entries_count = 0;
262 for (const auto& item : cache_) {
263 if (item.first.kind() == RasterCacheKeyKind::kDisplayListMetrics) {
264 display_list_cached_entries_count++;
265 }
266 }
267 return display_list_cached_entries_count;
268}
269
270void RasterCache::TraceStatsToTimeline() const {
271#if !FLUTTER_RELEASE
273 "flutter", //
274 "RasterCache", reinterpret_cast<int64_t>(this), //
275 "LayerCount", layer_metrics_.total_count(), //
276 "LayerMBytes", layer_metrics_.total_bytes() / kMegaByteSizeInBytes, //
277 "PictureCount", picture_metrics_.total_count(), //
278 "PictureMBytes", picture_metrics_.total_bytes() / kMegaByteSizeInBytes);
279
280#endif // !FLUTTER_RELEASE
281}
282
284 size_t layer_cache_bytes = 0;
285 for (const auto& item : cache_) {
286 if (item.first.kind() == RasterCacheKeyKind::kLayerMetrics &&
287 item.second.image) {
288 layer_cache_bytes += item.second.image->image_bytes();
289 }
290 }
291 return layer_cache_bytes;
292}
293
295 size_t picture_cache_bytes = 0;
296 for (const auto& item : cache_) {
297 if (item.first.kind() == RasterCacheKeyKind::kDisplayListMetrics &&
298 item.second.image) {
299 picture_cache_bytes += item.second.image->image_bytes();
300 }
301 }
302 return picture_cache_bytes;
303}
304
305RasterCacheMetrics& RasterCache::GetMetricsForKind(RasterCacheKeyKind kind) {
306 switch (kind) {
308 return picture_metrics_;
310 return layer_metrics_;
311 }
312}
313
314} // namespace flutter
315
316#endif // !SLIMPELLER
Developer-facing API for rendering anything within the engine.
Definition dl_canvas.h:32
virtual void TransformReset()=0
virtual void DrawImage(const sk_sp< DlImage > &image, const DlPoint &point, DlImageSampling sampling, const DlPaint *paint=nullptr)=0
virtual void Translate(DlScalar tx, DlScalar ty)=0
virtual DlMatrix GetMatrix() const =0
void Clear(DlColor color)
Definition dl_canvas.h:104
virtual void DrawImageRect(const sk_sp< DlImage > &image, const DlRect &src, const DlRect &dst, DlImageSampling sampling, const DlPaint *paint=nullptr, DlSrcRectConstraint constraint=DlSrcRectConstraint::kFast)=0
static sk_sp< DlImage > Make(const SkImage *image)
Backend implementation of |DlCanvas| for |SkCanvas|.
void Transform(const DlMatrix &matrix) override
void Translate(DlScalar tx, DlScalar ty) override
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)
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 DlRect &rect)> &draw_checkerboard) const
RasterCacheResult(sk_sp< DlImage > image, const SkRect &logical_rect, const char *type, sk_sp< const DlRTree > rtree=nullptr)
virtual void draw(DlCanvas &canvas, const DlPaint *paint, bool preserve_rtree) const
void Step(const char *label=nullptr) const
FlutterVulkanImage * image
VkSurfaceKHR surface
Definition main.cc:65
#define FML_DCHECK(condition)
Definition logging.h:122
const SkIRect & ToSkIRect(const DlIRect &rect)
void DrawCheckerboard(DlCanvas *canvas, const DlRect &rect)
SkMatrix ToSkMatrix(const DlMatrix &matrix)
constexpr double kMegaByteSizeInBytes
Definition constants.h:9
DlMatrix ToDlMatrix(const SkMatrix &matrix)
impeller::Point DlPoint
const DlRect & ToDlRect(const SkRect &rect)
const SkRect & ToSkRect(const DlRect &rect)
Definition ref_ptr.h:261
impeller::ShaderType type
static constexpr DlColor kTransparent()
Definition dl_color.h:68
const sk_sp< SkColorSpace > dst_color_space
static SkMatrix GetIntegralTransCTM(const SkMatrix &ctm)
Snap the translation components of the matrix to integers.
static SkRect GetRoundedOutDeviceBounds(const SkRect &rect, const SkMatrix &ctm)
constexpr TRect< T > Shift(T dx, T dy) const
Returns a new rectangle translated by the given offset.
Definition rect.h:636
#define FML_TRACE_COUNTER(category_group, name, counter_id, arg1,...)
Definition trace_event.h:85