compositing.dart 17.4 KB
Newer Older
M
Michael Goderbauer 已提交
1
// Copyright 2013 The Flutter Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

A
Adam Barth 已提交
5
part of dart.ui;
6

A
Adam Barth 已提交
7
/// An opaque object representing a composited scene.
H
Hixie 已提交
8 9 10 11 12
///
/// To create a Scene object, use a [SceneBuilder].
///
/// Scene objects can be displayed on the screen using the
/// [Window.render] method.
S
sjindel-google 已提交
13
@pragma('vm:entry-point')
H
Hixie 已提交
14
class Scene extends NativeFieldWrapperClass2 {
15 16
  /// This class is created by the engine, and should not be instantiated
  /// or extended directly.
H
Hixie 已提交
17
  ///
18
  /// To create a Scene object, use a [SceneBuilder].
19
  @pragma('vm:entry-point')
20
  Scene._();
H
Hixie 已提交
21

22 23 24 25 26 27 28 29 30 31 32 33 34

  /// Creates a raster image representation of the current state of the scene.
  /// This is a slow operation that is performed on a background thread.
  Future<Image> toImage(int width, int height) {
    if (width <= 0 || height <= 0)
      throw new Exception('Invalid image dimensions.');
    return _futurize(
      (_Callback<Image> callback) => _toImage(width, height, callback)
    );
  }

  String _toImage(int width, int height, _Callback<Image> callback) native 'Scene_toImage';

A
Adam Barth 已提交
35 36 37
  /// Releases the resources used by this scene.
  ///
  /// After calling this function, the scene is cannot be used further.
38
  void dispose() native 'Scene_dispose';
39 40
}

A
Adam Barth 已提交
41
/// Builds a [Scene] containing the given visuals.
H
Hixie 已提交
42 43 44 45 46 47
///
/// A [Scene] can then be rendered using [Window.render].
///
/// To draw graphical operations onto a [Scene], first create a
/// [Picture] using a [PictureRecorder] and a [Canvas], and then add
/// it to the scene using [addPicture].
48
class SceneBuilder extends NativeFieldWrapperClass2 {
H
Hixie 已提交
49
  /// Creates an empty [SceneBuilder] object.
50
  @pragma('vm:entry-point')
H
Hixie 已提交
51
  SceneBuilder() { _constructor(); }
52
  void _constructor() native 'SceneBuilder_constructor';
53

A
Adam Barth 已提交
54 55 56 57 58
  /// Pushes a transform operation onto the operation stack.
  ///
  /// The objects are transformed by the given matrix before rasterization.
  ///
  /// See [pop] for details about the operation stack.
59
  EngineLayer pushTransform(Float64List matrix4) {
60
    if (matrix4 == null)
61
      throw new ArgumentError('"matrix4" argument cannot be null');
62
    if (matrix4.length != 16)
63
      throw new ArgumentError('"matrix4" must have 16 entries.');
64
    return _pushTransform(matrix4);
65
  }
66
  EngineLayer _pushTransform(Float64List matrix4) native 'SceneBuilder_pushTransform';
A
Adam Barth 已提交
67

68 69 70 71 72
  /// Pushes an offset operation onto the operation stack.
  ///
  /// This is equivalent to [pushTransform] with a matrix with only translation.
  ///
  /// See [pop] for details about the operation stack.
73
  EngineLayer pushOffset(double dx, double dy) native 'SceneBuilder_pushOffset';
74

A
Adam Barth 已提交
75 76 77 78
  /// Pushes a rectangular clip operation onto the operation stack.
  ///
  /// Rasterization outside the given rectangle is discarded.
  ///
79 80
  /// See [pop] for details about the operation stack, and [Clip] for different clip modes.
  /// By default, the clip will be anti-aliased (clip = [Clip.antiAlias]).
81
  EngineLayer pushClipRect(Rect rect, {Clip clipBehavior = Clip.antiAlias}) {
82 83
    assert(clipBehavior != null);
    assert(clipBehavior != Clip.none);
84
    return _pushClipRect(rect.left, rect.right, rect.top, rect.bottom, clipBehavior.index);
85
  }
86 87 88 89 90
  EngineLayer _pushClipRect(double left,
                            double right,
                            double top,
                            double bottom,
                            int clipBehavior) native 'SceneBuilder_pushClipRect';
A
Adam Barth 已提交
91 92 93 94 95

