Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
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