diff --git a/packages/flutter/lib/src/painting/box_painter.dart b/packages/flutter/lib/src/painting/box_painter.dart index f1d66a575a..73bf5e4796 100644 --- a/packages/flutter/lib/src/painting/box_painter.dart +++ b/packages/flutter/lib/src/painting/box_painter.dart @@ -1200,6 +1200,9 @@ class BoxDecoration extends Decoration { ); } + @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 7cb3ab0b12..198a10665c 100644 --- a/packages/flutter/lib/src/painting/decoration.dart +++ b/packages/flutter/lib/src/painting/decoration.dart @@ -44,6 +44,9 @@ abstract class Decoration { /// 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 0ba4c8243c..95583b87d6 100644 --- a/packages/flutter/lib/src/rendering/layer.dart +++ b/packages/flutter/lib/src/rendering/layer.dart @@ -114,9 +114,24 @@ class PictureLayer extends Layer { /// 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 679640e749..5dcd98541d 100644 --- a/packages/flutter/lib/src/rendering/object.dart +++ b/packages/flutter/lib/src/rendering/object.dart @@ -192,6 +192,26 @@ class PaintingContext { 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 7ab769d6a4..84702a8755 100644 --- a/packages/flutter/lib/src/rendering/proxy_box.dart +++ b/packages/flutter/lib/src/rendering/proxy_box.dart @@ -1172,11 +1172,17 @@ class RenderDecoratedBox extends RenderProxyBox { 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