Skip to content

Commit 34725bc

Browse files
flarmboetger
authored andcommitted
[Impeller] Fix overdraw in DrawRect geometry (flutter#174735)
Fixes flutter#174579 Vertex lists for stroked rects were fixed by being more careful about the creation of the vertices so that they have no inherent overdraw. These operations continue to use the fastest kNormal vertex mode but no longer create rendering artifacts due to multiple triangles covering the same area.
1 parent 37c81c1 commit 34725bc

File tree

3 files changed

+248
-77
lines changed

3 files changed

+248
-77
lines changed

engine/src/flutter/impeller/display_list/aiks_dl_basic_unittests.cc

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,75 @@ TEST_P(AiksTest, CanRenderColoredRect) {
3535
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
3636
}
3737

38+
namespace {
39+
using DrawRectProc =
40+
std::function<void(DisplayListBuilder&, const DlRect&, const DlPaint&)>;
41+
42+
sk_sp<DisplayList> MakeWideStrokedRects(Point scale,
43+
const DrawRectProc& draw_rect) {
44+
DisplayListBuilder builder;
45+
builder.Scale(scale.x, scale.y);
46+
builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
47+
48+
DlPaint paint;
49+
paint.setColor(DlColor::kBlue().withAlphaF(0.5));
50+
paint.setDrawStyle(DlDrawStyle::kStroke);
51+
paint.setStrokeWidth(30.0f);
52+
53+
// Each of these 3 sets of rects includes (with different join types):
54+
// - One rectangle with a gap in the middle
55+
// - One rectangle with no gap because it is too narrow
56+
// - One rectangle with no gap because it is too short
57+
paint.setStrokeJoin(DlStrokeJoin::kBevel);
58+
draw_rect(builder, DlRect::MakeXYWH(100.0f, 100.0f, 100.0f, 100.0f), paint);
59+
draw_rect(builder, DlRect::MakeXYWH(250.0f, 100.0f, 10.0f, 100.0f), paint);
60+
draw_rect(builder, DlRect::MakeXYWH(100.0f, 250.0f, 100.0f, 10.0f), paint);
61+
62+
paint.setStrokeJoin(DlStrokeJoin::kRound);
63+
draw_rect(builder, DlRect::MakeXYWH(350.0f, 100.0f, 100.0f, 100.0f), paint);
64+
draw_rect(builder, DlRect::MakeXYWH(500.0f, 100.0f, 10.0f, 100.0f), paint);
65+
draw_rect(builder, DlRect::MakeXYWH(350.0f, 250.0f, 100.0f, 10.0f), paint);
66+
67+
paint.setStrokeJoin(DlStrokeJoin::kMiter);
68+
draw_rect(builder, DlRect::MakeXYWH(600.0f, 100.0f, 100.0f, 100.0f), paint);
69+
draw_rect(builder, DlRect::MakeXYWH(750.0f, 100.0f, 10.0f, 100.0f), paint);
70+
draw_rect(builder, DlRect::MakeXYWH(600.0f, 250.0f, 100.0f, 10.0f), paint);
71+
72+
// And now draw 3 rectangles with a stroke width so large that that it
73+
// overlaps in the middle in both directions (horizontal/vertical).
74+
paint.setStrokeWidth(110.0f);
75+
76+
paint.setStrokeJoin(DlStrokeJoin::kBevel);
77+
draw_rect(builder, DlRect::MakeXYWH(100.0f, 400.0f, 100.0f, 100.0f), paint);
78+
79+
paint.setStrokeJoin(DlStrokeJoin::kRound);
80+
draw_rect(builder, DlRect::MakeXYWH(350.0f, 400.0f, 100.0f, 100.0f), paint);
81+
82+
paint.setStrokeJoin(DlStrokeJoin::kMiter);
83+
draw_rect(builder, DlRect::MakeXYWH(600.0f, 400.0f, 100.0f, 100.0f), paint);
84+
85+
return builder.Build();
86+
}
87+
} // namespace
88+
89+
TEST_P(AiksTest, CanRenderWideStrokedRectWithoutOverlap) {
90+
ASSERT_TRUE(OpenPlaygroundHere(MakeWideStrokedRects(
91+
GetContentScale(), [](DisplayListBuilder& builder, const DlRect& rect,
92+
const DlPaint& paint) {
93+
// Draw the rect directly
94+
builder.DrawRect(rect, paint);
95+
})));
96+
}
97+
98+
TEST_P(AiksTest, CanRenderWideStrokedRectPathWithoutOverlap) {
99+
ASSERT_TRUE(OpenPlaygroundHere(MakeWideStrokedRects(
100+
GetContentScale(), [](DisplayListBuilder& builder, const DlRect& rect,
101+
const DlPaint& paint) {
102+
// Draw the rect as a Path
103+
builder.DrawPath(DlPath::MakeRect(rect), paint);
104+
})));
105+
}
106+
38107
TEST_P(AiksTest, CanRenderImage) {
39108
DisplayListBuilder builder;
40109
DlPaint paint;

0 commit comments

Comments
 (0)