Unverified Commit 783c028f authored by liyuqian's avatar liyuqian Committed by GitHub

Don't push offset to leaf layers (#21619)

For retained rendering, we don't want to push the offset down to each leaf layer. Otherwise, changing an offset layer on the very high level could cascade the change to too many leaves, which means that we can't retain them.

To not push the offset downwards, we simply push a TransformLayer when there's an offset. Skia has a fast path for concatenating scale/translation-only matrix so this operation should be fast (no performance regression is measured on Moto G4).

This is our first step towards https://github.com/flutter/flutter/issues/21756
parent 1c2f478e
...@@ -104,10 +104,7 @@ abstract class Layer extends AbstractNode with DiagnosticableTreeMixin { ...@@ -104,10 +104,7 @@ abstract class Layer extends AbstractNode with DiagnosticableTreeMixin {
S find<S>(Offset regionOffset); S find<S>(Offset regionOffset);
/// Override this method to upload this layer to the engine. /// Override this method to upload this layer to the engine.
/// void addToScene(ui.SceneBuilder builder, [Offset layerOffset = Offset.zero]);
/// The `layerOffset` is the accumulated offset of this layer's parent from the
/// origin of the builder's coordinate system.
void addToScene(ui.SceneBuilder builder, Offset layerOffset);
/// The object responsible for creating this layer. /// The object responsible for creating this layer.
/// ///
...@@ -171,7 +168,7 @@ class PictureLayer extends Layer { ...@@ -171,7 +168,7 @@ class PictureLayer extends Layer {
bool willChangeHint = false; bool willChangeHint = false;
@override @override
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, [Offset layerOffset = Offset.zero]) {
builder.addPicture(layerOffset, picture, isComplexHint: isComplexHint, willChangeHint: willChangeHint); builder.addPicture(layerOffset, picture, isComplexHint: isComplexHint, willChangeHint: willChangeHint);
} }
...@@ -237,7 +234,7 @@ class TextureLayer extends Layer { ...@@ -237,7 +234,7 @@ class TextureLayer extends Layer {
final bool freeze; final bool freeze;
@override @override
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, [Offset layerOffset = Offset.zero]) {
final Rect shiftedRect = rect.shift(layerOffset); final Rect shiftedRect = rect.shift(layerOffset);
builder.addTexture( builder.addTexture(
textureId, textureId,
...@@ -305,7 +302,7 @@ class PerformanceOverlayLayer extends Layer { ...@@ -305,7 +302,7 @@ class PerformanceOverlayLayer extends Layer {
final bool checkerboardOffscreenLayers; final bool checkerboardOffscreenLayers;
@override @override
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, [Offset layerOffset = Offset.zero]) {
assert(optionsMask != null); assert(optionsMask != null);
builder.addPerformanceOverlay(optionsMask, overlayRect.shift(layerOffset)); builder.addPerformanceOverlay(optionsMask, overlayRect.shift(layerOffset));
builder.setRasterizerTracingThreshold(rasterizerThreshold); builder.setRasterizerTracingThreshold(rasterizerThreshold);
...@@ -454,7 +451,7 @@ class ContainerLayer extends Layer { ...@@ -454,7 +451,7 @@ class ContainerLayer extends Layer {
} }
@override @override
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, [Offset layerOffset = Offset.zero]) {
addChildrenToScene(builder, layerOffset); addChildrenToScene(builder, layerOffset);
} }
...@@ -465,7 +462,7 @@ class ContainerLayer extends Layer { ...@@ -465,7 +462,7 @@ class ContainerLayer extends Layer {
/// to apply effects to the scene using the [SceneBuilder] API, then insert /// to apply effects to the scene using the [SceneBuilder] API, then insert
/// their children using [addChildrenToScene], then reverse the aforementioned /// their children using [addChildrenToScene], then reverse the aforementioned
/// effects before returning from [addToScene]. /// effects before returning from [addToScene].
void addChildrenToScene(ui.SceneBuilder builder, Offset childOffset) { void addChildrenToScene(ui.SceneBuilder builder, [Offset childOffset = Offset.zero]) {
Layer child = firstChild; Layer child = firstChild;
while (child != null) { while (child != null) {
child.addToScene(builder, childOffset); child.addToScene(builder, childOffset);
...@@ -560,8 +557,22 @@ class OffsetLayer extends ContainerLayer { ...@@ -560,8 +557,22 @@ class OffsetLayer extends ContainerLayer {
} }
@override @override
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void applyTransform(Layer child, Matrix4 transform) {
addChildrenToScene(builder, offset + layerOffset); assert(child != null);
assert(transform != null);
transform.multiply(Matrix4.translationValues(offset.dx, offset.dy, 0.0));
}
@override
void addToScene(ui.SceneBuilder builder, [Offset layerOffset = Offset.zero]) {
// Skia has a fast path for concatenating scale/translation only matrices.
// Hence pushing a translation-only transform layer should be fast. For
// retained rendering, we don't want to push the offset down to each leaf
// node. Otherwise, changing an offset layer on the very high level could
// cascade the change to too many leaves.
builder.pushOffset(layerOffset.dx + offset.dx, layerOffset.dy + offset.dy);
addChildrenToScene(builder);
builder.pop();
} }
@override @override
...@@ -597,7 +608,7 @@ class OffsetLayer extends ContainerLayer { ...@@ -597,7 +608,7 @@ class OffsetLayer extends ContainerLayer {
); );
transform.scale(pixelRatio, pixelRatio); transform.scale(pixelRatio, pixelRatio);
builder.pushTransform(transform.storage); builder.pushTransform(transform.storage);
addToScene(builder, Offset.zero); addToScene(builder);
final ui.Scene scene = builder.build(); final ui.Scene scene = builder.build();
try { try {
// Size is rounded up to the next pixel to make sure we don't clip off // Size is rounded up to the next pixel to make sure we don't clip off
...@@ -652,7 +663,7 @@ class ClipRectLayer extends ContainerLayer { ...@@ -652,7 +663,7 @@ class ClipRectLayer extends ContainerLayer {
} }
@override @override
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, [Offset layerOffset = Offset.zero]) {
bool enabled = true; bool enabled = true;
assert(() { assert(() {
enabled = !debugDisableClipLayers; enabled = !debugDisableClipLayers;
...@@ -708,7 +719,7 @@ class ClipRRectLayer extends ContainerLayer { ...@@ -708,7 +719,7 @@ class ClipRRectLayer extends ContainerLayer {
} }
@override @override
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, [Offset layerOffset = Offset.zero]) {
bool enabled = true; bool enabled = true;
assert(() { assert(() {
enabled = !debugDisableClipLayers; enabled = !debugDisableClipLayers;
...@@ -764,7 +775,7 @@ class ClipPathLayer extends ContainerLayer { ...@@ -764,7 +775,7 @@ class ClipPathLayer extends ContainerLayer {
} }
@override @override
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, [Offset layerOffset = Offset.zero]) {
bool enabled = true; bool enabled = true;
assert(() { assert(() {
enabled = !debugDisableClipLayers; enabled = !debugDisableClipLayers;
...@@ -815,7 +826,7 @@ class TransformLayer extends OffsetLayer { ...@@ -815,7 +826,7 @@ class TransformLayer extends OffsetLayer {
bool _inverseDirty = true; bool _inverseDirty = true;
@override @override
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, [Offset layerOffset = Offset.zero]) {
_lastEffectiveTransform = transform; _lastEffectiveTransform = transform;
final Offset totalOffset = offset + layerOffset; final Offset totalOffset = offset + layerOffset;
if (totalOffset != Offset.zero) { if (totalOffset != Offset.zero) {
...@@ -823,7 +834,7 @@ class TransformLayer extends OffsetLayer { ...@@ -823,7 +834,7 @@ class TransformLayer extends OffsetLayer {
..multiply(_lastEffectiveTransform); ..multiply(_lastEffectiveTransform);
} }
builder.pushTransform(_lastEffectiveTransform.storage); builder.pushTransform(_lastEffectiveTransform.storage);
addChildrenToScene(builder, Offset.zero); addChildrenToScene(builder);
builder.pop(); builder.pop();
} }
...@@ -876,7 +887,7 @@ class OpacityLayer extends ContainerLayer { ...@@ -876,7 +887,7 @@ class OpacityLayer extends ContainerLayer {
int alpha; int alpha;
@override @override
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, [Offset layerOffset = Offset.zero]) {
bool enabled = true; bool enabled = true;
assert(() { assert(() {
enabled = !debugDisableOpacityLayers; enabled = !debugDisableOpacityLayers;
...@@ -923,7 +934,7 @@ class ShaderMaskLayer extends ContainerLayer { ...@@ -923,7 +934,7 @@ class ShaderMaskLayer extends ContainerLayer {
BlendMode blendMode; BlendMode blendMode;
@override @override
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, [Offset layerOffset = Offset.zero]) {
builder.pushShaderMask(shader, maskRect.shift(layerOffset), blendMode); builder.pushShaderMask(shader, maskRect.shift(layerOffset), blendMode);
addChildrenToScene(builder, layerOffset); addChildrenToScene(builder, layerOffset);
builder.pop(); builder.pop();
...@@ -953,7 +964,7 @@ class BackdropFilterLayer extends ContainerLayer { ...@@ -953,7 +964,7 @@ class BackdropFilterLayer extends ContainerLayer {
ui.ImageFilter filter; ui.ImageFilter filter;
@override @override
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, [Offset layerOffset = Offset.zero]) {
builder.pushBackdropFilter(filter); builder.pushBackdropFilter(filter);
addChildrenToScene(builder, layerOffset); addChildrenToScene(builder, layerOffset);
builder.pop(); builder.pop();
...@@ -1024,7 +1035,7 @@ class PhysicalModelLayer extends ContainerLayer { ...@@ -1024,7 +1035,7 @@ class PhysicalModelLayer extends ContainerLayer {
} }
@override @override
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, [Offset layerOffset = Offset.zero]) {
bool enabled = true; bool enabled = true;
assert(() { assert(() {
enabled = !debugDisablePhysicalShapeLayers; enabled = !debugDisablePhysicalShapeLayers;
...@@ -1133,12 +1144,12 @@ class LeaderLayer extends ContainerLayer { ...@@ -1133,12 +1144,12 @@ class LeaderLayer extends ContainerLayer {
} }
@override @override
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, [Offset layerOffset = Offset.zero]) {
assert(offset != null); assert(offset != null);
_lastOffset = offset + layerOffset; _lastOffset = offset + layerOffset;
if (_lastOffset != Offset.zero) if (_lastOffset != Offset.zero)
builder.pushTransform(Matrix4.translationValues(_lastOffset.dx, _lastOffset.dy, 0.0).storage); builder.pushTransform(Matrix4.translationValues(_lastOffset.dx, _lastOffset.dy, 0.0).storage);
addChildrenToScene(builder, Offset.zero); addChildrenToScene(builder);
if (_lastOffset != Offset.zero) if (_lastOffset != Offset.zero)
builder.pop(); builder.pop();
} }
...@@ -1337,7 +1348,7 @@ class FollowerLayer extends ContainerLayer { ...@@ -1337,7 +1348,7 @@ class FollowerLayer extends ContainerLayer {
} }
@override @override
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, [Offset layerOffset = Offset.zero]) {
assert(link != null); assert(link != null);
assert(showWhenUnlinked != null); assert(showWhenUnlinked != null);
if (link.leader == null && !showWhenUnlinked) { if (link.leader == null && !showWhenUnlinked) {
...@@ -1349,12 +1360,15 @@ class FollowerLayer extends ContainerLayer { ...@@ -1349,12 +1360,15 @@ class FollowerLayer extends ContainerLayer {
_establishTransform(); _establishTransform();
if (_lastTransform != null) { if (_lastTransform != null) {
builder.pushTransform(_lastTransform.storage); builder.pushTransform(_lastTransform.storage);
addChildrenToScene(builder, Offset.zero); addChildrenToScene(builder);
builder.pop(); builder.pop();
_lastOffset = unlinkedOffset + layerOffset; _lastOffset = unlinkedOffset + layerOffset;
} else { } else {
_lastOffset = null; _lastOffset = null;
addChildrenToScene(builder, unlinkedOffset + layerOffset); final Matrix4 matrix = Matrix4.translationValues(unlinkedOffset.dx, unlinkedOffset.dy, .0);
builder.pushTransform(matrix.storage);
addChildrenToScene(builder);
builder.pop();
} }
_inverseDirty = true; _inverseDirty = true;
} }
...@@ -1363,8 +1377,11 @@ class FollowerLayer extends ContainerLayer { ...@@ -1363,8 +1377,11 @@ class FollowerLayer extends ContainerLayer {
void applyTransform(Layer child, Matrix4 transform) { void applyTransform(Layer child, Matrix4 transform) {
assert(child != null); assert(child != null);
assert(transform != null); assert(transform != null);
if (_lastTransform != null) if (_lastTransform != null) {
transform.multiply(_lastTransform); transform.multiply(_lastTransform);
} else {
transform.multiply(Matrix4.translationValues(unlinkedOffset.dx, unlinkedOffset.dy, .0));
}
} }
@override @override
......
...@@ -192,7 +192,7 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox> ...@@ -192,7 +192,7 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
Timeline.startSync('Compositing', arguments: timelineWhitelistArguments); Timeline.startSync('Compositing', arguments: timelineWhitelistArguments);
try { try {
final ui.SceneBuilder builder = ui.SceneBuilder(); final ui.SceneBuilder builder = ui.SceneBuilder();
layer.addToScene(builder, Offset.zero); layer.addToScene(builder);
final ui.Scene scene = builder.build(); final ui.Scene scene = builder.build();
if (automaticSystemUiAdjustment) if (automaticSystemUiAdjustment)
_updateSystemChrome(); _updateSystemChrome();
......
...@@ -54,7 +54,7 @@ class _ProxyLayer extends Layer { ...@@ -54,7 +54,7 @@ class _ProxyLayer extends Layer {
_ProxyLayer(this._layer); _ProxyLayer(this._layer);
@override @override
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, [Offset layerOffset = Offset.zero]) {
_layer.addToScene(builder, layerOffset); _layer.addToScene(builder, layerOffset);
} }
...@@ -312,7 +312,7 @@ Rect _calculateSubtreeBounds(RenderObject object) { ...@@ -312,7 +312,7 @@ Rect _calculateSubtreeBounds(RenderObject object) {
/// screenshots render to the scene in the local coordinate system of the layer. /// screenshots render to the scene in the local coordinate system of the layer.
class _ScreenshotContainerLayer extends OffsetLayer { class _ScreenshotContainerLayer extends OffsetLayer {
@override @override
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, [Offset layerOffset = Offset.zero]) {
addChildrenToScene(builder, layerOffset); addChildrenToScene(builder, layerOffset);
} }
} }
...@@ -588,7 +588,7 @@ class _ScreenshotPaintingContext extends PaintingContext { ...@@ -588,7 +588,7 @@ class _ScreenshotPaintingContext extends PaintingContext {
// We must build the regular scene before we can build the screenshot // We must build the regular scene before we can build the screenshot
// scene as building the screenshot scene assumes addToScene has already // scene as building the screenshot scene assumes addToScene has already
// been called successfully for all layers in the regular scene. // been called successfully for all layers in the regular scene.
repaintBoundary.layer.addToScene(ui.SceneBuilder(), Offset.zero); repaintBoundary.layer.addToScene(ui.SceneBuilder());
return data.containerLayer.toImage(renderBounds, pixelRatio: pixelRatio); return data.containerLayer.toImage(renderBounds, pixelRatio: pixelRatio);
} }
...@@ -2235,7 +2235,7 @@ class _InspectorOverlayLayer extends Layer { ...@@ -2235,7 +2235,7 @@ class _InspectorOverlayLayer extends Layer {
double _textPainterMaxWidth; double _textPainterMaxWidth;
@override @override
void addToScene(ui.SceneBuilder builder, Offset layerOffset) { void addToScene(ui.SceneBuilder builder, [Offset layerOffset = Offset.zero]) {
if (!selection.active) if (!selection.active)
return; return;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment