Commit 838bd631 authored by Jason Simmons's avatar Jason Simmons Committed by GitHub

Control raster cache flags in CustomPaint widgets (#11398)

parent 9f510ebd
......@@ -2064,6 +2064,8 @@ class RenderCustomPaint extends RenderProxyBox {
CustomPainter painter,
CustomPainter foregroundPainter,
Size preferredSize: Size.zero,
this.isComplex: false,
this.willChange: false,
RenderBox child,
}) : assert(preferredSize != null),
_painter = painter,
......@@ -2153,6 +2155,19 @@ class RenderCustomPaint extends RenderProxyBox {
markNeedsLayout();
}
/// Whether to hint that this layer's painting should be cached.
///
/// The compositor contains a raster cache that holds bitmaps of layers in
/// order to avoid the cost of repeatedly rendering those layers on each
/// frame. If this flag is not set, then the compositor will apply its own
/// heuristics to decide whether the this layer is complex enough to benefit
/// from caching.
bool isComplex;
/// Whether the raster cache should be told that this painting is likely
/// to change in the next frame.
bool willChange;
@override
void attach(PipelineOwner owner) {
super.attach(owner);
......@@ -2226,11 +2241,22 @@ class RenderCustomPaint extends RenderProxyBox {
@override
void paint(PaintingContext context, Offset offset) {
if (_painter != null)
if (_painter != null) {
_paintWithPainter(context.canvas, offset, _painter);
_setRasterCacheHints(context);
}
super.paint(context, offset);
if (_foregroundPainter != null)
if (_foregroundPainter != null) {
_paintWithPainter(context.canvas, offset, _foregroundPainter);
_setRasterCacheHints(context);
}
}
void _setRasterCacheHints(PaintingContext context) {
if (isComplex)
context.setIsComplexHint();
if (willChange)
context.setWillChangeHint();
}
}
......
......@@ -256,7 +256,10 @@ class BackdropFilter extends SingleChildRenderObjectWidget {
///
/// Custom painters normally size themselves to their child. If they do not have
/// a child, they attempt to size themselves to the [size], which defaults to
/// [Size.zero].
/// [Size.zero]. [size] must not be null.
///
/// [isComplex] and [willChange] are hints to the compositor's raster cache
/// and must not be null.
///
/// ## Sample code
///
......@@ -286,8 +289,17 @@ class BackdropFilter extends SingleChildRenderObjectWidget {
/// * [Canvas], the class that a custom painter uses to paint.
class CustomPaint extends SingleChildRenderObjectWidget {
/// Creates a widget that delegates its painting.
const CustomPaint({ Key key, this.painter, this.foregroundPainter, this.size: Size.zero, Widget child })
: assert(size != null),
const CustomPaint({
Key key,
this.painter,
this.foregroundPainter,
this.size: Size.zero,
this.isComplex: false,
this.willChange: false,
Widget child
}) : assert(size != null),
assert(isComplex != null),
assert(willChange != null),
super(key: key, child: child);
/// The painter that paints before the children.
......@@ -305,12 +317,27 @@ class CustomPaint extends SingleChildRenderObjectWidget {
/// instead.
final Size size;
/// Whether the painting is complex enough to benefit from caching.
///
/// The compositor contains a raster cache that holds bitmaps of layers in
/// order to avoid the cost of repeatedly rendering those layers on each
/// frame. If this flag is not set, then the compositor will apply its own
/// heuristics to decide whether the this layer is complex enough to benefit
/// from caching.
final bool isComplex;
/// Whether the raster cache should be told that this painting is likely
/// to change in the next frame.
final bool willChange;
@override
RenderCustomPaint createRenderObject(BuildContext context) {
return new RenderCustomPaint(
painter: painter,
foregroundPainter: foregroundPainter,
preferredSize: size,
isComplex: isComplex,
willChange: willChange,
);
}
......@@ -319,7 +346,9 @@ class CustomPaint extends SingleChildRenderObjectWidget {
renderObject
..painter = painter
..foregroundPainter = foregroundPainter
..preferredSize = size;
..preferredSize = size
..isComplex = isComplex
..willChange = willChange;
}
@override
......
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
class TestCustomPainter extends CustomPainter {
......@@ -77,4 +78,27 @@ void main() {
expect(target.currentContext.size, Size.zero);
});
testWidgets('Raster cache hints', (WidgetTester tester) async {
final GlobalKey target = new GlobalKey();
final List<String> log = <String>[];
await tester.pumpWidget(new CustomPaint(
key: target,
isComplex: true,
painter: new TestCustomPainter(log: log),
));
RenderCustomPaint renderCustom = target.currentContext.findRenderObject();
expect(renderCustom.isComplex, true);
expect(renderCustom.willChange, false);
await tester.pumpWidget(new CustomPaint(
key: target,
willChange: true,
foregroundPainter: new TestCustomPainter(log: log),
));
renderCustom = target.currentContext.findRenderObject();
expect(renderCustom.isComplex, false);
expect(renderCustom.willChange, true);
});
}
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