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
32namespace flutter {
33
34IMPLEMENT_WRAPPERTYPEINFO(ui, SceneBuilder);
35
36SceneBuilder::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
42SceneBuilder::~SceneBuilder() = default;
43
44void 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
59void 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
73void 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
93void 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
108void 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
124void 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
139void 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
152void 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
167void 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
182void 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
205void SceneBuilder::addRetained(const fml::RefPtr<EngineLayer>& retainedLayer) {
206 AddLayer(layer: retainedLayer->Layer());
207}
208
209void SceneBuilder::pop() {
210 PopLayer();
211}
212
213void 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
232void 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
247void 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
258void 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
271void SceneBuilder::setRasterizerTracingThreshold(uint32_t frameInterval) {
272 rasterizer_tracing_threshold_ = frameInterval;
273}
274
275void SceneBuilder::setCheckerboardRasterCacheImages(bool checkerboard) {
276 checkerboard_raster_cache_images_ = checkerboard;
277}
278
279void SceneBuilder::setCheckerboardOffscreenLayers(bool checkerboard) {
280 checkerboard_offscreen_layers_ = checkerboard;
281}
282
283void 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
293void 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
301void SceneBuilder::PushLayer(std::shared_ptr<ContainerLayer> layer) {
302 AddLayer(layer);
303 layer_stack_.push_back(x: std::move(layer));
304}
305
306void 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

source code of flutter_engine/flutter/lib/ui/compositing/scene_builder.cc