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] match rrect_blur math to the gaussian math #53130

Merged
merged 14 commits into from
Jun 3, 2024
82 changes: 81 additions & 1 deletion impeller/display_list/dl_golden_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace testing {
using impeller::PlaygroundBackend;
using impeller::PlaygroundTest;
using impeller::Point;
using impeller::Scalar;

INSTANTIATE_PLAYGROUND_SUITE(DlGoldenTest);

Expand Down Expand Up @@ -55,7 +56,7 @@ TEST_P(DlGoldenTest, Bug147807) {
Point content_scale = GetContentScale();
auto draw = [content_scale](DlCanvas* canvas,
const std::vector<sk_sp<DlImage>>& images) {
canvas->Transform2DAffine(content_scale.x, 0, 0, 0, content_scale.y, 0);
canvas->Scale(content_scale.x, content_scale.y);
DlPaint paint;
paint.setColor(DlColor(0xfffef7ff));
canvas->DrawRect(SkRect::MakeLTRB(0, 0, 375, 667), paint);
Expand Down Expand Up @@ -100,5 +101,84 @@ TEST_P(DlGoldenTest, Bug147807) {
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}

namespace {
void DrawBlurGrid(DlCanvas* canvas) {
DlPaint paint;
paint.setColor(DlColor(0xfffef7ff));
Scalar width = 150;
Scalar height = 150;
Scalar gap = 80;
std::vector<Scalar> blur_radii = {10, 30, 50};
for (size_t i = 0; i < blur_radii.size(); ++i) {
Scalar blur_radius = blur_radii[i];
auto blur_filter = std::make_shared<flutter::DlBlurMaskFilter>(
flutter::DlBlurStyle::kNormal, blur_radius);
paint.setMaskFilter(blur_filter);
SkRRect rrect;
Scalar yval = gap + i * (gap + height);
rrect.setNinePatch(SkRect::MakeXYWH(gap, yval, width, height), 10, 10, 10,
10);
canvas->DrawRRect(rrect, paint);
rrect.setNinePatch(SkRect::MakeXYWH(2.0 * gap + width, yval, width, height),
gaaclarke marked this conversation as resolved.
Show resolved Hide resolved
9, 10, 10, 10);
canvas->DrawRRect(rrect, paint);
}
}
} // namespace

TEST_P(DlGoldenTest, GaussianVsRRectBlur) {
Point content_scale = GetContentScale();
auto draw = [content_scale](DlCanvas* canvas,
const std::vector<sk_sp<DlImage>>& images) {
canvas->Scale(content_scale.x, content_scale.y);
canvas->DrawPaint(DlPaint().setColor(DlColor(0xff112233)));
DrawBlurGrid(canvas);
};

DisplayListBuilder builder;
std::vector<sk_sp<DlImage>> images;
draw(&builder, images);

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

TEST_P(DlGoldenTest, GaussianVsRRectBlurScaled) {
Point content_scale = GetContentScale();
auto draw = [content_scale](DlCanvas* canvas,
const std::vector<sk_sp<DlImage>>& images) {
canvas->Scale(content_scale.x, content_scale.y);
canvas->DrawPaint(DlPaint().setColor(DlColor(0xff112233)));
canvas->Scale(0.33, 0.33);
DrawBlurGrid(canvas);
};

DisplayListBuilder builder;
std::vector<sk_sp<DlImage>> images;
draw(&builder, images);

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

TEST_P(DlGoldenTest, GaussianVsRRectBlurScaledRotated) {
Point content_scale = GetContentScale();
auto draw = [content_scale](DlCanvas* canvas,
const std::vector<sk_sp<DlImage>>& images) {
canvas->Scale(content_scale.x, content_scale.y);
canvas->Translate(200, 200);
canvas->DrawPaint(DlPaint().setColor(DlColor(0xff112233)));
canvas->Scale(0.33, 0.33);
canvas->Translate(300, 300);
canvas->Rotate(45);
canvas->Translate(-300, -300);
DrawBlurGrid(canvas);
};

DisplayListBuilder builder;
std::vector<sk_sp<DlImage>> images;
draw(&builder, images);

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

} // namespace testing
} // namespace flutter
18 changes: 15 additions & 3 deletions impeller/entity/contents/filters/gaussian_blur_filter_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ const int32_t GaussianBlurFilterContents::kBlurFilterRequiredMipCount = 4;
namespace {

// 48 comes from gaussian.frag.
const int32_t kMaxKernelSize = 48;
const int32_t kMaxKernelSize = 50;
constexpr Scalar kMaxSigma = 500.0f;

SamplerDescriptor MakeSamplerDescriptor(MinMagFilter filter,
SamplerAddressMode address_mode) {
Expand Down Expand Up @@ -363,9 +364,14 @@ std::optional<Rect> GaussianBlurFilterContents::GetFilterCoverage(
return {};
}

Vector2 scaled_sigma = (effect_transform.Basis() *
Vector2 entity_scale_x = entity.GetTransform().Basis() * Vector2(1.0, 0.0);
Vector2 entity_scale_y = entity.GetTransform().Basis() * Vector2(0.0, 1.0);
Vector2 scaled_sigma = (Matrix::MakeScale({entity_scale_x.GetLength(),
entity_scale_y.GetLength(), 1.0}) *
Vector2(ScaleSigma(sigma_x_), ScaleSigma(sigma_y_)))
.Abs();
scaled_sigma.x = std::min(scaled_sigma.x, kMaxSigma);
scaled_sigma.y = std::min(scaled_sigma.y, kMaxSigma);
Vector2 blur_radius = Vector2(CalculateBlurRadius(scaled_sigma.x),
CalculateBlurRadius(scaled_sigma.y));
Vector2 padding(ceil(blur_radius.x), ceil(blur_radius.y));
Expand All @@ -384,9 +390,15 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
return std::nullopt;
}

Vector2 entity_scale_x = entity.GetTransform().Basis() * Vector2(1.0, 0.0);
Vector2 entity_scale_y = entity.GetTransform().Basis() * Vector2(0.0, 1.0);
Vector2 scaled_sigma = (effect_transform.Basis() *
Matrix::MakeScale({entity_scale_x.GetLength(),
entity_scale_y.GetLength(), 1.0}) *
Vector2(ScaleSigma(sigma_x_), ScaleSigma(sigma_y_)))
.Abs();
scaled_sigma.x = std::min(scaled_sigma.x, kMaxSigma);
scaled_sigma.y = std::min(scaled_sigma.y, kMaxSigma);
Vector2 blur_radius = Vector2(CalculateBlurRadius(scaled_sigma.x),
CalculateBlurRadius(scaled_sigma.y));
Vector2 padding(ceil(blur_radius.x), ceil(blur_radius.y));
Expand Down Expand Up @@ -582,7 +594,7 @@ Quad GaussianBlurFilterContents::CalculateUVs(
// that puts the minima there and a f(0)=1.
Scalar GaussianBlurFilterContents::ScaleSigma(Scalar sigma) {
// Limit the kernel size to 1000x1000 pixels, like Skia does.
Scalar clamped = std::min(sigma, 500.0f);
Scalar clamped = std::min(sigma, kMaxSigma);
constexpr Scalar a = 3.4e-06;
constexpr Scalar b = -3.4e-3;
constexpr Scalar c = 1.f;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ TEST_P(GaussianBlurFilterContentsTest,
if (result_coverage.has_value() && contents_coverage.has_value()) {
EXPECT_TRUE(RectNear(result_coverage.value(), contents_coverage.value()));
EXPECT_TRUE(RectNear(contents_coverage.value(),
Rect::MakeLTRB(98.f, 78.f, 302.f, 282.f)));
Rect::MakeXYWH(94.f, 74.f, 212.f, 212.f)));
flar marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion impeller/entity/shaders/filters/gaussian.frag
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ struct KernelSample {

uniform KernelSamples {
int sample_count;
KernelSample samples[48];
KernelSample samples[50];
gaaclarke marked this conversation as resolved.
Show resolved Hide resolved
}
blur_info;

Expand Down
9 changes: 9 additions & 0 deletions testing/impeller_golden_tests_output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -798,3 +798,12 @@ impeller_Play_DlGoldenTest_CanDrawPaint_Vulkan.png
impeller_Play_DlGoldenTest_CanRenderImage_Metal.png
impeller_Play_DlGoldenTest_CanRenderImage_OpenGLES.png
impeller_Play_DlGoldenTest_CanRenderImage_Vulkan.png
impeller_Play_DlGoldenTest_GaussianVsRRectBlurScaledRotated_Metal.png
impeller_Play_DlGoldenTest_GaussianVsRRectBlurScaledRotated_OpenGLES.png
impeller_Play_DlGoldenTest_GaussianVsRRectBlurScaledRotated_Vulkan.png
impeller_Play_DlGoldenTest_GaussianVsRRectBlurScaled_Metal.png
impeller_Play_DlGoldenTest_GaussianVsRRectBlurScaled_OpenGLES.png
impeller_Play_DlGoldenTest_GaussianVsRRectBlurScaled_Vulkan.png
impeller_Play_DlGoldenTest_GaussianVsRRectBlur_Metal.png
impeller_Play_DlGoldenTest_GaussianVsRRectBlur_OpenGLES.png
impeller_Play_DlGoldenTest_GaussianVsRRectBlur_Vulkan.png