Skip to content

Commit

Permalink
[Impeller] match sigma scaling to Skia scaling. (flutter#48434)
Browse files Browse the repository at this point in the history
The Impeller blur is scaling down about twice as fast as the Skia Blur. Instead adopt their approximate constant values, which results in less shaking as the blur gets bigger.

FYI @gaaclarke
  • Loading branch information
jonahwilliams authored Nov 28, 2023
1 parent fd3a33f commit 65776df
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 11 deletions.
25 changes: 14 additions & 11 deletions impeller/entity/contents/filters/gaussian_blur_filter_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -144,21 +144,21 @@ std::shared_ptr<Texture> MakeBlurSubpass(
return out_texture;
}

/// Calculate how much to scale down the texture depending on the blur radius.
/// This curve was taken from |DirectionalGaussianBlurFilterContents|.
Scalar CalculateScale(Scalar radius) {
constexpr Scalar decay = 4.0; // Larger is more gradual.
constexpr Scalar limit = 0.95; // The maximum percentage of the scaledown.
const Scalar curve =
std::min(1.0, decay / (std::max(1.0f, radius) + decay - 1.0));
return (curve - 1) * limit + 1;
};

} // namespace

GaussianBlurFilterContents::GaussianBlurFilterContents(Scalar sigma)
: sigma_(sigma) {}

// This value was extracted from Skia, see:
// * https://github.com/google/skia/blob/d29cc3fe182f6e8a8539004a6a4ee8251677a6fd/src/gpu/ganesh/GrBlurUtils.cpp#L2561-L2576
// * https://github.com/google/skia/blob/d29cc3fe182f6e8a8539004a6a4ee8251677a6fd/src/gpu/BlurUtils.h#L57
Scalar GaussianBlurFilterContents::CalculateScale(Scalar sigma) {
if (sigma <= 4) {
return 1.0;
}
return 4.0 / sigma;
};

std::optional<Rect> GaussianBlurFilterContents::GetFilterSourceCoverage(
const Matrix& effect_transform,
const Rect& output_limit) const {
Expand Down Expand Up @@ -213,7 +213,10 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
}

Scalar blur_radius = CalculateBlurRadius(sigma_);
Scalar desired_scalar = CalculateScale(blur_radius);
Scalar desired_scalar = CalculateScale(sigma_);
// TODO(jonahwilliams): if scaling value is 1.0, then skip the downsample
// pass.

Vector2 downsample_scalar(desired_scalar, desired_scalar);
Vector2 padding(ceil(blur_radius), ceil(blur_radius));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ class GaussianBlurFilterContents final : public FilterContents {
const Entity& entity,
const ISize& pass_size);

/// Calculate the scale factor for the downsample pass given a sigma value.
///
/// Visible for testing.
static Scalar CalculateScale(Scalar sigma);

private:
// |FilterContents|
std::optional<Entity> RenderFilter(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,15 @@ TEST(GaussianBlurFilterContentsTest, FilterSourceCoverage) {
ASSERT_EQ(coverage, Rect::MakeLTRB(100 - 2, 100 - 2, 200 + 2, 200 + 2));
}

TEST(GaussianBlurFilterContentsTest, CalculateSigmaValues) {
EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(1.0f), 1);
EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(2.0f), 1);
EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(3.0f), 1);
EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(4.0f), 1);
EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(16.0f), 0.25);
EXPECT_EQ(GaussianBlurFilterContents::CalculateScale(1024.0f), 4.f / 1024.f);
}

TEST_P(GaussianBlurFilterContentsTest, RenderCoverageMatchesGetCoverage) {
TextureDescriptor desc = {
.storage_mode = StorageMode::kDevicePrivate,
Expand Down

0 comments on commit 65776df

Please sign in to comment.