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_COMPOSITOR_CONTEXT_H_
6#define FLUTTER_FLOW_COMPOSITOR_CONTEXT_H_
7
8#include <memory>
9#include <string>
10
11#include "flutter/common/graphics/texture.h"
12#include "flutter/flow/diff_context.h"
13#include "flutter/flow/embedded_views.h"
14#include "flutter/flow/instrumentation.h"
15#include "flutter/flow/layer_snapshot_store.h"
16#include "flutter/flow/raster_cache.h"
17#include "flutter/fml/macros.h"
18#include "flutter/fml/raster_thread_merger.h"
19#include "third_party/skia/include/core/SkCanvas.h"
20#include "third_party/skia/include/gpu/GrDirectContext.h"
21
22namespace flutter {
23
24class LayerTree;
25
26enum class RasterStatus {
27 // Frame has been successfully rasterized.
28 kSuccess,
29 // Frame is submitted twice. This is only used on Android when
30 // switching the background surface to FlutterImageView.
31 //
32 // On Android, the first frame doesn't make the image available
33 // to the ImageReader right away. The second frame does.
34 //
35 // TODO(egarciad): https://github.com/flutter/flutter/issues/65652
36 kResubmit,
37 // Frame is dropped and a new frame with the same layer tree is
38 // attempted.
39 //
40 // This is currently used to wait for the thread merger to merge
41 // the raster and platform threads.
42 //
43 // Since the thread merger may be disabled,
44 kSkipAndRetry,
45 // Frame has been successfully rasterized, but "there are additional items in
46 // the pipeline waiting to be consumed. This is currently
47 // only used when thread configuration change occurs.
48 kEnqueuePipeline,
49 // Failed to rasterize the frame.
50 kFailed,
51 // Layer tree was discarded due to LayerTreeDiscardCallback or inability to
52 // access the GPU.
53 kDiscarded,
54 // Drawing was yielded to allow the correct thread to draw as a result of the
55 // RasterThreadMerger.
56 kYielded,
57};
58
59class FrameDamage {
60 public:
61 // Sets previous layer tree for calculating frame damage. If not set, entire
62 // frame will be repainted.
63 void SetPreviousLayerTree(const LayerTree* prev_layer_tree) {
64 prev_layer_tree_ = prev_layer_tree;
65 }
66
67 // Adds additional damage (accumulated for double / triple buffering).
68 // This is area that will be repainted alongside any changed part.
69 void AddAdditionalDamage(const SkIRect& damage) {
70 additional_damage_.join(r: damage);
71 }
72
73 // Specifies clip rect alignment.
74 void SetClipAlignment(int horizontal, int vertical) {
75 horizontal_clip_alignment_ = horizontal;
76 vertical_clip_alignment_ = vertical;
77 }
78
79 // Calculates clip rect for current rasterization. This is diff of layer tree
80 // and previous layer tree + any additional provided damage.
81 // If previous layer tree is not specified, clip rect will be nullopt,
82 // but the paint region of layer_tree will be calculated so that it can be
83 // used for diffing of subsequent frames.
84 std::optional<SkRect> ComputeClipRect(flutter::LayerTree& layer_tree,
85 bool has_raster_cache,
86 bool impeller_enabled);
87
88 // See Damage::frame_damage.
89 std::optional<SkIRect> GetFrameDamage() const {
90 return damage_ ? std::make_optional(v: damage_->frame_damage) : std::nullopt;
91 }
92
93 // See Damage::buffer_damage.
94 std::optional<SkIRect> GetBufferDamage() {
95 return (damage_ && !ignore_damage_)
96 ? std::make_optional(v&: damage_->buffer_damage)
97 : std::nullopt;
98 }
99
100 // Remove reported buffer_damage to inform clients that a partial repaint
101 // should not be performed on this frame.
102 // frame_damage is required to correctly track accumulated damage for
103 // subsequent frames.
104 void Reset() { ignore_damage_ = true; }
105
106 private:
107 SkIRect additional_damage_ = SkIRect::MakeEmpty();
108 std::optional<Damage> damage_;
109 const LayerTree* prev_layer_tree_ = nullptr;
110 int vertical_clip_alignment_ = 1;
111 int horizontal_clip_alignment_ = 1;
112 bool ignore_damage_ = false;
113};
114
115class CompositorContext {
116 public:
117 class ScopedFrame {
118 public:
119 ScopedFrame(CompositorContext& context,
120 GrDirectContext* gr_context,
121 DlCanvas* canvas,
122 ExternalViewEmbedder* view_embedder,
123 const SkMatrix& root_surface_transformation,
124 bool instrumentation_enabled,
125 bool surface_supports_readback,
126 fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger,
127 impeller::AiksContext* aiks_context);
128
129 virtual ~ScopedFrame();
130
131 DlCanvas* canvas() { return canvas_; }
132
133 ExternalViewEmbedder* view_embedder() { return view_embedder_; }
134
135 CompositorContext& context() const { return context_; }
136
137 const SkMatrix& root_surface_transformation() const {
138 return root_surface_transformation_;
139 }
140
141 bool surface_supports_readback() { return surface_supports_readback_; }
142
143 GrDirectContext* gr_context() const { return gr_context_; }
144
145 impeller::AiksContext* aiks_context() const { return aiks_context_; }
146
147 virtual RasterStatus Raster(LayerTree& layer_tree,
148 bool ignore_raster_cache,
149 FrameDamage* frame_damage);
150
151 private:
152 void PaintLayerTreeSkia(flutter::LayerTree& layer_tree,
153 std::optional<SkRect> clip_rect,
154 bool needs_save_layer,
155 bool ignore_raster_cache);
156
157 void PaintLayerTreeImpeller(flutter::LayerTree& layer_tree,
158 std::optional<SkRect> clip_rect,
159 bool ignore_raster_cache);
160
161 CompositorContext& context_;
162 GrDirectContext* gr_context_;
163 DlCanvas* canvas_;
164 impeller::AiksContext* aiks_context_;
165 ExternalViewEmbedder* view_embedder_;
166 const SkMatrix& root_surface_transformation_;
167 const bool instrumentation_enabled_;
168 const bool surface_supports_readback_;
169 fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger_;
170
171 FML_DISALLOW_COPY_AND_ASSIGN(ScopedFrame);
172 };
173
174 CompositorContext();
175
176 explicit CompositorContext(Stopwatch::RefreshRateUpdater& updater);
177
178 virtual ~CompositorContext();
179
180 virtual std::unique_ptr<ScopedFrame> AcquireFrame(
181 GrDirectContext* gr_context,
182 DlCanvas* canvas,
183 ExternalViewEmbedder* view_embedder,
184 const SkMatrix& root_surface_transformation,
185 bool instrumentation_enabled,
186 bool surface_supports_readback,
187 fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger,
188 impeller::AiksContext* aiks_context);
189
190 void OnGrContextCreated();
191
192 void OnGrContextDestroyed();
193
194 RasterCache& raster_cache() { return raster_cache_; }
195
196 std::shared_ptr<TextureRegistry> texture_registry() {
197 return texture_registry_;
198 }
199
200 const Stopwatch& raster_time() const { return raster_time_; }
201
202 Stopwatch& ui_time() { return ui_time_; }
203
204 LayerSnapshotStore& snapshot_store() { return layer_snapshot_store_; }
205
206 private:
207 RasterCache raster_cache_;
208 std::shared_ptr<TextureRegistry> texture_registry_;
209 Stopwatch raster_time_;
210 Stopwatch ui_time_;
211 LayerSnapshotStore layer_snapshot_store_;
212
213 /// Only used by default constructor of `CompositorContext`.
214 FixedRefreshRateUpdater fixed_refresh_rate_updater_;
215
216 void BeginFrame(ScopedFrame& frame, bool enable_instrumentation);
217
218 void EndFrame(ScopedFrame& frame, bool enable_instrumentation);
219
220 /// @brief Whether Impeller shouild attempt a partial repaint.
221 /// The Impeller backend requires an additional blit pass, which may
222 /// not be worthwhile if the damage region is large.
223 static bool ShouldPerformPartialRepaint(std::optional<SkRect> damage_rect,
224 SkISize layer_tree_size);
225
226 FML_DISALLOW_COPY_AND_ASSIGN(CompositorContext);
227};
228
229} // namespace flutter
230
231#endif // FLUTTER_FLOW_COMPOSITOR_CONTEXT_H_
232

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