Skip to content

Commit

Permalink
[Impeller] Correct coverage hint usage in PipelineBlend (flutter#43708)
Browse files Browse the repository at this point in the history
Resolves flutter/flutter#130411.

The remaining difference in appearance is due to flutter/flutter#127770 -- Impeller's blurs skew too large.

Before:

![Screen Shot 2023-07-14 at 3 36 02 PM](https://github.com/flutter/engine/assets/919017/54ad62ed-f091-4489-a346-a0e7580ed2f0)

After:

![Screen Shot 2023-07-14 at 3 22 25 PM](https://github.com/flutter/engine/assets/919017/252ac8bb-4a09-4c96-a405-5ddbb3ba6851)
  • Loading branch information
bdero authored Jul 17, 2023
1 parent aa3239c commit 105f6e3
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 24 deletions.
21 changes: 21 additions & 0 deletions impeller/aiks/aiks_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2984,6 +2984,27 @@ TEST_P(AiksTest, DrawScaledTextWithPerspectiveSaveLayer) {

ASSERT_TRUE(RenderTextInCanvas(GetContext(), canvas, "Hello world",
"Roboto-Regular.ttf"));
}

TEST_P(AiksTest, PipelineBlendSingleParameter) {
Canvas canvas;

// Should render a green square in the middle of a blue circle.
canvas.SaveLayer({});
{
canvas.Translate(Point(100, 100));
canvas.DrawCircle(Point(200, 200), 200, {.color = Color::Blue()});
canvas.ClipRect(Rect(100, 100, 200, 200));
canvas.DrawCircle(
Point(200, 200), 200,
{.color = Color::Green(),
.blend_mode = BlendMode::kSourceOver,
.image_filter = [](const FilterInput::Ref& input,
const Matrix& effect_transform, bool is_subpass) {
return ColorFilterContents::MakeBlend(BlendMode::kSource, {input});
}});
canvas.Restore();
}

ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
Expand Down
65 changes: 41 additions & 24 deletions impeller/entity/contents/filters/blend_filter_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,21 @@ static std::optional<Entity> AdvancedBlend(
src_uvs = maybe_src_uvs.value();
}

Rect subpass_coverage = coverage;
if (entity.GetContents()) {
auto coverage_hint = entity.GetContents()->GetCoverageHint();

if (coverage_hint.has_value()) {
auto maybe_subpass_coverage =
subpass_coverage.Intersection(*coverage_hint);
if (!maybe_subpass_coverage.has_value()) {
return std::nullopt; // Nothing to render.
}

subpass_coverage = *maybe_subpass_coverage;
}
}

//----------------------------------------------------------------------------
/// Render to texture.
///
Expand Down Expand Up @@ -159,7 +174,9 @@ static std::optional<Entity> AdvancedBlend(
auto blend_uniform = host_buffer.EmplaceUniform(blend_info);
FS::BindBlendInfo(cmd, blend_uniform);

frame_info.mvp = Matrix::MakeOrthographic(size);
frame_info.mvp =
Matrix::MakeOrthographic(size) *
Matrix::MakeTranslation(coverage.origin - subpass_coverage.origin);

auto uniform_view = host_buffer.EmplaceUniform(frame_info);
VS::BindFrameInfo(cmd, uniform_view);
Expand All @@ -168,22 +185,15 @@ static std::optional<Entity> AdvancedBlend(
return true;
};

auto subpass_size = ISize(coverage.size);
if (entity.GetContents()) {
auto coverage_hint = entity.GetContents()->GetCoverageHint();
if (coverage_hint.has_value()) {
subpass_size = subpass_size.Min(ISize(coverage_hint->size));
}
}
auto out_texture =
renderer.MakeSubpass("Advanced Blend Filter", subpass_size, callback);
auto out_texture = renderer.MakeSubpass(
"Advanced Blend Filter", ISize(subpass_coverage.size), callback);
if (!out_texture) {
return std::nullopt;
}

return Entity::FromSnapshot(
Snapshot{.texture = out_texture,
.transform = Matrix::MakeTranslation(coverage.origin),
.transform = Matrix::MakeTranslation(subpass_coverage.origin),
// Since we absorbed the transform of the inputs and used the
// respective snapshot sampling modes when blending, pass on
// the default NN clamp sampler.
Expand Down Expand Up @@ -498,7 +508,22 @@ static std::optional<Entity> PipelineBlend(
auto dst_snapshot =
inputs[0]->GetSnapshot("PipelineBlend(Dst)", renderer, entity);
if (!dst_snapshot.has_value()) {
return std::nullopt;
return std::nullopt; // Nothing to render.
}

Rect subpass_coverage = coverage;
if (entity.GetContents()) {
auto coverage_hint = entity.GetContents()->GetCoverageHint();

if (coverage_hint.has_value()) {
auto maybe_subpass_coverage =
subpass_coverage.Intersection(*coverage_hint);
if (!maybe_subpass_coverage.has_value()) {
return std::nullopt; // Nothing to render.
}

subpass_coverage = *maybe_subpass_coverage;
}
}

ContentContext::SubpassCallback callback = [&](const ContentContext& renderer,
Expand Down Expand Up @@ -538,8 +563,7 @@ static std::optional<Entity> PipelineBlend(

VS::FrameInfo frame_info;
frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
Matrix::MakeTranslation(
-input->GetCoverage().value_or(coverage).origin) *
Matrix::MakeTranslation(-subpass_coverage.origin) *
input->transform;
frame_info.texture_sampler_y_coord_scale =
input->texture->GetYCoordScale();
Expand Down Expand Up @@ -595,23 +619,16 @@ static std::optional<Entity> PipelineBlend(
return true;
};

auto subpass_size = ISize(coverage.size);
if (entity.GetContents()) {
auto coverage_hint = entity.GetContents()->GetCoverageHint();
if (coverage_hint.has_value()) {
subpass_size = subpass_size.Min(ISize(coverage_hint->size));
}
}
auto out_texture =
renderer.MakeSubpass("Pipeline Blend Filter", subpass_size, callback);
auto out_texture = renderer.MakeSubpass(
"Pipeline Blend Filter", ISize(subpass_coverage.size), callback);

if (!out_texture) {
return std::nullopt;
}

return Entity::FromSnapshot(
Snapshot{.texture = out_texture,
.transform = Matrix::MakeTranslation(coverage.origin),
.transform = Matrix::MakeTranslation(subpass_coverage.origin),
// Since we absorbed the transform of the inputs and used the
// respective snapshot sampling modes when blending, pass on
// the default NN clamp sampler.
Expand Down

0 comments on commit 105f6e3

Please sign in to comment.