@@ -121,7 +121,8 @@ fml::StatusOr<RenderTarget> MakeBlurSubpass(
121
121
const SamplerDescriptor& sampler_descriptor,
122
122
Entity::TileMode tile_mode,
123
123
const GaussianBlurFragmentShader::BlurInfo& blur_info,
124
- std::optional<RenderTarget> destination_target) {
124
+ std::optional<RenderTarget> destination_target,
125
+ const Quad& blur_uvs) {
125
126
if (blur_info.blur_sigma < kEhCloseEnough ) {
126
127
return input_pass;
127
128
}
@@ -153,10 +154,10 @@ fml::StatusOr<RenderTarget> MakeBlurSubpass(
153
154
154
155
BindVertices<GaussianBlurVertexShader>(cmd, host_buffer,
155
156
{
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 ] },
160
161
});
161
162
162
163
SamplerDescriptor linear_sampler_descriptor = sampler_descriptor;
@@ -183,6 +184,12 @@ fml::StatusOr<RenderTarget> MakeBlurSubpass(
183
184
}
184
185
}
185
186
187
+ Rect MakeReferenceUVs (const Rect& reference, const Rect& rect) {
188
+ Rect result = Rect::MakeOriginSize (rect.GetOrigin () - reference.GetOrigin (),
189
+ rect.GetSize ());
190
+ return result.Scale (1 .0f / Vector2 (reference.GetSize ()));
191
+ }
192
+
186
193
} // namespace
187
194
188
195
GaussianBlurFilterContents::GaussianBlurFilterContents (
@@ -311,6 +318,29 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
311
318
Vector2 pass1_pixel_size =
312
319
1.0 / Vector2 (pass1_out.value ().GetRenderTargetTexture ()->GetSize ());
313
320
321
+ std::optional<Rect> input_snapshot_coverage = input_snapshot->GetCoverage ();
322
+ Quad blur_uvs = {Point (0 , 0 ), Point (1 , 0 ), Point (0 , 1 ), Point (1 , 1 )};
323
+ if (expanded_coverage_hint.has_value () &&
324
+ input_snapshot_coverage.has_value () &&
325
+ // TODO(tbd): Remove this condition. There is some flaw in coverage
326
+ // stopping us from using this today. I attempted to use source
327
+ // coordinates to calculate the uvs, but that didn't work
328
+ // either
329
+ // (https://github.com/flutter/engine/pull/49299#issuecomment-1865311438).
330
+ input_snapshot.has_value () &&
331
+ input_snapshot.value ().transform .IsTranslationScaleOnly ()) {
332
+ // Only process the uvs where the blur is happening, not the whole texture.
333
+ std::optional<Rect> uvs = MakeReferenceUVs (input_snapshot_coverage.value (),
334
+ expanded_coverage_hint.value ())
335
+ .Intersection (Rect::MakeSize (Size (1 , 1 )));
336
+ if (uvs.has_value ()) {
337
+ blur_uvs[0 ] = uvs->GetLeftTop ();
338
+ blur_uvs[1 ] = uvs->GetRightTop ();
339
+ blur_uvs[2 ] = uvs->GetLeftBottom ();
340
+ blur_uvs[3 ] = uvs->GetRightBottom ();
341
+ }
342
+ }
343
+
314
344
fml::StatusOr<RenderTarget> pass2_out =
315
345
MakeBlurSubpass (renderer, /* input_pass=*/ pass1_out.value (),
316
346
input_snapshot->sampler_descriptor , tile_mode_,
@@ -320,7 +350,7 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
320
350
.blur_radius = blur_radius.y * effective_scalar.y ,
321
351
.step_size = 1.0 ,
322
352
},
323
- /* destination_target=*/ std::nullopt);
353
+ /* destination_target=*/ std::nullopt, blur_uvs );
324
354
325
355
if (!pass2_out.ok ()) {
326
356
return std::nullopt;
@@ -341,7 +371,7 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
341
371
.blur_radius = blur_radius.x * effective_scalar.x ,
342
372
.step_size = 1.0 ,
343
373
},
344
- pass3_destination);
374
+ pass3_destination, blur_uvs );
345
375
346
376
if (!pass3_out.ok ()) {
347
377
return std::nullopt;
0 commit comments