  /// Pushes a rounded-rectangular clip operation onto the operation stack.
  ///
  /// Rasterization outside the given rounded rectangle is discarded.
  ///
96 97
  /// See [pop] for details about the operation stack, and [Clip] for different clip modes.
  /// By default, the clip will be anti-aliased (clip = [Clip.antiAlias]).
98
  EngineLayer pushClipRRect(RRect rrect, {Clip clipBehavior = Clip.antiAlias}) {
99 100
    assert(clipBehavior != null);
    assert(clipBehavior != Clip.none);
101
    return _pushClipRRect(rrect._value, clipBehavior.index);
102
  }
103
  EngineLayer _pushClipRRect(Float32List rrect, int clipBehavior) native 'SceneBuilder_pushClipRRect';
A
Adam Barth 已提交
104 105 106 107 108

  /// Pushes a path clip operation onto the operation stack.
  ///
  /// Rasterization outside the given path is discarded.
  ///
109 110
  /// See [pop] for details about the operation stack. See [Clip] for different clip modes.
  /// By default, the clip will be anti-aliased (clip = [Clip.antiAlias]).
111
  EngineLayer pushClipPath(Path path, {Clip clipBehavior = Clip.antiAlias}) {
112 113
    assert(clipBehavior != null);
    assert(clipBehavior != Clip.none);
114
    return _pushClipPath(path, clipBehavior.index);
115
  }
116
  EngineLayer _pushClipPath(Path path, int clipBehavior) native 'SceneBuilder_pushClipPath';
A
Adam Barth 已提交
117 118 119 120 121 122 123 124 125

  /// Pushes an opacity operation onto the operation stack.
  ///
  /// The given alpha value is blended into the alpha value of the objects'
  /// rasterization. An alpha value of 0 makes the objects entirely invisible.
  /// An alpha value of 255 has no effect (i.e., the objects retain the current
  /// opacity).
  ///
  /// See [pop] for details about the operation stack.
126 127
  EngineLayer pushOpacity(int alpha, {Offset offset = Offset.zero}) {
    return _pushOpacity(alpha, offset.dx, offset.dy);
128
  }
129
  EngineLayer _pushOpacity(int alpha, double dx, double dy) native 'SceneBuilder_pushOpacity';
A
Adam Barth 已提交
130 131 132 133

