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.
This commit is contained in:
Ian Hickson 2016-04-15 14:55:18 -07:00
parent 347831bf7f
commit d348f28df7
2 changed files with 39 additions and 3 deletions

View File

@ -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 = <RenderObject>[];
// 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);

View File

@ -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);
});
}