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/flow/embedded_views.h"
12#include "flutter/flow/instrumentation.h"
13#include "flutter/flow/raster_cache.h"
14#include "flutter/flow/texture.h"
15#include "flutter/fml/build_config.h"
16#include "flutter/fml/compiler_specific.h"
17#include "flutter/fml/logging.h"
18#include "flutter/fml/macros.h"
19#include "flutter/fml/trace_event.h"
20#include "third_party/skia/include/core/SkCanvas.h"
21#include "third_party/skia/include/core/SkColor.h"
22#include "third_party/skia/include/core/SkColorFilter.h"
23#include "third_party/skia/include/core/SkMatrix.h"
24#include "third_party/skia/include/core/SkPath.h"
25#include "third_party/skia/include/core/SkPicture.h"
26#include "third_party/skia/include/core/SkRRect.h"
27#include "third_party/skia/include/core/SkRect.h"
28#include "third_party/skia/include/utils/SkNWayCanvas.h"
29
30#if defined(LEGACY_FUCHSIA_EMBEDDER)
31
32#include "flutter/flow/scene_update_context.h" //nogncheck
33#include "lib/ui/scenic/cpp/resources.h" //nogncheck
34#include "lib/ui/scenic/cpp/session.h" //nogncheck
35
36#endif
37
38namespace flutter {
39
40static constexpr SkRect kGiantRect = SkRect::MakeLTRB(-1E9F, -1E9F, 1E9F, 1E9F);
41
42// This should be an exact copy of the Clip enum in painting.dart.
43enum Clip { none, hardEdge, antiAlias, antiAliasWithSaveLayer };
44
45struct PrerollContext {
46 RasterCache* raster_cache;
47 GrDirectContext* gr_context;
48 ExternalViewEmbedder* view_embedder;
49 MutatorsStack& mutators_stack;
50 SkColorSpace* dst_color_space;
51 SkRect cull_rect;
52 bool surface_needs_readback;
53
54 // These allow us to paint in the end of subtree Preroll.
55 const Stopwatch& raster_time;
56 const Stopwatch& ui_time;
57 TextureRegistry& texture_registry;
58 const bool checkerboard_offscreen_layers;
59 const float frame_device_pixel_ratio;
60
61 // These allow us to track properties like elevation, opacity, and the
62 // prescence of a platform view during Preroll.
63 bool has_platform_view = false;
64 bool is_opaque = true;
65#if defined(LEGACY_FUCHSIA_EMBEDDER)
66 // True if, during the traversal so far, we have seen a child_scene_layer.
67 // Informs whether a layer needs to be system composited.
68 bool child_scene_layer_exists_below = false;
69#endif
70};
71
72// Represents a single composited layer. Created on the UI thread but then
73// subquently used on the Rasterizer thread.
74class Layer {
75 public:
76 Layer();
77 virtual ~Layer();
78
79 virtual void Preroll(PrerollContext* context, const SkMatrix& matrix);
80
81 // Used during Preroll by layers that employ a saveLayer to manage the
82 // PrerollContext settings with values affected by the saveLayer mechanism.
83 // This object must be created before calling Preroll on the children to
84 // set up the state for the children and then restore the state upon
85 // destruction.
86 class AutoPrerollSaveLayerState {
87 public:
88 [[nodiscard]] static AutoPrerollSaveLayerState Create(
89 PrerollContext* preroll_context,
90 bool save_layer_is_active = true,
91 bool layer_itself_performs_readback = false);
92
93 ~AutoPrerollSaveLayerState();
94
95 private:
96 AutoPrerollSaveLayerState(PrerollContext* preroll_context,
97 bool save_layer_is_active,
98 bool layer_itself_performs_readback);
99
100 PrerollContext* preroll_context_;
101 bool save_layer_is_active_;
102 bool layer_itself_performs_readback_;
103
104 bool prev_surface_needs_readback_;
105 };
106
107 struct PaintContext {
108 // When splitting the scene into multiple canvases (e.g when embedding
109 // a platform view on iOS) during the paint traversal we apply the non leaf
110 // flow layers to all canvases, and leaf layers just to the "current"
111 // canvas. Applying the non leaf layers to all canvases ensures that when
112 // we switch a canvas (when painting a PlatformViewLayer) the next canvas
113 // has the exact same state as the current canvas.
114 // The internal_nodes_canvas is a SkNWayCanvas which is used by non leaf
115 // and applies the operations to all canvases.
116 // The leaf_nodes_canvas is the "current" canvas and is used by leaf
117 // layers.
118 SkCanvas* internal_nodes_canvas;
119 SkCanvas* leaf_nodes_canvas;
120 GrDirectContext* gr_context;
121 ExternalViewEmbedder* view_embedder;
122 const Stopwatch& raster_time;
123 const Stopwatch& ui_time;
124 TextureRegistry& texture_registry;
125 const RasterCache* raster_cache;
126 const bool checkerboard_offscreen_layers;
127 const float frame_device_pixel_ratio;
128 };
129
130 // Calls SkCanvas::saveLayer and restores the layer upon destruction. Also
131 // draws a checkerboard over the layer if that is enabled in the PaintContext.
132 class AutoSaveLayer {
133 public:
134 [[nodiscard]] static AutoSaveLayer Create(const PaintContext& paint_context,
135 const SkRect& bounds,
136 const SkPaint* paint);
137
138 [[nodiscard]] static AutoSaveLayer Create(
139 const PaintContext& paint_context,
140 const SkCanvas::SaveLayerRec& layer_rec);
141
142 ~AutoSaveLayer();
143
144 private:
145 AutoSaveLayer(const PaintContext& paint_context,
146 const SkRect& bounds,
147 const SkPaint* paint);
148
149 AutoSaveLayer(const PaintContext& paint_context,
150 const SkCanvas::SaveLayerRec& layer_rec);
151
152 const PaintContext& paint_context_;
153 const SkRect bounds_;
154 };
155
156 virtual void Paint(PaintContext& context) const = 0;
157
158#if defined(LEGACY_FUCHSIA_EMBEDDER)
159 // Updates the system composited scene.
160 virtual void UpdateScene(SceneUpdateContext& context);
161 virtual void CheckForChildLayerBelow(PrerollContext* context);
162#endif
163
164 bool needs_system_composite() const { return needs_system_composite_; }
165 void set_needs_system_composite(bool value) {
166 needs_system_composite_ = value;
167 }
168
169 const SkRect& paint_bounds() const { return paint_bounds_; }
170
171 // This must be set by the time Preroll() returns otherwise the layer will
172 // be assumed to have empty paint bounds (paints no content).
173 void set_paint_bounds(const SkRect& paint_bounds) {
174 paint_bounds_ = paint_bounds;
175 }
176
177 bool needs_painting() const { return !paint_bounds_.isEmpty(); }
178
179 uint64_t unique_id() const { return unique_id_; }
180
181 protected:
182#if defined(LEGACY_FUCHSIA_EMBEDDER)
183 bool child_layer_exists_below_ = false;
184#endif
185
186 private:
187 SkRect paint_bounds_;
188 uint64_t unique_id_;
189 bool needs_system_composite_;
190
191 static uint64_t NextUniqueID();
192
193 FML_DISALLOW_COPY_AND_ASSIGN(Layer);
194};
195
196} // namespace flutter
197
198#endif // FLUTTER_FLOW_LAYERS_LAYER_H_
199