[Impeller] Set the coverage hint on everything (flutter/engine#42264)

Attaches a minimum coverage hint to all rendered entities. This makes ImageFilter blurs do less work when clipped. We can utilize this in a number of other filters as well.

![Screenshot 2023-05-23 at 3 16 49 PM](https://github.com/flutter/engine/assets/919017/5b7182c8-e704-4c4a-bb71-fdf226a60f4e)

The test I added also demonstrates a sampling issue in the gaussian blur that I'm trying to work out. Here it is without any clipping. This coverage hint change does not introduce the issue:

![Screenshot 2023-05-23 at 3 08 15 PM](https://github.com/flutter/engine/assets/919017/524c2fb1-3b58-4589-824b-0794c2bd5ea2)
This commit is contained in:
Brandon DeRosier 2023-05-23 19:06:19 -07:00 committed by GitHub
parent e9298a1d2a
commit 6828abffee
2 changed files with 27 additions and 11 deletions

View File

@ -2322,6 +2322,27 @@ TEST_P(AiksTest, CanRenderBackdropBlurHugeSigma) {
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
TEST_P(AiksTest, CanRenderClippedBlur) {
Canvas canvas;
canvas.ClipRect(Rect::MakeXYWH(100, 150, 400, 400));
canvas.DrawCircle(
{400, 400}, 200,
{
.color = Color::Green(),
.image_filter =
[](const FilterInput::Ref& input, const Matrix& effect_transform,
bool is_subpass) {
return FilterContents::MakeGaussianBlur(
input, Sigma(20), Sigma(20),
FilterContents::BlurStyle::kNormal,
Entity::TileMode::kClamp, effect_transform);
},
});
canvas.Restore();
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
// Regression test for https://github.com/flutter/flutter/issues/126701 .
TEST_P(AiksTest, CanRenderClippedRuntimeEffects) {
if (GetParam() != PlaygroundBackend::kMetal) {

View File

@ -615,6 +615,12 @@ bool EntityPass::OnRender(
stencil_coverage.coverage->origin += global_pass_position;
}
// The coverage hint tells the rendered Contents which portion of the
// rendered output will actually be used, and so we set this to the current
// stencil coverage (which is the max clip bounds). The contents may
// optionally use this hint to avoid unnecessary rendering work.
element_entity.GetContents()->SetCoverageHint(current_stencil_coverage);
switch (stencil_coverage.type) {
case Contents::StencilCoverage::Type::kNoChange:
break;
@ -685,17 +691,6 @@ bool EntityPass::OnRender(
return false;
}
// Tell the backdrop contents which portion of the rendered output will
// actually be used. The contents may optionally use this hint to avoid
// unnecessary rendering work.
if (!stencil_coverage_stack.empty() &&
stencil_coverage_stack.back().coverage.has_value()) {
auto coverage_hint = Rect(
stencil_coverage_stack.back().coverage->origin - global_pass_position,
stencil_coverage_stack.back().coverage->size);
backdrop_filter_contents->SetCoverageHint(coverage_hint);
}
Entity backdrop_entity;
backdrop_entity.SetContents(std::move(backdrop_filter_contents));
backdrop_entity.SetTransformation(