  /// Pushes a color filter operation onto the operation stack.
  ///
  /// The given color is applied to the objects' rasterization using the given
134
  /// blend mode.
A
Adam Barth 已提交
135 136
  ///
  /// See [pop] for details about the operation stack.
137 138
  EngineLayer pushColorFilter(Color color, BlendMode blendMode) {
    return _pushColorFilter(color.value, blendMode.index);
139
  }
140
  EngineLayer _pushColorFilter(int color, int blendMode) native 'SceneBuilder_pushColorFilter';
A
Adam Barth 已提交
141

142 143 144 145 146 147
  /// Pushes a backdrop filter operation onto the operation stack.
  ///
  /// The given filter is applied to the current contents of the scene prior to
  /// rasterizing the given objects.
  ///
  /// See [pop] for details about the operation stack.
148
  EngineLayer pushBackdropFilter(ImageFilter filter) native 'SceneBuilder_pushBackdropFilter';
149

A
Adam Barth 已提交
150 151 152
  /// Pushes a shader mask operation onto the operation stack.
  ///
  /// The given shader is applied to the object's rasterization in the given
153
  /// rectangle using the given blend mode.
A
Adam Barth 已提交
154 155
  ///
  /// See [pop] for details about the operation stack.
156 157 158 159 160 161 162
  EngineLayer pushShaderMask(Shader shader, Rect maskRect, BlendMode blendMode) {
    return _pushShaderMask(shader,
                           maskRect.left,
                           maskRect.right,
                           maskRect.top,
                           maskRect.bottom,
                           blendMode.index);
163
  }
164 165 166 167 168 169
  EngineLayer _pushShaderMask(Shader shader,
                              double maskRectLeft,
                              double maskRectRight,
                              double maskRectTop,
                              double maskRectBottom,
                              int blendMode) native 'SceneBuilder_pushShaderMask';
170

171
  /// Pushes a physical layer operation for an arbitrary shape onto the
172 173
  /// operation stack.
  ///
174 175 176 177 178
  /// By default, the layer's content will not be clipped (clip = [Clip.none]).
  /// If clip equals [Clip.hardEdge], [Clip.antiAlias], or [Clip.antiAliasWithSaveLayer],
  /// then the content is clipped to the given shape defined by [path].
  ///
  /// If [elevation] is greater than 0.0, then a shadow is drawn around the layer.
L
liyuqian 已提交
179
  /// [shadowColor] defines the color of the shadow if present and [color] defines the
180
  /// color of the layer background.
181
  ///
182 183
  /// See [pop] for details about the operation stack, and [Clip] for different clip modes.
  // ignore: deprecated_member_use
184
  EngineLayer pushPhysicalShape({ Path path, double elevation, Color color, Color shadowColor, Clip clipBehavior = Clip.none}) {
185
    return _pushPhysicalShape(path, elevation, color.value, shadowColor?.value ?? 0xFF000000, clipBehavior.index);
186
  }
187
  EngineLayer _pushPhysicalShape(Path path, double elevation, int color, int shadowColor, int clipBehavior) native
188
    'SceneBuilder_pushPhysicalShape';
189

A
Adam Barth 已提交
190 191 192 193 194 195
  /// Ends the effect of the most recently pushed operation.
  ///
  /// Internally the scene builder maintains a stack of operations. Each of the
  /// operations in the stack applies to each of the objects added to the scene.
  /// Calling this function removes the most recently added operation from the
  /// stack.
196
  void pop() native 'SceneBuilder_pop';
197

198 199 200 201 202
  /// Add a retained engine layer subtree from previous frames.
  ///
  /// All the engine layers that are in the subtree of the retained layer will
  /// be automatically appended to the current engine layer tree.
  ///
L
liyuqian 已提交
203
  /// Therefore, when implementing a subclass of the [Layer] concept defined in
204 205 206 207
  /// the rendering layer of Flutter's framework, once this is called, there's
  /// no need to call [addToScene] for its children layers.
  EngineLayer addRetained(EngineLayer retainedLayer) native 'SceneBuilder_addRetained';

A
Adam Barth 已提交
208 209 210 211 212
  /// Adds an object to the scene that displays performance statistics.
  ///
  /// Useful during development to assess the performance of the application.
  /// The enabledOptions controls which statistics are displayed. The bounds
  /// controls where the statistics are displayed.
H
Hixie 已提交
213 214
  ///
  /// enabledOptions is a bit field with the following bits defined:
H
Hixie 已提交
215 216 217 218
  ///  - 0x01: displayRasterizerStatistics - show GPU thread frame time
  ///  - 0x02: visualizeRasterizerStatistics - graph GPU thread frame times
  ///  - 0x04: displayEngineStatistics - show UI thread frame time
  ///  - 0x08: visualizeEngineStatistics - graph UI thread frame times
H
Hixie 已提交
219 220 221 222 223 224 225 226 227 228 229 230 231
  /// Set enabledOptions to 0x0F to enable all the currently defined features.
  ///
  /// The "UI thread" is the thread that includes all the execution of
  /// the main Dart isolate (the isolate that can call
  /// [Window.render]). The UI thread frame time is the total time
  /// spent executing the [Window.onBeginFrame] callback. The "GPU
  /// thread" is the thread (running on the CPU) that subsequently
  /// processes the [Scene] provided by the Dart code to turn it into
  /// GPU commands and send it to the GPU.
  ///
  /// See also the [PerformanceOverlayOption] enum in the rendering library.
  /// for more details.
  // Values above must match constants in //engine/src/sky/compositor/performance_overlay_layer.h
232 233 234 235 236 237 238 239 240 241 242
  void addPerformanceOverlay(int enabledOptions, Rect bounds) {
    _addPerformanceOverlay(enabledOptions,
                           bounds.left,
                           bounds.right,
                           bounds.top,
                           bounds.bottom);
  }
  void _addPerformanceOverlay(int enabledOptions,
                              double left,
                              double right,
                              double top,
243
                              double bottom) native 'SceneBuilder_addPerformanceOverlay';
A
Adam Barth 已提交
244

H
Hixie 已提交
245
  /// Adds a [Picture] to the scene.
A
Adam Barth 已提交
246 247
  ///
  /// The picture is rasterized at the given offset.
A
Adam Barth 已提交
248
  void addPicture(Offset offset, Picture picture, { bool isComplexHint: false, bool willChangeHint: false }) {
249
    int hints = 0;
A
Adam Barth 已提交
250
    if (isComplexHint)
251
      hints |= 1;
A
Adam Barth 已提交
252
    if (willChangeHint)
253 254
      hints |= 2;
    _addPicture(offset.dx, offset.dy, picture, hints);
255
  }
256
  void _addPicture(double dx, double dy, Picture picture, int hints) native 'SceneBuilder_addPicture';
A
Adam Barth 已提交
257

258 259 260
  /// Adds a backend texture to the scene.
  ///
  /// The texture is scaled to the given size and rasterized at the given offset.
A
amirh 已提交
261 262 263 264 265 266
  ///
  /// If `freeze` is true the texture that is added to the scene will not
  /// be updated with new frames. `freeze` is used when resizing an embedded
  /// Android view: When resizing an Android view there is a short period during
  /// which the framework cannot tell if the newest texture frame has the
  /// previous or new size, to workaround this the framework "freezes" the
267
  /// texture just before resizing the Android view and un-freezes it when it is
A
amirh 已提交
268 269
  /// certain that a frame with the new size is ready.
  void addTexture(int textureId, { Offset offset: Offset.zero, double width: 0.0, double height: 0.0 , bool freeze: false}) {
270
    assert(offset != null, 'Offset argument was null');
A
amirh 已提交
271
    _addTexture(offset.dx, offset.dy, width, height, textureId, freeze);
272
  }
A
amirh 已提交
273
  void _addTexture(double dx, double dy, double width, double height, int textureId, bool freeze) native 'SceneBuilder_addTexture';
274

275 276
  /// Adds a platform view (e.g an iOS UIView) to the scene.
  ///
277 278 279 280 281 282 283 284 285 286 287 288 289 290
  /// Only supported on iOS, this is currently a no-op on other platforms.
  ///
  /// On iOS this layer splits the current output surface into two surfaces, one for the scene nodes
  /// preceding the platform view, and one for the scene nodes following the platform view.
  ///
  /// ## Performance impact
  ///
  /// Adding an additional surface doubles the amount of graphics memory directly used by Flutter
  /// for output buffers. Quartz might allocated extra buffers for compositing the Flutter surfaces
  /// and the platform view.
  ///
  /// With a platform view in the scene, Quartz has to composite the two Flutter surfaces and the
  /// embedded UIView. In addition to that, on iOS versions greater than 9, the Flutter frames are
  /// synchronized with the UIView frames adding additional performance overhead.
291 292 293 294 295 296
  void addPlatformView(int viewId, { Offset offset: Offset.zero, double width: 0.0, double height: 0.0}) {
    assert(offset != null, 'Offset argument was null');
    _addPlatformView(offset.dx, offset.dy, width, height, viewId);
  }
  void _addPlatformView(double dx, double dy, double width, double height, int viewId) native 'SceneBuilder_addPlatformView';

297 298
  /// (Fuchsia-only) Adds a scene rendered by another application to the scene
  /// for this application.
299 300
  void addChildScene({
    Offset offset: Offset.zero,
301 302
    double width: 0.0,
    double height: 0.0,
303
    SceneHost sceneHost,
A
Adam Barth 已提交
304
    bool hitTestable: true
305
  }) {
306 307
    _addChildScene(offset.dx,
                   offset.dy,
308 309
                   width,
                   height,
310
                   sceneHost,
311
                   hitTestable);
312 313 314
  }
  void _addChildScene(double dx,
                      double dy,
315 316
                      double width,
                      double height,
317
                      SceneHost sceneHost,
318
                      bool hitTestable) native 'SceneBuilder_addChildScene';
A
Adam Barth 已提交
319 320 321 322 323 324 325

