Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Impeller] New impeller round rect class #55946

Merged
merged 3 commits into from
Oct 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ci/licenses_golden/excluded_files
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@
../../../flutter/impeller/geometry/matrix_unittests.cc
../../../flutter/impeller/geometry/path_unittests.cc
../../../flutter/impeller/geometry/rect_unittests.cc
../../../flutter/impeller/geometry/round_rect_unittests.cc
../../../flutter/impeller/geometry/saturated_math_unittests.cc
../../../flutter/impeller/geometry/size_unittests.cc
../../../flutter/impeller/geometry/trig_unittests.cc
Expand Down
4 changes: 4 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -42931,6 +42931,8 @@ ORIGIN: ../../../flutter/impeller/geometry/quaternion.cc + ../../../flutter/LICE
ORIGIN: ../../../flutter/impeller/geometry/quaternion.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/geometry/rect.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/geometry/rect.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/geometry/round_rect.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/geometry/round_rect.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/geometry/saturated_math.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/geometry/scalar.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/geometry/separated_vector.cc + ../../../flutter/LICENSE
Expand Down Expand Up @@ -45801,6 +45803,8 @@ FILE: ../../../flutter/impeller/geometry/quaternion.cc
FILE: ../../../flutter/impeller/geometry/quaternion.h
FILE: ../../../flutter/impeller/geometry/rect.cc
FILE: ../../../flutter/impeller/geometry/rect.h
FILE: ../../../flutter/impeller/geometry/round_rect.cc
FILE: ../../../flutter/impeller/geometry/round_rect.h
FILE: ../../../flutter/impeller/geometry/saturated_math.h
FILE: ../../../flutter/impeller/geometry/scalar.h
FILE: ../../../flutter/impeller/geometry/separated_vector.cc
Expand Down
24 changes: 13 additions & 11 deletions display_list/benchmarking/dl_complexity_gl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,8 @@ void DisplayListGLComplexityCalculator::GLHelper::drawCircle(
AccumulateComplexity(complexity);
}

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

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

