diff --git a/ci/licenses_golden/excluded_files b/ci/licenses_golden/excluded_files index bdc1265d8d400..48024c92d645f 100644 --- a/ci/licenses_golden/excluded_files +++ b/ci/licenses_golden/excluded_files @@ -128,7 +128,6 @@ ../../../flutter/impeller/.gitignore ../../../flutter/impeller/README.md ../../../flutter/impeller/aiks/aiks_blend_unittests.cc -../../../flutter/impeller/aiks/aiks_blur_unittests.cc ../../../flutter/impeller/aiks/aiks_gradient_unittests.cc ../../../flutter/impeller/aiks/aiks_unittests.cc ../../../flutter/impeller/aiks/aiks_unittests.h diff --git a/display_list/dl_color.h b/display_list/dl_color.h index bd1c657a89da4..cf7cb940f8013 100644 --- a/display_list/dl_color.h +++ b/display_list/dl_color.h @@ -90,6 +90,8 @@ struct DlColor { static constexpr DlColor kGreenYellow() {return DlColor(0xFFADFF2F);}; static constexpr DlColor kDarkMagenta() {return DlColor(0xFF8B008B);}; static constexpr DlColor kOrangeRed() {return DlColor(0xFFFF4500);}; + static constexpr DlColor kDarkGreen() {return DlColor(0xFF006400);}; + static constexpr DlColor kChartreuse() {return DlColor(0xFF7FFF00);}; // clang-format on constexpr bool isOpaque() const { return alpha_ >= 1.f; } diff --git a/impeller/aiks/BUILD.gn b/impeller/aiks/BUILD.gn index 34bf4a1c213be..4cef0a771b730 100644 --- a/impeller/aiks/BUILD.gn +++ b/impeller/aiks/BUILD.gn @@ -74,7 +74,6 @@ template("aiks_unittests_component") { target_name = invoker.target_name predefined_sources = [ "aiks_blend_unittests.cc", - "aiks_blur_unittests.cc", "aiks_gradient_unittests.cc", "aiks_unittests.cc", "aiks_unittests.h", diff --git a/impeller/aiks/aiks_blur_unittests.cc b/impeller/aiks/aiks_blur_unittests.cc deleted file mode 100644 index 640d8281ec5dd..0000000000000 --- a/impeller/aiks/aiks_blur_unittests.cc +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "flutter/impeller/aiks/aiks_unittests.h" - -#include "impeller/aiks/canvas.h" -#include "impeller/entity/render_target_cache.h" -#include "impeller/geometry/path_builder.h" -#include "impeller/playground/widgets.h" -#include "impeller/renderer/testing/mocks.h" -#include "third_party/imgui/imgui.h" - -//////////////////////////////////////////////////////////////////////////////// -// This is for tests of Canvas that are interested the results of rendering -// blurs. -//////////////////////////////////////////////////////////////////////////////// - -namespace impeller { -namespace testing { - -TEST_P(AiksTest, BlurredRectangleWithShader) { - Canvas canvas; - canvas.Scale(GetContentScale()); - - auto paint_lines = [&canvas](Scalar dx, Scalar dy, Paint paint) { - auto draw_line = [&canvas, &paint](Point a, Point b) { - canvas.DrawPath(PathBuilder{}.AddLine(a, b).TakePath(), paint); - }; - paint.stroke_width = 5; - paint.style = Paint::Style::kStroke; - draw_line(Point(dx + 100, dy + 100), Point(dx + 200, dy + 200)); - draw_line(Point(dx + 100, dy + 200), Point(dx + 200, dy + 100)); - draw_line(Point(dx + 150, dy + 100), Point(dx + 200, dy + 150)); - draw_line(Point(dx + 100, dy + 150), Point(dx + 150, dy + 200)); - }; - - AiksContext renderer(GetContext(), nullptr); - Canvas recorder_canvas; - for (int x = 0; x < 5; ++x) { - for (int y = 0; y < 5; ++y) { - Rect rect = Rect::MakeXYWH(x * 20, y * 20, 20, 20); - Paint paint{.color = - ((x + y) & 1) == 0 ? Color::Yellow() : Color::Blue()}; - recorder_canvas.DrawRect(rect, paint); - } - } - Picture picture = recorder_canvas.EndRecordingAsPicture(); - std::shared_ptr texture = - picture.ToImage(renderer, ISize{100, 100})->GetTexture(); - - ColorSource image_source = ColorSource::MakeImage( - texture, Entity::TileMode::kRepeat, Entity::TileMode::kRepeat, {}, {}); - std::shared_ptr blur_filter = ImageFilter::MakeBlur( - Sigma(5), Sigma(5), FilterContents::BlurStyle::kNormal, - Entity::TileMode::kDecal); - canvas.DrawRect(Rect::MakeLTRB(0, 0, 300, 600), - Paint{.color = Color::DarkGreen()}); - canvas.DrawRect(Rect::MakeLTRB(100, 100, 200, 200), - Paint{.color_source = image_source}); - canvas.DrawRect(Rect::MakeLTRB(300, 0, 600, 600), - Paint{.color = Color::Red()}); - canvas.DrawRect( - Rect::MakeLTRB(400, 100, 500, 200), - Paint{.color_source = image_source, .image_filter = blur_filter}); - paint_lines(0, 300, Paint{.color_source = image_source}); - paint_lines(300, 300, - Paint{.color_source = image_source, .image_filter = blur_filter}); - ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); -} - -#define FLT_FORWARD(mock, real, method) \ - EXPECT_CALL(*mock, method()) \ - .WillRepeatedly(::testing::Return(real->method())); - -TEST_P(AiksTest, GaussianBlurWithoutDecalSupport) { - if (GetParam() != PlaygroundBackend::kMetal) { - GTEST_SKIP() - << "This backend doesn't yet support setting device capabilities."; - } - if (!WillRenderSomething()) { - // Sometimes these tests are run without playgrounds enabled which is - // pointless for this test since we are asserting that - // `SupportsDecalSamplerAddressMode` is called. - GTEST_SKIP() << "This test requires playgrounds."; - } - - std::shared_ptr old_capabilities = - GetContext()->GetCapabilities(); - auto mock_capabilities = std::make_shared(); - EXPECT_CALL(*mock_capabilities, SupportsDecalSamplerAddressMode()) - .Times(::testing::AtLeast(1)) - .WillRepeatedly(::testing::Return(false)); - FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultColorFormat); - FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultStencilFormat); - FLT_FORWARD(mock_capabilities, old_capabilities, - GetDefaultDepthStencilFormat); - FLT_FORWARD(mock_capabilities, old_capabilities, SupportsOffscreenMSAA); - FLT_FORWARD(mock_capabilities, old_capabilities, - SupportsImplicitResolvingMSAA); - FLT_FORWARD(mock_capabilities, old_capabilities, SupportsReadFromResolve); - FLT_FORWARD(mock_capabilities, old_capabilities, SupportsFramebufferFetch); - FLT_FORWARD(mock_capabilities, old_capabilities, SupportsSSBO); - FLT_FORWARD(mock_capabilities, old_capabilities, SupportsCompute); - FLT_FORWARD(mock_capabilities, old_capabilities, - SupportsTextureToTextureBlits); - FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultGlyphAtlasFormat); - ASSERT_TRUE(SetCapabilities(mock_capabilities).ok()); - - auto texture = std::make_shared(CreateTextureForFixture("boston.jpg")); - Canvas canvas; - canvas.Scale(GetContentScale() * 0.5); - canvas.DrawPaint({.color = Color::Black()}); - canvas.DrawImage( - texture, Point(200, 200), - { - .image_filter = ImageFilter::MakeBlur( - Sigma(20.0), Sigma(20.0), FilterContents::BlurStyle::kNormal, - Entity::TileMode::kDecal), - }); - ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); -} - -// This addresses a bug where tiny blurs could result in mip maps that beyond -// the limits for the textures used for blurring. -// See also: b/323402168 -TEST_P(AiksTest, GaussianBlurSolidColorTinyMipMap) { - for (int32_t i = 1; i < 5; ++i) { - Canvas canvas; - Scalar fi = i; - canvas.DrawPath( - PathBuilder{} - .MoveTo({100, 100}) - .LineTo({100.f + fi, 100.f + fi}) - .TakePath(), - {.color = Color::Chartreuse(), - .image_filter = ImageFilter::MakeBlur( - Sigma(0.1), Sigma(0.1), 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); - std::shared_ptr image = picture.ToImage(aiks_context, {1024, 768}); - EXPECT_TRUE(image) << " length " << i; - } -} - -// This addresses a bug where tiny blurs could result in mip maps that beyond -// the limits for the textures used for blurring. -// See also: b/323402168 -TEST_P(AiksTest, GaussianBlurBackdropTinyMipMap) { - for (int32_t i = 0; i < 5; ++i) { - Canvas canvas; - ISize clip_size = ISize(i, i); - canvas.ClipRect( - Rect::MakeXYWH(400, 400, clip_size.width, clip_size.height)); - canvas.DrawCircle( - {400, 400}, 200, - { - .color = Color::Green(), - .image_filter = ImageFilter::MakeBlur( - Sigma(0.1), Sigma(0.1), FilterContents::BlurStyle::kNormal, - Entity::TileMode::kDecal), - }); - canvas.Restore(); - - Picture picture = canvas.EndRecordingAsPicture(); - std::shared_ptr cache = - std::make_shared( - GetContext()->GetResourceAllocator()); - AiksContext aiks_context(GetContext(), nullptr, cache); - std::shared_ptr image = picture.ToImage(aiks_context, {1024, 768}); - EXPECT_TRUE(image) << " clip rect " << i; - } -} - -} // namespace testing -} // namespace impeller diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index cc36718db17bd..eb1941e99fbe5 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -39,115 +39,6 @@ namespace testing { INSTANTIATE_PLAYGROUND_SUITE(AiksTest); -TEST_P(AiksTest, CanvasCTMCanBeUpdated) { - Canvas canvas; - Matrix identity; - ASSERT_MATRIX_NEAR(canvas.GetCurrentTransform(), identity); - canvas.Translate(Size{100, 100}); - ASSERT_MATRIX_NEAR(canvas.GetCurrentTransform(), - Matrix::MakeTranslation({100.0, 100.0, 0.0})); -} - -TEST_P(AiksTest, CanvasCanPushPopCTM) { - Canvas canvas; - ASSERT_EQ(canvas.GetSaveCount(), 1u); - ASSERT_EQ(canvas.Restore(), false); - - canvas.Translate(Size{100, 100}); - canvas.Save(); - ASSERT_EQ(canvas.GetSaveCount(), 2u); - ASSERT_MATRIX_NEAR(canvas.GetCurrentTransform(), - Matrix::MakeTranslation({100.0, 100.0, 0.0})); - ASSERT_TRUE(canvas.Restore()); - ASSERT_EQ(canvas.GetSaveCount(), 1u); - ASSERT_MATRIX_NEAR(canvas.GetCurrentTransform(), - Matrix::MakeTranslation({100.0, 100.0, 0.0})); -} - -TEST_P(AiksTest, CanPictureConvertToImage) { - Canvas recorder_canvas; - Paint paint; - paint.color = Color{0.9568, 0.2627, 0.2118, 1.0}; - recorder_canvas.DrawRect(Rect::MakeXYWH(100.0, 100.0, 600, 600), paint); - paint.color = Color{0.1294, 0.5882, 0.9529, 1.0}; - recorder_canvas.DrawRect(Rect::MakeXYWH(200.0, 200.0, 600, 600), paint); - - Canvas canvas; - AiksContext renderer(GetContext(), nullptr); - paint.color = Color::BlackTransparent(); - canvas.DrawPaint(paint); - Picture picture = recorder_canvas.EndRecordingAsPicture(); - auto image = picture.ToImage(renderer, ISize{1000, 1000}); - if (image) { - canvas.DrawImage(image, Point(), Paint()); - paint.color = Color{0.1, 0.1, 0.1, 0.2}; - canvas.DrawRect(Rect::MakeSize(ISize{1000, 1000}), paint); - } - - ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); -} - -// Regression test for https://github.com/flutter/flutter/issues/142358 . -// Without a change to force render pass construction the image is left in an -// undefined layout and triggers a validation error. -TEST_P(AiksTest, CanEmptyPictureConvertToImage) { - Canvas recorder_canvas; - - Canvas canvas; - AiksContext renderer(GetContext(), nullptr); - Paint paint; - paint.color = Color::BlackTransparent(); - canvas.DrawPaint(paint); - Picture picture = recorder_canvas.EndRecordingAsPicture(); - auto image = picture.ToImage(renderer, ISize{1000, 1000}); - if (image) { - canvas.DrawImage(image, Point(), Paint()); - paint.color = Color{0.1, 0.1, 0.1, 0.2}; - canvas.DrawRect(Rect::MakeSize(ISize{1000, 1000}), paint); - } - - ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); -} - -TEST_P(AiksTest, TransformMultipliesCorrectly) { - Canvas canvas; - ASSERT_MATRIX_NEAR(canvas.GetCurrentTransform(), Matrix()); - - // clang-format off - canvas.Translate(Vector3(100, 200)); - ASSERT_MATRIX_NEAR( - canvas.GetCurrentTransform(), - Matrix( 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 100, 200, 0, 1)); - - canvas.Rotate(Radians(kPiOver2)); - ASSERT_MATRIX_NEAR( - canvas.GetCurrentTransform(), - Matrix( 0, 1, 0, 0, - -1, 0, 0, 0, - 0, 0, 1, 0, - 100, 200, 0, 1)); - - canvas.Scale(Vector3(2, 3)); - ASSERT_MATRIX_NEAR( - canvas.GetCurrentTransform(), - Matrix( 0, 2, 0, 0, - -3, 0, 0, 0, - 0, 0, 0, 0, - 100, 200, 0, 1)); - - canvas.Translate(Vector3(100, 200)); - ASSERT_MATRIX_NEAR( - canvas.GetCurrentTransform(), - Matrix( 0, 2, 0, 0, - -3, 0, 0, 0, - 0, 0, 0, 0, - -500, 400, 0, 1)); - // clang-format on -} - #if IMPELLER_ENABLE_3D TEST_P(AiksTest, SceneColorSource) { // Load up the scene. @@ -495,6 +386,5 @@ TEST_P(AiksTest, CorrectClipDepthAssignedToEntities) { // █ // █ Subdivisions: // █ - aiks_blend_unittests.cc -// █ - aiks_blur_unittests.cc // █ - aiks_gradient_unittests.cc // █████████████████████████████████████████████████████████████████████████████ diff --git a/impeller/aiks/canvas_unittests.cc b/impeller/aiks/canvas_unittests.cc index e05a92b90302b..33623e356326d 100644 --- a/impeller/aiks/canvas_unittests.cc +++ b/impeller/aiks/canvas_unittests.cc @@ -6,6 +6,7 @@ #include "impeller/aiks/aiks_context.h" #include "impeller/aiks/aiks_unittests.h" #include "impeller/aiks/experimental_canvas.h" +#include "impeller/geometry/geometry_asserts.h" #include "impeller/geometry/path_builder.h" // TODO(zanderso): https://github.com/flutter/flutter/issues/127701 @@ -27,6 +28,76 @@ std::unique_ptr CreateTestCanvas( return std::make_unique(context, render_target, false); } +TEST_P(AiksTest, TransformMultipliesCorrectly) { + ContentContext context(GetContext(), nullptr); + auto canvas = CreateTestCanvas(context); + + ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(), Matrix()); + + // clang-format off + canvas->Translate(Vector3(100, 200)); + ASSERT_MATRIX_NEAR( + canvas->GetCurrentTransform(), + Matrix( 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 100, 200, 0, 1)); + + canvas->Rotate(Radians(kPiOver2)); + ASSERT_MATRIX_NEAR( + canvas->GetCurrentTransform(), + Matrix( 0, 1, 0, 0, + -1, 0, 0, 0, + 0, 0, 1, 0, + 100, 200, 0, 1)); + + canvas->Scale(Vector3(2, 3)); + ASSERT_MATRIX_NEAR( + canvas->GetCurrentTransform(), + Matrix( 0, 2, 0, 0, + -3, 0, 0, 0, + 0, 0, 0, 0, + 100, 200, 0, 1)); + + canvas->Translate(Vector3(100, 200)); + ASSERT_MATRIX_NEAR( + canvas->GetCurrentTransform(), + Matrix( 0, 2, 0, 0, + -3, 0, 0, 0, + 0, 0, 0, 0, + -500, 400, 0, 1)); + // clang-format on +} + +TEST_P(AiksTest, CanvasCanPushPopCTM) { + ContentContext context(GetContext(), nullptr); + auto canvas = CreateTestCanvas(context); + + ASSERT_EQ(canvas->GetSaveCount(), 1u); + ASSERT_EQ(canvas->Restore(), false); + + canvas->Translate(Size{100, 100}); + canvas->Save(10); + ASSERT_EQ(canvas->GetSaveCount(), 2u); + ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(), + Matrix::MakeTranslation({100.0, 100.0, 0.0})); + ASSERT_TRUE(canvas->Restore()); + ASSERT_EQ(canvas->GetSaveCount(), 1u); + ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(), + Matrix::MakeTranslation({100.0, 100.0, 0.0})); +} + +TEST_P(AiksTest, CanvasCTMCanBeUpdated) { + ContentContext context(GetContext(), nullptr); + auto canvas = CreateTestCanvas(context); + + Matrix identity; + ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(), identity); + canvas->Translate(Size{100, 100}); + ASSERT_MATRIX_NEAR(canvas->GetCurrentTransform(), + Matrix::MakeTranslation({100.0, 100.0, 0.0})); +} + TEST_P(AiksTest, EmptyCullRect) { ContentContext context(GetContext(), nullptr); auto canvas = CreateTestCanvas(context); diff --git a/impeller/display_list/aiks_dl_blur_unittests.cc b/impeller/display_list/aiks_dl_blur_unittests.cc index 0319bba01ddba..a8bffae708a9f 100644 --- a/impeller/display_list/aiks_dl_blur_unittests.cc +++ b/impeller/display_list/aiks_dl_blur_unittests.cc @@ -15,8 +15,11 @@ #include "display_list/effects/dl_mask_filter.h" #include "flutter/impeller/aiks/aiks_unittests.h" +#include "gmock/gmock.h" +#include "impeller/display_list/dl_dispatcher.h" #include "impeller/display_list/dl_image_impeller.h" #include "impeller/playground/widgets.h" +#include "impeller/renderer/testing/mocks.h" #include "include/core/SkRRect.h" #include "include/core/SkRect.h" #include "third_party/imgui/imgui.h" @@ -973,5 +976,173 @@ TEST_P(AiksTest, GaussianBlurRotatedNonUniform) { ASSERT_TRUE(OpenPlaygroundHere(callback)); } +TEST_P(AiksTest, BlurredRectangleWithShader) { + DisplayListBuilder builder; + builder.Scale(GetContentScale().x, GetContentScale().y); + + auto paint_lines = [&builder](Scalar dx, Scalar dy, DlPaint paint) { + auto draw_line = [&builder, &paint](SkPoint a, SkPoint b) { + SkPath line = SkPath::Line(a, b); + builder.DrawPath(line, paint); + }; + paint.setStrokeWidth(5); + paint.setDrawStyle(DlDrawStyle::kStroke); + draw_line(SkPoint::Make(dx + 100, dy + 100), + SkPoint::Make(dx + 200, dy + 200)); + draw_line(SkPoint::Make(dx + 100, dy + 200), + SkPoint::Make(dx + 200, dy + 100)); + draw_line(SkPoint::Make(dx + 150, dy + 100), + SkPoint::Make(dx + 200, dy + 150)); + draw_line(SkPoint::Make(dx + 100, dy + 150), + SkPoint::Make(dx + 150, dy + 200)); + }; + + AiksContext renderer(GetContext(), nullptr); + DisplayListBuilder recorder_builder; + for (int x = 0; x < 5; ++x) { + for (int y = 0; y < 5; ++y) { + SkRect rect = SkRect::MakeXYWH(x * 20, y * 20, 20, 20); + DlPaint paint; + paint.setColor(((x + y) & 1) == 0 ? DlColor::kYellow() + : DlColor::kBlue()); + + recorder_builder.DrawRect(rect, paint); + } + } + auto texture = + DisplayListToTexture(recorder_builder.Build(), {100, 100}, renderer); + + auto image_source = std::make_shared( + DlImageImpeller::Make(texture), DlTileMode::kRepeat, DlTileMode::kRepeat); + auto blur_filter = DlBlurImageFilter::Make(5, 5, DlTileMode::kDecal); + + DlPaint paint; + paint.setColor(DlColor::kDarkGreen()); + builder.DrawRect(SkRect::MakeLTRB(0, 0, 300, 600), paint); + + paint.setColorSource(image_source); + builder.DrawRect(SkRect::MakeLTRB(100, 100, 200, 200), paint); + + paint.setColorSource(nullptr); + paint.setColor(DlColor::kRed()); + builder.DrawRect(SkRect::MakeLTRB(300, 0, 600, 600), paint); + + paint.setColorSource(image_source); + paint.setImageFilter(blur_filter); + builder.DrawRect(SkRect::MakeLTRB(400, 100, 500, 200), paint); + + paint.setImageFilter(nullptr); + paint_lines(0, 300, paint); + + paint.setImageFilter(blur_filter); + paint_lines(300, 300, paint); + + ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); +} + +#define FLT_FORWARD(mock, real, method) \ + EXPECT_CALL(*mock, method()) \ + .WillRepeatedly(::testing::Return(real->method())); + +TEST_P(AiksTest, GaussianBlurWithoutDecalSupport) { + if (GetParam() != PlaygroundBackend::kMetal) { + GTEST_SKIP() + << "This backend doesn't yet support setting device capabilities."; + } + if (!WillRenderSomething()) { + // Sometimes these tests are run without playgrounds enabled which is + // pointless for this test since we are asserting that + // `SupportsDecalSamplerAddressMode` is called. + GTEST_SKIP() << "This test requires playgrounds."; + } + + std::shared_ptr old_capabilities = + GetContext()->GetCapabilities(); + auto mock_capabilities = std::make_shared(); + EXPECT_CALL(*mock_capabilities, SupportsDecalSamplerAddressMode()) + .Times(::testing::AtLeast(1)) + .WillRepeatedly(::testing::Return(false)); + FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultColorFormat); + FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultStencilFormat); + FLT_FORWARD(mock_capabilities, old_capabilities, + GetDefaultDepthStencilFormat); + FLT_FORWARD(mock_capabilities, old_capabilities, SupportsOffscreenMSAA); + FLT_FORWARD(mock_capabilities, old_capabilities, + SupportsImplicitResolvingMSAA); + FLT_FORWARD(mock_capabilities, old_capabilities, SupportsReadFromResolve); + FLT_FORWARD(mock_capabilities, old_capabilities, SupportsFramebufferFetch); + FLT_FORWARD(mock_capabilities, old_capabilities, SupportsSSBO); + FLT_FORWARD(mock_capabilities, old_capabilities, SupportsCompute); + FLT_FORWARD(mock_capabilities, old_capabilities, + SupportsTextureToTextureBlits); + FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultGlyphAtlasFormat); + ASSERT_TRUE(SetCapabilities(mock_capabilities).ok()); + + auto texture = DlImageImpeller::Make(CreateTextureForFixture("boston.jpg")); + + DisplayListBuilder builder; + builder.Scale(GetContentScale().x * 0.5, GetContentScale().y * 0.5); + + DlPaint paint; + paint.setColor(DlColor::kBlack()); + builder.DrawPaint(paint); + + auto blur_filter = DlBlurImageFilter::Make(20, 20, DlTileMode::kDecal); + paint.setImageFilter(blur_filter); + builder.DrawImage(texture, SkPoint::Make(200, 200), {}, &paint); + ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); +} + +// This addresses a bug where tiny blurs could result in mip maps that beyond +// the limits for the textures used for blurring. +// See also: b/323402168 +TEST_P(AiksTest, GaussianBlurSolidColorTinyMipMap) { + AiksContext renderer(GetContext(), nullptr); + + for (int32_t i = 1; i < 5; ++i) { + DisplayListBuilder builder; + Scalar fi = i; + SkPath path; + path.moveTo(100, 100); + path.lineTo(100 + fi, 100 + fi); + + DlPaint paint; + paint.setColor(DlColor::kChartreuse()); + auto blur_filter = DlBlurImageFilter::Make(0.1, 0.1, DlTileMode::kClamp); + paint.setImageFilter(blur_filter); + + builder.DrawPath(path, paint); + + auto image = DisplayListToTexture(builder.Build(), {1024, 768}, renderer); + EXPECT_TRUE(image) << " length " << i; + } +} + +// This addresses a bug where tiny blurs could result in mip maps that beyond +// the limits for the textures used for blurring. +// See also: b/323402168 +TEST_P(AiksTest, GaussianBlurBackdropTinyMipMap) { + AiksContext renderer(GetContext(), nullptr); + for (int32_t i = 1; i < 5; ++i) { + DisplayListBuilder builder; + + ISize clip_size = ISize(i, i); + builder.Save(); + builder.ClipRect( + SkRect::MakeXYWH(400, 400, clip_size.width, clip_size.height)); + + DlPaint paint; + paint.setColor(DlColor::kGreen()); + auto blur_filter = DlBlurImageFilter::Make(0.1, 0.1, DlTileMode::kDecal); + paint.setImageFilter(blur_filter); + + builder.DrawCircle({400, 400}, 200, paint); + builder.Restore(); + + auto image = DisplayListToTexture(builder.Build(), {1024, 768}, renderer); + EXPECT_TRUE(image) << " length " << i; + } +} + } // namespace testing } // namespace impeller diff --git a/impeller/display_list/aiks_dl_unittests.cc b/impeller/display_list/aiks_dl_unittests.cc index 6f488e959b20d..30a7d543d4744 100644 --- a/impeller/display_list/aiks_dl_unittests.cc +++ b/impeller/display_list/aiks_dl_unittests.cc @@ -18,6 +18,7 @@ #include "flutter/display_list/dl_paint.h" #include "flutter/testing/testing.h" #include "imgui.h" +#include "impeller/display_list/dl_dispatcher.h" #include "impeller/display_list/dl_image_impeller.h" #include "impeller/geometry/scalar.h" #include "include/core/SkMatrix.h" @@ -924,5 +925,54 @@ TEST_P(AiksTest, BackdropRestoreUsesCorrectCoverageForFirstRestoredClip) { ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } +TEST_P(AiksTest, CanPictureConvertToImage) { + DisplayListBuilder recorder_canvas; + DlPaint paint; + paint.setColor(DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0)); + recorder_canvas.DrawRect(SkRect::MakeXYWH(100.0, 100.0, 600, 600), paint); + paint.setColor(DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0)); + recorder_canvas.DrawRect(SkRect::MakeXYWH(200.0, 200.0, 600, 600), paint); + + DisplayListBuilder canvas; + AiksContext renderer(GetContext(), nullptr); + paint.setColor(DlColor::kTransparent()); + canvas.DrawPaint(paint); + + auto image = + DisplayListToTexture(recorder_canvas.Build(), {1000, 1000}, renderer); + if (image) { + canvas.DrawImage(DlImageImpeller::Make(image), {}, {}); + paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 0.2)); + canvas.DrawRect(SkRect::MakeSize({1000, 1000}), paint); + } + + ASSERT_TRUE(OpenPlaygroundHere(canvas.Build())); +} + +// Regression test for https://github.com/flutter/flutter/issues/142358 . +// Without a change to force render pass construction the image is left in an +// undefined layout and triggers a validation error. +TEST_P(AiksTest, CanEmptyPictureConvertToImage) { + DisplayListBuilder recorder_builder; + + DisplayListBuilder builder; + AiksContext renderer(GetContext(), nullptr); + + DlPaint paint; + paint.setColor(DlColor::kTransparent()); + builder.DrawPaint(paint); + + auto result_image = + DisplayListToTexture(builder.Build(), ISize{1000, 1000}, renderer); + if (result_image) { + recorder_builder.DrawImage(DlImageImpeller::Make(result_image), {}, {}); + + paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 0.2)); + recorder_builder.DrawRect(SkRect::MakeSize({1000, 1000}), paint); + } + + ASSERT_TRUE(OpenPlaygroundHere(recorder_builder.Build())); +} + } // namespace testing } // namespace impeller