@@ -19,16 +19,6 @@ using GaussianBlurFragmentShader = GaussianBlurPipeline::FragmentShader;
1919
2020namespace {
2121
22- std::optional<Rect> ExpandCoverageHint (const std::optional<Rect>& coverage_hint,
23- const Matrix& source_to_local_transform,
24- const Vector2& padding) {
25- if (!coverage_hint.has_value ()) {
26- return std::nullopt ;
27- }
28- Vector2 transformed_padding = (source_to_local_transform * padding).Abs ();
29- return coverage_hint->Expand (transformed_padding);
30- }
31-
3222SamplerDescriptor MakeSamplerDescriptor (MinMagFilter filter,
3323 SamplerAddressMode address_mode) {
3424 SamplerDescriptor sampler_desc;
@@ -48,12 +38,6 @@ void BindVertices(Command& cmd,
4838 cmd.BindVertices (vtx_builder.CreateVertexBuffer (host_buffer));
4939}
5040
51- Matrix MakeAnchorScale (const Point& anchor, Vector2 scale) {
52- return Matrix::MakeTranslation ({anchor.x , anchor.y , 0 }) *
53- Matrix::MakeScale (scale) *
54- Matrix::MakeTranslation ({-anchor.x , -anchor.y , 0 });
55- }
56-
5741void SetTileMode (SamplerDescriptor* descriptor,
5842 const ContentContext& renderer,
5943 Entity::TileMode tile_mode) {
@@ -87,7 +71,6 @@ std::shared_ptr<Texture> MakeDownsampleSubpass(
8771 const SamplerDescriptor& sampler_descriptor,
8872 const Quad& uvs,
8973 const ISize& subpass_size,
90- const Vector2 padding,
9174 Entity::TileMode tile_mode) {
9275 ContentContext::SubpassCallback subpass_callback =
9376 [&](const ContentContext& renderer, RenderPass& pass) {
@@ -104,23 +87,13 @@ std::shared_ptr<Texture> MakeDownsampleSubpass(
10487 frame_info.texture_sampler_y_coord_scale = 1.0 ;
10588 frame_info.alpha = 1.0 ;
10689
107- // Insert transparent gutter around the downsampled image so the blur
108- // creates a halo effect. This compensates for when the expanded clip
109- // region can't give us the full gutter we want.
110- Vector2 texture_size = Vector2 (input_texture->GetSize ());
111- Quad guttered_uvs =
112- MakeAnchorScale ({0.5 , 0.5 },
113- (texture_size + padding * 2 ) / texture_size)
114- .Transform (uvs);
115-
116- BindVertices<TextureFillVertexShader>(
117- cmd, host_buffer,
118- {
119- {Point (0 , 0 ), guttered_uvs[0 ]},
120- {Point (1 , 0 ), guttered_uvs[1 ]},
121- {Point (0 , 1 ), guttered_uvs[2 ]},
122- {Point (1 , 1 ), guttered_uvs[3 ]},
123- });
90+ BindVertices<TextureFillVertexShader>(cmd, host_buffer,
91+ {
92+ {Point (0 , 0 ), uvs[0 ]},
93+ {Point (1 , 0 ), uvs[1 ]},
94+ {Point (0 , 1 ), uvs[2 ]},
95+ {Point (1 , 1 ), uvs[3 ]},
96+ });
12497
12598 SamplerDescriptor linear_sampler_descriptor = sampler_descriptor;
12699 SetTileMode (&linear_sampler_descriptor, renderer, tile_mode);
@@ -270,17 +243,17 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
270243 Vector2 blur_radius = {CalculateBlurRadius (scaled_sigma.x ),
271244 CalculateBlurRadius (scaled_sigma.y )};
272245 Vector2 padding (ceil (blur_radius.x ), ceil (blur_radius.y ));
246+ Vector2 local_padding =
247+ (entity.GetTransform ().Basis () * effect_transform.Basis () * padding)
248+ .Abs ();
273249
274250 // Apply as much of the desired padding as possible from the source. This may
275251 // be ignored so must be accounted for in the downsample pass by adding a
276252 // transparent gutter.
277- std::optional<Rect> expanded_coverage_hint = ExpandCoverageHint (
278- coverage_hint, entity.GetTransform () * effect_transform, padding);
279- // TODO(gaaclarke): How much of the gutter is thrown away can be used to
280- // adjust the padding that is added in the downsample pass.
281- // For example, if we get all the padding we requested from
282- // the expanded_coverage_hint, there is no need to add a
283- // transparent gutter.
253+ std::optional<Rect> expanded_coverage_hint;
254+ if (coverage_hint.has_value ()) {
255+ expanded_coverage_hint = coverage_hint->Expand (local_padding);
256+ }
284257
285258 std::optional<Snapshot> input_snapshot =
286259 inputs[0 ]->GetSnapshot (" GaussianBlur" , renderer, entity,
@@ -300,21 +273,28 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
300273 // gutter from the expanded_coverage_hint, we can skip the downsample pass.
301274 // pass.
302275 Vector2 downsample_scalar (desired_scalar, desired_scalar);
303- Vector2 padded_size =
304- Vector2 (input_snapshot->texture ->GetSize ()) + 2.0 * padding;
305- Vector2 downsampled_size = padded_size * downsample_scalar;
306- // TODO(gaaclarke): I don't think we are correctly handling this fractional
307- // amount we are throwing away.
276+ Rect source_rect = Rect::MakeSize (input_snapshot->texture ->GetSize ());
277+ Rect source_rect_padded = source_rect.Expand (padding);
278+ Matrix padding_snapshot_adjustment = Matrix::MakeTranslation (-padding);
279+ // TODO(gaaclarke): The padding could be removed if we know it's not needed or
280+ // resized to account for the expanded_clip_coverage. There doesn't appear
281+ // to be the math to make those calculations though. The following
282+ // optimization works, but causes a shimmer as a result of
283+ // https://github.com/flutter/flutter/issues/140193 so it isn't applied.
284+ //
285+ // !input_snapshot->GetCoverage()->Expand(-local_padding)
286+ // .Contains(coverage_hint.value()))
287+ Vector2 downsampled_size = source_rect_padded.size * downsample_scalar;
308288 ISize subpass_size =
309289 ISize (round (downsampled_size.x ), round (downsampled_size.y ));
310- Vector2 effective_scalar = subpass_size / padded_size ;
290+ Vector2 effective_scalar = Vector2 ( subpass_size) / source_rect_padded. size ;
311291
312- Quad uvs =
313- CalculateUVs (inputs[ 0 ], entity, input_snapshot->texture ->GetSize ());
292+ Quad uvs = CalculateUVs (inputs[ 0 ], entity, source_rect_padded,
293+ input_snapshot->texture ->GetSize ());
314294
315295 std::shared_ptr<Texture> pass1_out_texture = MakeDownsampleSubpass (
316296 renderer, input_snapshot->texture , input_snapshot->sampler_descriptor ,
317- uvs, subpass_size, padding, tile_mode_);
297+ uvs, subpass_size, tile_mode_);
318298
319299 Vector2 pass1_pixel_size = 1.0 / Vector2 (pass1_out_texture->GetSize ());
320300
@@ -343,13 +323,12 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
343323 MinMagFilter::kLinear , SamplerAddressMode::kClampToEdge );
344324
345325 return Entity::FromSnapshot (
346- Snapshot{
347- .texture = pass3_out_texture,
348- .transform = input_snapshot->transform *
349- Matrix::MakeTranslation ({-padding.x , -padding.y , 0 }) *
350- Matrix::MakeScale (1 / effective_scalar),
351- .sampler_descriptor = sampler_desc,
352- .opacity = input_snapshot->opacity },
326+ Snapshot{.texture = pass3_out_texture,
327+ .transform = input_snapshot->transform *
328+ padding_snapshot_adjustment *
329+ Matrix::MakeScale (1 / effective_scalar),
330+ .sampler_descriptor = sampler_desc,
331+ .opacity = input_snapshot->opacity },
353332 entity.GetBlendMode (), entity.GetClipDepth ());
354333}
355334
@@ -360,11 +339,10 @@ Scalar GaussianBlurFilterContents::CalculateBlurRadius(Scalar sigma) {
360339Quad GaussianBlurFilterContents::CalculateUVs (
361340 const std::shared_ptr<FilterInput>& filter_input,
362341 const Entity& entity,
342+ const Rect& source_rect,
363343 const ISize& texture_size) {
364344 Matrix input_transform = filter_input->GetLocalTransform (entity);
365- Rect snapshot_rect =
366- Rect::MakeXYWH (0 , 0 , texture_size.width , texture_size.height );
367- Quad coverage_quad = snapshot_rect.GetTransformedPoints (input_transform);
345+ Quad coverage_quad = source_rect.GetTransformedPoints (input_transform);
368346
369347 Matrix uv_transform = Matrix::MakeScale (
370348 {1 .0f / texture_size.width , 1 .0f / texture_size.height , 1 .0f });
0 commit comments