Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
26 changes: 26 additions & 0 deletions impeller/aiks/aiks_blur_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,32 @@ TEST_P(AiksTest, GaussianBlurStyleSolid) {
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}

TEST_P(AiksTest, MaskBlurTexture) {
Scalar sigma = 30;
auto callback = [&](AiksContext& renderer) -> std::optional<Picture> {
if (AiksTest::ImGuiBegin("Controls", nullptr,
ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::SliderFloat("Sigma", &sigma, 0, 500);
ImGui::End();
}
Canvas canvas;
canvas.Scale(GetContentScale());
Paint paint;
paint.color = Color::Green();
paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{
.style = FilterContents::BlurStyle::kNormal,
.sigma = Sigma(sigma),
};
std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
canvas.DrawImage(std::make_shared<Image>(boston), {200, 200}, paint);
Paint red;
red.color = Color::Red();
canvas.DrawRect(Rect::MakeXYWH(0, 0, 200, 200), red);
return canvas.EndRecordingAsPicture();
};
ASSERT_TRUE(OpenPlaygroundHere(callback));
}

TEST_P(AiksTest, GuassianBlurUpdatesMipmapContents) {
// This makes sure if mip maps are recycled across invocations of blurs the
// contents get updated each frame correctly. If they aren't updated the color
Expand Down
21 changes: 13 additions & 8 deletions impeller/aiks/canvas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -728,14 +728,19 @@ void Canvas::DrawImageRect(const std::shared_ptr<Image>& image,
return;
}

auto contents = TextureContents::MakeRect(dest);
contents->SetTexture(image->GetTexture());
contents->SetSourceRect(source);
contents->SetStrictSourceRect(src_rect_constraint ==
SourceRectConstraint::kStrict);
contents->SetSamplerDescriptor(std::move(sampler));
contents->SetOpacity(paint.color.alpha);
contents->SetDeferApplyingOpacity(paint.HasColorFilter());
auto texture_contents = TextureContents::MakeRect(dest);
texture_contents->SetTexture(image->GetTexture());
texture_contents->SetSourceRect(source);
texture_contents->SetStrictSourceRect(src_rect_constraint ==
SourceRectConstraint::kStrict);
texture_contents->SetSamplerDescriptor(std::move(sampler));
texture_contents->SetOpacity(paint.color.alpha);
texture_contents->SetDeferApplyingOpacity(paint.HasColorFilter());

std::shared_ptr<Contents> contents = texture_contents;
if (paint.mask_blur_descriptor.has_value()) {
contents = paint.mask_blur_descriptor->CreateMaskBlur(texture_contents);
}

Entity entity;
entity.SetBlendMode(paint.blend_mode);
Expand Down
29 changes: 29 additions & 0 deletions impeller/aiks/paint.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "impeller/entity/contents/color_source_contents.h"
#include "impeller/entity/contents/filters/color_filter_contents.h"
#include "impeller/entity/contents/filters/filter_contents.h"
#include "impeller/entity/contents/filters/gaussian_blur_filter_contents.h"
#include "impeller/entity/contents/solid_color_contents.h"
#include "impeller/entity/geometry/geometry.h"

Expand Down Expand Up @@ -121,6 +122,34 @@ std::shared_ptr<Contents> Paint::WithColorFilter(
absorb_opacity);
}

std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
Copy link
Contributor

Choose a reason for hiding this comment

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

I would defer to @bdero to review the mask blur implementation. Overall code looks reasonable to me.

std::shared_ptr<TextureContents> texture_contents) const {
Scalar expand_amount = GaussianBlurFilterContents::CalculateBlurRadius(
GaussianBlurFilterContents::ScaleSigma(sigma.sigma));
texture_contents->SetSourceRect(
texture_contents->GetSourceRect().Expand(expand_amount, expand_amount));
auto mask = std::make_shared<SolidColorContents>();
mask->SetColor(Color::White());
std::optional<Rect> coverage = texture_contents->GetCoverage({});
std::shared_ptr<Geometry> geometry;
if (coverage) {
texture_contents->SetDestinationRect(
coverage.value().Expand(expand_amount, expand_amount));
geometry = Geometry::MakeRect(coverage.value());
}
mask->SetGeometry(geometry);
auto descriptor = texture_contents->GetSamplerDescriptor();
texture_contents->SetSamplerDescriptor(descriptor);
std::shared_ptr<FilterContents> blurred_mask =
FilterContents::MakeGaussianBlur(FilterInput::Make(mask), sigma, sigma,
Entity::TileMode::kDecal, style,
geometry);

return ColorFilterContents::MakeBlend(
BlendMode::kSourceIn,
{FilterInput::Make(blurred_mask), FilterInput::Make(texture_contents)});
}

