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] Started expanding the blur clip region #48535

Merged
merged 5 commits into from
Nov 30, 2023
Merged
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
41 changes: 34 additions & 7 deletions impeller/entity/contents/filters/gaussian_blur_filter_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ using GaussianBlurVertexShader = GaussianBlurPipeline::VertexShader;
using GaussianBlurFragmentShader = GaussianBlurPipeline::FragmentShader;

namespace {

std::optional<Rect> ExpandCoverageHint(const std::optional<Rect>& coverage_hint,
const Matrix& source_to_local_transform,
const Vector2& padding) {
if (!coverage_hint.has_value()) {
return std::nullopt;
}
Vector2 transformed_padding = (source_to_local_transform * padding).Abs();
return coverage_hint->Expand(transformed_padding);
}

SamplerDescriptor MakeSamplerDescriptor(MinMagFilter filter,
SamplerAddressMode address_mode) {
SamplerDescriptor sampler_desc;
Expand All @@ -43,6 +54,8 @@ Matrix MakeAnchorScale(const Point& anchor, Vector2 scale) {
Matrix::MakeTranslation({-anchor.x, -anchor.y, 0});
}

/// Makes a subpass that will render the scaled down input and add the
/// transparent gutter required for the blur halo.
std::shared_ptr<Texture> MakeDownsampleSubpass(
const ContentContext& renderer,
std::shared_ptr<Texture> input_texture,
Expand All @@ -66,7 +79,8 @@ std::shared_ptr<Texture> MakeDownsampleSubpass(
frame_info.alpha = 1.0;

// Insert transparent gutter around the downsampled image so the blur
// creates a halo effect.
// creates a halo effect. This compensates for when the expanded clip
// region can't give us the full gutter we want.
Vector2 texture_size = Vector2(input_texture->GetSize());
Quad vertices =
MakeAnchorScale({0.5, 0.5},
Expand Down Expand Up @@ -106,6 +120,8 @@ std::shared_ptr<Texture> MakeBlurSubpass(
std::shared_ptr<Texture> input_texture,
const SamplerDescriptor& sampler_descriptor,
const GaussianBlurFragmentShader::BlurInfo& blur_info) {
// TODO(gaaclarke): This blurs the whole image, but because we know the clip
// region we could focus on just blurring that.
ISize subpass_size = input_texture->GetSize();
ContentContext::SubpassCallback subpass_callback =
[&](const ContentContext& renderer, RenderPass& pass) {
Expand Down Expand Up @@ -200,9 +216,23 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
return std::nullopt;
}

Scalar blur_radius = CalculateBlurRadius(sigma_);
Vector2 padding(ceil(blur_radius), ceil(blur_radius));

// Apply as much of the desired padding as possible from the source. This may
// be ignored so must be accounted for in the downsample pass by adding a
// transparent gutter.
std::optional<Rect> expanded_coverage_hint = ExpandCoverageHint(
coverage_hint, entity.GetTransform() * effect_transform, padding);
// TODO(gaaclarke): How much of the gutter is thrown away can be used to
// adjust the padding that is added in the downsample pass.
// For example, if we get all the padding we requested from
// the expanded_coverage_hint, there is no need to add a
// transparent gutter.

std::optional<Snapshot> input_snapshot =
inputs[0]->GetSnapshot("GaussianBlur", renderer, entity,
/*coverage_limit=*/coverage_hint);
/*coverage_limit=*/expanded_coverage_hint);
if (!input_snapshot.has_value()) {
return std::nullopt;
}
Expand All @@ -212,14 +242,11 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
entity.GetClipDepth()); // No blur to render.
}

Scalar blur_radius = CalculateBlurRadius(sigma_);
Scalar desired_scalar = CalculateScale(sigma_);
// TODO(jonahwilliams): if scaling value is 1.0, then skip the downsample
// TODO(jonahwilliams): If desired_scalar is 1.0 and we fully acquired the
// gutter from the expanded_coverage_hint, we can skip the downsample pass.
// pass.

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

Vector2 padded_size =
Vector2(input_snapshot->texture->GetSize()) + 2.0 * padding;
Vector2 downsampled_size = padded_size * downsample_scalar;
Expand Down