void DisplayListGLComplexityCalculator::GLHelper::drawDRRect(
const SkRRect& outer,
const SkRRect& inner) {
void DisplayListGLComplexityCalculator::GLHelper::drawDiffRoundRect(
const DlRoundRect& outer,
const DlRoundRect& inner) {
if (IsComplex()) {
return;
}
Expand All @@ -307,8 +308,8 @@ void DisplayListGLComplexityCalculator::GLHelper::drawDRRect(
// There is also a kStrokeAndFill_Style that Skia exposes, but we do not
// currently use it anywhere in Flutter.
if (DrawStyle() == DlDrawStyle::kFill) {
unsigned int area = outer.width() * outer.height();
if (outer.getType() == SkRRect::Type::kComplex_Type) {
unsigned int area = outer.GetBounds().Area();
if (!outer.GetRadii().AreAllCornersSame()) {
// m = 1/500
// c = 0.5
complexity = (area + 250) / 5;
Expand All @@ -318,7 +319,8 @@ void DisplayListGLComplexityCalculator::GLHelper::drawDRRect(
complexity = (area + 3200) / 16;
}
} else {
unsigned int length = (outer.width() + outer.height()) / 2;
unsigned int length =
(outer.GetBounds().GetWidth() + outer.GetBounds().GetHeight()) / 2;
if (IsAntiAliased()) {
// m = 1/15
// c = 1
Expand Down
5 changes: 3 additions & 2 deletions display_list/benchmarking/dl_complexity_gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,9 @@ class DisplayListGLComplexityCalculator
void drawRect(const DlRect& rect) override;
void drawOval(const DlRect& bounds) override;
void drawCircle(const DlPoint& center, DlScalar radius) override;
void drawRRect(const SkRRect& rrect) override;
void drawDRRect(const SkRRect& outer, const SkRRect& inner) override;
void drawRoundRect(const DlRoundRect& rrect) override;
void drawDiffRoundRect(const DlRoundRect& outer,
const DlRoundRect& inner) override;
void drawPath(const DlPath& path) override;
void drawArc(const DlRect& oval_bounds,
DlScalar start_degrees,
Expand Down
24 changes: 12 additions & 12 deletions display_list/benchmarking/dl_complexity_metal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -242,21 +242,20 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawCircle(
AccumulateComplexity(complexity);
}

void DisplayListMetalComplexityCalculator::MetalHelper::drawRRect(
const SkRRect& rrect) {
void DisplayListMetalComplexityCalculator::MetalHelper::drawRoundRect(
const DlRoundRect& rrect) {
if (IsComplex()) {
return;
}
// RRects scale linearly with the area of the bounding rect.
unsigned int area = rrect.width() * rrect.height();
unsigned int area = rrect.GetBounds().Area();

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

unsigned int complexity;

Expand All @@ -278,9 +277,9 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawRRect(
AccumulateComplexity(complexity);
}

void DisplayListMetalComplexityCalculator::MetalHelper::drawDRRect(
const SkRRect& outer,
const SkRRect& inner) {
void DisplayListMetalComplexityCalculator::MetalHelper::drawDiffRoundRect(
const DlRoundRect& outer,
const DlRoundRect& inner) {
if (IsComplex()) {
return;
}
Expand All @@ -293,7 +292,8 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawDRRect(
// a) and c) scale linearly with the area, b) and d) scale linearly with
// a single dimension (length). In all cases, the dimensions refer to
// the outer RRect.
unsigned int length = (outer.width() + outer.height()) / 2;
unsigned int length =
(outer.GetBounds().GetWidth() + outer.GetBounds().GetHeight()) / 2;

unsigned int complexity;

Expand All @@ -304,8 +304,8 @@ void DisplayListMetalComplexityCalculator::MetalHelper::drawDRRect(
// There is also a kStrokeAndFill_Style that Skia exposes, but we do not
// currently use it anywhere in Flutter.
if (DrawStyle() == DlDrawStyle::kFill) {
unsigned int area = outer.width() * outer.height();
if (outer.getType() == SkRRect::Type::kComplex_Type) {
unsigned int area = outer.GetBounds().Area();
if (!outer.GetRadii().AreAllCornersSame()) {
// m = 1/1000
// c = 1
complexity = (area + 1000) / 10;
Expand Down
5 changes: 3 additions & 2 deletions display_list/benchmarking/dl_complexity_metal.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,9 @@ class DisplayListMetalComplexityCalculator
void drawRect(const DlRect& rect) override;
void drawOval(const DlRect& bounds) override;
void drawCircle(const DlPoint& center, DlScalar radius) override;
void drawRRect(const SkRRect& rrect) override;
void drawDRRect(const SkRRect& outer, const SkRRect& inner) override;
void drawRoundRect(const DlRoundRect& rrect) override;
void drawDiffRoundRect(const DlRoundRect& outer,
const DlRoundRect& inner) override;
void drawPath(const DlPath& path) override;
void drawArc(const DlRect& oval_bounds,
DlScalar start_degrees,
Expand Down
8 changes: 4 additions & 4 deletions display_list/display_list.cc
Original file line number Diff line number Diff line change
Expand Up @@ -310,11 +310,11 @@ DisplayListOpCategory DisplayList::GetOpCategory(DisplayListOpType type) {

case DisplayListOpType::kClipIntersectRect:
case DisplayListOpType::kClipIntersectOval:
case DisplayListOpType::kClipIntersectRRect:
case DisplayListOpType::kClipIntersectRoundRect:
case DisplayListOpType::kClipIntersectPath:
case DisplayListOpType::kClipDifferenceRect:
case DisplayListOpType::kClipDifferenceOval:
case DisplayListOpType::kClipDifferenceRRect:
case DisplayListOpType::kClipDifferenceRoundRect:
case DisplayListOpType::kClipDifferencePath:
return DisplayListOpCategory::kClip;

Expand All @@ -325,8 +325,8 @@ DisplayListOpCategory DisplayList::GetOpCategory(DisplayListOpType type) {
case DisplayListOpType::kDrawRect:
case DisplayListOpType::kDrawOval:
case DisplayListOpType::kDrawCircle:
case DisplayListOpType::kDrawRRect:
case DisplayListOpType::kDrawDRRect:
case DisplayListOpType::kDrawRoundRect:
case DisplayListOpType::kDrawDiffRoundRect:
case DisplayListOpType::kDrawArc:
case DisplayListOpType::kDrawPath:
case DisplayListOpType::kDrawPoints:
Expand Down
8 changes: 4 additions & 4 deletions display_list/display_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,11 @@ namespace flutter {
\
V(ClipIntersectRect) \
V(ClipIntersectOval) \
V(ClipIntersectRRect) \
V(ClipIntersectRoundRect) \
V(ClipIntersectPath) \
V(ClipDifferenceRect) \
V(ClipDifferenceOval) \
V(ClipDifferenceRRect) \
V(ClipDifferenceRoundRect) \
V(ClipDifferencePath) \
\
V(DrawPaint) \
Expand All @@ -115,8 +115,8 @@ namespace flutter {
V(DrawRect) \
V(DrawOval) \
V(DrawCircle) \
V(DrawRRect) \
V(DrawDRRect) \
V(DrawRoundRect) \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you!

V(DrawDiffRoundRect) \
V(DrawArc) \
V(DrawPath) \
\
Expand Down
20 changes: 11 additions & 9 deletions display_list/display_list_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2947,7 +2947,7 @@ TEST_F(DisplayListTest, ClipRRectTriggersDeferredSave) {
{
builder1.Save();
{
builder1.ClipRRect(kTestRRect, ClipOp::kIntersect, true);
builder1.ClipRRect(kTestSkRRect, ClipOp::kIntersect, true);

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

DisplayListBuilder builder2;
builder2.Save();
builder2.ClipRRect(kTestRRect, ClipOp::kIntersect, true);
builder2.ClipRRect(kTestSkRRect, ClipOp::kIntersect, true);

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

struct ClipExpectation {
std::variant<DlRect, SkRRect, DlPath> shape;
std::variant<DlRect, DlRoundRect, DlPath> shape;
bool is_oval;
ClipOp clip_op;
bool is_aa;
Expand All @@ -4548,7 +4548,7 @@ struct ClipExpectation {
case 0:
return is_oval ? "SkOval" : "SkRect";
case 1:
return "SkRRect";
return "DlRoundRect";
case 2:
return "DlPath";
default:
Expand All @@ -4567,7 +4567,7 @@ ::std::ostream& operator<<(::std::ostream& os, const ClipExpectation& expect) {
}
break;
case 1:
os << std::get<SkRRect>(expect.shape);
os << std::get<DlRoundRect>(expect.shape);
break;
case 2:
os << std::get<DlPath>(expect.shape).GetSkPath();
Expand Down Expand Up @@ -4626,8 +4626,10 @@ class ClipExpector : public virtual DlOpReceiver,
ClipExpector& addExpectation(const SkRRect& rrect,
ClipOp clip_op = ClipOp::kIntersect,
bool is_aa = false) {
auto dl_rrect = ToDlRoundRect(rrect);
EXPECT_EQ(ToSkRRect(dl_rrect), rrect);
clip_expectations_.push_back({
.shape = rrect,
.shape = dl_rrect,
.is_oval = false,
.clip_op = clip_op,
.is_aa = is_aa,
Expand Down Expand Up @@ -4663,9 +4665,9 @@ class ClipExpector : public virtual DlOpReceiver,
bool is_aa) override {
check(bounds, clip_op, is_aa, true);
}
void clipRRect(const SkRRect& rrect,
DlCanvas::ClipOp clip_op,
bool is_aa) override {
void clipRoundRect(const DlRoundRect& rrect,
DlCanvas::ClipOp clip_op,
bool is_aa) override {
check(rrect, clip_op, is_aa);
}
void clipPath(const DlPath& path,
Expand Down
53 changes: 27 additions & 26 deletions display_list/dl_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -995,15 +995,15 @@ void DisplayListBuilder::ClipOval(const DlRect& bounds,
break;
}
}
void DisplayListBuilder::ClipRRect(const SkRRect& rrect,
ClipOp clip_op,
bool is_aa) {
if (rrect.isRect()) {
ClipRect(ToDlRect(rrect.rect()), clip_op, is_aa);
void DisplayListBuilder::ClipRoundRect(const DlRoundRect& rrect,
ClipOp clip_op,
bool is_aa) {
if (rrect.IsRect()) {
ClipRect(rrect.GetBounds(), clip_op, is_aa);
return;
}
if (rrect.isOval()) {
ClipOval(ToDlRect(rrect.rect()), clip_op, is_aa);
if (rrect.IsOval()) {
ClipOval(rrect.GetBounds(), clip_op, is_aa);
return;
}
if (current_info().is_nop) {
Expand All @@ -1025,10 +1025,10 @@ void DisplayListBuilder::ClipRRect(const SkRRect& rrect,
checkForDeferredSave();
switch (clip_op) {
case ClipOp::kIntersect:
Push<ClipIntersectRRectOp>(0, rrect, is_aa);
Push<ClipIntersectRoundRectOp>(0, rrect, is_aa);
break;
case ClipOp::kDifference:
Push<ClipDifferenceRRectOp>(0, rrect, is_aa);
Push<ClipDifferenceRoundRectOp>(0, rrect, is_aa);
break;
}
}
Expand Down Expand Up @@ -1185,42 +1185,43 @@ void DisplayListBuilder::DrawCircle(const DlPoint& center,
SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawCircleFlags);
drawCircle(center, radius);
}
void DisplayListBuilder::drawRRect(const SkRRect& rrect) {
if (rrect.isRect()) {
drawRect(ToDlRect(rrect.rect()));
} else if (rrect.isOval()) {
drawOval(ToDlRect(rrect.rect()));
void DisplayListBuilder::drawRoundRect(const DlRoundRect& rrect) {
if (rrect.IsRect()) {
drawRect(rrect.GetBounds());
} else if (rrect.IsOval()) {
drawOval(rrect.GetBounds());
} else {
DisplayListAttributeFlags flags = kDrawRRectFlags;
OpResult result = PaintResult(current_, flags);
if (result != OpResult::kNoEffect &&
AccumulateOpBounds(rrect.getBounds(), flags)) {
Push<DrawRRectOp>(0, rrect);
AccumulateOpBounds(ToSkRect(rrect.GetBounds()), flags)) {
Push<DrawRoundRectOp>(0, rrect);
CheckLayerOpacityCompatibility();
UpdateLayerResult(result);
}
}
}
void DisplayListBuilder::DrawRRect(const SkRRect& rrect, const DlPaint& paint) {
void DisplayListBuilder::DrawRoundRect(const DlRoundRect& rrect,
const DlPaint& paint) {
SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawRRectFlags);
drawRRect(rrect);
drawRoundRect(rrect);
}
void DisplayListBuilder::drawDRRect(const SkRRect& outer,
const SkRRect& inner) {
void DisplayListBuilder::drawDiffRoundRect(const DlRoundRect& outer,
const DlRoundRect& inner) {
DisplayListAttributeFlags flags = kDrawDRRectFlags;
OpResult result = PaintResult(current_, flags);
if (result != OpResult::kNoEffect &&
AccumulateOpBounds(outer.getBounds(), flags)) {
Push<DrawDRRectOp>(0, outer, inner);
AccumulateOpBounds(ToSkRect(outer.GetBounds()), flags)) {
Push<DrawDiffRoundRectOp>(0, outer, inner);
CheckLayerOpacityCompatibility();
UpdateLayerResult(result);
}
}
void DisplayListBuilder::DrawDRRect(const SkRRect& outer,
const SkRRect& inner,
const DlPaint& paint) {
void DisplayListBuilder::DrawDiffRoundRect(const DlRoundRect& outer,
const DlRoundRect& inner,
const DlPaint& paint) {
SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawDRRectFlags);
drawDRRect(outer, inner);
drawDiffRoundRect(outer, inner);
}
void DisplayListBuilder::drawPath(const DlPath& path) {
DisplayListAttributeFlags flags = kDrawPathFlags;
Expand Down
Loading