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
37namespace flutter {
38
39static void SceneBuilder_constructor(Dart_NativeArguments args) {
40 UIDartState::ThrowIfUIOperationsProhibited();
41 DartCallConstructor(&SceneBuilder::create, args);
42}
43
44IMPLEMENT_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
69FOR_EACH_BINDING(DART_NATIVE_CALLBACK)
70#if defined(LEGACY_FUCHSIA_EMBEDDER)
71DART_NATIVE_CALLBACK(SceneBuilder, addChildScene)
72#endif
73
74void 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
84SceneBuilder::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
90SceneBuilder::~SceneBuilder() = default;
91
92void 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
102void 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
109void 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
123void 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
133void 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
144void 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
154void 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
162void 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
170void 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
177void 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
192void 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
206void SceneBuilder::addRetained(fml::RefPtr<EngineLayer> retainedLayer) {
207 AddLayer(retainedLayer->Layer());
208}
209
210void SceneBuilder::pop() {
211 PopLayer();
212}
213
214void 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
227void 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
240void 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)
251void 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
264void 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
276void SceneBuilder::setRasterizerTracingThreshold(uint32_t frameInterval) {
277 rasterizer_tracing_threshold_ = frameInterval;
278}
279
280void SceneBuilder::setCheckerboardRasterCacheImages(bool checkerboard) {
281 checkerboard_raster_cache_images_ = checkerboard;
282}
283
284void SceneBuilder::setCheckerboardOffscreenLayers(bool checkerboard) {
285 checkerboard_offscreen_layers_ = checkerboard;
286}
287
288void 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
297void 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
305void SceneBuilder::PushLayer(std::shared_ptr<ContainerLayer> layer) {
306 AddLayer(layer);
307 layer_stack_.push_back(std::move(layer));
308}
309
310void 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