Flutter Engine
scene_builder.cc
Go to the documentation of this file.
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/display_list_layer.h"
14 #include "flutter/flow/layers/image_filter_layer.h"
15 #include "flutter/flow/layers/layer.h"
16 #include "flutter/flow/layers/layer_tree.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 "third_party/skia/include/core/SkColorFilter.h"
33 
34 namespace flutter {
35 
36 static void SceneBuilder_constructor(Dart_NativeArguments args) {
39 }
40 
42 
43 #define FOR_EACH_BINDING(V) \
44  V(SceneBuilder, pushOffset) \
45  V(SceneBuilder, pushTransform) \
46  V(SceneBuilder, pushClipRect) \
47  V(SceneBuilder, pushClipRRect) \
48  V(SceneBuilder, pushClipPath) \
49  V(SceneBuilder, pushOpacity) \
50  V(SceneBuilder, pushColorFilter) \
51  V(SceneBuilder, pushImageFilter) \
52  V(SceneBuilder, pushBackdropFilter) \
53  V(SceneBuilder, pushShaderMask) \
54  V(SceneBuilder, pushPhysicalShape) \
55  V(SceneBuilder, pop) \
56  V(SceneBuilder, addPlatformView) \
57  V(SceneBuilder, addRetained) \
58  V(SceneBuilder, addPicture) \
59  V(SceneBuilder, addTexture) \
60  V(SceneBuilder, addPerformanceOverlay) \
61  V(SceneBuilder, setRasterizerTracingThreshold) \
62  V(SceneBuilder, setCheckerboardOffscreenLayers) \
63  V(SceneBuilder, setCheckerboardRasterCacheImages) \
64  V(SceneBuilder, build)
65 
67 
68 void SceneBuilder::RegisterNatives(tonic::DartLibraryNatives* natives) {
69  natives->Register(
70  {{"SceneBuilder_constructor", SceneBuilder_constructor, 1, true},
72 }
73 
74 SceneBuilder::SceneBuilder() {
75  // Add a ContainerLayer as the root layer, so that AddLayer operations are
76  // always valid.
77  PushLayer(std::make_shared<flutter::ContainerLayer>());
78 }
79 
80 SceneBuilder::~SceneBuilder() = default;
81 
82 void SceneBuilder::pushTransform(Dart_Handle layer_handle,
83  tonic::Float64List& matrix4,
84  fml::RefPtr<EngineLayer> oldLayer) {
85  SkMatrix sk_matrix = ToSkMatrix(matrix4);
86  auto layer = std::make_shared<flutter::TransformLayer>(sk_matrix);
87  PushLayer(layer);
88  // matrix4 has to be released before we can return another Dart object
89  matrix4.Release();
90  EngineLayer::MakeRetained(layer_handle, layer);
91 
92  if (oldLayer && oldLayer->Layer()) {
93  layer->AssignOldLayer(oldLayer->Layer().get());
94  }
95 }
96 
97 void SceneBuilder::pushOffset(Dart_Handle layer_handle,
98  double dx,
99  double dy,
100  fml::RefPtr<EngineLayer> oldLayer) {
101  SkMatrix sk_matrix = SkMatrix::Translate(dx, dy);
102  auto layer = std::make_shared<flutter::TransformLayer>(sk_matrix);
103  PushLayer(layer);
104  EngineLayer::MakeRetained(layer_handle, layer);
105 
106  if (oldLayer && oldLayer->Layer()) {
107  layer->AssignOldLayer(oldLayer->Layer().get());
108  }
109 }
110 
111 void SceneBuilder::pushClipRect(Dart_Handle layer_handle,
112  double left,
113  double right,
114  double top,
115  double bottom,
116  int clipBehavior,
117  fml::RefPtr<EngineLayer> oldLayer) {
118  SkRect clipRect = SkRect::MakeLTRB(left, top, right, bottom);
119  flutter::Clip clip_behavior = static_cast<flutter::Clip>(clipBehavior);
120  auto layer =
121  std::make_shared<flutter::ClipRectLayer>(clipRect, clip_behavior);
122  PushLayer(layer);
123  EngineLayer::MakeRetained(layer_handle, layer);
124 
125  if (oldLayer && oldLayer->Layer()) {
126  layer->AssignOldLayer(oldLayer->Layer().get());
127  }
128 }
129 
130 void SceneBuilder::pushClipRRect(Dart_Handle layer_handle,
131  const RRect& rrect,
132  int clipBehavior,
133  fml::RefPtr<EngineLayer> oldLayer) {
134  flutter::Clip clip_behavior = static_cast<flutter::Clip>(clipBehavior);
135  auto layer =
136  std::make_shared<flutter::ClipRRectLayer>(rrect.sk_rrect, clip_behavior);
137  PushLayer(layer);
138  EngineLayer::MakeRetained(layer_handle, layer);
139 
140  if (oldLayer && oldLayer->Layer()) {
141  layer->AssignOldLayer(oldLayer->Layer().get());
142  }
143 }
144 
145 void SceneBuilder::pushClipPath(Dart_Handle layer_handle,
146  const CanvasPath* path,
147  int clipBehavior,
148  fml::RefPtr<EngineLayer> oldLayer) {
149  flutter::Clip clip_behavior = static_cast<flutter::Clip>(clipBehavior);
150  FML_DCHECK(clip_behavior != flutter::Clip::none);
151  auto layer =
152  std::make_shared<flutter::ClipPathLayer>(path->path(), clip_behavior);
153  PushLayer(layer);
154  EngineLayer::MakeRetained(layer_handle, layer);
155 
156  if (oldLayer && oldLayer->Layer()) {
157  layer->AssignOldLayer(oldLayer->Layer().get());
158  }
159 }
160 
161 void SceneBuilder::pushOpacity(Dart_Handle layer_handle,
162  int alpha,
163  double dx,
164  double dy,
165  fml::RefPtr<EngineLayer> oldLayer) {
166  auto layer =
167  std::make_shared<flutter::OpacityLayer>(alpha, SkPoint::Make(dx, dy));
168  PushLayer(layer);
169  EngineLayer::MakeRetained(layer_handle, layer);
170 
171  if (oldLayer && oldLayer->Layer()) {
172  layer->AssignOldLayer(oldLayer->Layer().get());
173  }
174 }
175 
176 void SceneBuilder::pushColorFilter(Dart_Handle layer_handle,
177  const ColorFilter* color_filter,
178  fml::RefPtr<EngineLayer> oldLayer) {
179  auto layer =
180  std::make_shared<flutter::ColorFilterLayer>(color_filter->filter());
181  PushLayer(layer);
182  EngineLayer::MakeRetained(layer_handle, layer);
183 
184  if (oldLayer && oldLayer->Layer()) {
185  layer->AssignOldLayer(oldLayer->Layer().get());
186  }
187 }
188 
189 void SceneBuilder::pushImageFilter(Dart_Handle layer_handle,
190  const ImageFilter* image_filter,
191  fml::RefPtr<EngineLayer> oldLayer) {
192  auto layer =
193  std::make_shared<flutter::ImageFilterLayer>(image_filter->filter());
194  PushLayer(layer);
195  EngineLayer::MakeRetained(layer_handle, layer);
196 
197  if (oldLayer && oldLayer->Layer()) {
198  layer->AssignOldLayer(oldLayer->Layer().get());
199  }
200 }
201 
202 void SceneBuilder::pushBackdropFilter(Dart_Handle layer_handle,
203  ImageFilter* filter,
204  int blendMode,
205  fml::RefPtr<EngineLayer> oldLayer) {
206  auto layer = std::make_shared<flutter::BackdropFilterLayer>(
207  filter->filter(), static_cast<SkBlendMode>(blendMode));
208  PushLayer(layer);
209  EngineLayer::MakeRetained(layer_handle, layer);
210 
211  if (oldLayer && oldLayer->Layer()) {
212  layer->AssignOldLayer(oldLayer->Layer().get());
213  }
214 }
215 
216 void SceneBuilder::pushShaderMask(Dart_Handle layer_handle,
217  Shader* shader,
218  double maskRectLeft,
219  double maskRectRight,
220  double maskRectTop,
221  double maskRectBottom,
222  int blendMode,
223  int filterQualityIndex,
224  fml::RefPtr<EngineLayer> oldLayer) {
225  SkRect rect = SkRect::MakeLTRB(maskRectLeft, maskRectTop, maskRectRight,
226  maskRectBottom);
227  auto sampling = ImageFilter::SamplingFromIndex(filterQualityIndex);
228  auto layer = std::make_shared<flutter::ShaderMaskLayer>(
229  shader->shader(sampling), rect, static_cast<SkBlendMode>(blendMode));
230  PushLayer(layer);
231  EngineLayer::MakeRetained(layer_handle, layer);
232 
233  if (oldLayer && oldLayer->Layer()) {
234  layer->AssignOldLayer(oldLayer->Layer().get());
235  }
236 }
237 
238 void SceneBuilder::pushPhysicalShape(Dart_Handle layer_handle,
239  const CanvasPath* path,
240  double elevation,
241  int color,
242  int shadow_color,
243  int clipBehavior,
244  fml::RefPtr<EngineLayer> oldLayer) {
245  auto layer = std::make_shared<flutter::PhysicalShapeLayer>(
246  static_cast<SkColor>(color), static_cast<SkColor>(shadow_color),
247  static_cast<float>(elevation), path->path(),
248  static_cast<flutter::Clip>(clipBehavior));
249  PushLayer(layer);
250  EngineLayer::MakeRetained(layer_handle, layer);
251 
252  if (oldLayer && oldLayer->Layer()) {
253  layer->AssignOldLayer(oldLayer->Layer().get());
254  }
255 }
256 
258  AddLayer(retainedLayer->Layer());
259 }
260 
262  PopLayer();
263 }
264 
266  double dy,
267  Picture* picture,
268  int hints) {
269  if (picture->picture()) {
270  auto layer = std::make_unique<flutter::PictureLayer>(
271  SkPoint::Make(dx, dy), UIDartState::CreateGPUObject(picture->picture()),
272  !!(hints & 1), !!(hints & 2));
273  AddLayer(std::move(layer));
274  } else {
275  auto layer = std::make_unique<flutter::DisplayListLayer>(
276  SkPoint::Make(dx, dy),
277  UIDartState::CreateGPUObject(picture->display_list()), !!(hints & 1),
278  !!(hints & 2));
279  AddLayer(std::move(layer));
280  }
281 }
282 
284  double dy,
285  double width,
286  double height,
287  int64_t textureId,
288  bool freeze,
289  int filterQualityIndex) {
290  auto sampling = ImageFilter::SamplingFromIndex(filterQualityIndex);
291  auto layer = std::make_unique<flutter::TextureLayer>(
292  SkPoint::Make(dx, dy), SkSize::Make(width, height), textureId, freeze,
293  sampling);
294  AddLayer(std::move(layer));
295 }
296 
298  double dy,
299  double width,
300  double height,
301  int64_t viewId) {
302  auto layer = std::make_unique<flutter::PlatformViewLayer>(
303  SkPoint::Make(dx, dy), SkSize::Make(width, height), viewId);
304  AddLayer(std::move(layer));
305 }
306 
307 void SceneBuilder::addPerformanceOverlay(uint64_t enabledOptions,
308  double left,
309  double right,
310  double top,
311  double bottom) {
312  SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
313  auto layer =
314  std::make_unique<flutter::PerformanceOverlayLayer>(enabledOptions);
315  layer->set_paint_bounds(rect);
316  AddLayer(std::move(layer));
317 }
318 
319 void SceneBuilder::setRasterizerTracingThreshold(uint32_t frameInterval) {
320  rasterizer_tracing_threshold_ = frameInterval;
321 }
322 
324  checkerboard_raster_cache_images_ = checkerboard;
325 }
326 
328  checkerboard_offscreen_layers_ = checkerboard;
329 }
330 
331 void SceneBuilder::build(Dart_Handle scene_handle) {
332  FML_DCHECK(layer_stack_.size() >= 1);
333 
335  scene_handle, std::move(layer_stack_[0]), rasterizer_tracing_threshold_,
336  checkerboard_raster_cache_images_, checkerboard_offscreen_layers_);
337  layer_stack_.clear();
338  ClearDartWrapper(); // may delete this object.
339 }
340 
341 void SceneBuilder::AddLayer(std::shared_ptr<Layer> layer) {
342  FML_DCHECK(layer);
343 
344  if (!layer_stack_.empty()) {
345  layer_stack_.back()->Add(std::move(layer));
346  }
347 }
348 
349 void SceneBuilder::PushLayer(std::shared_ptr<ContainerLayer> layer) {
350  AddLayer(layer);
351  layer_stack_.push_back(std::move(layer));
352 }
353 
354 void SceneBuilder::PopLayer() {
355  // We never pop the root layer, so that AddLayer operations are always valid.
356  if (layer_stack_.size() > 1) {
357  layer_stack_.pop_back();
358  }
359 }
360 
361 } // namespace flutter
~SceneBuilder() override
void pushClipPath(Dart_Handle layer_handle, const CanvasPath *path, int clipBehavior, fml::RefPtr< EngineLayer > oldLayer)
G_BEGIN_DECLS FlValue * args
SkRRect sk_rrect
Definition: rrect.h:16
DEF_SWITCHES_START snapshot asset path
Definition: switches.h:32
void pushImageFilter(Dart_Handle layer_handle, const ImageFilter *image_filter, fml::RefPtr< EngineLayer > oldLayer)
void setCheckerboardRasterCacheImages(bool checkerboard)
static void create(Dart_Handle scene_handle, std::shared_ptr< flutter::Layer > rootLayer, uint32_t rasterizerTracingThreshold, bool checkerboardRasterCacheImages, bool checkerboardOffscreenLayers)
Definition: scene.cc:30
#define FML_DCHECK(condition)
Definition: logging.h:86
void addPlatformView(double dx, double dy, double width, double height, int64_t viewId)
void DartCallConstructor(Sig func, Dart_NativeArguments args)
Definition: dart_args.h:218
void addRetained(fml::RefPtr< EngineLayer > retainedLayer)
sk_sp< SkPicture > picture() const
Definition: picture.h:34
void pushClipRect(Dart_Handle layer_handle, double left, double right, double top, double bottom, int clipBehavior, fml::RefPtr< EngineLayer > oldLayer)
sk_sp< DisplayList > display_list() const
Definition: picture.h:35
void pushClipRRect(Dart_Handle layer_handle, const RRect &rrect, int clipBehavior, fml::RefPtr< EngineLayer > oldLayer)
#define DART_NATIVE_CALLBACK(CLASS, METHOD)
void build(Dart_Handle scene_handle)
void pushTransform(Dart_Handle layer_handle, tonic::Float64List &matrix4, fml::RefPtr< EngineLayer > oldLayer)
static fml::RefPtr< SceneBuilder > create()
Definition: scene_builder.h:31
virtual sk_sp< SkShader > shader(SkSamplingOptions)=0
IMPLEMENT_WRAPPERTYPEINFO(ui, Scene)
void setRasterizerTracingThreshold(uint32_t frameInterval)
void pushColorFilter(Dart_Handle layer_handle, const ColorFilter *color_filter, fml::RefPtr< EngineLayer > oldLayer)
const SkPath & path() const
Definition: path.h:112
static void ThrowIfUIOperationsProhibited()
void pushShaderMask(Dart_Handle layer_handle, Shader *shader, double maskRectLeft, double maskRectRight, double maskRectTop, double maskRectBottom, int blendMode, int filterQualityIndex, fml::RefPtr< EngineLayer > oldLayer)
int32_t width
T * get() const
Definition: ref_ptr.h:112
static SkSamplingOptions SamplingFromIndex(int filterQualityIndex)
Definition: image_filter.cc:50
int32_t height
static void MakeRetained(Dart_Handle dart_handle, std::shared_ptr< flutter::ContainerLayer > layer)
Definition: engine_layer.h:25
void setCheckerboardOffscreenLayers(bool checkerboard)
static void SceneBuilder_constructor(Dart_NativeArguments args)
void addPicture(double dx, double dy, Picture *picture, int hints)
void pushOffset(Dart_Handle layer_handle, double dx, double dy, fml::RefPtr< EngineLayer > oldLayer)
void addPerformanceOverlay(uint64_t enabledOptions, double left, double right, double top, double bottom)
const sk_sp< SkImageFilter > & filter() const
Definition: image_filter.h:35
#define FOR_EACH_BINDING(V)
#define DART_REGISTER_NATIVE(CLASS, METHOD)
void pushBackdropFilter(Dart_Handle layer_handle, ImageFilter *filter, int blendMode, fml::RefPtr< EngineLayer > oldLayer)
Clip
Definition: layer.h:40
void addTexture(double dx, double dy, double width, double height, int64_t textureId, bool freeze, int filterQuality)
SkMatrix ToSkMatrix(const tonic::Float64List &matrix4)
Definition: matrix.cc:20
static flutter::SkiaGPUObject< T > CreateGPUObject(sk_sp< T > object)
void pushPhysicalShape(Dart_Handle layer_handle, const CanvasPath *path, double elevation, int color, int shadowColor, int clipBehavior, fml::RefPtr< EngineLayer > oldLayer)
sk_sp< SkColorFilter > filter() const
Definition: color_filter.h:42
void pushOpacity(Dart_Handle layer_handle, int alpha, double dx, double dy, fml::RefPtr< EngineLayer > oldLayer)