Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 43d6539

Browse files
committed
[Impeller] limit blur uvs to the clip region
1 parent 9d89f87 commit 43d6539

File tree

1 file changed

+39
-7
lines changed

1 file changed

+39
-7
lines changed

impeller/entity/contents/filters/gaussian_blur_filter_contents.cc

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,8 @@ fml::StatusOr<RenderTarget> MakeBlurSubpass(
121121
const SamplerDescriptor& sampler_descriptor,
122122
Entity::TileMode tile_mode,
123123
const GaussianBlurFragmentShader::BlurInfo& blur_info,
124-
std::optional<RenderTarget> destination_target) {
124+
std::optional<RenderTarget> destination_target,
125+
const Quad& blur_uvs) {
125126
if (blur_info.blur_sigma < kEhCloseEnough) {
126127
return input_pass;
127128
}
@@ -153,10 +154,10 @@ fml::StatusOr<RenderTarget> MakeBlurSubpass(
153154

154155
BindVertices<GaussianBlurVertexShader>(cmd, host_buffer,
155156
{
156-
{Point(0, 0), Point(0, 0)},
157-
{Point(1, 0), Point(1, 0)},
158-
{Point(0, 1), Point(0, 1)},
159-
{Point(1, 1), Point(1, 1)},
157+
{blur_uvs[0], blur_uvs[0]},
158+
{blur_uvs[1], blur_uvs[1]},
159+
{blur_uvs[2], blur_uvs[2]},
160+
{blur_uvs[3], blur_uvs[3]},
160161
});
161162

162163
SamplerDescriptor linear_sampler_descriptor = sampler_descriptor;
@@ -183,6 +184,14 @@ fml::StatusOr<RenderTarget> MakeBlurSubpass(
183184
}
184185
}
185186

187+
/// Returns `rect` relative to `reference`, where Rect::MakeXYWH(0,0,1,1) will
188+
/// be returned when `rect` == `reference`.
189+
Rect MakeReferenceUVs(const Rect& reference, const Rect& rect) {
190+
Rect result = Rect::MakeOriginSize(rect.GetOrigin() - reference.GetOrigin(),
191+
rect.GetSize());
192+
return result.Scale(1.0f / Vector2(reference.GetSize()));
193+
}
194+
186195
} // namespace
187196

188197
GaussianBlurFilterContents::GaussianBlurFilterContents(
@@ -311,6 +320,29 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
311320
Vector2 pass1_pixel_size =
312321
1.0 / Vector2(pass1_out.value().GetRenderTargetTexture()->GetSize());
313322

323+
std::optional<Rect> input_snapshot_coverage = input_snapshot->GetCoverage();
324+
Quad blur_uvs = {Point(0, 0), Point(1, 0), Point(0, 1), Point(1, 1)};
325+
if (expanded_coverage_hint.has_value() &&
326+
input_snapshot_coverage.has_value() &&
327+
// TODO(tbd): Remove this condition. There is some flaw in coverage
328+
// stopping us from using this today. I attempted to use source
329+
// coordinates to calculate the uvs, but that didn't work
330+
// either
331+
// (https://github.com/flutter/engine/pull/49299#issuecomment-1865311438).
332+
input_snapshot.has_value() &&
333+
input_snapshot.value().transform.IsTranslationScaleOnly()) {
334+
// Only process the uvs where the blur is happening, not the whole texture.
335+
std::optional<Rect> uvs = MakeReferenceUVs(input_snapshot_coverage.value(),
336+
expanded_coverage_hint.value())
337+
.Intersection(Rect::MakeSize(Size(1, 1)));
338+
if (uvs.has_value()) {
339+
blur_uvs[0] = uvs->GetLeftTop();
340+
blur_uvs[1] = uvs->GetRightTop();
341+
blur_uvs[2] = uvs->GetLeftBottom();
342+
blur_uvs[3] = uvs->GetRightBottom();
343+
}
344+
}
345+
314346
fml::StatusOr<RenderTarget> pass2_out =
315347
MakeBlurSubpass(renderer, /*input_pass=*/pass1_out.value(),
316348
input_snapshot->sampler_descriptor, tile_mode_,
@@ -320,7 +352,7 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
320352
.blur_radius = blur_radius.y * effective_scalar.y,
321353
.step_size = 1.0,
322354
},
323-
/*destination_target=*/std::nullopt);
355+
/*destination_target=*/std::nullopt, blur_uvs);
324356

325357
if (!pass2_out.ok()) {
326358
return std::nullopt;
@@ -341,7 +373,7 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
341373
.blur_radius = blur_radius.x * effective_scalar.x,
342374
.step_size = 1.0,
343375
},
344-
pass3_destination);
376+
pass3_destination, blur_uvs);
345377

346378
if (!pass3_out.ok()) {
347379
return std::nullopt;

0 commit comments

Comments
 (0)