Skip to content

Commit

Permalink
[Impeller] Re-enable fast blur path for elliptical rrects (flutter#53704
Browse files Browse the repository at this point in the history
)

Fixes flutter/flutter#151034

Fast round rects were recently restricted to circular corners, but elliptical round rects can also go through the fast path.
  • Loading branch information
flar authored Jul 4, 2024
1 parent aaf179c commit 8e2d05f
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 11 deletions.
63 changes: 63 additions & 0 deletions impeller/display_list/dl_golden_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "impeller/display_list/dl_golden_unittests.h"

#include "flutter/display_list/dl_builder.h"
#include "flutter/impeller/geometry/path_builder.h"
#include "flutter/testing/testing.h"
#include "gtest/gtest.h"

Expand Down Expand Up @@ -182,6 +183,68 @@ TEST_P(DlGoldenTest, GaussianVsRRectBlurScaledRotated) {
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}

TEST_P(DlGoldenTest, FastVsGeneralGaussianMaskBlur) {
DisplayListBuilder builder;
builder.Scale(GetContentScale().x, GetContentScale().y);
builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);

auto blur_sigmas = std::array{5.0f, 10.0f, 20.0f};
auto blur_colors = std::array{
DlColor::kBlue(),
DlColor::kGreen(),
DlColor::kMaroon(),
};

auto make_rrect_path = [](const SkRect& rect, DlScalar rx,
DlScalar ry) -> SkPath {
auto add_corner = [](SkPath& path, SkPoint rCorner, SkPoint rEnd) {
static const auto magic = impeller::PathBuilder::kArcApproximationMagic;
path.rCubicTo(rCorner.fX * (1.0f - magic), rCorner.fY * (1.0f - magic),
rCorner.fX + rEnd.fX * magic, rCorner.fY + rEnd.fY * magic,
rCorner.fX + rEnd.fX, rCorner.fY + rEnd.fY);
};

SkPath path;
path.moveTo(rect.fRight - rx, rect.fTop);
add_corner(path, {rx, 0.0f}, {0.0f, ry});
path.lineTo(rect.fRight, rect.fBottom - ry);
add_corner(path, {0.0f, ry}, {-rx, 0.0f});
path.lineTo(rect.fLeft + rx, rect.fBottom);
add_corner(path, {-rx, 0.0f}, {0.0f, -ry});
path.lineTo(rect.fLeft, rect.fTop + ry);
add_corner(path, {0.0f, -ry}, {rx, 0.0f});
path.close();
return path;
};

for (size_t i = 0; i < blur_sigmas.size(); i++) {
auto rect = SkRect::MakeXYWH(i * 320.0f + 50.0f, 50.0f, 100.0f, 100.0f);
DlPaint paint = DlPaint() //
.setColor(blur_colors[i])
.setMaskFilter(DlBlurMaskFilter::Make(
DlBlurStyle::kNormal, blur_sigmas[i]));

builder.DrawRRect(SkRRect::MakeRectXY(rect, 10.0f, 10.0f), paint);
rect = rect.makeOffset(150.0f, 0.0f);
builder.DrawPath(make_rrect_path(rect, 10.0f, 10.0f), paint);
rect = rect.makeOffset(-150.0f, 0.0f);

rect = rect.makeOffset(0.0f, 200.0f);
builder.DrawRRect(SkRRect::MakeRectXY(rect, 10.0f, 30.0f), paint);
rect = rect.makeOffset(150.0f, 0.0f);
builder.DrawPath(make_rrect_path(rect, 10.0f, 20.0f), paint);
rect = rect.makeOffset(-150.0f, 0.0f);

rect = rect.makeOffset(0.0f, 200.0f);
builder.DrawRRect(SkRRect::MakeRectXY(rect, 30.0f, 10.0f), paint);
rect = rect.makeOffset(150.0f, 0.0f);
builder.DrawPath(make_rrect_path(rect, 20.0f, 10.0f), paint);
rect = rect.makeOffset(-150.0f, 0.0f);
}

ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}

