@@ -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
188197GaussianBlurFilterContents::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