[Impeller] Apply some recent color filter fixes to BlendFilterContents::CreateForegroundAdvancedBlend (flutter/engine#55470)

Some recent changes affecting color filters (https://github.com/flutter/engine/pull/55411, https://github.com/flutter/engine/pull/55448) need to be done for both Porter-Duff and advanced blend modes
This commit is contained in:
Jason Simmons 2024-09-27 14:42:49 -07:00 committed by GitHub
parent 9e2746c137
commit faa865b425
5 changed files with 102 additions and 7 deletions

View File

@ -22,6 +22,7 @@
#include "impeller/display_list/dl_dispatcher.h"
#include "impeller/playground/playground.h"
#include "impeller/playground/playground_test.h"
#include "impeller/renderer/testing/mocks.h"
#include "include/core/SkMatrix.h"
////////////////////////////////////////////////////////////////////////////////
@ -303,6 +304,97 @@ TEST_P(AiksTest, ColorFilterAdvancedBlend) {
ASSERT_TRUE(OpenPlaygroundHere(callback));
}
// Variant of the https://github.com/flutter/flutter/issues/155691 test that
// uses an advanced blend in the color filter and disables framebuffer fetch
// to force usage of BlendFilterContents::CreateForegroundAdvancedBlend.
TEST_P(AiksTest, ColorFilterAdvancedBlendNoFbFetch) {
if (GetParam() != PlaygroundBackend::kMetal) {
GTEST_SKIP()
<< "This backend doesn't yet support setting device capabilities.";
}
if (!WillRenderSomething()) {
GTEST_SKIP() << "This test requires playgrounds.";
}
std::shared_ptr<const Capabilities> old_capabilities =
GetContext()->GetCapabilities();
auto mock_capabilities = std::make_shared<MockCapabilities>();
EXPECT_CALL(*mock_capabilities, SupportsFramebufferFetch())
.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, SupportsSSBO);
FLT_FORWARD(mock_capabilities, old_capabilities, SupportsCompute);
FLT_FORWARD(mock_capabilities, old_capabilities,
SupportsTextureToTextureBlits);
FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultGlyphAtlasFormat);
FLT_FORWARD(mock_capabilities, old_capabilities, SupportsTriangleFan);
FLT_FORWARD(mock_capabilities, old_capabilities,
SupportsDecalSamplerAddressMode);
ASSERT_TRUE(SetCapabilities(mock_capabilities).ok());
bool has_color_filter = true;
auto callback = [&]() -> sk_sp<DisplayList> {
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<DlBlendMode> blend_modes = {
DlBlendMode::kScreen, DlBlendMode::kOverlay,
DlBlendMode::kDarken, DlBlendMode::kLighten,
DlBlendMode::kColorDodge, DlBlendMode::kColorBurn,
DlBlendMode::kHardLight, DlBlendMode::kSoftLight,
DlBlendMode::kDifference, DlBlendMode::kExclusion,
DlBlendMode::kMultiply, DlBlendMode::kHue,
DlBlendMode::kSaturation, DlBlendMode::kColor,
DlBlendMode::kLuminosity,
};
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<const DlColorFilter> color_filter =
DlBlendColorFilter::Make(DlColor::RGBA(0.9, 0.5, 0.0, 1.0),
DlBlendMode::kMultiply);
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(),

View File

@ -1041,10 +1041,6 @@ TEST_P(AiksTest, BlurredRectangleWithShader) {
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()

View File

@ -303,7 +303,7 @@ std::optional<Entity> BlendFilterContents::CreateForegroundAdvancedBlend(
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;
switch (blend_mode) {
@ -370,8 +370,9 @@ std::optional<Entity> BlendFilterContents::CreateForegroundAdvancedBlend(
FS::BindTextureSamplerDst(pass, dst_snapshot->texture, dst_sampler);
frame_info.dst_y_coord_scale = dst_snapshot->texture->GetYCoordScale();
frame_info.mvp = Entity::GetShaderTransform(entity.GetShaderClipDepth(),
pass, dst_snapshot->transform);
frame_info.mvp = Entity::GetShaderTransform(
entity.GetShaderClipDepth(), pass,
entity.GetTransform() * dst_snapshot->transform);
blend_info.dst_input_alpha =
absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
@ -402,6 +403,7 @@ std::optional<Entity> BlendFilterContents::CreateForegroundAdvancedBlend(
Entity sub_entity;
sub_entity.SetContents(std::move(contents));
sub_entity.SetBlendMode(entity.GetBlendMode());
return sub_entity;
}

View File

@ -16,6 +16,10 @@
#include "impeller/renderer/render_target.h"
#include "impeller/renderer/sampler_library.h"
#define FLT_FORWARD(mock, real, method) \
EXPECT_CALL(*mock, method()) \
.WillRepeatedly(::testing::Return(real->method()));
namespace impeller {
namespace testing {

View File

@ -523,6 +523,7 @@ impeller_Play_AiksTest_CollapsedDrawPaintInSubpassBackdropFilter_Vulkan.png
impeller_Play_AiksTest_CollapsedDrawPaintInSubpass_Metal.png
impeller_Play_AiksTest_CollapsedDrawPaintInSubpass_OpenGLES.png
impeller_Play_AiksTest_CollapsedDrawPaintInSubpass_Vulkan.png
impeller_Play_AiksTest_ColorFilterAdvancedBlendNoFbFetch_Metal.png
impeller_Play_AiksTest_ColorFilterAdvancedBlend_Metal.png
impeller_Play_AiksTest_ColorFilterAdvancedBlend_OpenGLES.png
impeller_Play_AiksTest_ColorFilterAdvancedBlend_Vulkan.png