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_LAYERS_LAYER_H_ |
6 | #define FLUTTER_FLOW_LAYERS_LAYER_H_ |
7 | |
8 | #include <algorithm> |
9 | #include <memory> |
10 | #include <unordered_set> |
11 | #include <vector> |
12 | |
13 | #include "flutter/common/graphics/texture.h" |
14 | #include "flutter/display_list/dl_canvas.h" |
15 | #include "flutter/flow/diff_context.h" |
16 | #include "flutter/flow/embedded_views.h" |
17 | #include "flutter/flow/instrumentation.h" |
18 | #include "flutter/flow/layer_snapshot_store.h" |
19 | #include "flutter/flow/layers/layer_state_stack.h" |
20 | #include "flutter/flow/raster_cache.h" |
21 | #include "flutter/fml/build_config.h" |
22 | #include "flutter/fml/compiler_specific.h" |
23 | #include "flutter/fml/logging.h" |
24 | #include "flutter/fml/macros.h" |
25 | #include "flutter/fml/trace_event.h" |
26 | #include "third_party/skia/include/core/SkCanvas.h" |
27 | #include "third_party/skia/include/core/SkColor.h" |
28 | #include "third_party/skia/include/core/SkColorFilter.h" |
29 | #include "third_party/skia/include/core/SkMatrix.h" |
30 | #include "third_party/skia/include/core/SkPath.h" |
31 | #include "third_party/skia/include/core/SkRRect.h" |
32 | #include "third_party/skia/include/core/SkRect.h" |
33 | #include "third_party/skia/include/utils/SkNWayCanvas.h" |
34 | |
35 | class GrDirectContext; |
36 | |
37 | namespace flutter { |
38 | |
39 | namespace testing { |
40 | class MockLayer; |
41 | } // namespace testing |
42 | |
43 | class ContainerLayer; |
44 | class DisplayListLayer; |
45 | class PerformanceOverlayLayer; |
46 | class TextureLayer; |
47 | class RasterCacheItem; |
48 | |
49 | static constexpr SkRect kGiantRect = SkRect::MakeLTRB(l: -1E9F, t: -1E9F, r: 1E9F, b: 1E9F); |
50 | |
51 | // This should be an exact copy of the Clip enum in painting.dart. |
52 | enum Clip { none, hardEdge, antiAlias, antiAliasWithSaveLayer }; |
53 | |
54 | struct PrerollContext { |
55 | RasterCache* raster_cache; |
56 | GrDirectContext* gr_context; |
57 | ExternalViewEmbedder* view_embedder; |
58 | LayerStateStack& state_stack; |
59 | SkColorSpace* dst_color_space; |
60 | bool surface_needs_readback; |
61 | |
62 | // These allow us to paint in the end of subtree Preroll. |
63 | const Stopwatch& raster_time; |
64 | const Stopwatch& ui_time; |
65 | std::shared_ptr<TextureRegistry> texture_registry; |
66 | |
67 | // These allow us to track properties like elevation, opacity, and the |
68 | // presence of a platform view during Preroll. |
69 | bool has_platform_view = false; |
70 | // These allow us to track properties like elevation, opacity, and the |
71 | // presence of a texture layer during Preroll. |
72 | bool has_texture_layer = false; |
73 | |
74 | bool impeller_enabled = false; |
75 | |
76 | // The list of flags that describe which rendering state attributes |
77 | // (such as opacity, ColorFilter, ImageFilter) a given layer can |
78 | // render itself without requiring the parent to perform a protective |
79 | // saveLayer with those attributes. |
80 | // For containers, the flags will be set to the intersection (logical |
81 | // and) of all of the state bits that all of the children can render |
82 | // or to 0 if some of the children overlap and, as such, cannot apply |
83 | // those attributes individually and separately. |
84 | int renderable_state_flags = 0; |
85 | |
86 | std::vector<RasterCacheItem*>* raster_cached_entries; |
87 | }; |
88 | |
89 | struct PaintContext { |
90 | // When splitting the scene into multiple canvases (e.g when embedding |
91 | // a platform view on iOS) during the paint traversal we apply any state |
92 | // changes which affect children (i.e. saveLayer attributes) to the |
93 | // state_stack and any local rendering state changes for leaf layers to |
94 | // the canvas or builder. |
95 | // When we switch a canvas or builder (when painting a PlatformViewLayer) |
96 | // the new canvas receives all of the stateful changes from the state_stack |
97 | // to put it into the exact same state that the outgoing canvas had at the |
98 | // time it was swapped out. |
99 | // The state stack lazily applies saveLayer calls to its current canvas, |
100 | // allowing leaf layers to report that they can handle rendering some of |
101 | // its state attributes themselves via the |applyState| method. |
102 | LayerStateStack& state_stack; |
103 | DlCanvas* canvas; |
104 | |
105 | // Whether current canvas is an overlay canvas. Used to determine if the |
106 | // raster cache is painting to a surface that will be displayed above a |
107 | // platform view, in which case it will attempt to preserve the R-Tree. |
108 | bool rendering_above_platform_view = false; |
109 | |
110 | GrDirectContext* gr_context; |
111 | SkColorSpace* dst_color_space; |
112 | ExternalViewEmbedder* view_embedder; |
113 | const Stopwatch& raster_time; |
114 | const Stopwatch& ui_time; |
115 | std::shared_ptr<TextureRegistry> texture_registry; |
116 | const RasterCache* raster_cache; |
117 | |
118 | // Snapshot store to collect leaf layer snapshots. The store is non-null |
119 | // only when leaf layer tracing is enabled. |
120 | LayerSnapshotStore* layer_snapshot_store = nullptr; |
121 | bool enable_leaf_layer_tracing = false; |
122 | bool impeller_enabled = false; |
123 | impeller::AiksContext* aiks_context; |
124 | }; |
125 | |
126 | // Represents a single composited layer. Created on the UI thread but then |
127 | // subsequently used on the Rasterizer thread. |
128 | class Layer { |
129 | public: |
130 | // The state attribute flags that represent which attributes a |
131 | // layer can render if it plans to use a saveLayer call in its |
132 | // |Paint| method. |
133 | static constexpr int kSaveLayerRenderFlags = |
134 | LayerStateStack::kCallerCanApplyOpacity | |
135 | LayerStateStack::kCallerCanApplyColorFilter | |
136 | LayerStateStack::kCallerCanApplyImageFilter; |
137 | |
138 | // The state attribute flags that represent which attributes a |
139 | // layer can render if it will be rendering its content/children |
140 | // from a cached representation. |
141 | static constexpr int kRasterCacheRenderFlags = |
142 | LayerStateStack::kCallerCanApplyOpacity; |
143 | |
144 | Layer(); |
145 | virtual ~Layer(); |
146 | |
147 | void AssignOldLayer(Layer* old_layer) { |
148 | original_layer_id_ = old_layer->original_layer_id_; |
149 | } |
150 | |
151 | // Used to establish link between old layer and new layer that replaces it. |
152 | // If this method returns true, it is assumed that this layer replaces the old |
153 | // layer in tree and is able to diff with it. |
154 | virtual bool IsReplacing(DiffContext* context, const Layer* old_layer) const { |
155 | return original_layer_id_ == old_layer->original_layer_id_; |
156 | } |
157 | |
158 | // Performs diff with given layer |
159 | virtual void Diff(DiffContext* context, const Layer* old_layer) {} |
160 | |
161 | // Used when diffing retained layer; In case the layer is identical, it |
162 | // doesn't need to be diffed, but the paint region needs to be stored in diff |
163 | // context so that it can be used in next frame |
164 | virtual void PreservePaintRegion(DiffContext* context) { |
165 | // retained layer means same instance so 'this' is used to index into both |
166 | // current and old region |
167 | context->SetLayerPaintRegion(layer: this, region: context->GetOldLayerPaintRegion(layer: this)); |
168 | } |
169 | |
170 | virtual void Preroll(PrerollContext* context) = 0; |
171 | |
172 | // Used during Preroll by layers that employ a saveLayer to manage the |
173 | // PrerollContext settings with values affected by the saveLayer mechanism. |
174 | // This object must be created before calling Preroll on the children to |
175 | // set up the state for the children and then restore the state upon |
176 | // destruction. |
177 | class AutoPrerollSaveLayerState { |
178 | public: |
179 | [[nodiscard]] static AutoPrerollSaveLayerState Create( |
180 | PrerollContext* preroll_context, |
181 | bool save_layer_is_active = true, |
182 | bool layer_itself_performs_readback = false); |
183 | |
184 | ~AutoPrerollSaveLayerState(); |
185 | |
186 | private: |
187 | AutoPrerollSaveLayerState(PrerollContext* preroll_context, |
188 | bool save_layer_is_active, |
189 | bool layer_itself_performs_readback); |
190 | |
191 | PrerollContext* preroll_context_; |
192 | bool save_layer_is_active_; |
193 | bool layer_itself_performs_readback_; |
194 | |
195 | bool prev_surface_needs_readback_; |
196 | }; |
197 | |
198 | virtual void Paint(PaintContext& context) const = 0; |
199 | |
200 | virtual void PaintChildren(PaintContext& context) const { FML_DCHECK(false); } |
201 | |
202 | bool subtree_has_platform_view() const { return subtree_has_platform_view_; } |
203 | void set_subtree_has_platform_view(bool value) { |
204 | subtree_has_platform_view_ = value; |
205 | } |
206 | |
207 | // Returns the paint bounds in the layer's local coordinate system |
208 | // as determined during Preroll(). The bounds should include any |
209 | // transform, clip or distortions performed by the layer itself, |
210 | // but not any similar modifications inherited from its ancestors. |
211 | const SkRect& paint_bounds() const { return paint_bounds_; } |
212 | |
213 | // This must be set by the time Preroll() returns otherwise the layer will |
214 | // be assumed to have empty paint bounds (paints no content). |
215 | // The paint bounds should be independent of the context outside of this |
216 | // layer as the layer may be painted under different conditions than |
217 | // the Preroll context. The most common example of this condition is |
218 | // that we might Preroll the layer with a cull_rect established by a |
219 | // clip layer above it but then we might be asked to paint anyway if |
220 | // another layer above us needs to cache its children. During the |
221 | // paint operation that arises due to the caching, the clip will |
222 | // be the bounds of the layer needing caching, not the cull_rect |
223 | // that we saw in the overall Preroll operation. |
224 | void set_paint_bounds(const SkRect& paint_bounds) { |
225 | paint_bounds_ = paint_bounds; |
226 | } |
227 | |
228 | // Determines if the layer has any content. |
229 | bool is_empty() const { return paint_bounds_.isEmpty(); } |
230 | |
231 | // Determines if the Paint() method is necessary based on the properties |
232 | // of the indicated PaintContext object. |
233 | bool needs_painting(PaintContext& context) const { |
234 | if (subtree_has_platform_view_) { |
235 | // Workaround for the iOS embedder. The iOS embedder expects that |
236 | // if we preroll it, then we will later call its Paint() method. |
237 | // Now that we preroll all layers without any culling, we may |
238 | // call its Preroll() without calling its Paint(). For now, we |
239 | // will not perform paint culling on any subtree that has a |
240 | // platform view. |
241 | // See https://github.com/flutter/flutter/issues/81419 |
242 | return true; |
243 | } |
244 | return !context.state_stack.painting_is_nop() && |
245 | !context.state_stack.content_culled(content_bounds: paint_bounds_); |
246 | } |
247 | |
248 | // Propagated unique_id of the first layer in "chain" of replacement layers |
249 | // that can be diffed. |
250 | uint64_t original_layer_id() const { return original_layer_id_; } |
251 | |
252 | uint64_t unique_id() const { return unique_id_; } |
253 | |
254 | virtual RasterCacheKeyID caching_key_id() const { |
255 | return RasterCacheKeyID(unique_id_, RasterCacheKeyType::kLayer); |
256 | } |
257 | virtual const ContainerLayer* as_container_layer() const { return nullptr; } |
258 | virtual const DisplayListLayer* as_display_list_layer() const { |
259 | return nullptr; |
260 | } |
261 | virtual const TextureLayer* as_texture_layer() const { return nullptr; } |
262 | virtual const PerformanceOverlayLayer* as_performance_overlay_layer() const { |
263 | return nullptr; |
264 | } |
265 | virtual const testing::MockLayer* as_mock_layer() const { return nullptr; } |
266 | |
267 | private: |
268 | SkRect paint_bounds_; |
269 | uint64_t unique_id_; |
270 | uint64_t original_layer_id_; |
271 | bool subtree_has_platform_view_; |
272 | |
273 | static uint64_t NextUniqueID(); |
274 | |
275 | FML_DISALLOW_COPY_AND_ASSIGN(Layer); |
276 | }; |
277 | |
278 | } // namespace flutter |
279 | |
280 | #endif // FLUTTER_FLOW_LAYERS_LAYER_H_ |
281 | |