diff --git a/engine/src/flutter/impeller/display_list/aiks_dl_clip_unittests.cc b/engine/src/flutter/impeller/display_list/aiks_dl_clip_unittests.cc index 5576f343f99..543ee827487 100644 --- a/engine/src/flutter/impeller/display_list/aiks_dl_clip_unittests.cc +++ b/engine/src/flutter/impeller/display_list/aiks_dl_clip_unittests.cc @@ -117,5 +117,30 @@ TEST_P(AiksTest, ClipsUseCurrentTransform) { ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); } +/// If correct, this test should draw a green circle. If any red is visible, +/// there is a depth bug. +TEST_P(AiksTest, FramebufferBlendsRespectClips) { + DisplayListBuilder builder; + + // Clear the whole canvas with white. + DlPaint paint; + paint.setColor(DlColor::kWhite()); + builder.DrawPaint(paint); + + builder.ClipPath(SkPath::Circle(150, 150, 50), DlCanvas::ClipOp::kIntersect); + + // Draw a red rectangle that should not show through the circle clip. + paint.setColor(DlColor::kRed()); + paint.setBlendMode(DlBlendMode::kMultiply); + builder.DrawRect(SkRect::MakeXYWH(100, 100, 100, 100), paint); + + // Draw a green circle that shows through the clip. + paint.setColor(DlColor::kGreen()); + paint.setBlendMode(DlBlendMode::kSrcOver); + builder.DrawCircle(SkPoint::Make(150, 150), 50, paint); + + ASSERT_TRUE(OpenPlaygroundHere(builder.Build())); +} + } // namespace testing } // namespace impeller 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 f7f3f2d94cd..2d5b61428d6 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 @@ -365,7 +365,8 @@ std::optional BlendFilterContents::CreateForegroundAdvancedBlend( FS::BindTextureSamplerDst(pass, dst_snapshot->texture, dst_sampler); frame_info.dst_y_coord_scale = dst_snapshot->texture->GetYCoordScale(); - frame_info.mvp = pass.GetOrthographicTransform() * dst_snapshot->transform; + frame_info.mvp = Entity::GetShaderTransform(entity.GetShaderClipDepth(), + pass, dst_snapshot->transform); blend_info.dst_input_alpha = absorb_opacity == ColorFilterContents::AbsorbOpacity::kYes @@ -454,7 +455,8 @@ std::optional BlendFilterContents::CreateForegroundPorterDuffBlend( FS::FragInfo frag_info; VS::FrameInfo frame_info; - frame_info.mvp = pass.GetOrthographicTransform() * dst_snapshot->transform; + frame_info.mvp = Entity::GetShaderTransform(entity.GetShaderClipDepth(), + pass, dst_snapshot->transform); auto dst_sampler_descriptor = dst_snapshot->sampler_descriptor; if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) { diff --git a/engine/src/flutter/testing/impeller_golden_tests_output.txt b/engine/src/flutter/testing/impeller_golden_tests_output.txt index 82812e676a4..a7e803cc170 100644 --- a/engine/src/flutter/testing/impeller_golden_tests_output.txt +++ b/engine/src/flutter/testing/impeller_golden_tests_output.txt @@ -644,6 +644,9 @@ impeller_Play_AiksTest_ForegroundPipelineBlendAppliesTransformCorrectly_Vulkan.p impeller_Play_AiksTest_FramebufferAdvancedBlendCoverage_Metal.png impeller_Play_AiksTest_FramebufferAdvancedBlendCoverage_OpenGLES.png impeller_Play_AiksTest_FramebufferAdvancedBlendCoverage_Vulkan.png +impeller_Play_AiksTest_FramebufferBlendsRespectClips_Metal.png +impeller_Play_AiksTest_FramebufferBlendsRespectClips_OpenGLES.png +impeller_Play_AiksTest_FramebufferBlendsRespectClips_Vulkan.png impeller_Play_AiksTest_GaussianBlurAnimatedBackdrop_Metal.png impeller_Play_AiksTest_GaussianBlurAnimatedBackdrop_OpenGLES.png impeller_Play_AiksTest_GaussianBlurAnimatedBackdrop_Vulkan.png