[Impeller] Downsample gaussian blur passes bidirectionally (flutter/engine#35561)

This commit is contained in:
Brandon DeRosier 2022-08-24 15:19:42 -07:00 committed by GitHub
parent 379215c159
commit a645e493ec
4 changed files with 32 additions and 14 deletions

View File

@ -79,6 +79,7 @@ std::shared_ptr<FilterContents> FilterContents::MakeDirectionalGaussianBlur(
BlurStyle blur_style,
Entity::TileMode tile_mode,
FilterInput::Ref source_override,
Sigma secondary_sigma,
const Matrix& effect_transform) {
auto blur = std::make_shared<DirectionalGaussianBlurFilterContents>();
blur->SetInputs({input});
@ -87,6 +88,7 @@ std::shared_ptr<FilterContents> FilterContents::MakeDirectionalGaussianBlur(
blur->SetBlurStyle(blur_style);
blur->SetTileMode(tile_mode);
blur->SetSourceOverride(source_override);
blur->SetSecondarySigma(secondary_sigma);
blur->SetEffectTransform(effect_transform);
return blur;
}
@ -100,10 +102,10 @@ std::shared_ptr<FilterContents> FilterContents::MakeGaussianBlur(
const Matrix& effect_transform) {
auto x_blur = MakeDirectionalGaussianBlur(input, sigma_x, Point(1, 0),
BlurStyle::kNormal, tile_mode,
nullptr, effect_transform);
nullptr, {}, effect_transform);
auto y_blur = MakeDirectionalGaussianBlur(FilterInput::Make(x_blur), sigma_y,
Point(0, 1), blur_style, tile_mode,
input, effect_transform);
input, sigma_x, effect_transform);
return y_blur;
}

View File

@ -48,6 +48,7 @@ class FilterContents : public Contents {
BlurStyle blur_style = BlurStyle::kNormal,
Entity::TileMode tile_mode = Entity::TileMode::kDecal,
FilterInput::Ref alpha_mask = nullptr,
Sigma secondary_sigma = {},
const Matrix& effect_transform = Matrix());
static std::shared_ptr<FilterContents> MakeGaussianBlur(

View File

@ -32,6 +32,10 @@ void DirectionalGaussianBlurFilterContents::SetSigma(Sigma sigma) {
blur_sigma_ = sigma;
}
void DirectionalGaussianBlurFilterContents::SetSecondarySigma(Sigma sigma) {
secondary_blur_sigma_ = sigma;
}
void DirectionalGaussianBlurFilterContents::SetDirection(Vector2 direction) {
blur_direction_ = direction.Normalize();
if (blur_direction_.IsZero()) {
@ -221,12 +225,22 @@ std::optional<Snapshot> DirectionalGaussianBlurFilterContents::RenderFilter(
return pass.AddCommand(cmd);
};
Scalar x_scale =
1.0 /
std::ceil(std::log2(std::max(2.0f, transformed_blur_radius_length)));
auto scaled_texture_width = pass_texture_rect.size.width * x_scale;
auto out_texture = renderer.MakeSubpass(
ISize(scaled_texture_width, pass_texture_rect.size.height), callback);
Vector2 scale;
{
scale.x =
1.0 /
std::ceil(std::log2(std::max(2.0f, transformed_blur_radius_length)));
Scalar y_radius = std::abs(pass_transform.GetDirectionScale(Vector2(
0, source_override_ ? Radius{secondary_blur_sigma_}.radius : 1)));
scale.y = 1.0 / std::ceil(std::log2(std::max(2.0f, y_radius)));
}
Vector2 scaled_size = pass_texture_rect.size * scale;
ISize floored_size = ISize(scaled_size.x, scaled_size.y);
auto out_texture = renderer.MakeSubpass(floored_size, callback);
if (!out_texture) {
return std::nullopt;
}
@ -238,12 +252,10 @@ std::optional<Snapshot> DirectionalGaussianBlurFilterContents::RenderFilter(
return Snapshot{
.texture = out_texture,
.transform = texture_rotate.Invert() *
Matrix::MakeTranslation(pass_texture_rect.origin) *
Matrix::MakeScale(Vector2(
(1 / x_scale) * (scaled_texture_width /
std::floor(scaled_texture_width)),
1)),
.transform =
texture_rotate.Invert() *
Matrix::MakeTranslation(pass_texture_rect.origin) *
Matrix::MakeScale((1 / scale) * (scaled_size / floored_size)),
.sampler_descriptor = sampler_desc};
}

View File

@ -19,6 +19,8 @@ class DirectionalGaussianBlurFilterContents final : public FilterContents {
void SetSigma(Sigma sigma);
void SetSecondarySigma(Sigma sigma);
void SetDirection(Vector2 direction);
void SetBlurStyle(BlurStyle blur_style);
@ -42,6 +44,7 @@ class DirectionalGaussianBlurFilterContents final : public FilterContents {
const Matrix& effect_transform,
const Rect& coverage) const override;
Sigma blur_sigma_;
Sigma secondary_blur_sigma_;
Vector2 blur_direction_;
BlurStyle blur_style_ = BlurStyle::kNormal;
Entity::TileMode tile_mode_ = Entity::TileMode::kDecal;