Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 4 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
28 changes: 28 additions & 0 deletions impeller/aiks/aiks_blur_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -644,5 +644,33 @@ TEST_P(AiksTest, GaussianBlurStyleOuter) {
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}

TEST_P(AiksTest, GaussianBlurStyleSolid) {
Canvas canvas;
canvas.Scale(GetContentScale());

canvas.DrawPaint({.color = Color(0.1, 0.1, 0.1, 1.0)});

Paint paint;
paint.color = Color::Green();
paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
.style = FilterContents::BlurStyle::kSolid,
.sigma = Sigma(30),
};
canvas.DrawPath(PathBuilder()
.MoveTo({200, 200})
.LineTo({300, 400})
.LineTo({100, 400})
.Close()
.TakePath(),
paint);

// Draw another thing to make sure the clip area is reset.
Paint red;
red.color = Color::Red();
canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);

ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}

} // namespace testing
} // namespace impeller
6 changes: 3 additions & 3 deletions impeller/entity/contents/filters/blend_filter_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,15 @@ static std::optional<Entity> AdvancedBlend(
if (!dst_snapshot.has_value()) {
return std::nullopt;
}
return Entity::FromSnapshot(dst_snapshot, entity.GetBlendMode(),
return Entity::FromSnapshot(dst_snapshot.value(), entity.GetBlendMode(),
entity.GetClipDepth());
}
auto maybe_src_uvs = src_snapshot->GetCoverageUVs(coverage);
if (!maybe_src_uvs.has_value()) {
if (!dst_snapshot.has_value()) {
return std::nullopt;
}
return Entity::FromSnapshot(dst_snapshot, entity.GetBlendMode(),
return Entity::FromSnapshot(dst_snapshot.value(), entity.GetBlendMode(),
entity.GetClipDepth());
}
src_uvs = maybe_src_uvs.value();
Expand Down Expand Up @@ -426,7 +426,7 @@ std::optional<Entity> BlendFilterContents::CreateForegroundPorterDuffBlend(
}

if (blend_mode == BlendMode::kDestination) {
return Entity::FromSnapshot(dst_snapshot, entity.GetBlendMode(),
return Entity::FromSnapshot(dst_snapshot.value(), entity.GetBlendMode(),
entity.GetClipDepth());
}

Expand Down
85 changes: 53 additions & 32 deletions impeller/entity/contents/filters/gaussian_blur_filter_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -204,31 +204,12 @@ int ScaleBlurRadius(Scalar radius, Scalar scalar) {
return static_cast<int>(std::round(radius * scalar));
}

Entity ApplyBlurStyle(FilterContents::BlurStyle blur_style,
const Entity& entity,
const std::shared_ptr<FilterInput>& input,
const Snapshot& input_snapshot,
Entity blur_entity,
const std::shared_ptr<Geometry>& geometry) {
if (blur_style == FilterContents::BlurStyle::kNormal) {
return blur_entity;
}
Entity::ClipOperation clip_operation;
switch (blur_style) {
case FilterContents::BlurStyle::kNormal:
FML_UNREACHABLE();
break;
case FilterContents::BlurStyle::kInner:
clip_operation = Entity::ClipOperation::kIntersect;
break;
case FilterContents::BlurStyle::kOuter:
clip_operation = Entity::ClipOperation::kDifference;
break;
case FilterContents::BlurStyle::kSolid:
FML_DLOG(ERROR) << "Unimplemented blur style";
return blur_entity;
}

Entity ApplyClippedBlurStyle(Entity::ClipOperation clip_operation,
const Entity& entity,
const std::shared_ptr<FilterInput>& input,
const Snapshot& input_snapshot,
Entity blur_entity,
const std::shared_ptr<Geometry>& geometry) {
auto shared_blur_entity = std::make_shared<Entity>(std::move(blur_entity));
shared_blur_entity->SetNewClipDepth(entity.GetNewClipDepth());
auto clipper = std::make_unique<ClipContents>();
Expand All @@ -255,6 +236,50 @@ Entity ApplyBlurStyle(FilterContents::BlurStyle blur_style,
}));
return result;
}

Entity ApplyBlurStyle(FilterContents::BlurStyle blur_style,
const Entity& entity,
const std::shared_ptr<FilterInput>& input,
const Snapshot& input_snapshot,
Entity blur_entity,
const std::shared_ptr<Geometry>& geometry) {
switch (blur_style) {
case FilterContents::BlurStyle::kNormal:
return blur_entity;
case FilterContents::BlurStyle::kInner:
return ApplyClippedBlurStyle(Entity::ClipOperation::kIntersect, entity,
input, input_snapshot,
std::move(blur_entity), geometry);
break;
case FilterContents::BlurStyle::kOuter:
return ApplyClippedBlurStyle(Entity::ClipOperation::kDifference, entity,
input, input_snapshot,
std::move(blur_entity), geometry);
case FilterContents::BlurStyle::kSolid: {
Entity blurred = ApplyClippedBlurStyle(Entity::ClipOperation::kIntersect,
entity, input, input_snapshot,
std::move(blur_entity), geometry);
Entity snapshot_entity = Entity::FromSnapshot(
input_snapshot, entity.GetBlendMode(), entity.GetClipDepth());
Entity result;
result.SetContents(Contents::MakeAnonymous(
fml::MakeCopyable([blurred = blurred.Clone(),
snapshot_entity = std::move(snapshot_entity)](
const ContentContext& renderer,
const Entity& entity,
RenderPass& pass) mutable {
bool did_render = true;
did_render = blurred.Render(renderer, pass) && did_render;
did_render = snapshot_entity.Render(renderer, pass) && did_render;
return did_render;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
bool did_render = true;
did_render = blurred.Render(renderer, pass) && did_render;
did_render = snapshot_entity.Render(renderer, pass) && did_render;
return did_render;
return blurred.Render(renderer, pass) && snapshot_entity.Render(renderer, pass);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not functionally equivalent because of short-circuiting. I was thinking we still want to render the snapshot even if the blurred draw fails for some reason.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If part of rendering fails then we should almost always be bailing out to a toplevel VALIDATION_LOG handler or error. partially correct is still wrong, so I'd prefer the simpler approach.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think those validation errors are noops in release builds though, right? Not a huge deal, done.

}),
fml::MakeCopyable([blurred = blurred.Clone()](const Entity& entity) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be simpler to grab the coverage here and pass it in?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

return blurred.GetCoverage();
})));
return result;
}
}
}
} // namespace

