@@ -19,16 +19,6 @@ using GaussianBlurFragmentShader = GaussianBlurPipeline::FragmentShader;
19
19
20
20
namespace {
21
21
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
-
32
22
SamplerDescriptor MakeSamplerDescriptor (MinMagFilter filter,
33
23
SamplerAddressMode address_mode) {
34
24
SamplerDescriptor sampler_desc;
@@ -48,12 +38,6 @@ void BindVertices(Command& cmd,
48
38
cmd.BindVertices (vtx_builder.CreateVertexBuffer (host_buffer));
49
39
}
50
40
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
-
57
41
void SetTileMode (SamplerDescriptor* descriptor,
58
42
const ContentContext& renderer,
59
43
Entity::TileMode tile_mode) {
@@ -87,7 +71,6 @@ std::shared_ptr<Texture> MakeDownsampleSubpass(
87
71
const SamplerDescriptor& sampler_descriptor,
88
72
const Quad& uvs,
89
73
const ISize& subpass_size,
90
- const Vector2 padding,
91
74
Entity::TileMode tile_mode) {
92
75
ContentContext::SubpassCallback subpass_callback =
93
76
[&](const ContentContext& renderer, RenderPass& pass) {
@@ -104,23 +87,13 @@ std::shared_ptr<Texture> MakeDownsampleSubpass(
104
87
frame_info.texture_sampler_y_coord_scale = 1.0 ;
105
88
frame_info.alpha = 1.0 ;
106
89
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
+ });
124
97
125
98
SamplerDescriptor linear_sampler_descriptor = sampler_descriptor;
126
99
SetTileMode (&linear_sampler_descriptor, renderer, tile_mode);
@@ -270,17 +243,17 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
270
243
Vector2 blur_radius = {CalculateBlurRadius (scaled_sigma.x ),
271
244
CalculateBlurRadius (scaled_sigma.y )};
272
245
Vector2 padding (ceil (blur_radius.x ), ceil (blur_radius.y ));
246
+ Vector2 local_padding =
247
+ (entity.GetTransform ().Basis () * effect_transform.Basis () * padding)
248
+ .Abs ();
273
249
274
250
// Apply as much of the desired padding as possible from the source. This may
275
251
// be ignored so must be accounted for in the downsample pass by adding a
276
252
// 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
+ }
284
257
285
258
std::optional<Snapshot> input_snapshot =
286
259
inputs[0 ]->GetSnapshot (" GaussianBlur" , renderer, entity,
@@ -300,21 +273,28 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
300
273
// gutter from the expanded_coverage_hint, we can skip the downsample pass.
301
274
// pass.
302
275
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;
308
288
ISize subpass_size =
309
289
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 ;
311
291
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 ());
314
294
315
295
std::shared_ptr<Texture> pass1_out_texture = MakeDownsampleSubpass (
316
296
renderer, input_snapshot->texture , input_snapshot->sampler_descriptor ,
317
- uvs, subpass_size, padding, tile_mode_);
297
+ uvs, subpass_size, tile_mode_);
318
298
319
299
Vector2 pass1_pixel_size = 1.0 / Vector2 (pass1_out_texture->GetSize ());
320
300
@@ -343,13 +323,12 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
343
323
MinMagFilter::kLinear , SamplerAddressMode::kClampToEdge );
344
324
345
325
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 },
353
332
entity.GetBlendMode (), entity.GetClipDepth ());
354
333
}
355
334
@@ -360,11 +339,10 @@ Scalar GaussianBlurFilterContents::CalculateBlurRadius(Scalar sigma) {
360
339
Quad GaussianBlurFilterContents::CalculateUVs (
361
340
const std::shared_ptr<FilterInput>& filter_input,
362
341
const Entity& entity,
342
+ const Rect& source_rect,
363
343
const ISize& texture_size) {
364
344
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);
368
346
369
347
Matrix uv_transform = Matrix::MakeScale (
370
348
{1 .0f / texture_size.width , 1 .0f / texture_size.height , 1 .0f });
0 commit comments