Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 68f9225

Browse files
authored
[Impeller] New impeller round rect class (#55946)
Impeller geometry class analogous to SkRRect - soon to be the standard round rectangle class throughout most of the engine that doesn't talk directly to Skia. More unit tests are being written, but this PR will enable developers to look at the API of the new class and comment as well as test its effect on any goldens (there should be none).
1 parent 53e187a commit 68f9225

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1773
-428
lines changed

ci/licenses_golden/excluded_files

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@
178178
../../../flutter/impeller/geometry/matrix_unittests.cc
179179
../../../flutter/impeller/geometry/path_unittests.cc
180180
../../../flutter/impeller/geometry/rect_unittests.cc
181+
../../../flutter/impeller/geometry/round_rect_unittests.cc
181182
../../../flutter/impeller/geometry/saturated_math_unittests.cc
182183
../../../flutter/impeller/geometry/size_unittests.cc
183184
../../../flutter/impeller/geometry/trig_unittests.cc

ci/licenses_golden/licenses_flutter

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42931,6 +42931,8 @@ ORIGIN: ../../../flutter/impeller/geometry/quaternion.cc + ../../../flutter/LICE
4293142931
ORIGIN: ../../../flutter/impeller/geometry/quaternion.h + ../../../flutter/LICENSE
4293242932
ORIGIN: ../../../flutter/impeller/geometry/rect.cc + ../../../flutter/LICENSE
4293342933
ORIGIN: ../../../flutter/impeller/geometry/rect.h + ../../../flutter/LICENSE
42934+
ORIGIN: ../../../flutter/impeller/geometry/round_rect.cc + ../../../flutter/LICENSE
42935+
ORIGIN: ../../../flutter/impeller/geometry/round_rect.h + ../../../flutter/LICENSE
4293442936
ORIGIN: ../../../flutter/impeller/geometry/saturated_math.h + ../../../flutter/LICENSE
4293542937
ORIGIN: ../../../flutter/impeller/geometry/scalar.h + ../../../flutter/LICENSE
4293642938
ORIGIN: ../../../flutter/impeller/geometry/separated_vector.cc + ../../../flutter/LICENSE
@@ -45801,6 +45803,8 @@ FILE: ../../../flutter/impeller/geometry/quaternion.cc
4580145803
FILE: ../../../flutter/impeller/geometry/quaternion.h
4580245804
FILE: ../../../flutter/impeller/geometry/rect.cc
4580345805
FILE: ../../../flutter/impeller/geometry/rect.h
45806+
FILE: ../../../flutter/impeller/geometry/round_rect.cc
45807+
FILE: ../../../flutter/impeller/geometry/round_rect.h
4580445808
FILE: ../../../flutter/impeller/geometry/saturated_math.h
4580545809
FILE: ../../../flutter/impeller/geometry/scalar.h
4580645810
FILE: ../../../flutter/impeller/geometry/separated_vector.cc

display_list/benchmarking/dl_complexity_gl.cc

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,8 @@ void DisplayListGLComplexityCalculator::GLHelper::drawCircle(
237237
AccumulateComplexity(complexity);
238238
}
239239

240-
void DisplayListGLComplexityCalculator::GLHelper::drawRRect(
241-
const SkRRect& rrect) {
240+
void DisplayListGLComplexityCalculator::GLHelper::drawRoundRect(
241+
const DlRoundRect& rrect) {
242242
if (IsComplex()) {
243243
return;
244244
}
@@ -257,14 +257,15 @@ void DisplayListGLComplexityCalculator::GLHelper::drawRRect(
257257
// approximately matching the measured data, normalising the data so that
258258
// 0.0005ms resulted in a score of 100 then simplifying down the formula.
259259
if (DrawStyle() == DlDrawStyle::kFill ||
260-
((rrect.getType() == SkRRect::Type::kSimple_Type) && IsAntiAliased())) {
261-
unsigned int area = rrect.width() * rrect.height();
260+
((rrect.GetRadii().AreAllCornersSame()) && IsAntiAliased())) {
261+
unsigned int area = rrect.GetBounds().Area();
262262
// m = 1/3200
263263
// c = 0.5
264264
complexity = (area + 1600) / 80;
265265
} else {
266266
// Take the average of the width and height.
267-
unsigned int length = (rrect.width() + rrect.height()) / 2;
267+
unsigned int length =
268+
(rrect.GetBounds().GetWidth() + rrect.GetBounds().GetHeight()) / 2;
268269

269270
// There is some difference between hairline and non-hairline performance
270271
// but the spread is relatively inconsistent and it's pretty much a wash.
@@ -282,9 +283,9 @@ void DisplayListGLComplexityCalculator::GLHelper::drawRRect(
282283
AccumulateComplexity(complexity);
283284
}
284285

285-
void DisplayListGLComplexityCalculator::GLHelper::drawDRRect(
286-
const SkRRect& outer,
287-
const SkRRect& inner) {
286+
void DisplayListGLComplexityCalculator::GLHelper::drawDiffRoundRect(
287+
const DlRoundRect& outer,
288+
const DlRoundRect& inner) {
288289
if (IsComplex()) {
289290
return;
290291
}
@@ -307,8 +308,8 @@ void DisplayListGLComplexityCalculator::GLHelper::drawDRRect(
307308
// There is also a kStrokeAndFill_Style that Skia exposes, but we do not
308309
// currently use it anywhere in Flutter.
309310
if (DrawStyle() == DlDrawStyle::kFill) {
310-
unsigned int area = outer.width() * outer.height();
311-
if (outer.getType() == SkRRect::Type::kComplex_Type) {
311+
unsigned int area = outer.GetBounds().Area();
312+
if (!outer.GetRadii().AreAllCornersSame()) {
312313
// m = 1/500
313314
// c = 0.5
314315
complexity = (area + 250) / 5;
@@ -318,7 +319,8 @@ void DisplayListGLComplexityCalculator::GLHelper::drawDRRect(
318319
complexity = (area + 3200) / 16;
319320
}
320321
} else {
321-
unsigned int length = (outer.width() + outer.height()) / 2;
322+
unsigned int length =
323+
(outer.GetBounds().GetWidth() + outer.GetBounds().GetHeight()) / 2;
322324
if (IsAntiAliased()) {
323325
// m = 1/15
324326
// c = 1

display_list/benchmarking/dl_complexity_gl.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,9 @@ class DisplayListGLComplexityCalculator
4848
void drawRect(const DlRect& rect) override;
4949
void drawOval(const DlRect& bounds) override;
5050
void drawCircle(const DlPoint& center, DlScalar radius) override;
51-
void drawRRect(const SkRRect& rrect) override;
52-
void drawDRRect(const SkRRect& outer, const SkRRect& inner) override;
51+
void drawRoundRect(const DlRoundRect& rrect) override;
52+
void drawDiffRoundRect(const DlRoundRect& outer,
53+
const DlRoundRect& inner) override;
5354
void drawPath(const DlPath& path) override;
5455
void drawArc(const DlRect& oval_bounds,
5556
DlScalar start_degrees,

display_list/benchmarking/dl_complexity_metal.cc

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -242,21 +242,20 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawCircle(
242242
AccumulateComplexity(complexity);
243243
}
244244

245-
void DisplayListMetalComplexityCalculator::MetalHelper::drawRRect(
246-
const SkRRect& rrect) {
245+
void DisplayListMetalComplexityCalculator::MetalHelper::drawRoundRect(
246+
const DlRoundRect& rrect) {
247247
if (IsComplex()) {
248248
return;
249249
}
250250
// RRects scale linearly with the area of the bounding rect.
251-
unsigned int area = rrect.width() * rrect.height();
251+
unsigned int area = rrect.GetBounds().Area();
252252

253253
// Drawing RRects is split into two performance tiers; an expensive
254254
// one and a less expensive one. Both scale linearly with area.
255255
//
256256
// Expensive: All filled style, symmetric w/AA.
257-
bool expensive =
258-
(DrawStyle() == DlDrawStyle::kFill) ||
259-
((rrect.getType() == SkRRect::Type::kSimple_Type) && IsAntiAliased());
257+
bool expensive = (DrawStyle() == DlDrawStyle::kFill) ||
258+
(rrect.GetRadii().AreAllCornersSame() && IsAntiAliased());
260259

261260
unsigned int complexity;
262261

@@ -278,9 +277,9 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawRRect(
278277
AccumulateComplexity(complexity);
279278
}
280279

281-
void DisplayListMetalComplexityCalculator::MetalHelper::drawDRRect(
282-
const SkRRect& outer,
283-
const SkRRect& inner) {
280+
void DisplayListMetalComplexityCalculator::MetalHelper::drawDiffRoundRect(
281+
const DlRoundRect& outer,
282+
const DlRoundRect& inner) {
284283
if (IsComplex()) {
285284
return;
286285
}
@@ -293,7 +292,8 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawDRRect(
293292
// a) and c) scale linearly with the area, b) and d) scale linearly with
294293
// a single dimension (length). In all cases, the dimensions refer to
295294
// the outer RRect.
296-
unsigned int length = (outer.width() + outer.height()) / 2;
295+
unsigned int length =
296+
(outer.GetBounds().GetWidth() + outer.GetBounds().GetHeight()) / 2;
297297

298298
unsigned int complexity;
299299

@@ -304,8 +304,8 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawDRRect(
304304
// There is also a kStrokeAndFill_Style that Skia exposes, but we do not
305305
// currently use it anywhere in Flutter.
306306
if (DrawStyle() == DlDrawStyle::kFill) {
307-
unsigned int area = outer.width() * outer.height();
308-
if (outer.getType() == SkRRect::Type::kComplex_Type) {
307+
unsigned int area = outer.GetBounds().Area();
308+
if (!outer.GetRadii().AreAllCornersSame()) {
309309
// m = 1/1000
310310
// c = 1
311311
complexity = (area + 1000) / 10;

display_list/benchmarking/dl_complexity_metal.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,9 @@ class DisplayListMetalComplexityCalculator
4848
void drawRect(const DlRect& rect) override;
4949
void drawOval(const DlRect& bounds) override;
5050
void drawCircle(const DlPoint& center, DlScalar radius) override;
51-
void drawRRect(const SkRRect& rrect) override;
52-
void drawDRRect(const SkRRect& outer, const SkRRect& inner) override;
51+
void drawRoundRect(const DlRoundRect& rrect) override;
52+
void drawDiffRoundRect(const DlRoundRect& outer,
53+
const DlRoundRect& inner) override;
5354
void drawPath(const DlPath& path) override;
5455
void drawArc(const DlRect& oval_bounds,
5556
DlScalar start_degrees,

display_list/display_list.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -310,11 +310,11 @@ DisplayListOpCategory DisplayList::GetOpCategory(DisplayListOpType type) {
310310

311311
case DisplayListOpType::kClipIntersectRect:
312312
case DisplayListOpType::kClipIntersectOval:
313-
case DisplayListOpType::kClipIntersectRRect:
313+
case DisplayListOpType::kClipIntersectRoundRect:
314314
case DisplayListOpType::kClipIntersectPath:
315315
case DisplayListOpType::kClipDifferenceRect:
316316
case DisplayListOpType::kClipDifferenceOval:
317-
case DisplayListOpType::kClipDifferenceRRect:
317+
case DisplayListOpType::kClipDifferenceRoundRect:
318318
case DisplayListOpType::kClipDifferencePath:
319319
return DisplayListOpCategory::kClip;
320320

@@ -325,8 +325,8 @@ DisplayListOpCategory DisplayList::GetOpCategory(DisplayListOpType type) {
325325
case DisplayListOpType::kDrawRect:
326326
case DisplayListOpType::kDrawOval:
327327
case DisplayListOpType::kDrawCircle:
328-
case DisplayListOpType::kDrawRRect:
329-
case DisplayListOpType::kDrawDRRect:
328+
case DisplayListOpType::kDrawRoundRect:
329+
case DisplayListOpType::kDrawDiffRoundRect:
330330
case DisplayListOpType::kDrawArc:
331331
case DisplayListOpType::kDrawPath:
332332
case DisplayListOpType::kDrawPoints:

display_list/display_list.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,11 @@ namespace flutter {
100100
\
101101
V(ClipIntersectRect) \
102102
V(ClipIntersectOval) \
103-
V(ClipIntersectRRect) \
103+
V(ClipIntersectRoundRect) \
104104
V(ClipIntersectPath) \
105105
V(ClipDifferenceRect) \
106106
V(ClipDifferenceOval) \
107-
V(ClipDifferenceRRect) \
107+
V(ClipDifferenceRoundRect) \
108108
V(ClipDifferencePath) \
109109
\
110110
V(DrawPaint) \
@@ -115,8 +115,8 @@ namespace flutter {
115115
V(DrawRect) \
116116
V(DrawOval) \
117117
V(DrawCircle) \
118-
V(DrawRRect) \
119-
V(DrawDRRect) \
118+
V(DrawRoundRect) \
119+
V(DrawDiffRoundRect) \
120120
V(DrawArc) \
121121
V(DrawPath) \
122122
\

display_list/display_list_unittests.cc

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2947,7 +2947,7 @@ TEST_F(DisplayListTest, ClipRRectTriggersDeferredSave) {
29472947
{
29482948
builder1.Save();
29492949
{
2950-
builder1.ClipRRect(kTestRRect, ClipOp::kIntersect, true);
2950+
builder1.ClipRRect(kTestSkRRect, ClipOp::kIntersect, true);
29512951

29522952
builder1.DrawRect(SkRect{0, 0, 100, 100}, DlPaint());
29532953
}
@@ -2963,7 +2963,7 @@ TEST_F(DisplayListTest, ClipRRectTriggersDeferredSave) {
29632963

29642964
DisplayListBuilder builder2;
29652965
builder2.Save();
2966-
builder2.ClipRRect(kTestRRect, ClipOp::kIntersect, true);
2966+
builder2.ClipRRect(kTestSkRRect, ClipOp::kIntersect, true);
29672967

29682968
builder2.DrawRect(SkRect{0, 0, 100, 100}, DlPaint());
29692969
builder2.Restore();
@@ -4538,7 +4538,7 @@ TEST_F(DisplayListTest, DrawDisplayListForwardsBackdropFlag) {
45384538
#define CLIP_EXPECTOR(name) ClipExpector name(__FILE__, __LINE__)
45394539

45404540
struct ClipExpectation {
4541-
std::variant<DlRect, SkRRect, DlPath> shape;
4541+
std::variant<DlRect, DlRoundRect, DlPath> shape;
45424542
bool is_oval;
45434543
ClipOp clip_op;
45444544
bool is_aa;
@@ -4548,7 +4548,7 @@ struct ClipExpectation {
45484548
case 0:
45494549
return is_oval ? "SkOval" : "SkRect";
45504550
case 1:
4551-
return "SkRRect";
4551+
return "DlRoundRect";
45524552
case 2:
45534553
return "DlPath";
45544554
default:
@@ -4567,7 +4567,7 @@ ::std::ostream& operator<<(::std::ostream& os, const ClipExpectation& expect) {
45674567
}
45684568
break;
45694569
case 1:
4570-
os << std::get<SkRRect>(expect.shape);
4570+
os << std::get<DlRoundRect>(expect.shape);
45714571
break;
45724572
case 2:
45734573
os << std::get<DlPath>(expect.shape).GetSkPath();
@@ -4626,8 +4626,10 @@ class ClipExpector : public virtual DlOpReceiver,
46264626
ClipExpector& addExpectation(const SkRRect& rrect,
46274627
ClipOp clip_op = ClipOp::kIntersect,
46284628
bool is_aa = false) {
4629+
auto dl_rrect = ToDlRoundRect(rrect);
4630+
EXPECT_EQ(ToSkRRect(dl_rrect), rrect);
46294631
clip_expectations_.push_back({
4630-
.shape = rrect,
4632+
.shape = dl_rrect,
46314633
.is_oval = false,
46324634
.clip_op = clip_op,
46334635
.is_aa = is_aa,
@@ -4663,9 +4665,9 @@ class ClipExpector : public virtual DlOpReceiver,
46634665
bool is_aa) override {
46644666
check(bounds, clip_op, is_aa, true);
46654667
}
4666-
void clipRRect(const SkRRect& rrect,
4667-
DlCanvas::ClipOp clip_op,
4668-
bool is_aa) override {
4668+
void clipRoundRect(const DlRoundRect& rrect,
4669+
DlCanvas::ClipOp clip_op,
4670+
bool is_aa) override {
46694671
check(rrect, clip_op, is_aa);
46704672
}
46714673
void clipPath(const DlPath& path,

display_list/dl_builder.cc

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -995,15 +995,15 @@ void DisplayListBuilder::ClipOval(const DlRect& bounds,
995995
break;
996996
}
997997
}
998-
void DisplayListBuilder::ClipRRect(const SkRRect& rrect,
999-
ClipOp clip_op,
1000-
bool is_aa) {
1001-
if (rrect.isRect()) {
1002-
ClipRect(ToDlRect(rrect.rect()), clip_op, is_aa);
998+
void DisplayListBuilder::ClipRoundRect(const DlRoundRect& rrect,
999+
ClipOp clip_op,
1000+
bool is_aa) {
1001+
if (rrect.IsRect()) {
1002+
ClipRect(rrect.GetBounds(), clip_op, is_aa);
10031003
return;
10041004
}
1005-
if (rrect.isOval()) {
1006-
ClipOval(ToDlRect(rrect.rect()), clip_op, is_aa);
1005+
if (rrect.IsOval()) {
1006+
ClipOval(rrect.GetBounds(), clip_op, is_aa);
10071007
return;
10081008
}
10091009
if (current_info().is_nop) {
@@ -1025,10 +1025,10 @@ void DisplayListBuilder::ClipRRect(const SkRRect& rrect,
10251025
checkForDeferredSave();
10261026
switch (clip_op) {
10271027
case ClipOp::kIntersect:
1028-
Push<ClipIntersectRRectOp>(0, rrect, is_aa);
1028+
Push<ClipIntersectRoundRectOp>(0, rrect, is_aa);
10291029
break;
10301030
case ClipOp::kDifference:
1031-
Push<ClipDifferenceRRectOp>(0, rrect, is_aa);
1031+
Push<ClipDifferenceRoundRectOp>(0, rrect, is_aa);
10321032
break;
10331033
}
10341034
}
@@ -1185,42 +1185,43 @@ void DisplayListBuilder::DrawCircle(const DlPoint& center,
11851185
SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawCircleFlags);
11861186
drawCircle(center, radius);
11871187
}
1188-
void DisplayListBuilder::drawRRect(const SkRRect& rrect) {
1189-
if (rrect.isRect()) {
1190-
drawRect(ToDlRect(rrect.rect()));
1191-
} else if (rrect.isOval()) {
1192-
drawOval(ToDlRect(rrect.rect()));
1188+
void DisplayListBuilder::drawRoundRect(const DlRoundRect& rrect) {
1189+
if (rrect.IsRect()) {
1190+
drawRect(rrect.GetBounds());
1191+
} else if (rrect.IsOval()) {
1192+
drawOval(rrect.GetBounds());
11931193
} else {
11941194
DisplayListAttributeFlags flags = kDrawRRectFlags;
11951195
OpResult result = PaintResult(current_, flags);
11961196
if (result != OpResult::kNoEffect &&
1197-
AccumulateOpBounds(rrect.getBounds(), flags)) {
1198-
Push<DrawRRectOp>(0, rrect);
1197+
AccumulateOpBounds(ToSkRect(rrect.GetBounds()), flags)) {
1198+
Push<DrawRoundRectOp>(0, rrect);
11991199
CheckLayerOpacityCompatibility();
12001200
UpdateLayerResult(result);
12011201
}
12021202
}
12031203
}
1204-
void DisplayListBuilder::DrawRRect(const SkRRect& rrect, const DlPaint& paint) {
1204+
void DisplayListBuilder::DrawRoundRect(const DlRoundRect& rrect,
1205+
const DlPaint& paint) {
12051206
SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawRRectFlags);
1206-
drawRRect(rrect);
1207+
drawRoundRect(rrect);
12071208
}
1208-
void DisplayListBuilder::drawDRRect(const SkRRect& outer,
1209-
const SkRRect& inner) {
1209+
void DisplayListBuilder::drawDiffRoundRect(const DlRoundRect& outer,
1210+
const DlRoundRect& inner) {
12101211
DisplayListAttributeFlags flags = kDrawDRRectFlags;
12111212
OpResult result = PaintResult(current_, flags);
12121213
if (result != OpResult::kNoEffect &&
1213-
AccumulateOpBounds(outer.getBounds(), flags)) {
1214-
Push<DrawDRRectOp>(0, outer, inner);
1214+
AccumulateOpBounds(ToSkRect(outer.GetBounds()), flags)) {
1215+
Push<DrawDiffRoundRectOp>(0, outer, inner);
12151216
CheckLayerOpacityCompatibility();
12161217
UpdateLayerResult(result);
12171218
}
12181219
}
1219-
void DisplayListBuilder::DrawDRRect(const SkRRect& outer,
1220-
const SkRRect& inner,
1221-
const DlPaint& paint) {
1220+
void DisplayListBuilder::DrawDiffRoundRect(const DlRoundRect& outer,
1221+
const DlRoundRect& inner,
1222+
const DlPaint& paint) {
12221223
SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawDRRectFlags);
1223-
drawDRRect(outer, inner);
1224+
drawDiffRoundRect(outer, inner);
12241225
}
12251226
void DisplayListBuilder::drawPath(const DlPath& path) {
12261227
DisplayListAttributeFlags flags = kDrawPathFlags;

0 commit comments

Comments
 (0)