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 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
66 changes: 66 additions & 0 deletions impeller/display_list/aiks_dl_blur_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,72 @@ TEST_P(AiksTest, SolidColorOvalsMaskBlurTinySigma) {
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}

sk_sp<flutter::DisplayList> DoGradientOvalStrokeMaskBlur(Vector2 content_Scale,
Scalar sigma,
DlBlurStyle style) {
DisplayListBuilder builder;
builder.Scale(content_Scale.x, content_Scale.y);

DlPaint background_paint;
background_paint.setColor(DlColor(1, 0.1, 0.1, 0.1, DlColorSpace::kSRGB));
builder.DrawPaint(background_paint);

std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue()};
std::vector<Scalar> stops = {0.0, 1.0};

DlPaint paint;
paint.setMaskFilter(DlBlurMaskFilter::Make(style, sigma));
auto gradient = DlColorSource::MakeLinear(
{0, 0}, {200, 200}, 2, colors.data(), stops.data(), DlTileMode::kClamp);
paint.setColorSource(gradient);
paint.setColor(DlColor::kWhite());
paint.setDrawStyle(DlDrawStyle::kStroke);
paint.setStrokeWidth(20);

builder.Save();
builder.Translate(100, 100);

{
DlPaint line_paint;
line_paint.setColor(DlColor::kWhite());
builder.DrawLine({100, 0}, {100, 60}, line_paint);
builder.DrawLine({0, 30}, {200, 30}, line_paint);
}

SkRRect rrect =
SkRRect::MakeRectXY(SkRect::MakeXYWH(0, 0, 200.0f, 60.0f), 50, 100);
builder.DrawRRect(rrect, paint);
builder.Restore();

return builder.Build();
}

// https://github.com/flutter/flutter/issues/155930
TEST_P(AiksTest, GradientOvalStrokeMaskBlur) {
ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
GetContentScale(), /*sigma=*/10, DlBlurStyle::kNormal)));
}

TEST_P(AiksTest, GradientOvalStrokeMaskBlurSigmaZero) {
ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
GetContentScale(), /*sigma=*/0, DlBlurStyle::kNormal)));
}

TEST_P(AiksTest, GradientOvalStrokeMaskBlurOuter) {
ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
GetContentScale(), /*sigma=*/10, DlBlurStyle::kOuter)));
}

TEST_P(AiksTest, GradientOvalStrokeMaskBlurInner) {
ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
GetContentScale(), /*sigma=*/10, DlBlurStyle::kInner)));
}

TEST_P(AiksTest, GradientOvalStrokeMaskBlurSolid) {
ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
GetContentScale(), /*sigma=*/10, DlBlurStyle::kSolid)));
}

