Hint that painting shadows are complex (#5000)
Previously, we considered them one operation in the compositor, which didn't
trigger caching. Now we have a way to explicitly hint that the compositor
should cache a layer.
diff --git a/packages/flutter/lib/src/painting/box_painter.dart b/packages/flutter/lib/src/painting/box_painter.dart
index f1d66a5..73bf5e4 100644
--- a/packages/flutter/lib/src/painting/box_painter.dart
+++ b/packages/flutter/lib/src/painting/box_painter.dart
@@ -1200,6 +1200,9 @@
);
}
+ @override
+ bool get isComplex => boxShadow != null;
+
/// Linearly interpolate between two box decorations.
///
/// Interpolates each parameter of the box decoration separately.
diff --git a/packages/flutter/lib/src/painting/decoration.dart b/packages/flutter/lib/src/painting/decoration.dart
index 7cb3ab0..198a106 100644
--- a/packages/flutter/lib/src/painting/decoration.dart
+++ b/packages/flutter/lib/src/painting/decoration.dart
@@ -44,6 +44,9 @@
/// to inset the children so as to not overlap the frame.
EdgeInsets get padding => null;
+ /// Whether this decoration is complex enough to benefit from caching its painting.
+ bool get isComplex => false;
+
/// Linearly interpolates from [a] to [this].
Decoration lerpFrom(Decoration a, double t) => this;
diff --git a/packages/flutter/lib/src/rendering/layer.dart b/packages/flutter/lib/src/rendering/layer.dart
index 0ba4c82..95583b8 100644
--- a/packages/flutter/lib/src/rendering/layer.dart
+++ b/packages/flutter/lib/src/rendering/layer.dart
@@ -114,9 +114,24 @@
/// The picture's coodinate system matches this layer's coodinate system
ui.Picture picture;
+ /// Hints that the painting in this layer is complex and would benefit from
+ /// caching.
+ ///
+ /// If this hint is not set, the compositor will apply its own heuristics to
+ /// decide whether the this layer is complex enough to benefit from caching.
+ bool isComplexHint = false;
+
+ /// Hints that the painting in this layer is likely to change next frame.
+ ///
+ /// This hint tells the compositor not to cache this layer because the cache
+ /// will not be used in the future. If this hint is not set, the compositor
+ /// will apply its own heuristics to decide whether this layer is likely to be
+ /// reused in the future.
+ bool willChangeHint = false;
+
@override
void addToScene(ui.SceneBuilder builder, Offset layerOffset) {
- builder.addPicture(layerOffset, picture);
+ builder.addPicture(layerOffset, picture, isComplexHint: isComplexHint, willChangeHint: willChangeHint);
}
}
diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart
index 679640e..5dcd985 100644
--- a/packages/flutter/lib/src/rendering/object.dart
+++ b/packages/flutter/lib/src/rendering/object.dart
@@ -192,6 +192,26 @@
static final Paint _disableAntialias = new Paint()..isAntiAlias = false;
+ /// Hints that the painting in the current layer is complex and would benefit
+ /// from caching.
+ ///
+ /// If this hint is not set, the compositor will apply its own heuristics to
+ /// decide whether the current layer is complex enough to benefit from
+ /// caching.
+ void setIsComplexHint() {
+ _currentLayer?.isComplexHint = true;
+ }
+
+ /// Hints that the painting in the current layer is likely to change next frame.
+ ///
+ /// This hint tells the compositor not to cache the current layer because the
+ /// cache will not be used in the future. If this hint is not set, the
+ /// compositor will apply its own heuristics to decide whether the current
+ /// layer is likely to be reused in the future.
+ void setWillChangeHint() {
+ _currentLayer?.willChangeHint = true;
+ }
+
/// Adds a performance overlay to the scene.
///
/// * `offset` is the offset from the origin of the canvas' coordinate system
diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart
index 7ab769d..84702a8 100644
--- a/packages/flutter/lib/src/rendering/proxy_box.dart
+++ b/packages/flutter/lib/src/rendering/proxy_box.dart
@@ -1172,11 +1172,17 @@
assert(size.height != null);
_painter ??= _decoration.createBoxPainter(markNeedsPaint);
final ImageConfiguration filledConfiguration = configuration.copyWith(size: size);
- if (position == DecorationPosition.background)
+ if (position == DecorationPosition.background) {
_painter.paint(context.canvas, offset, filledConfiguration);
+ if (decoration.isComplex)
+ context.setIsComplexHint();
+ }
super.paint(context, offset);
- if (position == DecorationPosition.foreground)
+ if (position == DecorationPosition.foreground) {
_painter.paint(context.canvas, offset, filledConfiguration);
+ if (decoration.isComplex)
+ context.setIsComplexHint();
+ }
}
@override