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