TEST_P(AiksTest, SolidColorCircleMaskBlurTinySigma) {
DisplayListBuilder builder;
builder.Scale(GetContentScale().x, GetContentScale().y);
Expand Down
1 change: 1 addition & 0 deletions impeller/display_list/aiks_dl_text_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ TEST_P(AiksTest, CanRenderEmojiTextFrame) {
TEST_P(AiksTest, CanRenderEmojiTextFrameWithBlur) {
DisplayListBuilder builder;

builder.Scale(GetContentScale().x, GetContentScale().y);
DlPaint paint;
paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
builder.DrawPaint(paint);
Expand Down
33 changes: 24 additions & 9 deletions impeller/entity/contents/filters/gaussian_blur_filter_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ Vector2 ExtractScale(const Matrix& matrix) {
struct BlurInfo {
/// The scalar that is used to get from source space to unrotated local space.
Vector2 source_space_scalar;
/// The translation that is used to get from source space to unrotated local
/// space.
Vector2 source_space_offset;
/// Sigma when considering an entity's scale and the effect transform.
Vector2 scaled_sigma;
/// Blur radius in source pixels based on scaled_sigma.
Expand All @@ -95,6 +98,8 @@ BlurInfo CalculateBlurInfo(const Entity& entity,
// applied to the result of the blur as part of the result's transform.
const Vector2 source_space_scalar =
ExtractScale(entity.GetTransform().Basis());
const Vector2 source_space_offset =
Vector2(entity.GetTransform().m[12], entity.GetTransform().m[13]);

Vector2 scaled_sigma =
(effect_transform.Basis() * Matrix::MakeScale(source_space_scalar) * //
Expand All @@ -110,6 +115,7 @@ BlurInfo CalculateBlurInfo(const Entity& entity,
(Matrix::MakeScale(source_space_scalar) * padding).Abs();
return {
.source_space_scalar = source_space_scalar,
.source_space_offset = source_space_offset,
.scaled_sigma = scaled_sigma,
.blur_radius = blur_radius,
.padding = padding,
Expand Down Expand Up @@ -545,7 +551,8 @@ Entity ApplyBlurStyle(FilterContents::BlurStyle blur_style,
const Snapshot& input_snapshot,
Entity blur_entity,
const Geometry* geometry,
Vector2 source_space_scalar) {
Vector2 source_space_scalar,
Vector2 source_space_offset) {
switch (blur_style) {
case FilterContents::BlurStyle::kNormal:
return blur_entity;
Expand All @@ -563,9 +570,11 @@ Entity ApplyBlurStyle(FilterContents::BlurStyle blur_style,
Entity::FromSnapshot(input_snapshot, entity.GetBlendMode());
Entity result;
Matrix blurred_transform = blur_entity.GetTransform();
Matrix snapshot_transform = entity.GetTransform() * //
Matrix::MakeScale(1.f / source_space_scalar) *
input_snapshot.transform;
Matrix snapshot_transform =
entity.GetTransform() * //
Matrix::MakeScale(1.f / source_space_scalar) *
Matrix::MakeTranslation(-1 * source_space_offset) *
input_snapshot.transform;
result.SetContents(Contents::MakeAnonymous(
fml::MakeCopyable([blur_entity = blur_entity.Clone(),
blurred_transform, snapshot_transform,
Expand Down Expand Up @@ -697,11 +706,13 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(

Entity snapshot_entity = entity.Clone();
snapshot_entity.SetTransform(
Matrix::MakeTranslation(blur_info.source_space_offset) *
Matrix::MakeScale(blur_info.source_space_scalar));

std::optional<Rect> source_expanded_coverage_hint;
if (expanded_coverage_hint.has_value()) {
source_expanded_coverage_hint = expanded_coverage_hint->TransformBounds(
Matrix::MakeTranslation(blur_info.source_space_offset) *
Matrix::MakeScale(blur_info.source_space_scalar) *
entity.GetTransform().Invert());
}
Expand All @@ -717,9 +728,11 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
Entity result =
Entity::FromSnapshot(input_snapshot.value(),
entity.GetBlendMode()); // No blur to render.
result.SetTransform(entity.GetTransform() *
Matrix::MakeScale(1.f / blur_info.source_space_scalar) *
input_snapshot->transform);
result.SetTransform(
entity.GetTransform() *
Matrix::MakeScale(1.f / blur_info.source_space_scalar) *
Matrix::MakeTranslation(-1 * blur_info.source_space_offset) *
input_snapshot->transform);
return result;
}

Expand Down Expand Up @@ -827,15 +840,17 @@ std::optional<Entity> GaussianBlurFilterContents::RenderFilter(
.transform =
entity.GetTransform() * //
Matrix::MakeScale(1.f / blur_info.source_space_scalar) * //
downsample_pass_args.transform * //
Matrix::MakeTranslation(-1 * blur_info.source_space_offset) *
downsample_pass_args.transform * //
Matrix::MakeScale(1 / downsample_pass_args.effective_scalar),
.sampler_descriptor = sampler_desc,
.opacity = input_snapshot->opacity},
entity.GetBlendMode());

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

Scalar GaussianBlurFilterContents::CalculateBlurRadius(Scalar sigma) {
Expand Down
15 changes: 15 additions & 0 deletions testing/impeller_golden_tests_output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,21 @@ impeller_Play_AiksTest_GaussianBlurStyleSolid_Metal.png
impeller_Play_AiksTest_GaussianBlurStyleSolid_OpenGLES.png
impeller_Play_AiksTest_GaussianBlurStyleSolid_Vulkan.png
impeller_Play_AiksTest_GaussianBlurWithoutDecalSupport_Metal.png
impeller_Play_AiksTest_GradientOvalStrokeMaskBlurInner_Metal.png
impeller_Play_AiksTest_GradientOvalStrokeMaskBlurInner_OpenGLES.png
impeller_Play_AiksTest_GradientOvalStrokeMaskBlurInner_Vulkan.png
impeller_Play_AiksTest_GradientOvalStrokeMaskBlurOuter_Metal.png
impeller_Play_AiksTest_GradientOvalStrokeMaskBlurOuter_OpenGLES.png
impeller_Play_AiksTest_GradientOvalStrokeMaskBlurOuter_Vulkan.png
impeller_Play_AiksTest_GradientOvalStrokeMaskBlurSigmaZero_Metal.png
impeller_Play_AiksTest_GradientOvalStrokeMaskBlurSigmaZero_OpenGLES.png
impeller_Play_AiksTest_GradientOvalStrokeMaskBlurSigmaZero_Vulkan.png
impeller_Play_AiksTest_GradientOvalStrokeMaskBlurSolid_Metal.png
impeller_Play_AiksTest_GradientOvalStrokeMaskBlurSolid_OpenGLES.png
impeller_Play_AiksTest_GradientOvalStrokeMaskBlurSolid_Vulkan.png
impeller_Play_AiksTest_GradientOvalStrokeMaskBlur_Metal.png
impeller_Play_AiksTest_GradientOvalStrokeMaskBlur_OpenGLES.png
impeller_Play_AiksTest_GradientOvalStrokeMaskBlur_Vulkan.png
impeller_Play_AiksTest_GradientStrokesRenderCorrectly_Metal.png
impeller_Play_AiksTest_GradientStrokesRenderCorrectly_OpenGLES.png
impeller_Play_AiksTest_GradientStrokesRenderCorrectly_Vulkan.png
Expand Down