|
4 | 4 |
|
5 | 5 | #include "flutter/impeller/aiks/aiks_unittests.h" |
6 | 6 |
|
| 7 | +#include <algorithm> |
7 | 8 | #include <array> |
8 | 9 | #include <cmath> |
9 | 10 | #include <cstdlib> |
|
26 | 27 | #include "impeller/entity/contents/radial_gradient_contents.h" |
27 | 28 | #include "impeller/entity/contents/solid_color_contents.h" |
28 | 29 | #include "impeller/entity/contents/sweep_gradient_contents.h" |
| 30 | +#include "impeller/entity/render_target_cache.h" |
29 | 31 | #include "impeller/geometry/color.h" |
30 | 32 | #include "impeller/geometry/constants.h" |
31 | 33 | #include "impeller/geometry/geometry_asserts.h" |
@@ -3716,5 +3718,81 @@ TEST_P(AiksTest, SubpassWithClearColorOptimization) { |
3716 | 3718 | // will be filled with NaNs and may produce a magenta texture on macOS or iOS. |
3717 | 3719 | ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); |
3718 | 3720 | } |
| 3721 | + |
| 3722 | +TEST_P(AiksTest, GuassianBlurUpdatesMipmapContents) { |
| 3723 | + // This makes sure if mip maps are recycled across invocations of blurs the |
| 3724 | + // contents get updated each frame correctly. If they aren't updated the color |
| 3725 | + // inside the blur and outside the blur will be different. |
| 3726 | + // |
| 3727 | + // If there is some change to render target caching this could display a false |
| 3728 | + // positive in the future. Also, if the LOD that is rendered is 1 it could |
| 3729 | + // present a false positive. |
| 3730 | + int32_t count = 0; |
| 3731 | + auto callback = [&](AiksContext& renderer) -> std::optional<Picture> { |
| 3732 | + Canvas canvas; |
| 3733 | + if (count++ == 0) { |
| 3734 | + canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()}); |
| 3735 | + } else { |
| 3736 | + canvas.DrawCircle({100, 100}, 50, {.color = Color::Chartreuse()}); |
| 3737 | + } |
| 3738 | + canvas.ClipRRect(Rect::MakeLTRB(75, 50, 375, 275), {20, 20}); |
| 3739 | + canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt, |
| 3740 | + ImageFilter::MakeBlur(Sigma(30.0), Sigma(30.0), |
| 3741 | + FilterContents::BlurStyle::kNormal, |
| 3742 | + Entity::TileMode::kClamp)); |
| 3743 | + canvas.Restore(); |
| 3744 | + return canvas.EndRecordingAsPicture(); |
| 3745 | + }; |
| 3746 | + |
| 3747 | + ASSERT_TRUE(OpenPlaygroundHere(callback)); |
| 3748 | +} |
| 3749 | + |
| 3750 | +TEST_P(AiksTest, GaussianBlurSetsMipCountOnPass) { |
| 3751 | + Canvas canvas; |
| 3752 | + canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()}); |
| 3753 | + canvas.SaveLayer({}, std::nullopt, |
| 3754 | + ImageFilter::MakeBlur(Sigma(3), Sigma(3), |
| 3755 | + FilterContents::BlurStyle::kNormal, |
| 3756 | + Entity::TileMode::kClamp)); |
| 3757 | + canvas.Restore(); |
| 3758 | + |
| 3759 | + Picture picture = canvas.EndRecordingAsPicture(); |
| 3760 | + |
| 3761 | + int32_t max_mip_count = 0; |
| 3762 | + picture.pass->IterateAllElements([&](EntityPass::Element& element) -> bool { |
| 3763 | + if (auto subpass = std::get_if<std::unique_ptr<EntityPass>>(&element)) { |
| 3764 | + max_mip_count = |
| 3765 | + std::max(max_mip_count, subpass->get()->GetRequiredMipCount()); |
| 3766 | + } |
| 3767 | + return true; |
| 3768 | + }); |
| 3769 | + |
| 3770 | + EXPECT_EQ(1, max_mip_count); |
| 3771 | +} |
| 3772 | + |
| 3773 | +TEST_P(AiksTest, GaussianBlurAllocatesCorrectMipCountRenderTarget) { |
| 3774 | + Canvas canvas; |
| 3775 | + canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()}); |
| 3776 | + canvas.SaveLayer({}, std::nullopt, |
| 3777 | + ImageFilter::MakeBlur(Sigma(3), Sigma(3), |
| 3778 | + FilterContents::BlurStyle::kNormal, |
| 3779 | + Entity::TileMode::kClamp)); |
| 3780 | + canvas.Restore(); |
| 3781 | + |
| 3782 | + Picture picture = canvas.EndRecordingAsPicture(); |
| 3783 | + std::shared_ptr<RenderTargetCache> cache = |
| 3784 | + std::make_shared<RenderTargetCache>(GetContext()->GetResourceAllocator()); |
| 3785 | + AiksContext aiks_context(GetContext(), nullptr, cache); |
| 3786 | + picture.ToImage(aiks_context, {100, 100}); |
| 3787 | + |
| 3788 | + size_t max_mip_count = 0; |
| 3789 | + for (auto it = cache->GetTextureDataBegin(); it != cache->GetTextureDataEnd(); |
| 3790 | + ++it) { |
| 3791 | + max_mip_count = |
| 3792 | + std::max(it->texture->GetTextureDescriptor().mip_count, max_mip_count); |
| 3793 | + } |
| 3794 | + EXPECT_EQ(max_mip_count, 1lu); |
| 3795 | +} |
| 3796 | + |
3719 | 3797 | } // namespace testing |
3720 | 3798 | } // namespace impeller |
0 commit comments