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