Check for invalid elevations#30215
Conversation
| } | ||
|
|
||
| /// Returns the descendants of this layer in depth first order. | ||
| Iterable<Layer> depthFirstIterateChildren() sync* { |
There was a problem hiding this comment.
In general sync* has very bad performance, it is better to avoid it.
There was a problem hiding this comment.
Is there some way to inspect the generated code here? I strongly suspect it will be at least as efficient as writing our own iterable implementation for this in the current usage...
There was a problem hiding this comment.
Although this is making me realize that I'm modifying the tree while iterating it which is a bad idea. I can fix that though.
| List<PictureLayer> _debugCheckElevations() { | ||
| final List<PhysicalModelLayer> physicalModelLayers = depthFirstIterateChildren().whereType<PhysicalModelLayer>().toList(); | ||
| final List<PictureLayer> addedLayers = <PictureLayer>[]; | ||
| bool _predecessorIsNotDirectAncestor(PhysicalModelLayer predecessor, Layer child) { |
There was a problem hiding this comment.
This should be _predecessorIsAncestor
goderbauer
left a comment
There was a problem hiding this comment.
There's also the one elevation case I just showed you that didn't seem to work. Probably needs elevation addition?
| void applyTransform(Layer child, Matrix4 transform) { | ||
| assert(child != null); | ||
| assert(transform != null); | ||
| if (_lastEffectiveTransform == null && this.transform != null) { |
There was a problem hiding this comment.
What if transform is also null? Wouldn't line 1210 throw then? If it is guaranteed to not be null, maybe add an assert instead?
| ]; | ||
| } | ||
|
|
||
| /// Checks that no [PhysicalModelLayer] would paint after another |
There was a problem hiding this comment.
Should this maybe mention that this condition is only problematic if they are overlapping?
|
|
||
| List<PictureLayer> _processConflictingPhysicalLayers(PhysicalModelLayer predecessor, PhysicalModelLayer child) { | ||
| FlutterError.reportError(FlutterErrorDetails( | ||
| exception: FlutterError('Painting order is out of order with respect to elevation.'), |
There was a problem hiding this comment.
This could be more informative. Can we give any call to action to resolve the issue? Where can a developer learn more?
There was a problem hiding this comment.
The full error ends up looking like this:
I/flutter (15065): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter (15065): The following assertion was thrown during compositing:
I/flutter (15065): Painting order is out of order with respect to elevation.
I/flutter (15065):
I/flutter (15065): Attempted to composite layer:
I/flutter (15065): PhysicalModelLayer#c1c68(creator: PhysicalModel ← AnimatedPhysicalModel ← Material ← ConstrainedBox
I/flutter (15065): ← Container ← Stack ← Column ← Directionality ← [root], elevation: 1.0, color: MaterialColor(primary
I/flutter (15065): value: Color(0xff2196f3)))
I/flutter (15065): after layer:
I/flutter (15065): PhysicalModelLayer#d7ff6(creator: PhysicalModel ← AnimatedPhysicalModel ← Material ← ConstrainedBox
I/flutter (15065): ← Container ← Stack ← Column ← Directionality ← [root], elevation: 1.2, color: MaterialColor(primary
I/flutter (15065): value: Color(0xff4caf50)))
I/flutter (15065): which occupies the same area at a higher elevation.
I/flutter (15065): ════════════════════════════════════════════════════════════════════════════════════════════════════
Although unfortunately only for the first one. Is there some way you think I could highlight that this will be added with more information elsewhere?
There was a problem hiding this comment.
Maybe we need a doc page on flutter.dev going over this concept?
There was a problem hiding this comment.
Linking to somewhere with more information would probable be good. For now maybe just link back to the docs of debugCheckElevationsEnabled which have a nice example?
| bool debugRepaintTextRainbowEnabled = false; | ||
|
|
||
| /// Causes [PhysicalModelLayer]s to paint a red rectangle around themselves if | ||
| /// they are painted out of order with regard to their elevation. |
There was a problem hiding this comment.
Should this summary maybe already include the overlapping bit?
|
|
||
| List<PictureLayer> _processConflictingPhysicalLayers(PhysicalModelLayer predecessor, PhysicalModelLayer child) { | ||
| FlutterError.reportError(FlutterErrorDetails( | ||
| exception: FlutterError('Painting order is out of order with respect to elevation.'), |
There was a problem hiding this comment.
Linking to somewhere with more information would probable be good. For now maybe just link back to the docs of debugCheckElevationsEnabled which have a nice example?
| debugDisableShadows = true; | ||
| } | ||
|
|
||
| testWidgets('entirely overlapping, direct child', (WidgetTester tester) async { |
There was a problem hiding this comment.
Future me who may have to debug these in the future wishes there were diagrams on these too
| /// For example, a rectangular elevation at 3.0 that is painted before an | ||
| /// overlapping rectangular elevation at 2.0 would render this way on Android | ||
| /// and iOS (with fake shadows): | ||
| /// ┌───────────────────┐ |
There was a problem hiding this comment.
nit: should these be enclosed in ``` to ensure they render with a fixed-width font in dartdocs?
jacob314
left a comment
There was a problem hiding this comment.
Thanks for the heads up! I've filed flutter/devtools#508
to track adding this service extension to devtools.
* master: (209 commits) Allow mouse hover to only respond to some mouse events but not all. (flutter#30886) Fix issue 23527: Exception: RenderViewport exceeded its maximum number of layout cycles (flutter#30809) Keep hover annotation layers in sync with the mouse detector. (flutter#30829) Use identical instead of '==' in a constant expression. (flutter#30921) Add toggle for debugProfileWidgetBuilds (flutter#30867) Revert "Manual engine roll with disabled service authentication codes (flutter#30919)" (flutter#30930) Manual engine roll with disabled service authentication codes (flutter#30919) Baseline Aligned Row (flutter#30746) [Material] Fix showDialog crasher caused by old contexts (flutter#30754) Let `sliver.dart` `_createErrorWidget` work with other Widgets (flutter#30880) Add more dialog doc cross-reference (flutter#30887) Allow downloading of desktop embedding artifacts (flutter#30648) CupertinoDatePicker initialDateTime accounts for minuteInterval (flutter#30862) add golden tests for CupertinoDatePicker (flutter#30828) Simplify toImage future handling (flutter#30876) Fixed Table flex column layout error flutter#30437 (flutter#30470) Fix iTunes Transporter quirk (flutter#30883) Bump Android build tools to 28.0.3 in Dockerfile (flutter#30832) Update the upload key which seems to have trouble for some reason (flutter#30871) Check for invalid elevations (flutter#30215) ...
|
Apologies if mentioned above - are there plans to allow iOS/Android to render in elevation order? If not, is there a best practice for bringing a widget out of a multi child? I've tried a few things, but the only way I've found to avoid typing the widget code out in 2 places is GlobalKey.currentWidget |
Description
Today, Android and iOS render in painting order regaredless of elevation. Fuchsia renders in elevation order regardless of painting order. This can lead to vastly different rendering output between the two platforms, particularly when stacks are involved.
This test expects that overlapping layers at the same z-index will be handled in some other way, and are valid.
This patch creates a check at the layer tree level for invalid elevation with regard to painting order in
PhysicalModelLayers. This is a recording with the check turned on in some parts of the Flutter Gallery that currently violate this.The key to turn this on from the console is
z. Alternatively, it can be programatically enabled via thedebugCheckElevationsEnabledservice extension, or by settingdebugCheckElevationsEnabledto true fromrendering/debug.dart./cc @mklim who is working on related efforts for z-fighting.
/cc @jacob314 and @DanTup - at some point there may be a desire to enable toggling this from the IDE plugins.
Related Issues
Fixes #25673
#27891 - which enabled physical layer compositing on all platforms, making this check possible.
#27137 - which was an initial attempt at this that fails we can't trust a call to
painton the widgets being tested.Tests
I added the following tests:
Checklist
Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes (
[x]). This will ensure a smooth and quick review process.///).flutter analyze --flutter-repo) does not report any problems on my PR.Breaking Change
Does your PR require Flutter developers to manually update their apps to accommodate your change?