• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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