From d348f28df7f469e8a425766adb1dfd467b33228c Mon Sep 17 00:00:00 2001 From: Ian Hickson Date: Fri, 15 Apr 2016 14:55:18 -0700 Subject: [PATCH] Use the same logic in flushPaint as flushLayout (#3353) If two repaint boundaries mark themselves dirty, but the second one is a child of the first, then the second one will get repainted by the first and then when we come to paint it directly, we get confused because it isn't dirty any more. We ran into this in layout before. Apply the same fix. Also, apply the same fix to composition while we're at it. --- .../flutter/lib/src/rendering/object.dart | 5 +-- .../test/rendering/repaint_boundary_test.dart | 37 +++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 packages/flutter/test/rendering/repaint_boundary_test.dart diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart index 12466768d0..4a12125f3f 100644 --- a/packages/flutter/lib/src/rendering/object.dart +++ b/packages/flutter/lib/src/rendering/object.dart @@ -742,7 +742,7 @@ class PipelineOwner { Timeline.startSync('Compositing Bits'); _nodesNeedingCompositingBitsUpdate.sort((RenderObject a, RenderObject b) => a.depth - b.depth); for (RenderObject node in _nodesNeedingCompositingBitsUpdate) { - if (node.owner == this) + if (node._needsCompositingBitsUpdate && node.owner == this) node._updateCompositingBits(); } _nodesNeedingCompositingBitsUpdate.clear(); @@ -767,8 +767,7 @@ class PipelineOwner { _nodesNeedingPaint = []; // Sort the dirty nodes in reverse order (deepest first). for (RenderObject node in dirtyNodes..sort((RenderObject a, RenderObject b) => b.depth - a.depth)) { - assert(node._needsPaint); - if (node.owner == this) + if (node._needsPaint && node.owner == this) PaintingContext.repaintCompositedChild(node); }; assert(_nodesNeedingPaint.length == 0); diff --git a/packages/flutter/test/rendering/repaint_boundary_test.dart b/packages/flutter/test/rendering/repaint_boundary_test.dart new file mode 100644 index 0000000000..25880b8c7f --- /dev/null +++ b/packages/flutter/test/rendering/repaint_boundary_test.dart @@ -0,0 +1,37 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/rendering.dart'; +import 'package:test/test.dart'; + +import 'rendering_tester.dart'; + +void main() { + test("nested repaint boundaries - smoke test", () { + RenderOpacity a, b, c; + a = new RenderOpacity( + opacity: 1.0, + child: new RenderRepaintBoundary( + child: b = new RenderOpacity( + opacity: 1.0, + child: new RenderRepaintBoundary( + child: c = new RenderOpacity( + opacity: 1.0 + ) + ) + ) + ) + ); + layout(a, phase: EnginePhase.flushSemantics); + c.opacity = 0.9; + layout(a, phase: EnginePhase.flushSemantics); + a.opacity = 0.8; + c.opacity = 0.8; + layout(a, phase: EnginePhase.flushSemantics); + a.opacity = 0.7; + b.opacity = 0.7; + c.opacity = 0.7; + layout(a, phase: EnginePhase.flushSemantics); + }); +}