[Impeller] Fix handling of destination opacity in advanced blends (flutter/engine#56251)

The framebuffer blend pipeline needs to support a dst_input_alpha parameter in order to implement the AbsorbOpacity flag.

Also, dst_input_alpha should only be applied to the alpha channel of the unpremultiplied destination color.

Fixes https://github.com/flutter/flutter/issues/157716
This commit is contained in:
Jason Simmons 2024-10-31 18:02:10 -07:00 committed by GitHub
parent f81ed55e63
commit 09c811781d
7 changed files with 44 additions and 14 deletions

View File

@ -906,5 +906,25 @@ TEST_P(AiksTest, DestructiveBlendColorFilterFloodsClip) {
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
TEST_P(AiksTest, AdvancedBlendColorFilterWithDestinationOpacity) {
DisplayListBuilder builder;
builder.DrawPaint(DlPaint(DlColor::kWhite()));
DlPaint save_paint;
save_paint.setOpacity(0.3);
save_paint.setColorFilter(DlBlendColorFilter::Make(DlColor::kTransparent(),
DlBlendMode::kSaturation));
builder.SaveLayer(nullptr, &save_paint);
builder.DrawRect(SkRect::MakeXYWH(100, 100, 300, 300),
DlPaint(DlColor::kMaroon()));
builder.DrawRect(SkRect::MakeXYWH(200, 200, 300, 300),
DlPaint(DlColor::kBlue()));
builder.Restore();
// Should be solid red as the destructive color filter floods the clip.
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
} // namespace testing
} // namespace impeller

View File

@ -850,6 +850,10 @@ std::optional<Entity> BlendFilterContents::CreateFramebufferAdvancedBlend(
VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
frag_info.src_input_alpha = 1.0;
frag_info.dst_input_alpha =
absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes
? dst_snapshot->opacity
: 1.0;
FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
return pass.Draw().ok();

View File

@ -139,6 +139,7 @@ bool FramebufferBlendContents::Render(const ContentContext& renderer,
VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
frag_info.src_input_alpha = src_snapshot->opacity;
frag_info.dst_input_alpha = 1.0;
FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
return pass.Draw().ok();

View File

@ -40,7 +40,7 @@ void main() {
IPHalfUnpremultiply(Sample(texture_sampler_dst, // sampler
v_dst_texture_coords // texture coordinates
));
dst *= blend_info.dst_input_alpha;
dst.a *= blend_info.dst_input_alpha;
f16vec4 src = blend_info.color_factor > 0.0hf
? blend_info.color
: IPHalfUnpremultiply(Sample(

View File

@ -28,6 +28,7 @@ uniform sampler2D texture_sampler_src;
uniform FragInfo {
float16_t src_input_alpha;
float16_t dst_input_alpha;
}
frag_info;
@ -44,6 +45,7 @@ vec4 Sample(sampler2D texture_sampler, vec2 texture_coords) {
void main() {
f16vec4 dst = IPHalfUnpremultiply(f16vec4(ReadDestination()));
dst.a *= frag_info.dst_input_alpha;
f16vec4 src = IPHalfUnpremultiply(
f16vec4(Sample(texture_sampler_src, // sampler
v_src_texture_coords // texture coordinates

View File

@ -20,8 +20,8 @@
"arith_fma"
],
"longest_path_cycles": [
0.578125,
0.578125,
0.53125,
0.53125,
0.21875,
0.125,
0.0,
@ -42,8 +42,8 @@
"arith_fma"
],
"shortest_path_cycles": [
0.53125,
0.53125,
0.484375,
0.484375,
0.203125,
0.0625,
0.0,
@ -55,8 +55,8 @@
"arith_fma"
],
"total_cycles": [
0.578125,
0.578125,
0.53125,
0.53125,
0.296875,
0.125,
0.0,
@ -1114,8 +1114,8 @@
"arith_fma"
],
"longest_path_cycles": [
0.578125,
0.578125,
0.53125,
0.53125,
0.265625,
0.125,
0.0,
@ -1136,8 +1136,8 @@
"arith_fma"
],
"shortest_path_cycles": [
0.53125,
0.53125,
0.484375,
0.484375,
0.21875,
0.0625,
0.0,
@ -1149,8 +1149,8 @@
"arith_fma"
],
"total_cycles": [
0.578125,
0.578125,
0.53125,
0.53125,
0.34375,
0.125,
0.0,
@ -1178,7 +1178,7 @@
"arithmetic"
],
"longest_path_cycles": [
4.289999961853027,
3.9600000381469727,
2.0,
2.0
],

View File

@ -1,5 +1,8 @@
digest.json
impeller_GoldenTests_ConicalGradient.png
impeller_Play_AiksTest_AdvancedBlendColorFilterWithDestinationOpacity_Metal.png
impeller_Play_AiksTest_AdvancedBlendColorFilterWithDestinationOpacity_OpenGLES.png
impeller_Play_AiksTest_AdvancedBlendColorFilterWithDestinationOpacity_Vulkan.png
impeller_Play_AiksTest_BackdropRestoreUsesCorrectCoverageForFirstRestoredClip_Metal.png
impeller_Play_AiksTest_BackdropRestoreUsesCorrectCoverageForFirstRestoredClip_OpenGLES.png
impeller_Play_AiksTest_BackdropRestoreUsesCorrectCoverageForFirstRestoredClip_Vulkan.png