std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
std::shared_ptr<ColorSourceContents> color_source_contents,
Copy link
Contributor

Choose a reason for hiding this comment

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

We already have a path for creating a mask blur from a color source contents. If we created a TiledTextureContents (which is a color source contents) instead of a TextureContents for drawImageRect calls with a mask blur descriptor, then could we pass it into this function and have it just work?

Copy link
Member Author

Choose a reason for hiding this comment

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

Nope, we have to essentially create a transparent halo around the texture to make the blending work correctly. That requires modifying texcoords. The path below doesn't know anything about that, just expanding geometry which would stretch the image.

Copy link
Member Author

Choose a reason for hiding this comment

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

Sorry, not a transparent halo, but sampling outside of the image based on whatever the sampler settings are.

Copy link
Member

Choose a reason for hiding this comment

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

Oh, that's a bug in the existing path, then. And that same issue actually applies to all the ColorSource types (except for solid colors, of course).

One easy solution for that would be to amend the effect transform of the ColorSourceContents.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh yea, that would explain some of the stretching I saw of gradients. I'll file an issue.

Copy link
Member Author

Choose a reason for hiding this comment

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

const std::shared_ptr<ColorFilter>& color_filter) const {
Expand Down
4 changes: 4 additions & 0 deletions impeller/aiks/paint.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "impeller/entity/contents/contents.h"
#include "impeller/entity/contents/filters/color_filter_contents.h"
#include "impeller/entity/contents/filters/filter_contents.h"
#include "impeller/entity/contents/texture_contents.h"
#include "impeller/entity/entity.h"
#include "impeller/entity/geometry/geometry.h"
#include "impeller/geometry/color.h"
Expand Down Expand Up @@ -43,6 +44,9 @@ struct Paint {
std::shared_ptr<ColorSourceContents> color_source_contents,
const std::shared_ptr<ColorFilter>& color_filter) const;

std::shared_ptr<FilterContents> CreateMaskBlur(
std::shared_ptr<TextureContents> texture_contents) const;

std::shared_ptr<FilterContents> CreateMaskBlur(
const FilterInput::Ref& input,
bool is_solid_color) const;
Expand Down
3 changes: 3 additions & 0 deletions testing/impeller_golden_tests_output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,9 @@ impeller_Play_AiksTest_ImageFilteredUnboundedSaveLayerWithUnboundedContents_Vulk
impeller_Play_AiksTest_LinearToSrgbFilterSubpassCollapseOptimization_Metal.png
impeller_Play_AiksTest_LinearToSrgbFilterSubpassCollapseOptimization_OpenGLES.png
impeller_Play_AiksTest_LinearToSrgbFilterSubpassCollapseOptimization_Vulkan.png
impeller_Play_AiksTest_MaskBlurTexture_Metal.png
impeller_Play_AiksTest_MaskBlurTexture_OpenGLES.png
impeller_Play_AiksTest_MaskBlurTexture_Vulkan.png
impeller_Play_AiksTest_MaskBlurVariantTestInnerTranslucentWithBlurImageFilter_Metal.png
impeller_Play_AiksTest_MaskBlurVariantTestInnerTranslucentWithBlurImageFilter_OpenGLES.png
impeller_Play_AiksTest_MaskBlurVariantTestInnerTranslucentWithBlurImageFilter_Vulkan.png
Expand Down