TEST_P(DlGoldenTest, DashedLinesTest) {
Point content_scale = GetContentScale();
auto draw = [content_scale](DlCanvas* canvas,
Expand Down
24 changes: 14 additions & 10 deletions impeller/display_list/skia_conversions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,22 @@
namespace impeller {
namespace skia_conversions {

bool IsNearlySimpleRRect(const SkRRect& rr) {
auto [a, b] = rr.radii(SkRRect::kUpperLeft_Corner);
auto [c, d] = rr.radii(SkRRect::kLowerLeft_Corner);
auto [e, f] = rr.radii(SkRRect::kUpperRight_Corner);
auto [g, h] = rr.radii(SkRRect::kLowerRight_Corner);
static inline bool SkScalarsNearlyEqual(SkScalar a,
SkScalar b,
SkScalar c,
SkScalar d) {
return SkScalarNearlyEqual(a, b, kEhCloseEnough) &&
SkScalarNearlyEqual(a, c, kEhCloseEnough) &&
SkScalarNearlyEqual(a, d, kEhCloseEnough) &&
SkScalarNearlyEqual(a, e, kEhCloseEnough) &&
SkScalarNearlyEqual(a, f, kEhCloseEnough) &&
SkScalarNearlyEqual(a, g, kEhCloseEnough) &&
SkScalarNearlyEqual(a, h, kEhCloseEnough);
SkScalarNearlyEqual(a, d, kEhCloseEnough);
}

bool IsNearlySimpleRRect(const SkRRect& rr) {
auto [xa, ya] = rr.radii(SkRRect::kUpperLeft_Corner);
auto [xb, yb] = rr.radii(SkRRect::kLowerLeft_Corner);
auto [xc, yc] = rr.radii(SkRRect::kUpperRight_Corner);
auto [xd, yd] = rr.radii(SkRRect::kLowerRight_Corner);
return SkScalarsNearlyEqual(xa, xb, xc, xd) &&
SkScalarsNearlyEqual(ya, yb, yc, yd);
}

Rect ToRect(const SkRect& rect) {
Expand Down
29 changes: 28 additions & 1 deletion impeller/display_list/skia_conversions_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,35 @@ TEST(SkiaConversionsTest, IsNearlySimpleRRect) {
SkRRect::MakeRectXY(SkRect::MakeLTRB(0, 0, 10, 10), 10, 10)));
EXPECT_TRUE(skia_conversions::IsNearlySimpleRRect(
SkRRect::MakeRectXY(SkRect::MakeLTRB(0, 0, 10, 10), 10, 9.999)));
EXPECT_FALSE(skia_conversions::IsNearlySimpleRRect(
EXPECT_TRUE(skia_conversions::IsNearlySimpleRRect(
SkRRect::MakeRectXY(SkRect::MakeLTRB(0, 0, 10, 10), 10, 9)));
EXPECT_TRUE(skia_conversions::IsNearlySimpleRRect(
SkRRect::MakeRectXY(SkRect::MakeLTRB(0, 0, 10, 10), 10, 5)));
SkRect rect = SkRect::MakeLTRB(0, 0, 10, 10);
SkRRect rrect;
union {
SkPoint radii[4] = {
{10.0f, 9.0f},
{10.0f, 9.0f},
{10.0f, 9.0f},
{10.0f, 9.0f},
};
SkScalar values[8];
} test;
rrect.setRectRadii(rect, test.radii);
EXPECT_TRUE(skia_conversions::IsNearlySimpleRRect(rrect));
for (int i = 0; i < 8; i++) {
auto save = test.values[i];
test.values[i] -= kEhCloseEnough * 0.5f;
rrect.setRectRadii(rect, test.radii);
EXPECT_TRUE(skia_conversions::IsNearlySimpleRRect(rrect))
<< "values[" << i << "] == " << test.values[i];
test.values[i] -= kEhCloseEnough * 2.0f;
rrect.setRectRadii(rect, test.radii);
EXPECT_FALSE(skia_conversions::IsNearlySimpleRRect(rrect))
<< "values[" << i << "] == " << test.values[i];
test.values[i] = save;
}
}

} // namespace testing
Expand Down
3 changes: 3 additions & 0 deletions testing/impeller_golden_tests_output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -855,6 +855,9 @@ impeller_Play_DlGoldenTest_CanRenderImage_Vulkan.png
impeller_Play_DlGoldenTest_DashedLinesTest_Metal.png
impeller_Play_DlGoldenTest_DashedLinesTest_OpenGLES.png
impeller_Play_DlGoldenTest_DashedLinesTest_Vulkan.png
impeller_Play_DlGoldenTest_FastVsGeneralGaussianMaskBlur_Metal.png
impeller_Play_DlGoldenTest_FastVsGeneralGaussianMaskBlur_OpenGLES.png
impeller_Play_DlGoldenTest_FastVsGeneralGaussianMaskBlur_Vulkan.png
impeller_Play_DlGoldenTest_GaussianVsRRectBlurScaledRotated_Metal.png
impeller_Play_DlGoldenTest_GaussianVsRRectBlurScaledRotated_OpenGLES.png
impeller_Play_DlGoldenTest_GaussianVsRRectBlurScaledRotated_Vulkan.png
Expand Down

0 comments on commit 8e2d05f

Please sign in to comment.