@@ -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,12 @@ fml::StatusOr<RenderTarget> MakeBlurSubpass(
183184 }
184185}
185186
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+
186193} // namespace
187194
188195GaussianBlurFilterContents::GaussianBlurFilterContents (
@@ -311,6 +318,29 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
311318 Vector2 pass1_pixel_size =
312319 1.0 / Vector2 (pass1_out.value ().GetRenderTargetTexture ()->GetSize ());
313320
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+
314344 fml::StatusOr<RenderTarget> pass2_out =
315345 MakeBlurSubpass (renderer, /* input_pass=*/ pass1_out.value (),
316346 input_snapshot->sampler_descriptor , tile_mode_,
@@ -320,7 +350,7 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
320350 .blur_radius = blur_radius.y * effective_scalar.y ,
321351 .step_size = 1.0 ,
322352 },
323- /* destination_target=*/ std::nullopt );
353+ /* destination_target=*/ std::nullopt , blur_uvs );
324354
325355 if (!pass2_out.ok ()) {
326356 return std::nullopt ;
@@ -341,7 +371,7 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
341371 .blur_radius = blur_radius.x * effective_scalar.x ,
342372 .step_size = 1.0 ,
343373 },
344- pass3_destination);
374+ pass3_destination, blur_uvs );
345375
346376 if (!pass3_out.ok ()) {
347377 return std::nullopt ;
0 commit comments