From e21a452b633e262aa4d03b0f2c2680619471005f Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Wed, 6 Mar 2024 22:06:19 -0800 Subject: [PATCH 1/8] [Impeller] Add mask blur style support to the RRect blur fast path. --- impeller/aiks/aiks_unittests.cc | 137 ++++++++++++++++++++++++++++++++ impeller/aiks/canvas.cc | 112 ++++++++++++++++++++++---- impeller/aiks/canvas.h | 2 +- 3 files changed, 234 insertions(+), 17 deletions(-) diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index 0d4fcb16aee64..b1486bc60bdf8 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -1614,6 +1614,143 @@ TEST_P(AiksTest, SolidColorCirclesOvalsRRectsMaskBlurCorrectly) { ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } +TEST_P(AiksTest, + SolidColorCirclesOvalsRRectsMaskBlurCorrectlyBlurStyleVariations) { + Canvas canvas; + canvas.Scale(GetContentScale()); + canvas.Scale(Vector2{0.8f, 0.8f}); + Paint paint; + paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{ + .style = FilterContents::BlurStyle::kNormal, + .sigma = Sigma{1}, + }; + + canvas.DrawPaint({.color = Color::AntiqueWhite()}); + + struct MaskBlurTestConfig { + FilterContents::BlurStyle style = FilterContents::BlurStyle::kNormal; + Scalar sigma = 1.0f; + Scalar alpha = 1.0f; + std::shared_ptr image_filter; + bool invert_colors = false; + BlendMode blend_mode = BlendMode::kSourceOver; + }; + + std::vector paint_variations = { + // 1. Normal style, translucent, zero sigma. + {.style = FilterContents::BlurStyle::kNormal, + .sigma = 0.0f, + .alpha = 0.5f}, + // 2. Normal style, translucent. + {.style = FilterContents::BlurStyle::kNormal, + .sigma = 8.0f, + .alpha = 0.5f}, + // 3. Solid style, translucent. + {.style = FilterContents::BlurStyle::kSolid, + .sigma = 8.0f, + .alpha = 0.5f}, + // 4. Solid style, opaque. + {.style = FilterContents::BlurStyle::kSolid, .sigma = 8.0f}, + // 5. Solid style, translucent, color & image filtered. + {.style = FilterContents::BlurStyle::kSolid, + .sigma = 8.0f, + .alpha = 0.5f, + .image_filter = ImageFilter::MakeBlur(Sigma{3}, Sigma{3}, + FilterContents::BlurStyle::kNormal, + Entity::TileMode::kClamp), + .invert_colors = true}, + // 6. Solid style, translucent, exclusion blended. + {.style = FilterContents::BlurStyle::kSolid, + .sigma = 8.0f, + .alpha = 0.5f, + .blend_mode = BlendMode::kExclusion}, + // 7. Inner style, translucent. + {.style = FilterContents::BlurStyle::kInner, + .sigma = 8.0f, + .alpha = 0.5f}, + // 8. Inner style, translucent, blurred. + {.style = FilterContents::BlurStyle::kInner, + .sigma = 8.0f, + .alpha = 0.5f, + .image_filter = ImageFilter::MakeBlur(Sigma{3}, Sigma{3}, + FilterContents::BlurStyle::kNormal, + Entity::TileMode::kClamp)}, + // 9. Outer style, translucent. + {.style = FilterContents::BlurStyle::kOuter, + .sigma = 8.0f, + .alpha = 0.5f}, + // 10. Outer style, opaque, image filtered. + {.style = FilterContents::BlurStyle::kOuter, + .sigma = 8.0f, + .image_filter = ImageFilter::MakeBlur(Sigma{3}, Sigma{3}, + FilterContents::BlurStyle::kNormal, + Entity::TileMode::kClamp)}, + }; + + for (size_t i = 0; i < paint_variations.size(); i++) { + const MaskBlurTestConfig& config = paint_variations[i]; + paint.mask_blur_descriptor->style = config.style; + paint.mask_blur_descriptor->sigma = Sigma{config.sigma}; + paint.image_filter = config.image_filter; + paint.invert_colors = config.invert_colors; + paint.blend_mode = config.blend_mode; + + const Scalar x = 50 + i * 80; + const Scalar radius = 20.0f; + const Scalar y_spacing = 100.0f; + + Scalar y = 50; + paint.color = Color::Crimson().WithAlpha(config.alpha); + canvas.DrawRect(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, // + radius, 60.0f - radius), + paint); + + y += y_spacing; + paint.color = Color::Blue().WithAlpha(config.alpha); + canvas.DrawCircle({x + 25, y + 25}, radius, paint); + + y += y_spacing; + paint.color = Color::Green().WithAlpha(config.alpha); + canvas.DrawOval(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, // + radius, 60.0f - radius), + paint); + + y += y_spacing; + paint.color = Color::Purple().WithAlpha(config.alpha); + canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), // + {radius, radius}, // + paint); + + y += y_spacing; + paint.color = Color::Orange().WithAlpha(config.alpha); + canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), // + {radius, 5.0f}, paint); + + y += y_spacing; + paint.color = Color::Maroon().WithAlpha(config.alpha); + canvas.DrawPath(PathBuilder{} + .MoveTo({x + 0, y + 60}) + .LineTo({x + 30, y + 0}) + .LineTo({x + 60, y + 60}) + .Close() + .TakePath(), + paint); + + y += y_spacing; + paint.color = Color::Maroon().WithAlpha(config.alpha); + canvas.DrawPath(PathBuilder{} + .AddArc(Rect::MakeXYWH(x + 5, y, 50, 50), + Radians{kPi / 2}, Radians{kPi}) + .AddArc(Rect::MakeXYWH(x + 25, y, 50, 50), + Radians{kPi / 2}, Radians{kPi}) + .Close() + .TakePath(), + paint); + } + + ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); +} + TEST_P(AiksTest, FilledRoundRectPathsRenderCorrectly) { Canvas canvas; canvas.Scale(GetContentScale()); diff --git a/impeller/aiks/canvas.cc b/impeller/aiks/canvas.cc index 2fbfe2b2394d5..79c27ed09e43d 100644 --- a/impeller/aiks/canvas.cc +++ b/impeller/aiks/canvas.cc @@ -308,41 +308,121 @@ void Canvas::DrawPaint(const Paint& paint) { } bool Canvas::AttemptDrawBlurredRRect(const Rect& rect, - Size corner_radius, + Size corner_radii, const Paint& paint) { if (paint.color_source.GetType() != ColorSource::Type::kColor || paint.style != Paint::Style::kFill) { return false; } - if (!paint.mask_blur_descriptor.has_value() || - paint.mask_blur_descriptor->style != FilterContents::BlurStyle::kNormal) { + if (!paint.mask_blur_descriptor.has_value()) { return false; } + // A blur sigma that is not positive enough should not result in a blur. if (paint.mask_blur_descriptor->sigma.sigma <= kEhCloseEnough) { return false; } - Paint new_paint = paint; - // For symmetrically mask blurred solid RRects, absorb the mask blur and use // a faster SDF approximation. - auto contents = std::make_shared(); - contents->SetColor(new_paint.color); - contents->SetSigma(new_paint.mask_blur_descriptor->sigma); - contents->SetRRect(rect, corner_radius); + Paint rrect_paint = paint; + + // Absorb the color filter, if any. + if (rrect_paint.HasColorFilter()) { + rrect_paint.color = + rrect_paint.GetColorFilter()->GetCPUColorFilterProc()(paint.color); + rrect_paint.color_filter = nullptr; + rrect_paint.invert_colors = false; + } + + // In some cases, we need to render the mask blur to a separate layer. + // + // 1. If the blur style is normal, we'll be drawing using one draw call and + // no clips. And so we can just wrap the RRect contents with the + // ImageFilter, which will get applied to the result as per usual. + // + // 2. If the blur style is solid, we combine the non-blurred RRect with the + // blurred RRect via two separate draw calls, and so we need to defer any + // fancy blending, translucency, or image filtering until after these two + // draws have been combined in a separate layer. + // + // 3. If the blur style is outer or inner, we apply the blur style via a + // clip. The ImageFilter needs to be applied to the mask blurred result. + // And so if there's an ImageFilter, we need to defer applying it until + // after the clipped RRect blur has been drawn to a separate texture. + // However, since there's only one draw call that produces color, we + // don't need to worry about the blend mode or translucency (unlike with + // BlurStyle::kSolid). + // + if ((rrect_paint.mask_blur_descriptor->style != + FilterContents::BlurStyle::kNormal && + rrect_paint.image_filter) || + (rrect_paint.mask_blur_descriptor->style == + FilterContents::BlurStyle::kSolid && + (!rrect_paint.color.IsOpaque() || + rrect_paint.blend_mode != BlendMode::kSourceOver))) { + // Defer the alpha, blend mode, and image filter to a separate layer. + SaveLayer({.color = Color::White().WithAlpha(rrect_paint.color.alpha), + .blend_mode = rrect_paint.blend_mode, + .image_filter = rrect_paint.image_filter}); + rrect_paint.color = rrect_paint.color.WithAlpha(1); + rrect_paint.blend_mode = BlendMode::kSourceOver; + rrect_paint.image_filter = nullptr; + } else { + Save(); + } - new_paint.mask_blur_descriptor = std::nullopt; + auto draw_blurred_rrect = [this, &rect, &corner_radii, &rrect_paint]() { + auto contents = std::make_shared(); - Entity entity; - entity.SetTransform(GetCurrentTransform()); - entity.SetClipDepth(GetClipDepth()); - entity.SetBlendMode(new_paint.blend_mode); - entity.SetContents(new_paint.WithFilters(std::move(contents))); + contents->SetColor(rrect_paint.color); + contents->SetSigma(rrect_paint.mask_blur_descriptor->sigma); + contents->SetRRect(rect, corner_radii); - AddEntityToCurrentPass(std::move(entity)); + Entity blurred_rrect_entity; + blurred_rrect_entity.SetTransform(GetCurrentTransform()); + blurred_rrect_entity.SetClipDepth(GetClipDepth()); + blurred_rrect_entity.SetBlendMode(rrect_paint.blend_mode); + + rrect_paint.mask_blur_descriptor = std::nullopt; + blurred_rrect_entity.SetContents( + rrect_paint.WithFilters(std::move(contents))); + AddEntityToCurrentPass(std::move(blurred_rrect_entity)); + }; + + switch (rrect_paint.mask_blur_descriptor->style) { + case FilterContents::BlurStyle::kNormal: { + draw_blurred_rrect(); + break; + } + case FilterContents::BlurStyle::kSolid: { + // First, draw the blurred RRect. + draw_blurred_rrect(); + // Then, draw the non-blurred RRect on top. + Entity entity; + entity.SetTransform(GetCurrentTransform()); + entity.SetClipDepth(GetClipDepth()); + entity.SetBlendMode(rrect_paint.blend_mode); + entity.SetContents(CreateContentsForGeometryWithFilters( + rrect_paint, Geometry::MakeRoundRect(rect, corner_radii))); + AddEntityToCurrentPass(std::move(entity)); + break; + } + case FilterContents::BlurStyle::kOuter: { + ClipRRect(rect, corner_radii, Entity::ClipOperation::kDifference); + draw_blurred_rrect(); + break; + } + case FilterContents::BlurStyle::kInner: { + ClipRRect(rect, corner_radii, Entity::ClipOperation::kIntersect); + draw_blurred_rrect(); + break; + } + } + + Restore(); return true; } diff --git a/impeller/aiks/canvas.h b/impeller/aiks/canvas.h index b4ba0838bec8d..867c5b8535069 100644 --- a/impeller/aiks/canvas.h +++ b/impeller/aiks/canvas.h @@ -207,7 +207,7 @@ class Canvas { void RestoreClip(); bool AttemptDrawBlurredRRect(const Rect& rect, - Size corner_radius, + Size corner_radii, const Paint& paint); Canvas(const Canvas&) = delete; From 79b6c8a9f041195b0c993843215d63bc2bebb76e Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Thu, 7 Mar 2024 14:18:54 -0800 Subject: [PATCH 2/8] Split up test --- impeller/aiks/aiks_unittests.cc | 257 +++++++++++++---------- testing/impeller_golden_tests_output.txt | 30 +++ 2 files changed, 173 insertions(+), 114 deletions(-) diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index b1486bc60bdf8..69cbca465771c 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -1614,10 +1614,19 @@ TEST_P(AiksTest, SolidColorCirclesOvalsRRectsMaskBlurCorrectly) { ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } -TEST_P(AiksTest, - SolidColorCirclesOvalsRRectsMaskBlurCorrectlyBlurStyleVariations) { +struct MaskBlurTestConfig { + FilterContents::BlurStyle style = FilterContents::BlurStyle::kNormal; + Scalar sigma = 1.0f; + Scalar alpha = 1.0f; + std::shared_ptr image_filter; + bool invert_colors = false; + BlendMode blend_mode = BlendMode::kSourceOver; +}; + +static Picture MaskBlurVariantTest(const AiksTest& test_context, + const MaskBlurTestConfig& config) { Canvas canvas; - canvas.Scale(GetContentScale()); + canvas.Scale(test_context.GetContentScale()); canvas.Scale(Vector2{0.8f, 0.8f}); Paint paint; paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{ @@ -1627,129 +1636,149 @@ TEST_P(AiksTest, canvas.DrawPaint({.color = Color::AntiqueWhite()}); - struct MaskBlurTestConfig { - FilterContents::BlurStyle style = FilterContents::BlurStyle::kNormal; - Scalar sigma = 1.0f; - Scalar alpha = 1.0f; - std::shared_ptr image_filter; - bool invert_colors = false; - BlendMode blend_mode = BlendMode::kSourceOver; - }; + paint.mask_blur_descriptor->style = config.style; + paint.mask_blur_descriptor->sigma = Sigma{config.sigma}; + paint.image_filter = config.image_filter; + paint.invert_colors = config.invert_colors; + paint.blend_mode = config.blend_mode; - std::vector paint_variations = { - // 1. Normal style, translucent, zero sigma. - {.style = FilterContents::BlurStyle::kNormal, - .sigma = 0.0f, - .alpha = 0.5f}, - // 2. Normal style, translucent. - {.style = FilterContents::BlurStyle::kNormal, - .sigma = 8.0f, - .alpha = 0.5f}, - // 3. Solid style, translucent. - {.style = FilterContents::BlurStyle::kSolid, - .sigma = 8.0f, - .alpha = 0.5f}, - // 4. Solid style, opaque. - {.style = FilterContents::BlurStyle::kSolid, .sigma = 8.0f}, - // 5. Solid style, translucent, color & image filtered. - {.style = FilterContents::BlurStyle::kSolid, - .sigma = 8.0f, - .alpha = 0.5f, - .image_filter = ImageFilter::MakeBlur(Sigma{3}, Sigma{3}, - FilterContents::BlurStyle::kNormal, - Entity::TileMode::kClamp), - .invert_colors = true}, - // 6. Solid style, translucent, exclusion blended. - {.style = FilterContents::BlurStyle::kSolid, - .sigma = 8.0f, - .alpha = 0.5f, - .blend_mode = BlendMode::kExclusion}, - // 7. Inner style, translucent. - {.style = FilterContents::BlurStyle::kInner, - .sigma = 8.0f, - .alpha = 0.5f}, - // 8. Inner style, translucent, blurred. - {.style = FilterContents::BlurStyle::kInner, - .sigma = 8.0f, - .alpha = 0.5f, - .image_filter = ImageFilter::MakeBlur(Sigma{3}, Sigma{3}, - FilterContents::BlurStyle::kNormal, - Entity::TileMode::kClamp)}, - // 9. Outer style, translucent. - {.style = FilterContents::BlurStyle::kOuter, - .sigma = 8.0f, - .alpha = 0.5f}, - // 10. Outer style, opaque, image filtered. - {.style = FilterContents::BlurStyle::kOuter, - .sigma = 8.0f, - .image_filter = ImageFilter::MakeBlur(Sigma{3}, Sigma{3}, - FilterContents::BlurStyle::kNormal, - Entity::TileMode::kClamp)}, - }; + const Scalar x = 50; + const Scalar radius = 20.0f; + const Scalar y_spacing = 100.0f; - for (size_t i = 0; i < paint_variations.size(); i++) { - const MaskBlurTestConfig& config = paint_variations[i]; - paint.mask_blur_descriptor->style = config.style; - paint.mask_blur_descriptor->sigma = Sigma{config.sigma}; - paint.image_filter = config.image_filter; - paint.invert_colors = config.invert_colors; - paint.blend_mode = config.blend_mode; + Scalar y = 50; + paint.color = Color::Crimson().WithAlpha(config.alpha); + canvas.DrawRect(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, // + radius, 60.0f - radius), + paint); - const Scalar x = 50 + i * 80; - const Scalar radius = 20.0f; - const Scalar y_spacing = 100.0f; + y += y_spacing; + paint.color = Color::Blue().WithAlpha(config.alpha); + canvas.DrawCircle({x + 25, y + 25}, radius, paint); - Scalar y = 50; - paint.color = Color::Crimson().WithAlpha(config.alpha); - canvas.DrawRect(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, // - radius, 60.0f - radius), - paint); + y += y_spacing; + paint.color = Color::Green().WithAlpha(config.alpha); + canvas.DrawOval(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, // + radius, 60.0f - radius), + paint); - y += y_spacing; - paint.color = Color::Blue().WithAlpha(config.alpha); - canvas.DrawCircle({x + 25, y + 25}, radius, paint); + y += y_spacing; + paint.color = Color::Purple().WithAlpha(config.alpha); + canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), // + {radius, radius}, // + paint); - y += y_spacing; - paint.color = Color::Green().WithAlpha(config.alpha); - canvas.DrawOval(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, // - radius, 60.0f - radius), - paint); + y += y_spacing; + paint.color = Color::Orange().WithAlpha(config.alpha); + canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), // + {radius, 5.0f}, paint); - y += y_spacing; - paint.color = Color::Purple().WithAlpha(config.alpha); - canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), // - {radius, radius}, // - paint); + y += y_spacing; + paint.color = Color::Maroon().WithAlpha(config.alpha); + canvas.DrawPath(PathBuilder{} + .MoveTo({x + 0, y + 60}) + .LineTo({x + 30, y + 0}) + .LineTo({x + 60, y + 60}) + .Close() + .TakePath(), + paint); - y += y_spacing; - paint.color = Color::Orange().WithAlpha(config.alpha); - canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), // - {radius, 5.0f}, paint); + y += y_spacing; + paint.color = Color::Maroon().WithAlpha(config.alpha); + canvas.DrawPath(PathBuilder{} + .AddArc(Rect::MakeXYWH(x + 5, y, 50, 50), + Radians{kPi / 2}, Radians{kPi}) + .AddArc(Rect::MakeXYWH(x + 25, y, 50, 50), + Radians{kPi / 2}, Radians{kPi}) + .Close() + .TakePath(), + paint); - y += y_spacing; - paint.color = Color::Maroon().WithAlpha(config.alpha); - canvas.DrawPath(PathBuilder{} - .MoveTo({x + 0, y + 60}) - .LineTo({x + 30, y + 0}) - .LineTo({x + 60, y + 60}) - .Close() - .TakePath(), - paint); + return canvas.EndRecordingAsPicture(); +} - y += y_spacing; - paint.color = Color::Maroon().WithAlpha(config.alpha); - canvas.DrawPath(PathBuilder{} - .AddArc(Rect::MakeXYWH(x + 5, y, 50, 50), - Radians{kPi / 2}, Radians{kPi}) - .AddArc(Rect::MakeXYWH(x + 25, y, 50, 50), - Radians{kPi / 2}, Radians{kPi}) - .Close() - .TakePath(), - paint); +static const std::map kPaintVariations = { + // 1. Normal style, translucent, zero sigma. + {"NormalTranslucentZeroSigma", + {.style = FilterContents::BlurStyle::kNormal, + .sigma = 0.0f, + .alpha = 0.5f}}, + // 2. Normal style, translucent. + {"NormalTranslucent", + {.style = FilterContents::BlurStyle::kNormal, + .sigma = 8.0f, + .alpha = 0.5f}}, + // 3. Solid style, translucent. + {"SolidTranslucent", + {.style = FilterContents::BlurStyle::kSolid, + .sigma = 8.0f, + .alpha = 0.5f}}, + // 4. Solid style, opaque. + {"SolidOpaque", + {.style = FilterContents::BlurStyle::kSolid, .sigma = 8.0f}}, + // 5. Solid style, translucent, color & image filtered. + {"SolidTranslucentWithFilters", + {.style = FilterContents::BlurStyle::kSolid, + .sigma = 8.0f, + .alpha = 0.5f, + .image_filter = ImageFilter::MakeBlur(Sigma{3}, + Sigma{3}, + FilterContents::BlurStyle::kNormal, + Entity::TileMode::kClamp), + .invert_colors = true}}, + // 6. Solid style, translucent, exclusion blended. + {"SolidTranslucentExclusionBlend", + {.style = FilterContents::BlurStyle::kSolid, + .sigma = 8.0f, + .alpha = 0.5f, + .blend_mode = BlendMode::kExclusion}}, + // 7. Inner style, translucent. + {"InnerTranslucent", + {.style = FilterContents::BlurStyle::kInner, + .sigma = 8.0f, + .alpha = 0.5f}}, + // 8. Inner style, translucent, blurred. + {"InnerTranslucentWithBlurImageFilter", + {.style = FilterContents::BlurStyle::kInner, + .sigma = 8.0f, + .alpha = 0.5f, + .image_filter = ImageFilter::MakeBlur(Sigma{3}, + Sigma{3}, + FilterContents::BlurStyle::kNormal, + Entity::TileMode::kClamp)}}, + // 9. Outer style, translucent. + {"OuterTranslucent", + {.style = FilterContents::BlurStyle::kOuter, + .sigma = 8.0f, + .alpha = 0.5f}}, + // 10. Outer style, opaque, image filtered. + {"OuterOpaqueWithBlurImageFilter", + {.style = FilterContents::BlurStyle::kOuter, + .sigma = 8.0f, + .image_filter = ImageFilter::MakeBlur(Sigma{3}, + Sigma{3}, + FilterContents::BlurStyle::kNormal, + Entity::TileMode::kClamp)}}, +}; + +#define MASK_BLUR_VARIANT_TEST(config) \ + TEST_P(AiksTest, MaskBlurVariantTest##config) { \ + ASSERT_TRUE(OpenPlaygroundHere( \ + MaskBlurVariantTest(*this, kPaintVariations.at(#config)))); \ } - ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); -} +MASK_BLUR_VARIANT_TEST(NormalTranslucentZeroSigma) +MASK_BLUR_VARIANT_TEST(NormalTranslucent) +MASK_BLUR_VARIANT_TEST(SolidTranslucent) +MASK_BLUR_VARIANT_TEST(SolidOpaque) +MASK_BLUR_VARIANT_TEST(SolidTranslucentWithFilters) +MASK_BLUR_VARIANT_TEST(SolidTranslucentExclusionBlend) +MASK_BLUR_VARIANT_TEST(InnerTranslucent) +MASK_BLUR_VARIANT_TEST(InnerTranslucentWithBlurImageFilter) +MASK_BLUR_VARIANT_TEST(OuterTranslucent) +MASK_BLUR_VARIANT_TEST(OuterOpaqueWithBlurImageFilter) + +#undef MASK_BLUR_VARIANT_TEST TEST_P(AiksTest, FilledRoundRectPathsRenderCorrectly) { Canvas canvas; diff --git a/testing/impeller_golden_tests_output.txt b/testing/impeller_golden_tests_output.txt index 26f73d04bad0a..10845f31f61bf 100644 --- a/testing/impeller_golden_tests_output.txt +++ b/testing/impeller_golden_tests_output.txt @@ -516,6 +516,36 @@ 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_MaskBlurVariantTestInnerTranslucent_Metal.png +impeller_Play_AiksTest_MaskBlurVariantTestInnerTranslucent_OpenGLES.png +impeller_Play_AiksTest_MaskBlurVariantTestInnerTranslucent_Vulkan.png +impeller_Play_AiksTest_MaskBlurVariantTestInnerTranslucentWithBlurImageFilter_Metal.png +impeller_Play_AiksTest_MaskBlurVariantTestInnerTranslucentWithBlurImageFilter_OpenGLES.png +impeller_Play_AiksTest_MaskBlurVariantTestInnerTranslucentWithBlurImageFilter_Vulkan.png +impeller_Play_AiksTest_MaskBlurVariantTestNormalTranslucent_Metal.png +impeller_Play_AiksTest_MaskBlurVariantTestNormalTranslucent_OpenGLES.png +impeller_Play_AiksTest_MaskBlurVariantTestNormalTranslucent_Vulkan.png +impeller_Play_AiksTest_MaskBlurVariantTestNormalTranslucentZeroSigma_Metal.png +impeller_Play_AiksTest_MaskBlurVariantTestNormalTranslucentZeroSigma_OpenGLES.png +impeller_Play_AiksTest_MaskBlurVariantTestNormalTranslucentZeroSigma_Vulkan.png +impeller_Play_AiksTest_MaskBlurVariantTestOuterTranslucent_Metal.png +impeller_Play_AiksTest_MaskBlurVariantTestOuterTranslucent_OpenGLES.png +impeller_Play_AiksTest_MaskBlurVariantTestOuterTranslucent_Vulkan.png +impeller_Play_AiksTest_MaskBlurVariantTestOuterOpaqueWithBlurImageFilter_Metal.png +impeller_Play_AiksTest_MaskBlurVariantTestOuterOpaqueWithBlurImageFilter_OpenGLES.png +impeller_Play_AiksTest_MaskBlurVariantTestOuterOpaqueWithBlurImageFilter_Vulkan.png +impeller_Play_AiksTest_MaskBlurVariantTestSolidOpaque_Metal.png +impeller_Play_AiksTest_MaskBlurVariantTestSolidOpaque_OpenGLES.png +impeller_Play_AiksTest_MaskBlurVariantTestSolidOpaque_Vulkan.png +impeller_Play_AiksTest_MaskBlurVariantTestSolidTranslucent_Metal.png +impeller_Play_AiksTest_MaskBlurVariantTestSolidTranslucent_OpenGLES.png +impeller_Play_AiksTest_MaskBlurVariantTestSolidTranslucent_Vulkan.png +impeller_Play_AiksTest_MaskBlurVariantTestSolidTranslucentExclusionBlend_Metal.png +impeller_Play_AiksTest_MaskBlurVariantTestSolidTranslucentExclusionBlend_OpenGLES.png +impeller_Play_AiksTest_MaskBlurVariantTestSolidTranslucentExclusionBlend_Vulkan.png +impeller_Play_AiksTest_MaskBlurVariantTestSolidTranslucentWithFilters_Metal.png +impeller_Play_AiksTest_MaskBlurVariantTestSolidTranslucentWithFilters_OpenGLES.png +impeller_Play_AiksTest_MaskBlurVariantTestSolidTranslucentWithFilters_Vulkan.png impeller_Play_AiksTest_MaskBlurWithZeroSigmaIsSkipped_Metal.png impeller_Play_AiksTest_MaskBlurWithZeroSigmaIsSkipped_OpenGLES.png impeller_Play_AiksTest_MaskBlurWithZeroSigmaIsSkipped_Vulkan.png From 6108b8be6331ee34dfa3fa53ac1af5f09c47465e Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Thu, 7 Mar 2024 15:10:53 -0800 Subject: [PATCH 3/8] test --- testing/impeller_golden_tests_output.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/testing/impeller_golden_tests_output.txt b/testing/impeller_golden_tests_output.txt index 10845f31f61bf..bf98bbbf2f4f5 100644 --- a/testing/impeller_golden_tests_output.txt +++ b/testing/impeller_golden_tests_output.txt @@ -525,15 +525,24 @@ impeller_Play_AiksTest_MaskBlurVariantTestInnerTranslucentWithBlurImageFilter_Vu impeller_Play_AiksTest_MaskBlurVariantTestNormalTranslucent_Metal.png impeller_Play_AiksTest_MaskBlurVariantTestNormalTranslucent_OpenGLES.png impeller_Play_AiksTest_MaskBlurVariantTestNormalTranslucent_Vulkan.png +impeller_Play_AiksTest_MaskBlurVariantTestInnerTranslucent_Metal.png +impeller_Play_AiksTest_MaskBlurVariantTestInnerTranslucent_OpenGLES.png +impeller_Play_AiksTest_MaskBlurVariantTestInnerTranslucent_Vulkan.png impeller_Play_AiksTest_MaskBlurVariantTestNormalTranslucentZeroSigma_Metal.png impeller_Play_AiksTest_MaskBlurVariantTestNormalTranslucentZeroSigma_OpenGLES.png impeller_Play_AiksTest_MaskBlurVariantTestNormalTranslucentZeroSigma_Vulkan.png impeller_Play_AiksTest_MaskBlurVariantTestOuterTranslucent_Metal.png impeller_Play_AiksTest_MaskBlurVariantTestOuterTranslucent_OpenGLES.png impeller_Play_AiksTest_MaskBlurVariantTestOuterTranslucent_Vulkan.png +impeller_Play_AiksTest_MaskBlurVariantTestNormalTranslucent_Metal.png +impeller_Play_AiksTest_MaskBlurVariantTestNormalTranslucent_OpenGLES.png +impeller_Play_AiksTest_MaskBlurVariantTestNormalTranslucent_Vulkan.png impeller_Play_AiksTest_MaskBlurVariantTestOuterOpaqueWithBlurImageFilter_Metal.png impeller_Play_AiksTest_MaskBlurVariantTestOuterOpaqueWithBlurImageFilter_OpenGLES.png impeller_Play_AiksTest_MaskBlurVariantTestOuterOpaqueWithBlurImageFilter_Vulkan.png +impeller_Play_AiksTest_MaskBlurVariantTestOuterTranslucent_Metal.png +impeller_Play_AiksTest_MaskBlurVariantTestOuterTranslucent_OpenGLES.png +impeller_Play_AiksTest_MaskBlurVariantTestOuterTranslucent_Vulkan.png impeller_Play_AiksTest_MaskBlurVariantTestSolidOpaque_Metal.png impeller_Play_AiksTest_MaskBlurVariantTestSolidOpaque_OpenGLES.png impeller_Play_AiksTest_MaskBlurVariantTestSolidOpaque_Vulkan.png @@ -546,6 +555,9 @@ impeller_Play_AiksTest_MaskBlurVariantTestSolidTranslucentExclusionBlend_Vulkan. impeller_Play_AiksTest_MaskBlurVariantTestSolidTranslucentWithFilters_Metal.png impeller_Play_AiksTest_MaskBlurVariantTestSolidTranslucentWithFilters_OpenGLES.png impeller_Play_AiksTest_MaskBlurVariantTestSolidTranslucentWithFilters_Vulkan.png +impeller_Play_AiksTest_MaskBlurVariantTestSolidTranslucent_Metal.png +impeller_Play_AiksTest_MaskBlurVariantTestSolidTranslucent_OpenGLES.png +impeller_Play_AiksTest_MaskBlurVariantTestSolidTranslucent_Vulkan.png impeller_Play_AiksTest_MaskBlurWithZeroSigmaIsSkipped_Metal.png impeller_Play_AiksTest_MaskBlurWithZeroSigmaIsSkipped_OpenGLES.png impeller_Play_AiksTest_MaskBlurWithZeroSigmaIsSkipped_Vulkan.png From 086ace4f434ea1d588866ae53d3eff427f9573a3 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Thu, 7 Mar 2024 16:17:32 -0800 Subject: [PATCH 4/8] Fix test list again --- testing/impeller_golden_tests_output.txt | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/testing/impeller_golden_tests_output.txt b/testing/impeller_golden_tests_output.txt index bf98bbbf2f4f5..0a6c28e5bb62d 100644 --- a/testing/impeller_golden_tests_output.txt +++ b/testing/impeller_golden_tests_output.txt @@ -516,24 +516,15 @@ 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_MaskBlurVariantTestInnerTranslucent_Metal.png -impeller_Play_AiksTest_MaskBlurVariantTestInnerTranslucent_OpenGLES.png -impeller_Play_AiksTest_MaskBlurVariantTestInnerTranslucent_Vulkan.png impeller_Play_AiksTest_MaskBlurVariantTestInnerTranslucentWithBlurImageFilter_Metal.png impeller_Play_AiksTest_MaskBlurVariantTestInnerTranslucentWithBlurImageFilter_OpenGLES.png impeller_Play_AiksTest_MaskBlurVariantTestInnerTranslucentWithBlurImageFilter_Vulkan.png -impeller_Play_AiksTest_MaskBlurVariantTestNormalTranslucent_Metal.png -impeller_Play_AiksTest_MaskBlurVariantTestNormalTranslucent_OpenGLES.png -impeller_Play_AiksTest_MaskBlurVariantTestNormalTranslucent_Vulkan.png impeller_Play_AiksTest_MaskBlurVariantTestInnerTranslucent_Metal.png impeller_Play_AiksTest_MaskBlurVariantTestInnerTranslucent_OpenGLES.png impeller_Play_AiksTest_MaskBlurVariantTestInnerTranslucent_Vulkan.png impeller_Play_AiksTest_MaskBlurVariantTestNormalTranslucentZeroSigma_Metal.png impeller_Play_AiksTest_MaskBlurVariantTestNormalTranslucentZeroSigma_OpenGLES.png impeller_Play_AiksTest_MaskBlurVariantTestNormalTranslucentZeroSigma_Vulkan.png -impeller_Play_AiksTest_MaskBlurVariantTestOuterTranslucent_Metal.png -impeller_Play_AiksTest_MaskBlurVariantTestOuterTranslucent_OpenGLES.png -impeller_Play_AiksTest_MaskBlurVariantTestOuterTranslucent_Vulkan.png impeller_Play_AiksTest_MaskBlurVariantTestNormalTranslucent_Metal.png impeller_Play_AiksTest_MaskBlurVariantTestNormalTranslucent_OpenGLES.png impeller_Play_AiksTest_MaskBlurVariantTestNormalTranslucent_Vulkan.png @@ -546,9 +537,6 @@ impeller_Play_AiksTest_MaskBlurVariantTestOuterTranslucent_Vulkan.png impeller_Play_AiksTest_MaskBlurVariantTestSolidOpaque_Metal.png impeller_Play_AiksTest_MaskBlurVariantTestSolidOpaque_OpenGLES.png impeller_Play_AiksTest_MaskBlurVariantTestSolidOpaque_Vulkan.png -impeller_Play_AiksTest_MaskBlurVariantTestSolidTranslucent_Metal.png -impeller_Play_AiksTest_MaskBlurVariantTestSolidTranslucent_OpenGLES.png -impeller_Play_AiksTest_MaskBlurVariantTestSolidTranslucent_Vulkan.png impeller_Play_AiksTest_MaskBlurVariantTestSolidTranslucentExclusionBlend_Metal.png impeller_Play_AiksTest_MaskBlurVariantTestSolidTranslucentExclusionBlend_OpenGLES.png impeller_Play_AiksTest_MaskBlurVariantTestSolidTranslucentExclusionBlend_Vulkan.png From a1d91e2c9f30ce178354a82352e818aecff2e64a Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Thu, 7 Mar 2024 16:17:53 -0800 Subject: [PATCH 5/8] Move tests --- impeller/aiks/aiks_blur_unittests.cc | 166 +++++++++++++++++++++++++++ impeller/aiks/aiks_unittests.cc | 166 --------------------------- 2 files changed, 166 insertions(+), 166 deletions(-) diff --git a/impeller/aiks/aiks_blur_unittests.cc b/impeller/aiks/aiks_blur_unittests.cc index d6ad5ebe41884..59fef60d69cc8 100644 --- a/impeller/aiks/aiks_blur_unittests.cc +++ b/impeller/aiks/aiks_blur_unittests.cc @@ -281,6 +281,172 @@ TEST_P(AiksTest, MaskBlurWithZeroSigmaIsSkipped) { ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } +struct MaskBlurTestConfig { + FilterContents::BlurStyle style = FilterContents::BlurStyle::kNormal; + Scalar sigma = 1.0f; + Scalar alpha = 1.0f; + std::shared_ptr image_filter; + bool invert_colors = false; + BlendMode blend_mode = BlendMode::kSourceOver; +}; + +static Picture MaskBlurVariantTest(const AiksTest& test_context, + const MaskBlurTestConfig& config) { + Canvas canvas; + canvas.Scale(test_context.GetContentScale()); + canvas.Scale(Vector2{0.8f, 0.8f}); + Paint paint; + paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{ + .style = FilterContents::BlurStyle::kNormal, + .sigma = Sigma{1}, + }; + + canvas.DrawPaint({.color = Color::AntiqueWhite()}); + + paint.mask_blur_descriptor->style = config.style; + paint.mask_blur_descriptor->sigma = Sigma{config.sigma}; + paint.image_filter = config.image_filter; + paint.invert_colors = config.invert_colors; + paint.blend_mode = config.blend_mode; + + const Scalar x = 50; + const Scalar radius = 20.0f; + const Scalar y_spacing = 100.0f; + + Scalar y = 50; + paint.color = Color::Crimson().WithAlpha(config.alpha); + canvas.DrawRect(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, // + radius, 60.0f - radius), + paint); + + y += y_spacing; + paint.color = Color::Blue().WithAlpha(config.alpha); + canvas.DrawCircle({x + 25, y + 25}, radius, paint); + + y += y_spacing; + paint.color = Color::Green().WithAlpha(config.alpha); + canvas.DrawOval(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, // + radius, 60.0f - radius), + paint); + + y += y_spacing; + paint.color = Color::Purple().WithAlpha(config.alpha); + canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), // + {radius, radius}, // + paint); + + y += y_spacing; + paint.color = Color::Orange().WithAlpha(config.alpha); + canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), // + {radius, 5.0f}, paint); + + y += y_spacing; + paint.color = Color::Maroon().WithAlpha(config.alpha); + canvas.DrawPath(PathBuilder{} + .MoveTo({x + 0, y + 60}) + .LineTo({x + 30, y + 0}) + .LineTo({x + 60, y + 60}) + .Close() + .TakePath(), + paint); + + y += y_spacing; + paint.color = Color::Maroon().WithAlpha(config.alpha); + canvas.DrawPath(PathBuilder{} + .AddArc(Rect::MakeXYWH(x + 5, y, 50, 50), + Radians{kPi / 2}, Radians{kPi}) + .AddArc(Rect::MakeXYWH(x + 25, y, 50, 50), + Radians{kPi / 2}, Radians{kPi}) + .Close() + .TakePath(), + paint); + + return canvas.EndRecordingAsPicture(); +} + +static const std::map kPaintVariations = { + // 1. Normal style, translucent, zero sigma. + {"NormalTranslucentZeroSigma", + {.style = FilterContents::BlurStyle::kNormal, + .sigma = 0.0f, + .alpha = 0.5f}}, + // 2. Normal style, translucent. + {"NormalTranslucent", + {.style = FilterContents::BlurStyle::kNormal, + .sigma = 8.0f, + .alpha = 0.5f}}, + // 3. Solid style, translucent. + {"SolidTranslucent", + {.style = FilterContents::BlurStyle::kSolid, + .sigma = 8.0f, + .alpha = 0.5f}}, + // 4. Solid style, opaque. + {"SolidOpaque", + {.style = FilterContents::BlurStyle::kSolid, .sigma = 8.0f}}, + // 5. Solid style, translucent, color & image filtered. + {"SolidTranslucentWithFilters", + {.style = FilterContents::BlurStyle::kSolid, + .sigma = 8.0f, + .alpha = 0.5f, + .image_filter = ImageFilter::MakeBlur(Sigma{3}, + Sigma{3}, + FilterContents::BlurStyle::kNormal, + Entity::TileMode::kClamp), + .invert_colors = true}}, + // 6. Solid style, translucent, exclusion blended. + {"SolidTranslucentExclusionBlend", + {.style = FilterContents::BlurStyle::kSolid, + .sigma = 8.0f, + .alpha = 0.5f, + .blend_mode = BlendMode::kExclusion}}, + // 7. Inner style, translucent. + {"InnerTranslucent", + {.style = FilterContents::BlurStyle::kInner, + .sigma = 8.0f, + .alpha = 0.5f}}, + // 8. Inner style, translucent, blurred. + {"InnerTranslucentWithBlurImageFilter", + {.style = FilterContents::BlurStyle::kInner, + .sigma = 8.0f, + .alpha = 0.5f, + .image_filter = ImageFilter::MakeBlur(Sigma{3}, + Sigma{3}, + FilterContents::BlurStyle::kNormal, + Entity::TileMode::kClamp)}}, + // 9. Outer style, translucent. + {"OuterTranslucent", + {.style = FilterContents::BlurStyle::kOuter, + .sigma = 8.0f, + .alpha = 0.5f}}, + // 10. Outer style, opaque, image filtered. + {"OuterOpaqueWithBlurImageFilter", + {.style = FilterContents::BlurStyle::kOuter, + .sigma = 8.0f, + .image_filter = ImageFilter::MakeBlur(Sigma{3}, + Sigma{3}, + FilterContents::BlurStyle::kNormal, + Entity::TileMode::kClamp)}}, +}; + +#define MASK_BLUR_VARIANT_TEST(config) \ + TEST_P(AiksTest, MaskBlurVariantTest##config) { \ + ASSERT_TRUE(OpenPlaygroundHere( \ + MaskBlurVariantTest(*this, kPaintVariations.at(#config)))); \ + } + +MASK_BLUR_VARIANT_TEST(NormalTranslucentZeroSigma) +MASK_BLUR_VARIANT_TEST(NormalTranslucent) +MASK_BLUR_VARIANT_TEST(SolidTranslucent) +MASK_BLUR_VARIANT_TEST(SolidOpaque) +MASK_BLUR_VARIANT_TEST(SolidTranslucentWithFilters) +MASK_BLUR_VARIANT_TEST(SolidTranslucentExclusionBlend) +MASK_BLUR_VARIANT_TEST(InnerTranslucent) +MASK_BLUR_VARIANT_TEST(InnerTranslucentWithBlurImageFilter) +MASK_BLUR_VARIANT_TEST(OuterTranslucent) +MASK_BLUR_VARIANT_TEST(OuterOpaqueWithBlurImageFilter) + +#undef MASK_BLUR_VARIANT_TEST + TEST_P(AiksTest, GaussianBlurAtPeripheryVertical) { Canvas canvas; diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index 69cbca465771c..0d4fcb16aee64 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -1614,172 +1614,6 @@ TEST_P(AiksTest, SolidColorCirclesOvalsRRectsMaskBlurCorrectly) { ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } -struct MaskBlurTestConfig { - FilterContents::BlurStyle style = FilterContents::BlurStyle::kNormal; - Scalar sigma = 1.0f; - Scalar alpha = 1.0f; - std::shared_ptr image_filter; - bool invert_colors = false; - BlendMode blend_mode = BlendMode::kSourceOver; -}; - -static Picture MaskBlurVariantTest(const AiksTest& test_context, - const MaskBlurTestConfig& config) { - Canvas canvas; - canvas.Scale(test_context.GetContentScale()); - canvas.Scale(Vector2{0.8f, 0.8f}); - Paint paint; - paint.mask_blur_descriptor = Paint::MaskBlurDescriptor{ - .style = FilterContents::BlurStyle::kNormal, - .sigma = Sigma{1}, - }; - - canvas.DrawPaint({.color = Color::AntiqueWhite()}); - - paint.mask_blur_descriptor->style = config.style; - paint.mask_blur_descriptor->sigma = Sigma{config.sigma}; - paint.image_filter = config.image_filter; - paint.invert_colors = config.invert_colors; - paint.blend_mode = config.blend_mode; - - const Scalar x = 50; - const Scalar radius = 20.0f; - const Scalar y_spacing = 100.0f; - - Scalar y = 50; - paint.color = Color::Crimson().WithAlpha(config.alpha); - canvas.DrawRect(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, // - radius, 60.0f - radius), - paint); - - y += y_spacing; - paint.color = Color::Blue().WithAlpha(config.alpha); - canvas.DrawCircle({x + 25, y + 25}, radius, paint); - - y += y_spacing; - paint.color = Color::Green().WithAlpha(config.alpha); - canvas.DrawOval(Rect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, // - radius, 60.0f - radius), - paint); - - y += y_spacing; - paint.color = Color::Purple().WithAlpha(config.alpha); - canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), // - {radius, radius}, // - paint); - - y += y_spacing; - paint.color = Color::Orange().WithAlpha(config.alpha); - canvas.DrawRRect(Rect::MakeXYWH(x, y, 60.0f, 60.0f), // - {radius, 5.0f}, paint); - - y += y_spacing; - paint.color = Color::Maroon().WithAlpha(config.alpha); - canvas.DrawPath(PathBuilder{} - .MoveTo({x + 0, y + 60}) - .LineTo({x + 30, y + 0}) - .LineTo({x + 60, y + 60}) - .Close() - .TakePath(), - paint); - - y += y_spacing; - paint.color = Color::Maroon().WithAlpha(config.alpha); - canvas.DrawPath(PathBuilder{} - .AddArc(Rect::MakeXYWH(x + 5, y, 50, 50), - Radians{kPi / 2}, Radians{kPi}) - .AddArc(Rect::MakeXYWH(x + 25, y, 50, 50), - Radians{kPi / 2}, Radians{kPi}) - .Close() - .TakePath(), - paint); - - return canvas.EndRecordingAsPicture(); -} - -static const std::map kPaintVariations = { - // 1. Normal style, translucent, zero sigma. - {"NormalTranslucentZeroSigma", - {.style = FilterContents::BlurStyle::kNormal, - .sigma = 0.0f, - .alpha = 0.5f}}, - // 2. Normal style, translucent. - {"NormalTranslucent", - {.style = FilterContents::BlurStyle::kNormal, - .sigma = 8.0f, - .alpha = 0.5f}}, - // 3. Solid style, translucent. - {"SolidTranslucent", - {.style = FilterContents::BlurStyle::kSolid, - .sigma = 8.0f, - .alpha = 0.5f}}, - // 4. Solid style, opaque. - {"SolidOpaque", - {.style = FilterContents::BlurStyle::kSolid, .sigma = 8.0f}}, - // 5. Solid style, translucent, color & image filtered. - {"SolidTranslucentWithFilters", - {.style = FilterContents::BlurStyle::kSolid, - .sigma = 8.0f, - .alpha = 0.5f, - .image_filter = ImageFilter::MakeBlur(Sigma{3}, - Sigma{3}, - FilterContents::BlurStyle::kNormal, - Entity::TileMode::kClamp), - .invert_colors = true}}, - // 6. Solid style, translucent, exclusion blended. - {"SolidTranslucentExclusionBlend", - {.style = FilterContents::BlurStyle::kSolid, - .sigma = 8.0f, - .alpha = 0.5f, - .blend_mode = BlendMode::kExclusion}}, - // 7. Inner style, translucent. - {"InnerTranslucent", - {.style = FilterContents::BlurStyle::kInner, - .sigma = 8.0f, - .alpha = 0.5f}}, - // 8. Inner style, translucent, blurred. - {"InnerTranslucentWithBlurImageFilter", - {.style = FilterContents::BlurStyle::kInner, - .sigma = 8.0f, - .alpha = 0.5f, - .image_filter = ImageFilter::MakeBlur(Sigma{3}, - Sigma{3}, - FilterContents::BlurStyle::kNormal, - Entity::TileMode::kClamp)}}, - // 9. Outer style, translucent. - {"OuterTranslucent", - {.style = FilterContents::BlurStyle::kOuter, - .sigma = 8.0f, - .alpha = 0.5f}}, - // 10. Outer style, opaque, image filtered. - {"OuterOpaqueWithBlurImageFilter", - {.style = FilterContents::BlurStyle::kOuter, - .sigma = 8.0f, - .image_filter = ImageFilter::MakeBlur(Sigma{3}, - Sigma{3}, - FilterContents::BlurStyle::kNormal, - Entity::TileMode::kClamp)}}, -}; - -#define MASK_BLUR_VARIANT_TEST(config) \ - TEST_P(AiksTest, MaskBlurVariantTest##config) { \ - ASSERT_TRUE(OpenPlaygroundHere( \ - MaskBlurVariantTest(*this, kPaintVariations.at(#config)))); \ - } - -MASK_BLUR_VARIANT_TEST(NormalTranslucentZeroSigma) -MASK_BLUR_VARIANT_TEST(NormalTranslucent) -MASK_BLUR_VARIANT_TEST(SolidTranslucent) -MASK_BLUR_VARIANT_TEST(SolidOpaque) -MASK_BLUR_VARIANT_TEST(SolidTranslucentWithFilters) -MASK_BLUR_VARIANT_TEST(SolidTranslucentExclusionBlend) -MASK_BLUR_VARIANT_TEST(InnerTranslucent) -MASK_BLUR_VARIANT_TEST(InnerTranslucentWithBlurImageFilter) -MASK_BLUR_VARIANT_TEST(OuterTranslucent) -MASK_BLUR_VARIANT_TEST(OuterOpaqueWithBlurImageFilter) - -#undef MASK_BLUR_VARIANT_TEST - TEST_P(AiksTest, FilledRoundRectPathsRenderCorrectly) { Canvas canvas; canvas.Scale(GetContentScale()); From 8e95fe4ccb11271f06f177763cf4658124f3ee46 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Thu, 7 Mar 2024 16:18:37 -0800 Subject: [PATCH 6/8] Move color filter absorption to a new method --- impeller/aiks/canvas.cc | 7 +------ impeller/aiks/paint.cc | 16 ++++++++++++++++ impeller/aiks/paint.h | 9 +++++++++ 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/impeller/aiks/canvas.cc b/impeller/aiks/canvas.cc index 79c27ed09e43d..381eb84557ef0 100644 --- a/impeller/aiks/canvas.cc +++ b/impeller/aiks/canvas.cc @@ -330,12 +330,7 @@ bool Canvas::AttemptDrawBlurredRRect(const Rect& rect, Paint rrect_paint = paint; // Absorb the color filter, if any. - if (rrect_paint.HasColorFilter()) { - rrect_paint.color = - rrect_paint.GetColorFilter()->GetCPUColorFilterProc()(paint.color); - rrect_paint.color_filter = nullptr; - rrect_paint.invert_colors = false; - } + rrect_paint.AbsorbColorFilterIntoColor(); // In some cases, we need to render the mask blur to a separate layer. // diff --git a/impeller/aiks/paint.cc b/impeller/aiks/paint.cc index 94951236e6650..5250ada495dc8 100644 --- a/impeller/aiks/paint.cc +++ b/impeller/aiks/paint.cc @@ -199,4 +199,20 @@ bool Paint::HasColorFilter() const { return !!color_filter || invert_colors; } +void Paint::AbsorbColorFilterIntoColor() { + // This method should only ever be used when the caller knows that the color + // source is a solid color. This is not a valid way to apply the color filter + // for other color sources. + FML_DCHECK(color_source.GetType() == ColorSource::Type::kColor); + + std::shared_ptr final_color_filter = GetColorFilter(); + if (!final_color_filter) { + return; // Nothing to absorb. + } + + color = GetColorFilter()->GetCPUColorFilterProc()(color); + color_filter = nullptr; + invert_colors = false; +} + } // namespace impeller diff --git a/impeller/aiks/paint.h b/impeller/aiks/paint.h index 126f152dba84c..f96d1c62c154e 100644 --- a/impeller/aiks/paint.h +++ b/impeller/aiks/paint.h @@ -104,6 +104,15 @@ struct Paint { std::shared_ptr input, ColorFilterContents::AbsorbOpacity absorb_opacity = ColorFilterContents::AbsorbOpacity::kNo) const; + + /// @brief Absorbs the color filter (if any) into the Paint's color. + /// There are multiple paint attributes that can result in a + /// filter being applied. + /// This is only valid if the color source is set is a solid + /// color. + void AbsorbColorFilterIntoColor(); + + friend class Canvas; }; } // namespace impeller From 9caf72abb5040d4f5b9069390487248409bd01e4 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Thu, 7 Mar 2024 16:24:45 -0800 Subject: [PATCH 7/8] Revert "Move color filter absorption to a new method" This reverts commit 8e95fe4ccb11271f06f177763cf4658124f3ee46. --- impeller/aiks/canvas.cc | 7 ++++++- impeller/aiks/paint.cc | 16 ---------------- impeller/aiks/paint.h | 9 --------- 3 files changed, 6 insertions(+), 26 deletions(-) diff --git a/impeller/aiks/canvas.cc b/impeller/aiks/canvas.cc index 381eb84557ef0..79c27ed09e43d 100644 --- a/impeller/aiks/canvas.cc +++ b/impeller/aiks/canvas.cc @@ -330,7 +330,12 @@ bool Canvas::AttemptDrawBlurredRRect(const Rect& rect, Paint rrect_paint = paint; // Absorb the color filter, if any. - rrect_paint.AbsorbColorFilterIntoColor(); + if (rrect_paint.HasColorFilter()) { + rrect_paint.color = + rrect_paint.GetColorFilter()->GetCPUColorFilterProc()(paint.color); + rrect_paint.color_filter = nullptr; + rrect_paint.invert_colors = false; + } // In some cases, we need to render the mask blur to a separate layer. // diff --git a/impeller/aiks/paint.cc b/impeller/aiks/paint.cc index 5250ada495dc8..94951236e6650 100644 --- a/impeller/aiks/paint.cc +++ b/impeller/aiks/paint.cc @@ -199,20 +199,4 @@ bool Paint::HasColorFilter() const { return !!color_filter || invert_colors; } -void Paint::AbsorbColorFilterIntoColor() { - // This method should only ever be used when the caller knows that the color - // source is a solid color. This is not a valid way to apply the color filter - // for other color sources. - FML_DCHECK(color_source.GetType() == ColorSource::Type::kColor); - - std::shared_ptr final_color_filter = GetColorFilter(); - if (!final_color_filter) { - return; // Nothing to absorb. - } - - color = GetColorFilter()->GetCPUColorFilterProc()(color); - color_filter = nullptr; - invert_colors = false; -} - } // namespace impeller diff --git a/impeller/aiks/paint.h b/impeller/aiks/paint.h index f96d1c62c154e..126f152dba84c 100644 --- a/impeller/aiks/paint.h +++ b/impeller/aiks/paint.h @@ -104,15 +104,6 @@ struct Paint { std::shared_ptr input, ColorFilterContents::AbsorbOpacity absorb_opacity = ColorFilterContents::AbsorbOpacity::kNo) const; - - /// @brief Absorbs the color filter (if any) into the Paint's color. - /// There are multiple paint attributes that can result in a - /// filter being applied. - /// This is only valid if the color source is set is a solid - /// color. - void AbsorbColorFilterIntoColor(); - - friend class Canvas; }; } // namespace impeller From 67b9e611b95a42340f5ffb95767c5b817082c6db Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Thu, 7 Mar 2024 16:40:50 -0800 Subject: [PATCH 8/8] Improve paint construction --- impeller/aiks/canvas.cc | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/impeller/aiks/canvas.cc b/impeller/aiks/canvas.cc index 79c27ed09e43d..5a0a86faebbf2 100644 --- a/impeller/aiks/canvas.cc +++ b/impeller/aiks/canvas.cc @@ -327,15 +327,13 @@ bool Canvas::AttemptDrawBlurredRRect(const Rect& rect, // For symmetrically mask blurred solid RRects, absorb the mask blur and use // a faster SDF approximation. - Paint rrect_paint = paint; + Color rrect_color = + paint.HasColorFilter() + // Absorb the color filter, if any. + ? paint.GetColorFilter()->GetCPUColorFilterProc()(paint.color) + : paint.color; - // Absorb the color filter, if any. - if (rrect_paint.HasColorFilter()) { - rrect_paint.color = - rrect_paint.GetColorFilter()->GetCPUColorFilterProc()(paint.color); - rrect_paint.color_filter = nullptr; - rrect_paint.invert_colors = false; - } + Paint rrect_paint = {.mask_blur_descriptor = paint.mask_blur_descriptor}; // In some cases, we need to render the mask blur to a separate layer. // @@ -356,21 +354,21 @@ bool Canvas::AttemptDrawBlurredRRect(const Rect& rect, // don't need to worry about the blend mode or translucency (unlike with // BlurStyle::kSolid). // - if ((rrect_paint.mask_blur_descriptor->style != + if ((paint.mask_blur_descriptor->style != FilterContents::BlurStyle::kNormal && - rrect_paint.image_filter) || - (rrect_paint.mask_blur_descriptor->style == - FilterContents::BlurStyle::kSolid && - (!rrect_paint.color.IsOpaque() || - rrect_paint.blend_mode != BlendMode::kSourceOver))) { + paint.image_filter) || + (paint.mask_blur_descriptor->style == FilterContents::BlurStyle::kSolid && + (!rrect_color.IsOpaque() || + paint.blend_mode != BlendMode::kSourceOver))) { // Defer the alpha, blend mode, and image filter to a separate layer. - SaveLayer({.color = Color::White().WithAlpha(rrect_paint.color.alpha), - .blend_mode = rrect_paint.blend_mode, - .image_filter = rrect_paint.image_filter}); - rrect_paint.color = rrect_paint.color.WithAlpha(1); - rrect_paint.blend_mode = BlendMode::kSourceOver; - rrect_paint.image_filter = nullptr; + SaveLayer({.color = Color::White().WithAlpha(rrect_color.alpha), + .blend_mode = paint.blend_mode, + .image_filter = paint.image_filter}); + rrect_paint.color = rrect_color.WithAlpha(1); } else { + rrect_paint.color = rrect_color; + rrect_paint.blend_mode = paint.blend_mode; + rrect_paint.image_filter = paint.image_filter; Save(); }