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
35class GrDirectContext;
36
37namespace flutter {
38
39namespace testing {
40class MockLayer;
41} // namespace testing
42
43class ContainerLayer;
44class DisplayListLayer;
45class PerformanceOverlayLayer;
46class TextureLayer;
47class RasterCacheItem;
48
49static 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.
52enum Clip { none, hardEdge, antiAlias, antiAliasWithSaveLayer };
53
54struct 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
89struct 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.
128class 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

source code of flutter_engine/flutter/flow/layers/layer.h