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