Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
compositor_context.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#include "flutter/flow/compositor_context.h"
6
7#include <optional>
8#include <utility>
9#include "flutter/flow/layers/layer_tree.h"
11
12namespace flutter {
13
14std::optional<SkRect> FrameDamage::ComputeClipRect(
15 flutter::LayerTree& layer_tree,
16 bool has_raster_cache,
17 bool impeller_enabled) {
18 if (layer_tree.root_layer()) {
19 PaintRegionMap empty_paint_region_map;
20 DiffContext context(layer_tree.frame_size(), layer_tree.paint_region_map(),
21 prev_layer_tree_ ? prev_layer_tree_->paint_region_map()
22 : empty_paint_region_map,
23 has_raster_cache, impeller_enabled);
24 context.PushCullRect(SkRect::MakeIWH(layer_tree.frame_size().width(),
25 layer_tree.frame_size().height()));
26 {
27 DiffContext::AutoSubtreeRestore subtree(&context);
28 const Layer* prev_root_layer = nullptr;
29 if (!prev_layer_tree_ ||
30 prev_layer_tree_->frame_size() != layer_tree.frame_size()) {
31 // If there is no previous layer tree assume the entire frame must be
32 // repainted.
33 context.MarkSubtreeDirty(SkRect::MakeIWH(
34 layer_tree.frame_size().width(), layer_tree.frame_size().height()));
35 } else {
36 prev_root_layer = prev_layer_tree_->root_layer();
37 }
38 layer_tree.root_layer()->Diff(&context, prev_root_layer);
39 }
40
41 damage_ =
42 context.ComputeDamage(additional_damage_, horizontal_clip_alignment_,
43 vertical_clip_alignment_);
44 return SkRect::Make(damage_->buffer_damage);
45 }
46 return std::nullopt;
47}
48
50 : texture_registry_(std::make_shared<TextureRegistry>()),
51 raster_time_(fixed_refresh_rate_updater_),
52 ui_time_(fixed_refresh_rate_updater_) {}
53
55 : texture_registry_(std::make_shared<TextureRegistry>()),
56 raster_time_(updater),
57 ui_time_(updater) {}
58
60
61void CompositorContext::BeginFrame(ScopedFrame& frame,
62 bool enable_instrumentation) {
63 if (enable_instrumentation) {
64 raster_time_.Start();
65 }
66}
67
68void CompositorContext::EndFrame(ScopedFrame& frame,
69 bool enable_instrumentation) {
70 if (enable_instrumentation) {
71 raster_time_.Stop();
72 }
73}
74
75std::unique_ptr<CompositorContext::ScopedFrame> CompositorContext::AcquireFrame(
76 GrDirectContext* gr_context,
77 DlCanvas* canvas,
78 ExternalViewEmbedder* view_embedder,
79 const SkMatrix& root_surface_transformation,
80 bool instrumentation_enabled,
81 bool surface_supports_readback,
83 raster_thread_merger, // NOLINT(performance-unnecessary-value-param)
84 impeller::AiksContext* aiks_context) {
85 return std::make_unique<ScopedFrame>(
86 *this, gr_context, canvas, view_embedder, root_surface_transformation,
87 instrumentation_enabled, surface_supports_readback, raster_thread_merger,
88 aiks_context);
89}
90
92 CompositorContext& context,
93 GrDirectContext* gr_context,
94 DlCanvas* canvas,
95 ExternalViewEmbedder* view_embedder,
96 const SkMatrix& root_surface_transformation,
97 bool instrumentation_enabled,
98 bool surface_supports_readback,
99 fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger,
100 impeller::AiksContext* aiks_context)
101 : context_(context),
102 gr_context_(gr_context),
103 canvas_(canvas),
104 aiks_context_(aiks_context),
105 view_embedder_(view_embedder),
106 root_surface_transformation_(root_surface_transformation),
107 instrumentation_enabled_(instrumentation_enabled),
108 surface_supports_readback_(surface_supports_readback),
109 raster_thread_merger_(std::move(raster_thread_merger)) {
110 context_.BeginFrame(*this, instrumentation_enabled_);
111}
112
114 context_.EndFrame(*this, instrumentation_enabled_);
115}
116
118 flutter::LayerTree& layer_tree,
119 bool ignore_raster_cache,
120 FrameDamage* frame_damage) {
121 TRACE_EVENT0("flutter", "CompositorContext::ScopedFrame::Raster");
122
123 std::optional<SkRect> clip_rect;
124 if (frame_damage) {
125 clip_rect = frame_damage->ComputeClipRect(layer_tree, !ignore_raster_cache,
126 !gr_context_);
127
128 if (aiks_context_ &&
129 !ShouldPerformPartialRepaint(clip_rect, layer_tree.frame_size())) {
130 clip_rect = std::nullopt;
131 frame_damage->Reset();
132 }
133 }
134
135 bool root_needs_readback = layer_tree.Preroll(
136 *this, ignore_raster_cache, clip_rect ? *clip_rect : kGiantRect);
137 bool needs_save_layer = root_needs_readback && !surface_supports_readback();
139 if (view_embedder_ && raster_thread_merger_) {
140 post_preroll_result =
141 view_embedder_->PostPrerollAction(raster_thread_merger_);
142 }
143
144 if (post_preroll_result == PostPrerollResult::kResubmitFrame) {
146 }
147 if (post_preroll_result == PostPrerollResult::kSkipAndRetryFrame) {
149 }
150
151 if (aiks_context_) {
152 PaintLayerTreeImpeller(layer_tree, clip_rect, ignore_raster_cache);
153 } else {
154 PaintLayerTreeSkia(layer_tree, clip_rect, needs_save_layer,
155 ignore_raster_cache);
156 }
158}
159
160void CompositorContext::ScopedFrame::PaintLayerTreeSkia(
161 flutter::LayerTree& layer_tree,
162 std::optional<SkRect> clip_rect,
163 bool needs_save_layer,
164 bool ignore_raster_cache) {
165 DlAutoCanvasRestore restore(canvas(), clip_rect.has_value());
166
167 if (canvas()) {
168 if (clip_rect) {
169 canvas()->ClipRect(*clip_rect);
170 }
171
172 if (needs_save_layer) {
173 TRACE_EVENT0("flutter", "Canvas::saveLayer");
174 SkRect bounds = SkRect::Make(layer_tree.frame_size());
176 paint.setBlendMode(DlBlendMode::kSrc);
177 canvas()->SaveLayer(&bounds, &paint);
178 }
179 canvas()->Clear(DlColor::kTransparent());
180 }
181
182 // The canvas()->Restore() is taken care of by the DlAutoCanvasRestore
183 layer_tree.Paint(*this, ignore_raster_cache);
184}
185
186void CompositorContext::ScopedFrame::PaintLayerTreeImpeller(
187 flutter::LayerTree& layer_tree,
188 std::optional<SkRect> clip_rect,
189 bool ignore_raster_cache) {
190 if (canvas() && clip_rect) {
191 canvas()->Translate(-clip_rect->x(), -clip_rect->y());
192 }
193
194 layer_tree.Paint(*this, ignore_raster_cache);
195}
196
197/// @brief The max ratio of pixel width or height to size that is dirty which
198/// results in a partial repaint.
199///
200/// Performing a partial repaint has a small overhead - Impeller needs to
201/// allocate a fairly large resolve texture for the root pass instead of
202/// using the drawable texture, and a final blit must be performed. At a
203/// minimum, if the damage rect is the entire buffer, we must not perform
204/// a partial repaint. Beyond that, we could only experimentally
205/// determine what this value should be. From looking at the Flutter
206/// Gallery, we noticed that there are occassionally small partial
207/// repaints which shave off trivial numbers of pixels.
208constexpr float kImpellerRepaintRatio = 0.7f;
209
210bool CompositorContext::ShouldPerformPartialRepaint(
211 std::optional<SkRect> damage_rect,
212 SkISize layer_tree_size) {
213 if (!damage_rect.has_value()) {
214 return false;
215 }
216 if (damage_rect->width() >= layer_tree_size.width() &&
217 damage_rect->height() >= layer_tree_size.height()) {
218 return false;
219 }
220 auto rx = damage_rect->width() / layer_tree_size.width();
221 auto ry = damage_rect->height() / layer_tree_size.height();
222 return rx <= kImpellerRepaintRatio || ry <= kImpellerRepaintRatio;
223}
224
226 texture_registry_->OnGrContextCreated();
227 raster_cache_.Clear();
228}
229
231 texture_registry_->OnGrContextDestroyed();
232 raster_cache_.Clear();
233}
234
235} // namespace flutter
ScopedFrame(CompositorContext &context, GrDirectContext *gr_context, DlCanvas *canvas, ExternalViewEmbedder *view_embedder, const SkMatrix &root_surface_transformation, bool instrumentation_enabled, bool surface_supports_readback, fml::RefPtr< fml::RasterThreadMerger > raster_thread_merger, impeller::AiksContext *aiks_context)
virtual RasterStatus Raster(LayerTree &layer_tree, bool ignore_raster_cache, FrameDamage *frame_damage)
virtual std::unique_ptr< ScopedFrame > AcquireFrame(GrDirectContext *gr_context, DlCanvas *canvas, ExternalViewEmbedder *view_embedder, const SkMatrix &root_surface_transformation, bool instrumentation_enabled, bool surface_supports_readback, fml::RefPtr< fml::RasterThreadMerger > raster_thread_merger, impeller::AiksContext *aiks_context)
bool PushCullRect(const SkRect &clip)
Developer-facing API for rendering anything within the engine.
Definition dl_canvas.h:37
std::optional< SkRect > ComputeClipRect(flutter::LayerTree &layer_tree, bool has_raster_cache, bool impeller_enabled)
Layer * root_layer() const
Definition layer_tree.h:57
bool Preroll(CompositorContext::ScopedFrame &frame, bool ignore_raster_cache=false, SkRect cull_rect=kGiantRect)
Definition layer_tree.cc:33
const SkISize & frame_size() const
Definition layer_tree.h:58
void Paint(CompositorContext::ScopedFrame &frame, bool ignore_raster_cache=false) const
const PaintRegionMap & paint_region_map() const
Definition layer_tree.h:60
virtual void Diff(DiffContext *context, const Layer *old_layer)
Definition layer.h:157
The refresh rate interface for Stopwatch.
Definition stopwatch.h:20
const Paint & paint
double frame
Definition examples.cpp:31
std::map< uint64_t, PaintRegion > PaintRegionMap
constexpr float kImpellerRepaintRatio
The max ratio of pixel width or height to size that is dirty which results in a partial repaint.
static constexpr SkRect kGiantRect
Definition layer.h:49
Definition ref_ptr.h:256
constexpr int32_t width() const
Definition SkSize.h:36
constexpr int32_t height() const
Definition SkSize.h:37
static SkRect Make(const SkISize &size)
Definition SkRect.h:669
static SkRect MakeIWH(int w, int h)
Definition SkRect.h:623
static constexpr DlColor kTransparent()
Definition dl_color.h:21
#define TRACE_EVENT0(category_group, name)