You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Rendering errors with Rect.largest when used with toImage (e.g. gold image tests) using impeller #144643
If you run the following using flutter test --enable-impeller, you get a test.png containing a hollow square with the top left corner damaged, but it should just be a hollow square:
// Copyright 2014 The Flutter 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'dart:io';
import'dart:ui';
constdouble z =1000000000; // aka _giantScalar, used in Rect.largestvoidmain() async {
finalPictureRecorder recorder =PictureRecorder();
finalCanvas canvas =Canvas(recorder);
finalPath clip =Path()
..fillType =PathFillType.evenOdd
..addRect(constRect.fromLTRB(-z, -z, z, z))
..addRect(constOffset(50.0, 50.0) &constSize(100.0, 100.0));
canvas.clipPath(clip);
canvas.drawPaint(Paint()..color =constColor(0xFF33CC66));
finalPicture picture = recorder.endRecording();
awaitFile('test.png').writeAsBytes((await (await picture.toImage(200, 200)).toByteData(format:ImageByteFormat.png))!.buffer.asUint8List());
}
I dunno man, the old version had more correct pixels. ;-)
(But yeah looks like maybe we had two bugs, and now we're down to one? The original rendering was pretty strange.)
// Copyright 2014 The Flutter 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'dart:io';
import'dart:ui';
constdouble z =1000000000; // aka _giantScalar, used in Rect.largestvoidmain() async {
finalPictureRecorder recorder =PictureRecorder();
finalCanvas canvas =Canvas(recorder);
canvas.drawCircle(constOffset(12.0, 12.0), 10.0, Paint()..color =constColor(0xFFFF0000)); // should be obscured
canvas.drawRect(constRect.fromLTRB(-z, -z, z, z), Paint()..color =constColor(0xFF00FF00)); // should cover everything finalPicture picture = recorder.endRecording();
awaitFile('test.png').writeAsBytes((await (await picture.toImage(200, 200)).toByteData(format:ImageByteFormat.png))!.buffer.asUint8List());
}
You would expect a 200x200 green square, but instead you get:
The red circle should get obscured but the rectangle doesn't paint to the left of x=18.
Ok after further investigation, I am indeed finding that I can't reproduce this with Impeller when rendering to a real device (I tried Android and Linux with @jason-simmons' patch).
I was playing with this some more to try to get inspiration about what the bug could be (I traced this through a bunch of Impeller, logging out coordinates and so on, without finding anything wrong) and found a rectangle that renders wildly wrong again, similar to the original failure. So removing libtess2 didn't improve matters, it just made them different.
In the following snippets, "..." should be replaced with a path to the directory containing the flutter and engine checkouts.
// Copyright 2014 The Flutter 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'dart:async';
import'dart:io';
import'dart:typed_data';
import'dart:ui';
constdouble z =1000000000; // 1e9voidmain() async {
finalTimer timer =Timer.periodic(constDuration(seconds:1), (Timer timer) { });
finalPictureRecorder recorder =PictureRecorder();
finalCanvas canvas =Canvas(recorder);
canvas.drawCircle(constOffset(12.0, 12.0), 10.0, Paint()..color =constColor(0xFFFF0000)); // should be obscured
canvas.drawRect(constRect.fromLTRB(-z, -z, z/7, z/3), Paint()..color =constColor(0xFF009900)); // should cover everythingfinalPicture picture = recorder.endRecording();
finalImage image = picture.toImageSync(100, 100);
finalByteData? bytes =await image.toByteData(format:ImageByteFormat.png);
awaitFile('/.../test.png').writeAsBytes(bytes!.buffer.asUint8List());
timer.cancel();
}
changed the title [-]Rendering errors with clip paths with very large numbers[/-][+]Rendering errors with rects with very large numbers when used with toImage (e.g. gold image tests)[/+]on Mar 24, 2024
The rendering errors reproduce in renderdoc when using the llvmpipe ICD if you capture the above rendering, and notably change as you change the zoom level. I think this means this is probably an upstream bug in the mesa drivers. I wonder if we should consider reducing Rect.largest to use 1e8 instead of 1e9 for now.
changed the title [-]Rendering errors with rects with very large numbers when used with toImage (e.g. gold image tests)[/-][+]Rendering errors with Rect.largest when used with toImage (e.g. gold image tests)[/+]on Mar 26, 2024
changed the title [-]Rendering errors with Rect.largest when used with toImage (e.g. gold image tests)[/-][+]Rendering errors with Rect.largest when used with toImage (e.g. gold image tests) using impeller[/+]on Mar 26, 2024
Activity
jonahwilliams commentedon Mar 5, 2024
We're going to very quickly learn if this is a bug in entities or a bug in libtess...
#144647 is the PR that switches the technique used to render evenOdd paths
jonahwilliams commentedon Mar 6, 2024
I can reproduce this before: #144659 but not after. I suspect switching to Stencil then Cover and removing the usage of libtess2 has fixed this issue.
dnfield commentedon Mar 6, 2024
We should still probably try to clean this up, since libtess2 will be a fallback path for some cases right?
dnfield commentedon Mar 6, 2024
Disregard, the plan is to drop libtess2 and related codepaths once StC sticks.
jonahwilliams commentedon Mar 6, 2024
right, libtess2 will be deleted!
Hixie commentedon Mar 6, 2024
On trunk I get this:

