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