std::string_view GaussianBlurFilterContents::kNoMipsError =
Expand Down Expand Up @@ -499,7 +524,7 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
SamplerDescriptor sampler_desc = MakeSamplerDescriptor(
MinMagFilter::kLinear, SamplerAddressMode::kClampToEdge);

auto blur_output_entity = Entity::FromSnapshot(
Entity blur_output_entity = Entity::FromSnapshot(
Snapshot{.texture = pass3_out.value().GetRenderTargetTexture(),
.transform = input_snapshot->transform *
padding_snapshot_adjustment *
Expand All @@ -508,13 +533,9 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
.opacity = input_snapshot->opacity},
entity.GetBlendMode(), entity.GetClipDepth());

if (!blur_output_entity.has_value()) {
return std::nullopt;
}

return ApplyBlurStyle(mask_blur_style_, entity, inputs[0],
input_snapshot.value(),
std::move(blur_output_entity.value()), mask_geometry_);
input_snapshot.value(), std::move(blur_output_entity),
mask_geometry_);
}

Scalar GaussianBlurFilterContents::CalculateBlurRadius(Scalar sigma) {
Expand Down
10 changes: 7 additions & 3 deletions impeller/entity/contents/filters/local_matrix_filter_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,13 @@ std::optional<Entity> LocalMatrixFilterContents::RenderFilter(
const Matrix& effect_transform,
const Rect& coverage,
const std::optional<Rect>& coverage_hint) const {
return Entity::FromSnapshot(
inputs[0]->GetSnapshot("LocalMatrix", renderer, entity),
entity.GetBlendMode(), entity.GetClipDepth());
std::optional<Snapshot> snapshot =
inputs[0]->GetSnapshot("LocalMatrix", renderer, entity);
if (!snapshot.has_value()) {
return std::nullopt;
}
return Entity::FromSnapshot(snapshot.value(), entity.GetBlendMode(),
entity.GetClipDepth());
}

} // namespace impeller
5 changes: 4 additions & 1 deletion impeller/entity/contents/filters/matrix_filter_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ std::optional<Entity> MatrixFilterContents::RenderFilter(
snapshot->transform;

snapshot->sampler_descriptor = sampler_descriptor_;
return Entity::FromSnapshot(snapshot, entity.GetBlendMode(),
if (!snapshot.has_value()) {
return std::nullopt;
}
return Entity::FromSnapshot(snapshot.value(), entity.GetBlendMode(),
entity.GetClipDepth());
}

Expand Down
21 changes: 8 additions & 13 deletions impeller/entity/entity.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,21 @@

namespace impeller {

std::optional<Entity> Entity::FromSnapshot(
const std::optional<Snapshot>& snapshot,
BlendMode blend_mode,
uint32_t clip_depth) {
if (!snapshot.has_value()) {
return std::nullopt;
}

auto texture_rect = Rect::MakeSize(snapshot->texture->GetSize());
Entity Entity::FromSnapshot(const Snapshot& snapshot,
BlendMode blend_mode,
uint32_t clip_depth) {
auto texture_rect = Rect::MakeSize(snapshot.texture->GetSize());

auto contents = TextureContents::MakeRect(texture_rect);
contents->SetTexture(snapshot->texture);
contents->SetSamplerDescriptor(snapshot->sampler_descriptor);
contents->SetTexture(snapshot.texture);
contents->SetSamplerDescriptor(snapshot.sampler_descriptor);
contents->SetSourceRect(texture_rect);
contents->SetOpacity(snapshot->opacity);
contents->SetOpacity(snapshot.opacity);

Entity entity;
entity.SetBlendMode(blend_mode);
entity.SetClipDepth(clip_depth);
entity.SetTransform(snapshot->transform);
entity.SetTransform(snapshot.transform);
entity.SetContents(contents);
return entity;
}
Expand Down
7 changes: 3 additions & 4 deletions impeller/entity/entity.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,9 @@ class Entity {
};

/// @brief Create an entity that can be used to render a given snapshot.
static std::optional<Entity> FromSnapshot(
const std::optional<Snapshot>& snapshot,
BlendMode blend_mode = BlendMode::kSourceOver,
uint32_t clip_depth = 0);
static Entity FromSnapshot(const Snapshot& snapshot,
BlendMode blend_mode = BlendMode::kSourceOver,
uint32_t clip_depth = 0);

Entity();

Expand Down