From ad894bd2f0a62de7624bf0bcb5312781615bbc63 Mon Sep 17 00:00:00 2001 From: gaaclarke <30870216+gaaclarke@users.noreply.github.com> Date: Wed, 25 Sep 2024 12:57:45 -0700 Subject: [PATCH] Fixes blend + color filter (flutter/engine#55411) fixes https://github.com/flutter/flutter/issues/155456 Thanks @jason-simmons for identifying the fix. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide] and the [C++, Objective-C, Java style guides]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I added new tests to check the change I am making or feature I am adding, or the PR is [test-exempt]. See [testing the engine] for instructions on writing and running engine tests. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I signed the [CLA]. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. [Contributor Guide]: https://github.com/flutter/flutter/wiki/Tree-hygiene#overview [Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene [test-exempt]: https://github.com/flutter/flutter/wiki/Tree-hygiene#tests [Flutter Style Guide]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style [testing the engine]: https://github.com/flutter/flutter/wiki/Testing-the-engine [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/wiki/Chat --- .../display_list/aiks_dl_blend_unittests.cc | 52 +++++++++++++++++++ .../contents/filters/blend_filter_contents.cc | 3 +- .../testing/impeller_golden_tests_output.txt | 3 ++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/engine/src/flutter/impeller/display_list/aiks_dl_blend_unittests.cc b/engine/src/flutter/impeller/display_list/aiks_dl_blend_unittests.cc index cdddca59811..0c9fcd51ae8 100644 --- a/engine/src/flutter/impeller/display_list/aiks_dl_blend_unittests.cc +++ b/engine/src/flutter/impeller/display_list/aiks_dl_blend_unittests.cc @@ -194,6 +194,58 @@ TEST_P(AiksTest, PaintBlendModeIsRespected) { ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } +// Compare results with https://api.flutter.dev/flutter/dart-ui/BlendMode.html +TEST_P(AiksTest, ImageFilterBlend) { + bool has_color_filter = true; + auto callback = [&]() -> sk_sp { + if (AiksTest::ImGuiBegin("Controls", nullptr, + ImGuiWindowFlags_AlwaysAutoResize)) { + ImGui::Checkbox("has color filter", &has_color_filter); + ImGui::End(); + } + + DisplayListBuilder builder; + builder.Scale(GetContentScale().x, GetContentScale().y); + + auto src_image = + DlImageImpeller::Make(CreateTextureForFixture("blend_mode_src.png")); + auto dst_image = + DlImageImpeller::Make(CreateTextureForFixture("blend_mode_dst.png")); + + std::vector blend_modes = { + DlBlendMode::kSrc, DlBlendMode::kSrcATop, DlBlendMode::kSrcOver, + DlBlendMode::kSrcIn, DlBlendMode::kSrcOut, DlBlendMode::kDst, + DlBlendMode::kDstATop, DlBlendMode::kDstOver, DlBlendMode::kDstIn, + DlBlendMode::kDstOut, DlBlendMode::kClear, DlBlendMode::kXor}; + + for (uint32_t i = 0; i < blend_modes.size(); ++i) { + builder.Save(); + builder.Translate((i % 5) * 200, (i / 5) * 200); + builder.Scale(0.4, 0.4); + { + DlPaint dstPaint; + builder.DrawImage(dst_image, {0, 0}, DlImageSampling::kMipmapLinear, + &dstPaint); + } + { + DlPaint srcPaint; + srcPaint.setBlendMode(blend_modes[i]); + if (has_color_filter) { + std::shared_ptr color_filter = + DlBlendColorFilter::Make(DlColor::RGBA(0.9, 0.5, 0.0, 1.0), + DlBlendMode::kSrcIn); + srcPaint.setColorFilter(color_filter); + } + builder.DrawImage(src_image, {0, 0}, DlImageSampling::kMipmapLinear, + &srcPaint); + } + builder.Restore(); + } + return builder.Build(); + }; + ASSERT_TRUE(OpenPlaygroundHere(callback)); +} + // Bug: https://github.com/flutter/flutter/issues/142549 TEST_P(AiksTest, BlendModePlusAlphaWideGamut) { EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(), diff --git a/engine/src/flutter/impeller/entity/contents/filters/blend_filter_contents.cc b/engine/src/flutter/impeller/entity/contents/filters/blend_filter_contents.cc index 9148e920a37..59c21d2caf8 100644 --- a/engine/src/flutter/impeller/entity/contents/filters/blend_filter_contents.cc +++ b/engine/src/flutter/impeller/entity/contents/filters/blend_filter_contents.cc @@ -454,7 +454,7 @@ std::optional BlendFilterContents::CreateForegroundPorterDuffBlend( BlendModeToString(blend_mode))); #endif // IMPELLER_DEBUG pass.SetVertexBuffer(std::move(vtx_buffer)); - auto options = OptionsFromPass(pass); + auto options = OptionsFromPassAndEntity(pass, entity); options.primitive_type = PrimitiveType::kTriangleStrip; pass.SetPipeline(renderer.GetPorterDuffBlendPipeline(options)); @@ -505,6 +505,7 @@ std::optional BlendFilterContents::CreateForegroundPorterDuffBlend( Entity sub_entity; sub_entity.SetContents(std::move(contents)); + sub_entity.SetBlendMode(entity.GetBlendMode()); return sub_entity; } diff --git a/engine/src/flutter/testing/impeller_golden_tests_output.txt b/engine/src/flutter/testing/impeller_golden_tests_output.txt index d219c257836..eb2565823f4 100644 --- a/engine/src/flutter/testing/impeller_golden_tests_output.txt +++ b/engine/src/flutter/testing/impeller_golden_tests_output.txt @@ -711,6 +711,9 @@ impeller_Play_AiksTest_GradientStrokesRenderCorrectly_Vulkan.png impeller_Play_AiksTest_ImageColorSourceEffectTransform_Metal.png impeller_Play_AiksTest_ImageColorSourceEffectTransform_OpenGLES.png impeller_Play_AiksTest_ImageColorSourceEffectTransform_Vulkan.png +impeller_Play_AiksTest_ImageFilterBlend_Metal.png +impeller_Play_AiksTest_ImageFilterBlend_OpenGLES.png +impeller_Play_AiksTest_ImageFilterBlend_Vulkan.png impeller_Play_AiksTest_ImageFilteredSaveLayerWithUnboundedContents_Metal.png impeller_Play_AiksTest_ImageFilteredSaveLayerWithUnboundedContents_OpenGLES.png impeller_Play_AiksTest_ImageFilteredSaveLayerWithUnboundedContents_Vulkan.png