...which is still wrong, it's missing 20 pixels on the left side.
jonahwilliams commentedon Mar 6, 2024
seems less wrong though :)
Hixie commentedon Mar 6, 2024
I dunno man, the old version had more correct pixels. ;-)
(But yeah looks like maybe we had two bugs, and now we're down to one? The original rendering was pretty strange.)
Hixie commentedon Mar 8, 2024
This repros the problem without clips:
You would expect a 200x200 green square, but instead you get:

The red circle should get obscured but the rectangle doesn't paint to the left of x=18.
cc @flar since @chinmaygarde mentioned you've been working in this area
Hixie commentedon Mar 18, 2024
Hixie commentedon Mar 19, 2024
Ok after further investigation, I am indeed finding that I can't reproduce this with Impeller when rendering to a real device (I tried Android and Linux with @jason-simmons' patch).
Hixie commentedon Mar 22, 2024
I was playing with this some more to try to get inspiration about what the bug could be (I traced this through a bunch of Impeller, logging out coordinates and so on, without finding anything wrong) and found a rectangle that renders wildly wrong again, similar to the original failure. So removing libtess2 didn't improve matters, it just made them different.
In the following snippets, "..." should be replaced with a path to the directory containing the
flutterandenginecheckouts.I compile this using:
...and run it using:
The result should be a 100x100 green PNG, but is instead:
[-]Rendering errors with clip paths with very large numbers[/-][+]Rendering errors with rects with very large numbers when used with toImage (e.g. gold image tests)[/+]Hixie commentedon Mar 26, 2024
Ok I have a pure impeller repro:
Compile and run with:
gclient sync -D flutter/tools/gn --unopt ninja -C out/host_debug_unopt out/host_debug_unopt/impeller_unittests --gtest_filter="*Repro144643/Vulkan" --enable_playground --use_swiftshaderOutput looks like this:
Notice that it should cover the whole window but is missing a bit on the left. Different sizes change the intensity of the effect, e.g.:
Hixie commentedon Mar 26, 2024
You get particularly weird results with:
contents->SetGeometry(Geometry::MakeRect(Rect::MakeLTRB(-1e9, -1e9, 1e9/7.0, 1e9/3.0)));Hixie commentedon Mar 26, 2024
The rendering errors reproduce in renderdoc when using the llvmpipe ICD if you capture the above rendering, and notably change as you change the zoom level. I think this means this is probably an upstream bug in the mesa drivers. I wonder if we should consider reducing Rect.largest to use 1e8 instead of 1e9 for now.
[-]Rendering errors with rects with very large numbers when used with toImage (e.g. gold image tests)[/-][+]Rendering errors with Rect.largest when used with toImage (e.g. gold image tests)[/+][-]Rendering errors with Rect.largest when used with toImage (e.g. gold image tests)[/-][+]Rendering errors with Rect.largest when used with toImage (e.g. gold image tests) using impeller[/+]