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 | #include "flutter/lib/ui/compositing/scene_builder.h" |
6 | |
7 | #include "flutter/flow/layers/backdrop_filter_layer.h" |
8 | #include "flutter/flow/layers/clip_path_layer.h" |
9 | #include "flutter/flow/layers/clip_rect_layer.h" |
10 | #include "flutter/flow/layers/clip_rrect_layer.h" |
11 | #include "flutter/flow/layers/color_filter_layer.h" |
12 | #include "flutter/flow/layers/container_layer.h" |
13 | #include "flutter/flow/layers/display_list_layer.h" |
14 | #include "flutter/flow/layers/image_filter_layer.h" |
15 | #include "flutter/flow/layers/layer.h" |
16 | #include "flutter/flow/layers/layer_tree.h" |
17 | #include "flutter/flow/layers/opacity_layer.h" |
18 | #include "flutter/flow/layers/performance_overlay_layer.h" |
19 | #include "flutter/flow/layers/platform_view_layer.h" |
20 | #include "flutter/flow/layers/shader_mask_layer.h" |
21 | #include "flutter/flow/layers/texture_layer.h" |
22 | #include "flutter/flow/layers/transform_layer.h" |
23 | #include "flutter/fml/build_config.h" |
24 | #include "flutter/lib/ui/floating_point.h" |
25 | #include "flutter/lib/ui/painting/matrix.h" |
26 | #include "flutter/lib/ui/painting/shader.h" |
27 | #include "third_party/tonic/converter/dart_converter.h" |
28 | #include "third_party/tonic/dart_args.h" |
29 | #include "third_party/tonic/dart_binding_macros.h" |
30 | #include "third_party/tonic/dart_library_natives.h" |
31 | |
32 | namespace flutter { |
33 | |
34 | IMPLEMENT_WRAPPERTYPEINFO(ui, SceneBuilder); |
35 | |
36 | SceneBuilder::SceneBuilder() { |
37 | // Add a ContainerLayer as the root layer, so that AddLayer operations are |
38 | // always valid. |
39 | PushLayer(layer: std::make_shared<flutter::ContainerLayer>()); |
40 | } |
41 | |
42 | SceneBuilder::~SceneBuilder() = default; |
43 | |
44 | void SceneBuilder::pushTransform(Dart_Handle layer_handle, |
45 | tonic::Float64List& matrix4, |
46 | const fml::RefPtr<EngineLayer>& oldLayer) { |
47 | SkM44 sk_matrix = ToSkM44(matrix4); |
48 | auto layer = std::make_shared<flutter::TransformLayer>(args&: sk_matrix); |
49 | PushLayer(layer); |
50 | // matrix4 has to be released before we can return another Dart object |
51 | matrix4.Release(); |
52 | EngineLayer::MakeRetained(dart_handle: layer_handle, layer); |
53 | |
54 | if (oldLayer && oldLayer->Layer()) { |
55 | layer->AssignOldLayer(old_layer: oldLayer->Layer().get()); |
56 | } |
57 | } |
58 | |
59 | void SceneBuilder::pushOffset(Dart_Handle layer_handle, |
60 | double dx, |
61 | double dy, |
62 | const fml::RefPtr<EngineLayer>& oldLayer) { |
63 | SkMatrix sk_matrix = SkMatrix::Translate(dx: SafeNarrow(value: dx), dy: SafeNarrow(value: dy)); |
64 | auto layer = std::make_shared<flutter::TransformLayer>(args&: sk_matrix); |
65 | PushLayer(layer); |
66 | EngineLayer::MakeRetained(dart_handle: layer_handle, layer); |
67 | |
68 | if (oldLayer && oldLayer->Layer()) { |
69 | layer->AssignOldLayer(old_layer: oldLayer->Layer().get()); |
70 | } |
71 | } |
72 | |
73 | void SceneBuilder::pushClipRect(Dart_Handle layer_handle, |
74 | double left, |
75 | double right, |
76 | double top, |
77 | double bottom, |
78 | int clipBehavior, |
79 | const fml::RefPtr<EngineLayer>& oldLayer) { |
80 | SkRect clipRect = SkRect::MakeLTRB(l: SafeNarrow(value: left), t: SafeNarrow(value: top), |
81 | r: SafeNarrow(value: right), b: SafeNarrow(value: bottom)); |
82 | flutter::Clip clip_behavior = static_cast<flutter::Clip>(clipBehavior); |
83 | auto layer = |
84 | std::make_shared<flutter::ClipRectLayer>(args&: clipRect, args&: clip_behavior); |
85 | PushLayer(layer); |
86 | EngineLayer::MakeRetained(dart_handle: layer_handle, layer); |
87 | |
88 | if (oldLayer && oldLayer->Layer()) { |
89 | layer->AssignOldLayer(old_layer: oldLayer->Layer().get()); |
90 | } |
91 | } |
92 | |
93 | void SceneBuilder::pushClipRRect(Dart_Handle layer_handle, |
94 | const RRect& rrect, |
95 | int clipBehavior, |
96 | const fml::RefPtr<EngineLayer>& oldLayer) { |
97 | flutter::Clip clip_behavior = static_cast<flutter::Clip>(clipBehavior); |
98 | auto layer = |
99 | std::make_shared<flutter::ClipRRectLayer>(args: rrect.sk_rrect, args&: clip_behavior); |
100 | PushLayer(layer); |
101 | EngineLayer::MakeRetained(dart_handle: layer_handle, layer); |
102 | |
103 | if (oldLayer && oldLayer->Layer()) { |
104 | layer->AssignOldLayer(old_layer: oldLayer->Layer().get()); |
105 | } |
106 | } |
107 | |
108 | void SceneBuilder::pushClipPath(Dart_Handle layer_handle, |
109 | const CanvasPath* path, |
110 | int clipBehavior, |
111 | const fml::RefPtr<EngineLayer>& oldLayer) { |
112 | flutter::Clip clip_behavior = static_cast<flutter::Clip>(clipBehavior); |
113 | FML_DCHECK(clip_behavior != flutter::Clip::none); |
114 | auto layer = |
115 | std::make_shared<flutter::ClipPathLayer>(args: path->path(), args&: clip_behavior); |
116 | PushLayer(layer); |
117 | EngineLayer::MakeRetained(dart_handle: layer_handle, layer); |
118 | |
119 | if (oldLayer && oldLayer->Layer()) { |
120 | layer->AssignOldLayer(old_layer: oldLayer->Layer().get()); |
121 | } |
122 | } |
123 | |
124 | void SceneBuilder::pushOpacity(Dart_Handle layer_handle, |
125 | int alpha, |
126 | double dx, |
127 | double dy, |
128 | const fml::RefPtr<EngineLayer>& oldLayer) { |
129 | auto layer = std::make_shared<flutter::OpacityLayer>( |
130 | args&: alpha, args: SkPoint::Make(x: SafeNarrow(value: dx), y: SafeNarrow(value: dy))); |
131 | PushLayer(layer); |
132 | EngineLayer::MakeRetained(dart_handle: layer_handle, layer); |
133 | |
134 | if (oldLayer && oldLayer->Layer()) { |
135 | layer->AssignOldLayer(old_layer: oldLayer->Layer().get()); |
136 | } |
137 | } |
138 | |
139 | void SceneBuilder::pushColorFilter(Dart_Handle layer_handle, |
140 | const ColorFilter* color_filter, |
141 | const fml::RefPtr<EngineLayer>& oldLayer) { |
142 | auto layer = |
143 | std::make_shared<flutter::ColorFilterLayer>(args: color_filter->filter()); |
144 | PushLayer(layer); |
145 | EngineLayer::MakeRetained(dart_handle: layer_handle, layer); |
146 | |
147 | if (oldLayer && oldLayer->Layer()) { |
148 | layer->AssignOldLayer(old_layer: oldLayer->Layer().get()); |
149 | } |
150 | } |
151 | |
152 | void SceneBuilder::pushImageFilter(Dart_Handle layer_handle, |
153 | const ImageFilter* image_filter, |
154 | double dx, |
155 | double dy, |
156 | const fml::RefPtr<EngineLayer>& oldLayer) { |
157 | auto layer = std::make_shared<flutter::ImageFilterLayer>( |
158 | args: image_filter->filter(), args: SkPoint::Make(x: SafeNarrow(value: dx), y: SafeNarrow(value: dy))); |
159 | PushLayer(layer); |
160 | EngineLayer::MakeRetained(dart_handle: layer_handle, layer); |
161 | |
162 | if (oldLayer && oldLayer->Layer()) { |
163 | layer->AssignOldLayer(old_layer: oldLayer->Layer().get()); |
164 | } |
165 | } |
166 | |
167 | void SceneBuilder::pushBackdropFilter( |
168 | Dart_Handle layer_handle, |
169 | ImageFilter* filter, |
170 | int blendMode, |
171 | const fml::RefPtr<EngineLayer>& oldLayer) { |
172 | auto layer = std::make_shared<flutter::BackdropFilterLayer>( |
173 | args: filter->filter(), args: static_cast<DlBlendMode>(blendMode)); |
174 | PushLayer(layer); |
175 | EngineLayer::MakeRetained(dart_handle: layer_handle, layer); |
176 | |
177 | if (oldLayer && oldLayer->Layer()) { |
178 | layer->AssignOldLayer(old_layer: oldLayer->Layer().get()); |
179 | } |
180 | } |
181 | |
182 | void SceneBuilder::pushShaderMask(Dart_Handle layer_handle, |
183 | Shader* shader, |
184 | double maskRectLeft, |
185 | double maskRectRight, |
186 | double maskRectTop, |
187 | double maskRectBottom, |
188 | int blendMode, |
189 | int filterQualityIndex, |
190 | const fml::RefPtr<EngineLayer>& oldLayer) { |
191 | SkRect rect = |
192 | SkRect::MakeLTRB(l: SafeNarrow(value: maskRectLeft), t: SafeNarrow(value: maskRectTop), |
193 | r: SafeNarrow(value: maskRectRight), b: SafeNarrow(value: maskRectBottom)); |
194 | auto sampling = ImageFilter::SamplingFromIndex(filterQualityIndex); |
195 | auto layer = std::make_shared<flutter::ShaderMaskLayer>( |
196 | args: shader->shader(sampling), args&: rect, args: static_cast<DlBlendMode>(blendMode)); |
197 | PushLayer(layer); |
198 | EngineLayer::MakeRetained(dart_handle: layer_handle, layer); |
199 | |
200 | if (oldLayer && oldLayer->Layer()) { |
201 | layer->AssignOldLayer(old_layer: oldLayer->Layer().get()); |
202 | } |
203 | } |
204 | |
205 | void SceneBuilder::addRetained(const fml::RefPtr<EngineLayer>& retainedLayer) { |
206 | AddLayer(layer: retainedLayer->Layer()); |
207 | } |
208 | |
209 | void SceneBuilder::pop() { |
210 | PopLayer(); |
211 | } |
212 | |
213 | void SceneBuilder::addPicture(double dx, |
214 | double dy, |
215 | Picture* picture, |
216 | int hints) { |
217 | if (!picture) { |
218 | // Picture::dispose was called and it has been collected. |
219 | return; |
220 | } |
221 | |
222 | // Explicitly check for display_list, since the picture object might have |
223 | // been disposed but not collected yet, but the display list is null. |
224 | if (picture->display_list()) { |
225 | auto layer = std::make_unique<flutter::DisplayListLayer>( |
226 | args: SkPoint::Make(x: SafeNarrow(value: dx), y: SafeNarrow(value: dy)), args: picture->display_list(), |
227 | args: !!(hints & 1), args: !!(hints & 2)); |
228 | AddLayer(layer: std::move(layer)); |
229 | } |
230 | } |
231 | |
232 | void SceneBuilder::addTexture(double dx, |
233 | double dy, |
234 | double width, |
235 | double height, |
236 | int64_t textureId, |
237 | bool freeze, |
238 | int filterQualityIndex) { |
239 | auto sampling = ImageFilter::SamplingFromIndex(filterQualityIndex); |
240 | auto layer = std::make_unique<flutter::TextureLayer>( |
241 | args: SkPoint::Make(x: SafeNarrow(value: dx), y: SafeNarrow(value: dy)), |
242 | args: SkSize::Make(w: SafeNarrow(value: width), h: SafeNarrow(value: height)), args&: textureId, args&: freeze, |
243 | args&: sampling); |
244 | AddLayer(layer: std::move(layer)); |
245 | } |
246 | |
247 | void SceneBuilder::addPlatformView(double dx, |
248 | double dy, |
249 | double width, |
250 | double height, |
251 | int64_t viewId) { |
252 | auto layer = std::make_unique<flutter::PlatformViewLayer>( |
253 | args: SkPoint::Make(x: SafeNarrow(value: dx), y: SafeNarrow(value: dy)), |
254 | args: SkSize::Make(w: SafeNarrow(value: width), h: SafeNarrow(value: height)), args&: viewId); |
255 | AddLayer(layer: std::move(layer)); |
256 | } |
257 | |
258 | void SceneBuilder::addPerformanceOverlay(uint64_t enabledOptions, |
259 | double left, |
260 | double right, |
261 | double top, |
262 | double bottom) { |
263 | SkRect rect = SkRect::MakeLTRB(l: SafeNarrow(value: left), t: SafeNarrow(value: top), |
264 | r: SafeNarrow(value: right), b: SafeNarrow(value: bottom)); |
265 | auto layer = |
266 | std::make_unique<flutter::PerformanceOverlayLayer>(args&: enabledOptions); |
267 | layer->set_paint_bounds(rect); |
268 | AddLayer(layer: std::move(layer)); |
269 | } |
270 | |
271 | void SceneBuilder::setRasterizerTracingThreshold(uint32_t frameInterval) { |
272 | rasterizer_tracing_threshold_ = frameInterval; |
273 | } |
274 | |
275 | void SceneBuilder::setCheckerboardRasterCacheImages(bool checkerboard) { |
276 | checkerboard_raster_cache_images_ = checkerboard; |
277 | } |
278 | |
279 | void SceneBuilder::setCheckerboardOffscreenLayers(bool checkerboard) { |
280 | checkerboard_offscreen_layers_ = checkerboard; |
281 | } |
282 | |
283 | void SceneBuilder::build(Dart_Handle scene_handle) { |
284 | FML_DCHECK(layer_stack_.size() >= 1); |
285 | |
286 | Scene::create( |
287 | scene_handle, rootLayer: std::move(layer_stack_[0]), rasterizerTracingThreshold: rasterizer_tracing_threshold_, |
288 | checkerboardRasterCacheImages: checkerboard_raster_cache_images_, checkerboardOffscreenLayers: checkerboard_offscreen_layers_); |
289 | layer_stack_.clear(); |
290 | ClearDartWrapper(); // may delete this object. |
291 | } |
292 | |
293 | void SceneBuilder::AddLayer(std::shared_ptr<Layer> layer) { |
294 | FML_DCHECK(layer); |
295 | |
296 | if (!layer_stack_.empty()) { |
297 | layer_stack_.back()->Add(layer: std::move(layer)); |
298 | } |
299 | } |
300 | |
301 | void SceneBuilder::PushLayer(std::shared_ptr<ContainerLayer> layer) { |
302 | AddLayer(layer); |
303 | layer_stack_.push_back(x: std::move(layer)); |
304 | } |
305 | |
306 | void SceneBuilder::PopLayer() { |
307 | // We never pop the root layer, so that AddLayer operations are always valid. |
308 | if (layer_stack_.size() > 1) { |
309 | layer_stack_.pop_back(); |
310 | } |
311 | } |
312 | |
313 | } // namespace flutter |
314 | |