Flutter Engine
layer.h
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 #ifndef FLUTTER_FLOW_LAYERS_LAYER_H_
6 #define FLUTTER_FLOW_LAYERS_LAYER_H_
7 
8 #include <memory>
9 #include <vector>
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/raster_cache.h"
16 #include "flutter/fml/build_config.h"
17 #include "flutter/fml/compiler_specific.h"
18 #include "flutter/fml/logging.h"
19 #include "flutter/fml/macros.h"
20 #include "flutter/fml/trace_event.h"
21 #include "third_party/skia/include/core/SkCanvas.h"
22 #include "third_party/skia/include/core/SkColor.h"
23 #include "third_party/skia/include/core/SkColorFilter.h"
24 #include "third_party/skia/include/core/SkMatrix.h"
25 #include "third_party/skia/include/core/SkPath.h"
26 #include "third_party/skia/include/core/SkPicture.h"
27 #include "third_party/skia/include/core/SkRRect.h"
28 #include "third_party/skia/include/core/SkRect.h"
29 #include "third_party/skia/include/utils/SkNWayCanvas.h"
30 
31 namespace flutter {
32 
33 namespace testing {
34 class MockLayer;
35 } // namespace testing
36 
37 static constexpr SkRect kGiantRect = SkRect::MakeLTRB(-1E9F, -1E9F, 1E9F, 1E9F);
38 
39 // This should be an exact copy of the Clip enum in painting.dart.
41 
44  GrDirectContext* gr_context;
47  SkColorSpace* dst_color_space;
48  SkRect cull_rect;
50 
51  // These allow us to paint in the end of subtree Preroll.
57 
58  // These allow us to track properties like elevation, opacity, and the
59  // prescence of a platform view during Preroll.
60  bool has_platform_view = false;
61  // These allow us to track properties like elevation, opacity, and the
62  // prescence of a texture layer during Preroll.
63  bool has_texture_layer = false;
64 };
65 
66 class PictureLayer;
67 class DisplayListLayer;
69 class TextureLayer;
70 
71 // Represents a single composited layer. Created on the UI thread but then
72 // subquently used on the Rasterizer thread.
73 class Layer {
74  public:
75  Layer();
76  virtual ~Layer();
77 
78  void AssignOldLayer(Layer* old_layer) {
79  original_layer_id_ = old_layer->original_layer_id_;
80  }
81 
82 #ifdef FLUTTER_ENABLE_DIFF_CONTEXT
83 
84  // Used to establish link between old layer and new layer that replaces it.
85  // If this method returns true, it is assumed that this layer replaces the old
86  // layer in tree and is able to diff with it.
87  virtual bool IsReplacing(DiffContext* context, const Layer* old_layer) const {
88  return original_layer_id_ == old_layer->original_layer_id_;
89  }
90 
91  // Performs diff with given layer
92  virtual void Diff(DiffContext* context, const Layer* old_layer) {}
93 
94  // Used when diffing retained layer; In case the layer is identical, it
95  // doesn't need to be diffed, but the paint region needs to be stored in diff
96  // context so that it can be used in next frame
97  virtual void PreservePaintRegion(DiffContext* context) {
98  // retained layer means same instance so 'this' is used to index into both
99  // current and old region
100  context->SetLayerPaintRegion(this, context->GetOldLayerPaintRegion(this));
101  }
102 
103 #endif // FLUTTER_ENABLE_DIFF_CONTEXT
104 
105  virtual void Preroll(PrerollContext* context, const SkMatrix& matrix);
106 
107  // Used during Preroll by layers that employ a saveLayer to manage the
108  // PrerollContext settings with values affected by the saveLayer mechanism.
109  // This object must be created before calling Preroll on the children to
110  // set up the state for the children and then restore the state upon
111  // destruction.
113  public:
114  [[nodiscard]] static AutoPrerollSaveLayerState Create(
115  PrerollContext* preroll_context,
116  bool save_layer_is_active = true,
117  bool layer_itself_performs_readback = false);
118 
120 
121  private:
122  AutoPrerollSaveLayerState(PrerollContext* preroll_context,
123  bool save_layer_is_active,
124  bool layer_itself_performs_readback);
125 
126  PrerollContext* preroll_context_;
127  bool save_layer_is_active_;
128  bool layer_itself_performs_readback_;
129 
130  bool prev_surface_needs_readback_;
131  };
132 
133  struct PaintContext {
134  // When splitting the scene into multiple canvases (e.g when embedding
135  // a platform view on iOS) during the paint traversal we apply the non leaf
136  // flow layers to all canvases, and leaf layers just to the "current"
137  // canvas. Applying the non leaf layers to all canvases ensures that when
138  // we switch a canvas (when painting a PlatformViewLayer) the next canvas
139  // has the exact same state as the current canvas.
140  // The internal_nodes_canvas is a SkNWayCanvas which is used by non leaf
141  // and applies the operations to all canvases.
142  // The leaf_nodes_canvas is the "current" canvas and is used by leaf
143  // layers.
145  SkCanvas* leaf_nodes_canvas;
146  GrDirectContext* gr_context;
154  };
155 
156  // Calls SkCanvas::saveLayer and restores the layer upon destruction. Also
157  // draws a checkerboard over the layer if that is enabled in the PaintContext.
159  public:
160  // Indicates which canvas the layer should be saved on.
161  //
162  // Usually layers are saved on the internal_nodes_canvas, so that all
163  // the canvas keep track of the current state of the layer tree.
164  // In some special cases, layers should only save on the leaf_nodes_canvas,
165  // See https:://flutter.dev/go/backdrop-filter-with-overlay-canvas for why
166  // it is the case for Backdrop filter layer.
167  enum SaveMode {
168  // The layer is saved on the internal_nodes_canvas.
170  // The layer is saved on the leaf_nodes_canvas.
171  kLeafNodesCanvas
172  };
173 
174  // Create a layer and save it on the canvas.
175  //
176  // The layer is restored from the canvas in destructor.
177  //
178  // By default, the layer is saved on and restored from
179  // `internal_nodes_canvas`. The `save_mode` parameter can be modified to
180  // save the layer on other canvases.
181  [[nodiscard]] static AutoSaveLayer Create(
182  const PaintContext& paint_context,
183  const SkRect& bounds,
184  const SkPaint* paint,
185  SaveMode save_mode = SaveMode::kInternalNodesCanvas);
186  // Create a layer and save it on the canvas.
187  //
188  // The layer is restored from the canvas in destructor.
189  //
190  // By default, the layer is saved on and restored from
191  // `internal_nodes_canvas`. The `save_mode` parameter can be modified to
192  // save the layer on other canvases.
193  [[nodiscard]] static AutoSaveLayer Create(
194  const PaintContext& paint_context,
195  const SkCanvas::SaveLayerRec& layer_rec,
196  SaveMode save_mode = SaveMode::kInternalNodesCanvas);
197 
198  ~AutoSaveLayer();
199 
200  private:
201  AutoSaveLayer(const PaintContext& paint_context,
202  const SkRect& bounds,
203  const SkPaint* paint,
204  SaveMode save_mode = SaveMode::kInternalNodesCanvas);
205 
206  AutoSaveLayer(const PaintContext& paint_context,
207  const SkCanvas::SaveLayerRec& layer_rec,
208  SaveMode save_mode = SaveMode::kInternalNodesCanvas);
209 
210  const PaintContext& paint_context_;
211  const SkRect bounds_;
212  // The canvas that this layer is saved on and popped from.
213  SkCanvas& canvas_;
214  };
215 
216  virtual void Paint(PaintContext& context) const = 0;
217 
218  bool subtree_has_platform_view() const { return subtree_has_platform_view_; }
220  subtree_has_platform_view_ = value;
221  }
222 
223  // Returns the paint bounds in the layer's local coordinate system
224  // as determined during Preroll(). The bounds should include any
225  // transform, clip or distortions performed by the layer itself,
226  // but not any similar modifications inherited from its ancestors.
227  const SkRect& paint_bounds() const { return paint_bounds_; }
228 
229  // This must be set by the time Preroll() returns otherwise the layer will
230  // be assumed to have empty paint bounds (paints no content).
231  // The paint bounds should be independent of the context outside of this
232  // layer as the layer may be painted under different conditions than
233  // the Preroll context. The most common example of this condition is
234  // that we might Preroll the layer with a cull_rect established by a
235  // clip layer above it but then we might be asked to paint anyway if
236  // another layer above us needs to cache its children. During the
237  // paint operation that arises due to the caching, the clip will
238  // be the bounds of the layer needing caching, not the cull_rect
239  // that we saw in the overall Preroll operation.
240  void set_paint_bounds(const SkRect& paint_bounds) {
241  paint_bounds_ = paint_bounds;
242  }
243 
244  // Determines if the layer has any content.
245  bool is_empty() const { return paint_bounds_.isEmpty(); }
246 
247  // Determines if the Paint() method is necessary based on the properties
248  // of the indicated PaintContext object.
249  bool needs_painting(PaintContext& context) const {
250  if (subtree_has_platform_view_) {
251  // Workaround for the iOS embedder. The iOS embedder expects that
252  // if we preroll it, then we will later call its Paint() method.
253  // Now that we preroll all layers without any culling, we may
254  // call its Preroll() without calling its Paint(). For now, we
255  // will not perform paint culling on any subtree that has a
256  // platform view.
257  // See https://github.com/flutter/flutter/issues/81419
258  return true;
259  }
260  // Workaround for Skia bug (quickReject does not reject empty bounds).
261  // https://bugs.chromium.org/p/skia/issues/detail?id=10951
262  if (paint_bounds_.isEmpty()) {
263  return false;
264  }
265  return !context.leaf_nodes_canvas->quickReject(paint_bounds_);
266  }
267 
268  // Propagated unique_id of the first layer in "chain" of replacement layers
269  // that can be diffed.
270  uint64_t original_layer_id() const { return original_layer_id_; }
271 
272  uint64_t unique_id() const { return unique_id_; }
273 
274 #ifdef FLUTTER_ENABLE_DIFF_CONTEXT
275 
276  virtual const PictureLayer* as_picture_layer() const { return nullptr; }
277  virtual const DisplayListLayer* as_display_list_layer() const {
278  return nullptr;
279  }
280  virtual const TextureLayer* as_texture_layer() const { return nullptr; }
281  virtual const PerformanceOverlayLayer* as_performance_overlay_layer() const {
282  return nullptr;
283  }
284  virtual const testing::MockLayer* as_mock_layer() const { return nullptr; }
285 
286 #endif // FLUTTER_ENABLE_DIFF_CONTEXT
287 
288  private:
289  SkRect paint_bounds_;
290  uint64_t unique_id_;
291  uint64_t original_layer_id_;
292  bool subtree_has_platform_view_;
293 
294  static uint64_t NextUniqueID();
295 
297 };
298 
299 } // namespace flutter
300 
301 #endif // FLUTTER_FLOW_LAYERS_LAYER_H_
const Stopwatch & ui_time
Definition: layer.h:53
void set_subtree_has_platform_view(bool value)
Definition: layer.h:219
ExternalViewEmbedder * view_embedder
Definition: layer.h:147
const Stopwatch & ui_time
Definition: layer.h:149
TextureRegistry & texture_registry
Definition: layer.h:150
GrDirectContext * gr_context
Definition: layer.h:44
const bool checkerboard_offscreen_layers
Definition: layer.h:152
const Stopwatch & raster_time
Definition: layer.h:52
bool is_empty() const
Definition: layer.h:245
static constexpr SkRect kGiantRect
Definition: layer.h:37
GrDirectContext * gr_context
Definition: layer.h:146
bool needs_painting(PaintContext &context) const
Definition: layer.h:249
const Stopwatch & raster_time
Definition: layer.h:148
void AssignOldLayer(Layer *old_layer)
Definition: layer.h:78
TextureRegistry & texture_registry
Definition: layer.h:54
const RasterCache * raster_cache
Definition: layer.h:151
uint8_t value
const bool checkerboard_offscreen_layers
Definition: layer.h:55
const float frame_device_pixel_ratio
Definition: layer.h:153
SkColorSpace * dst_color_space
Definition: layer.h:47
const SkRect & paint_bounds() const
Definition: layer.h:227
const float frame_device_pixel_ratio
Definition: layer.h:56
SkCanvas * leaf_nodes_canvas
Definition: layer.h:145
void set_paint_bounds(const SkRect &paint_bounds)
Definition: layer.h:240
uint64_t unique_id() const
Definition: layer.h:272
Clip
Definition: layer.h:40
RasterCache * raster_cache
Definition: layer.h:43
SkCanvas * internal_nodes_canvas
Definition: layer.h:144
ExternalViewEmbedder * view_embedder
Definition: layer.h:45
bool surface_needs_readback
Definition: layer.h:49
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: macros.h:27
uint64_t original_layer_id() const
Definition: layer.h:270
MutatorsStack & mutators_stack
Definition: layer.h:46
bool subtree_has_platform_view() const
Definition: layer.h:218