  /// Sets a threshold after which additional debugging information should be recorded.
  ///
  /// Currently this interface is difficult to use by end-developers. If you're
  /// interested in using this feature, please contact [flutter-dev](https://groups.google.com/forum/#!forum/flutter-dev).
  /// We'll hopefully be able to figure out how to make this feature more useful
  /// to you.
326
  void setRasterizerTracingThreshold(int frameInterval) native 'SceneBuilder_setRasterizerTracingThreshold';
327

328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
  /// Sets whether the raster cache should checkerboard cached entries. This is
  /// only useful for debugging purposes.
  ///
  /// The compositor can sometimes decide to cache certain portions of the
  /// widget hierarchy. Such portions typically don't change often from frame to
  /// frame and are expensive to render. This can speed up overall rendering. However,
  /// there is certain upfront cost to constructing these cache entries. And, if
  /// the cache entries are not used very often, this cost may not be worth the
  /// speedup in rendering of subsequent frames. If the developer wants to be certain
  /// that populating the raster cache is not causing stutters, this option can be
  /// set. Depending on the observations made, hints can be provided to the compositor
  /// that aid it in making better decisions about caching.
  ///
  /// Currently this interface is difficult to use by end-developers. If you're
  /// interested in using this feature, please contact [flutter-dev](https://groups.google.com/forum/#!forum/flutter-dev).
343
  void setCheckerboardRasterCacheImages(bool checkerboard) native 'SceneBuilder_setCheckerboardRasterCacheImages';
344

345 346 347 348
  /// Sets whether the compositor should checkerboard layers that are rendered
  /// to offscreen bitmaps.
  ///
  /// This is only useful for debugging purposes.
349
  void setCheckerboardOffscreenLayers(bool checkerboard) native 'SceneBuilder_setCheckerboardOffscreenLayers';
350

A
Adam Barth 已提交
351 352
  /// Finishes building the scene.
  ///
H
Hixie 已提交
353 354 355
  /// Returns a [Scene] containing the objects that have been added to
  /// this scene builder. The [Scene] can then be displayed on the
  /// screen with [Window.render].
A
Adam Barth 已提交
356 357 358
  ///
  /// After calling this function, the scene builder object is invalid and
  /// cannot be used further.
359
  Scene build() native 'SceneBuilder_build';
360
}
361 362 363 364 365 366 367 368 369 370

/// (Fuchsia-only) Hosts content provided by another application.
class SceneHost extends NativeFieldWrapperClass2 {
  /// Creates a host for a child scene.
  ///
  /// The export token is bound to a scene graph node which acts as a container
  /// for the child's content.  The creator of the scene host is responsible for
  /// sending the corresponding import token (the other endpoint of the event pair)
  /// to the child.
  ///
371
  /// The export token is a dart:zircon Handle, but that type isn't
372
  /// available here. This is called by ChildViewConnection in
373
  /// //topaz/public/lib/ui/flutter/.
374
  ///
375
  /// The scene host takes ownership of the provided export token handle.
376 377
  SceneHost(dynamic exportTokenHandle) {
    _constructor(exportTokenHandle);
378
  }
379
  void _constructor(dynamic exportTokenHandle) native 'SceneHost_constructor';
380 381 382 383

  /// Releases the resources associated with the child scene host.
  ///
  /// After calling this function, the child scene host cannot be used further.
384
  void dispose() native 'SceneHost_dispose';
385
}