From 74fee3dbf1a9f67ffe10f18732fa8d3b9d83a95e Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Thu, 7 Mar 2024 16:10:34 -0800 Subject: [PATCH] [Impeller] moved tests to aiks_blur_unittests, added warning to aiks_unittests --- impeller/aiks/aiks_blur_unittests.cc | 183 +++++++++++++++++++++++++ impeller/aiks/aiks_unittests.cc | 193 ++------------------------- 2 files changed, 193 insertions(+), 183 deletions(-) diff --git a/impeller/aiks/aiks_blur_unittests.cc b/impeller/aiks/aiks_blur_unittests.cc index d6ad5ebe41884..44d05aa237ebe 100644 --- a/impeller/aiks/aiks_blur_unittests.cc +++ b/impeller/aiks/aiks_blur_unittests.cc @@ -5,6 +5,7 @@ #include "flutter/impeller/aiks/aiks_unittests.h" #include "impeller/aiks/canvas.h" +#include "impeller/entity/contents/filters/gaussian_blur_filter_contents.h" #include "impeller/entity/render_target_cache.h" #include "impeller/geometry/path_builder.h" #include "impeller/playground/widgets.h" @@ -672,5 +673,187 @@ TEST_P(AiksTest, GaussianBlurStyleSolid) { ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } +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 + // inside the blur and outside the blur will be different. + // + // If there is some change to render target caching this could display a false + // positive in the future. Also, if the LOD that is rendered is 1 it could + // present a false positive. + int32_t count = 0; + auto callback = [&](AiksContext& renderer) -> std::optional { + Canvas canvas; + if (count++ == 0) { + canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()}); + } else { + canvas.DrawCircle({100, 100}, 50, {.color = Color::Chartreuse()}); + } + canvas.ClipRRect(Rect::MakeLTRB(75, 50, 375, 275), {20, 20}); + canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt, + ImageFilter::MakeBlur(Sigma(30.0), Sigma(30.0), + FilterContents::BlurStyle::kNormal, + Entity::TileMode::kClamp)); + canvas.Restore(); + return canvas.EndRecordingAsPicture(); + }; + + ASSERT_TRUE(OpenPlaygroundHere(callback)); +} + +TEST_P(AiksTest, GaussianBlurSetsMipCountOnPass) { + Canvas canvas; + canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()}); + canvas.SaveLayer({}, std::nullopt, + ImageFilter::MakeBlur(Sigma(3), Sigma(3), + FilterContents::BlurStyle::kNormal, + Entity::TileMode::kClamp)); + canvas.Restore(); + + Picture picture = canvas.EndRecordingAsPicture(); + EXPECT_EQ(4, picture.pass->GetRequiredMipCount()); +} + +TEST_P(AiksTest, GaussianBlurAllocatesCorrectMipCountRenderTarget) { + size_t blur_required_mip_count = + GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4; + + Canvas canvas; + canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()}); + canvas.SaveLayer({}, std::nullopt, + ImageFilter::MakeBlur(Sigma(3), Sigma(3), + FilterContents::BlurStyle::kNormal, + Entity::TileMode::kClamp)); + canvas.Restore(); + + Picture picture = canvas.EndRecordingAsPicture(); + std::shared_ptr cache = + std::make_shared(GetContext()->GetResourceAllocator()); + AiksContext aiks_context(GetContext(), nullptr, cache); + picture.ToImage(aiks_context, {100, 100}); + + size_t max_mip_count = 0; + for (auto it = cache->GetRenderTargetDataBegin(); + it != cache->GetRenderTargetDataEnd(); ++it) { + max_mip_count = std::max(it->config.mip_count, max_mip_count); + } + EXPECT_EQ(max_mip_count, blur_required_mip_count); +} + +TEST_P(AiksTest, GaussianBlurMipMapNestedLayer) { + fml::testing::LogCapture log_capture; + size_t blur_required_mip_count = + GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4; + + Canvas canvas; + canvas.DrawPaint({.color = Color::Wheat()}); + canvas.SaveLayer({.blend_mode = BlendMode::kMultiply}); + canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()}); + canvas.SaveLayer({}, std::nullopt, + ImageFilter::MakeBlur(Sigma(30), Sigma(30), + FilterContents::BlurStyle::kNormal, + Entity::TileMode::kClamp)); + canvas.DrawCircle({200, 200}, 50, {.color = Color::Chartreuse()}); + + Picture picture = canvas.EndRecordingAsPicture(); + std::shared_ptr cache = + std::make_shared(GetContext()->GetResourceAllocator()); + AiksContext aiks_context(GetContext(), nullptr, cache); + picture.ToImage(aiks_context, {100, 100}); + + size_t max_mip_count = 0; + for (auto it = cache->GetRenderTargetDataBegin(); + it != cache->GetRenderTargetDataEnd(); ++it) { + max_mip_count = std::max(it->config.mip_count, max_mip_count); + } + EXPECT_EQ(max_mip_count, blur_required_mip_count); + // The log is FML_DLOG, so only check in debug builds. +#ifndef NDEBUG + if (GetParam() != PlaygroundBackend::kOpenGLES) { + EXPECT_EQ(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError), + std::string::npos); + } else { + EXPECT_NE(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError), + std::string::npos); + } +#endif +} + +TEST_P(AiksTest, GaussianBlurMipMapImageFilter) { + size_t blur_required_mip_count = + GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4; + fml::testing::LogCapture log_capture; + Canvas canvas; + canvas.SaveLayer( + {.image_filter = ImageFilter::MakeBlur(Sigma(30), Sigma(30), + FilterContents::BlurStyle::kNormal, + Entity::TileMode::kClamp)}); + canvas.DrawCircle({200, 200}, 50, {.color = Color::Chartreuse()}); + + Picture picture = canvas.EndRecordingAsPicture(); + std::shared_ptr cache = + std::make_shared(GetContext()->GetResourceAllocator()); + AiksContext aiks_context(GetContext(), nullptr, cache); + picture.ToImage(aiks_context, {1024, 768}); + + size_t max_mip_count = 0; + for (auto it = cache->GetRenderTargetDataBegin(); + it != cache->GetRenderTargetDataEnd(); ++it) { + max_mip_count = std::max(it->config.mip_count, max_mip_count); + } + EXPECT_EQ(max_mip_count, blur_required_mip_count); + // The log is FML_DLOG, so only check in debug builds. +#ifndef NDEBUG + if (GetParam() != PlaygroundBackend::kOpenGLES) { + EXPECT_EQ(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError), + std::string::npos); + } else { + EXPECT_NE(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError), + std::string::npos); + } +#endif +} + +TEST_P(AiksTest, GaussianBlurMipMapSolidColor) { + size_t blur_required_mip_count = + GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4; + fml::testing::LogCapture log_capture; + Canvas canvas; + canvas.DrawPath(PathBuilder{} + .MoveTo({100, 100}) + .LineTo({200, 100}) + .LineTo({150, 200}) + .LineTo({50, 200}) + .Close() + .TakePath(), + {.color = Color::Chartreuse(), + .image_filter = ImageFilter::MakeBlur( + Sigma(30), Sigma(30), FilterContents::BlurStyle::kNormal, + Entity::TileMode::kClamp)}); + + Picture picture = canvas.EndRecordingAsPicture(); + std::shared_ptr cache = + std::make_shared(GetContext()->GetResourceAllocator()); + AiksContext aiks_context(GetContext(), nullptr, cache); + picture.ToImage(aiks_context, {1024, 768}); + + size_t max_mip_count = 0; + for (auto it = cache->GetRenderTargetDataBegin(); + it != cache->GetRenderTargetDataEnd(); ++it) { + max_mip_count = std::max(it->config.mip_count, max_mip_count); + } + EXPECT_EQ(max_mip_count, blur_required_mip_count); + // The log is FML_DLOG, so only check in debug builds. +#ifndef NDEBUG + if (GetParam() != PlaygroundBackend::kOpenGLES) { + EXPECT_EQ(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError), + std::string::npos); + } else { + EXPECT_NE(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError), + std::string::npos); + } +#endif +} + } // namespace testing } // namespace impeller diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index 0d4fcb16aee64..87e7df88be7d9 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -21,7 +21,6 @@ #include "impeller/aiks/paint_pass_delegate.h" #include "impeller/aiks/testing/context_spy.h" #include "impeller/core/capture.h" -#include "impeller/entity/contents/filters/gaussian_blur_filter_contents.h" #include "impeller/entity/contents/solid_color_contents.h" #include "impeller/entity/render_target_cache.h" #include "impeller/geometry/color.h" @@ -3288,188 +3287,6 @@ TEST_P(AiksTest, SubpassWithClearColorOptimization) { ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } -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 - // inside the blur and outside the blur will be different. - // - // If there is some change to render target caching this could display a false - // positive in the future. Also, if the LOD that is rendered is 1 it could - // present a false positive. - int32_t count = 0; - auto callback = [&](AiksContext& renderer) -> std::optional { - Canvas canvas; - if (count++ == 0) { - canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()}); - } else { - canvas.DrawCircle({100, 100}, 50, {.color = Color::Chartreuse()}); - } - canvas.ClipRRect(Rect::MakeLTRB(75, 50, 375, 275), {20, 20}); - canvas.SaveLayer({.blend_mode = BlendMode::kSource}, std::nullopt, - ImageFilter::MakeBlur(Sigma(30.0), Sigma(30.0), - FilterContents::BlurStyle::kNormal, - Entity::TileMode::kClamp)); - canvas.Restore(); - return canvas.EndRecordingAsPicture(); - }; - - ASSERT_TRUE(OpenPlaygroundHere(callback)); -} - -TEST_P(AiksTest, GaussianBlurSetsMipCountOnPass) { - Canvas canvas; - canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()}); - canvas.SaveLayer({}, std::nullopt, - ImageFilter::MakeBlur(Sigma(3), Sigma(3), - FilterContents::BlurStyle::kNormal, - Entity::TileMode::kClamp)); - canvas.Restore(); - - Picture picture = canvas.EndRecordingAsPicture(); - EXPECT_EQ(4, picture.pass->GetRequiredMipCount()); -} - -TEST_P(AiksTest, GaussianBlurAllocatesCorrectMipCountRenderTarget) { - size_t blur_required_mip_count = - GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4; - - Canvas canvas; - canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()}); - canvas.SaveLayer({}, std::nullopt, - ImageFilter::MakeBlur(Sigma(3), Sigma(3), - FilterContents::BlurStyle::kNormal, - Entity::TileMode::kClamp)); - canvas.Restore(); - - Picture picture = canvas.EndRecordingAsPicture(); - std::shared_ptr cache = - std::make_shared(GetContext()->GetResourceAllocator()); - AiksContext aiks_context(GetContext(), nullptr, cache); - picture.ToImage(aiks_context, {100, 100}); - - size_t max_mip_count = 0; - for (auto it = cache->GetRenderTargetDataBegin(); - it != cache->GetRenderTargetDataEnd(); ++it) { - max_mip_count = std::max(it->config.mip_count, max_mip_count); - } - EXPECT_EQ(max_mip_count, blur_required_mip_count); -} - -TEST_P(AiksTest, GaussianBlurMipMapNestedLayer) { - fml::testing::LogCapture log_capture; - size_t blur_required_mip_count = - GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4; - - Canvas canvas; - canvas.DrawPaint({.color = Color::Wheat()}); - canvas.SaveLayer({.blend_mode = BlendMode::kMultiply}); - canvas.DrawCircle({100, 100}, 50, {.color = Color::CornflowerBlue()}); - canvas.SaveLayer({}, std::nullopt, - ImageFilter::MakeBlur(Sigma(30), Sigma(30), - FilterContents::BlurStyle::kNormal, - Entity::TileMode::kClamp)); - canvas.DrawCircle({200, 200}, 50, {.color = Color::Chartreuse()}); - - Picture picture = canvas.EndRecordingAsPicture(); - std::shared_ptr cache = - std::make_shared(GetContext()->GetResourceAllocator()); - AiksContext aiks_context(GetContext(), nullptr, cache); - picture.ToImage(aiks_context, {100, 100}); - - size_t max_mip_count = 0; - for (auto it = cache->GetRenderTargetDataBegin(); - it != cache->GetRenderTargetDataEnd(); ++it) { - max_mip_count = std::max(it->config.mip_count, max_mip_count); - } - EXPECT_EQ(max_mip_count, blur_required_mip_count); - // The log is FML_DLOG, so only check in debug builds. -#ifndef NDEBUG - if (GetParam() != PlaygroundBackend::kOpenGLES) { - EXPECT_EQ(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError), - std::string::npos); - } else { - EXPECT_NE(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError), - std::string::npos); - } -#endif -} - -TEST_P(AiksTest, GaussianBlurMipMapImageFilter) { - size_t blur_required_mip_count = - GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4; - fml::testing::LogCapture log_capture; - Canvas canvas; - canvas.SaveLayer( - {.image_filter = ImageFilter::MakeBlur(Sigma(30), Sigma(30), - FilterContents::BlurStyle::kNormal, - Entity::TileMode::kClamp)}); - canvas.DrawCircle({200, 200}, 50, {.color = Color::Chartreuse()}); - - Picture picture = canvas.EndRecordingAsPicture(); - std::shared_ptr cache = - std::make_shared(GetContext()->GetResourceAllocator()); - AiksContext aiks_context(GetContext(), nullptr, cache); - picture.ToImage(aiks_context, {1024, 768}); - - size_t max_mip_count = 0; - for (auto it = cache->GetRenderTargetDataBegin(); - it != cache->GetRenderTargetDataEnd(); ++it) { - max_mip_count = std::max(it->config.mip_count, max_mip_count); - } - EXPECT_EQ(max_mip_count, blur_required_mip_count); - // The log is FML_DLOG, so only check in debug builds. -#ifndef NDEBUG - if (GetParam() != PlaygroundBackend::kOpenGLES) { - EXPECT_EQ(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError), - std::string::npos); - } else { - EXPECT_NE(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError), - std::string::npos); - } -#endif -} - -TEST_P(AiksTest, GaussianBlurMipMapSolidColor) { - size_t blur_required_mip_count = - GetParam() == PlaygroundBackend::kOpenGLES ? 1 : 4; - fml::testing::LogCapture log_capture; - Canvas canvas; - canvas.DrawPath(PathBuilder{} - .MoveTo({100, 100}) - .LineTo({200, 100}) - .LineTo({150, 200}) - .LineTo({50, 200}) - .Close() - .TakePath(), - {.color = Color::Chartreuse(), - .image_filter = ImageFilter::MakeBlur( - Sigma(30), Sigma(30), FilterContents::BlurStyle::kNormal, - Entity::TileMode::kClamp)}); - - Picture picture = canvas.EndRecordingAsPicture(); - std::shared_ptr cache = - std::make_shared(GetContext()->GetResourceAllocator()); - AiksContext aiks_context(GetContext(), nullptr, cache); - picture.ToImage(aiks_context, {1024, 768}); - - size_t max_mip_count = 0; - for (auto it = cache->GetRenderTargetDataBegin(); - it != cache->GetRenderTargetDataEnd(); ++it) { - max_mip_count = std::max(it->config.mip_count, max_mip_count); - } - EXPECT_EQ(max_mip_count, blur_required_mip_count); - // The log is FML_DLOG, so only check in debug builds. -#ifndef NDEBUG - if (GetParam() != PlaygroundBackend::kOpenGLES) { - EXPECT_EQ(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError), - std::string::npos); - } else { - EXPECT_NE(log_capture.str().find(GaussianBlurFilterContents::kNoMipsError), - std::string::npos); - } -#endif -} - TEST_P(AiksTest, ImageColorSourceEffectTransform) { // Compare with https://fiddle.skia.org/c/6cdc5aefb291fda3833b806ca347a885 @@ -3566,3 +3383,13 @@ TEST_P(AiksTest, CorrectClipDepthAssignedToEntities) { } // namespace testing } // namespace impeller + +// █████████████████████████████████████████████████████████████████████████████ +// █ NOTICE: Before adding new tests to this file consider adding it to one of +// █ the subdivisions of AiksTest to avoid having one massive file. +// █ +// █ Subdivisions: +// █ - aiks_blur_unittests.cc +// █ - aiks_gradient_unittests.cc +// █ - aiks_path_unittests.cc +// █████████████████████████████████████████████████████████████████████████████