Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[Impeller] Use basis of effect transform in MatrixFilter. #43990

Merged
merged 2 commits into from
Jul 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 21 additions & 9 deletions impeller/aiks/aiks_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2908,15 +2908,27 @@ TEST_P(AiksTest, DrawPictureWithText) {

TEST_P(AiksTest, MatrixBackdropFilter) {
Canvas canvas;
canvas.SaveLayer({}, std::nullopt,
[](const FilterInput::Ref& input,
const Matrix& effect_transform, bool is_subpass) {
return FilterContents::MakeMatrixFilter(
input, Matrix::MakeTranslation(Vector2(100, 100)), {},
Matrix(), true);
});
canvas.DrawCircle(Point(100, 100), 100,
{.color = Color::Green(), .blend_mode = BlendMode::kPlus});
canvas.DrawPaint({.color = Color::Black()});
canvas.SaveLayer({}, std::nullopt);
{
canvas.DrawCircle(Point(200, 200), 100,
{.color = Color::Green().WithAlpha(0.5),
.blend_mode = BlendMode::kPlus});
// Should render a second circle, centered on the bottom-right-most edge of
// the circle.
canvas.SaveLayer({}, std::nullopt,
[](const FilterInput::Ref& input,
const Matrix& effect_transform, bool is_subpass) {
Matrix matrix =
Matrix::MakeTranslation(Vector2(1, 1) *
(100 + 100 * k1OverSqrt2)) *
Matrix::MakeScale(Vector2(1, 1) * 0.2) *
Matrix::MakeTranslation(Vector2(-100, -100));
return FilterContents::MakeMatrixFilter(
input, matrix, {}, Matrix(), true);
});
canvas.Restore();
}
canvas.Restore();

ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
Expand Down
19 changes: 18 additions & 1 deletion impeller/entity/contents/filters/matrix_filter_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,28 @@ std::optional<Entity> MatrixFilterContents::RenderFilter(
return std::nullopt;
}

auto& transform = is_subpass_ ? effect_transform : entity.GetTransformation();
// The filter's matrix needs to be applied within the space defined by the
// scene's current transformation matrix (CTM). For example: If the CTM is
// scaled up, then translations applied by the matrix should be magnified
// accordingly.
//
// To accomplish this, we sandwitch the filter's matrix within the CTM in both
// cases. But notice that for the subpass backdrop filter case, we use the
// "effect transform" instead of the Entity's transform!
//
// That's because in the subpass backdrop filter case, the Entity's transform
// isn't actually the captured CTM of the scene like it usually is; instead,
// it's just a screen space translation that offsets the backdrop texture (as
// mentioned above). And so we sneak the subpass's captured CTM in through the
// effect transform.

auto transform = is_subpass_ ? effect_transform.Basis()
: entity.GetTransformation().Basis();
snapshot->transform = transform * //
matrix_ * //
transform.Invert() * //
snapshot->transform;

snapshot->sampler_descriptor = sampler_descriptor_;
return Entity::FromSnapshot(snapshot, entity.GetBlendMode(),
entity.GetStencilDepth());
Expand Down
34 changes: 18 additions & 16 deletions impeller/entity/entity_pass.cc
Original file line number Diff line number Diff line change
Expand Up @@ -465,12 +465,12 @@ EntityPass::EntityResult EntityPass::GetEntityForElement(
return EntityPass::EntityResult::Skip();
}

std::shared_ptr<Contents> backdrop_filter_contents = nullptr;
std::shared_ptr<Contents> subpass_backdrop_filter_contents = nullptr;
if (subpass->backdrop_filter_proc_) {
auto texture = pass_context.GetTexture();
// Render the backdrop texture before any of the pass elements.
const auto& proc = subpass->backdrop_filter_proc_;
backdrop_filter_contents =
subpass_backdrop_filter_contents =
proc(FilterInput::Make(std::move(texture)), subpass->xformation_,
/*is_subpass*/ true);

Expand Down Expand Up @@ -507,9 +507,10 @@ EntityPass::EntityResult EntityPass::GetEntityForElement(
return EntityPass::EntityResult::Skip();
}

auto subpass_coverage = (subpass->flood_clip_ || backdrop_filter_contents)
? coverage_limit
: GetSubpassCoverage(*subpass, coverage_limit);
auto subpass_coverage =
(subpass->flood_clip_ || subpass_backdrop_filter_contents)
? coverage_limit
: GetSubpassCoverage(*subpass, coverage_limit);
if (!subpass_coverage.has_value()) {
return EntityPass::EntityResult::Skip();
}
Expand All @@ -532,17 +533,18 @@ EntityPass::EntityResult EntityPass::GetEntityForElement(

// Stencil textures aren't shared between EntityPasses (as much of the
// time they are transient).
if (!subpass->OnRender(renderer, // renderer
root_pass_size, // root_pass_size
subpass_target, // pass_target
subpass_coverage->origin, // global_pass_position
subpass_coverage->origin -
global_pass_position, // local_pass_position
++pass_depth, // pass_depth
stencil_coverage_stack, // stencil_coverage_stack
subpass->stencil_depth_, // stencil_depth_floor
backdrop_filter_contents // backdrop_filter_contents
)) {
if (!subpass->OnRender(
renderer, // renderer
root_pass_size, // root_pass_size
subpass_target, // pass_target
subpass_coverage->origin, // global_pass_position
subpass_coverage->origin -
global_pass_position, // local_pass_position
++pass_depth, // pass_depth
stencil_coverage_stack, // stencil_coverage_stack
subpass->stencil_depth_, // stencil_depth_floor
subpass_backdrop_filter_contents // backdrop_filter_contents
)) {
// Validation error messages are triggered for all `OnRender()` failure
// cases.
return EntityPass::EntityResult::Failure();
Expand Down