• 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/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