[Impeller] Skip clip entity replay that cannot impact current clip. (#162113)
Fixes https://github.com/flutter/flutter/issues/161262 Sometimes we end up with clip replay entities that have clip depth values substantially below the current depth. I suspect this is due to either mismatched save/restore or a bug in our code. Update: this isn't a bug/bug but its definitely a bug. We can have multiple clips per save, but the restore will remove at most one from the record/replay. If a clip has a depth value that is less than the current clip depth, it cannot by definition impact anything that draws after it.
This commit is contained in:
parent
74ade43341
commit
b82e9022a3
@ -1592,5 +1592,33 @@ TEST_P(AiksTest, NoDimplesInRRectPath) {
|
||||
ASSERT_TRUE(OpenPlaygroundHere(callback));
|
||||
}
|
||||
|
||||
TEST_P(AiksTest, BackdropFilterOverUnclosedClip) {
|
||||
DisplayListBuilder builder;
|
||||
|
||||
builder.DrawPaint(DlPaint().setColor(DlColor::kWhite()));
|
||||
builder.Save();
|
||||
{
|
||||
builder.ClipRect(DlRect::MakeLTRB(100, 100, 800, 800));
|
||||
|
||||
builder.Save();
|
||||
{
|
||||
builder.ClipRect(DlRect::MakeLTRB(600, 600, 800, 800));
|
||||
builder.DrawPaint(DlPaint().setColor(DlColor::kRed()));
|
||||
builder.DrawPaint(DlPaint().setColor(DlColor::kBlue().withAlphaF(0.5)));
|
||||
builder.ClipRect(DlRect::MakeLTRB(700, 700, 750, 800));
|
||||
builder.DrawPaint(DlPaint().setColor(DlColor::kRed().withAlphaF(0.5)));
|
||||
}
|
||||
builder.Restore();
|
||||
|
||||
auto image_filter = DlImageFilter::MakeBlur(10, 10, DlTileMode::kDecal);
|
||||
builder.SaveLayer(std::nullopt, nullptr, image_filter.get());
|
||||
}
|
||||
builder.Restore();
|
||||
builder.DrawCircle(SkPoint{100, 100}, 100,
|
||||
DlPaint().setColor(DlColor::kAqua()));
|
||||
|
||||
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace impeller
|
||||
|
@ -1662,6 +1662,10 @@ std::shared_ptr<Texture> Canvas::FlipBackdrop(Point global_pass_position,
|
||||
// applied.
|
||||
auto& replay_entities = clip_coverage_stack_.GetReplayEntities();
|
||||
for (const auto& replay : replay_entities) {
|
||||
if (replay.clip_depth <= current_depth_) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SetClipScissor(replay.clip_coverage, current_render_pass,
|
||||
global_pass_position);
|
||||
if (!replay.clip_contents.Render(renderer_, current_render_pass,
|
||||
|
@ -83,6 +83,9 @@ EntityPassClipStack::ClipStateResult EntityPassClipStack::RecordRestore(
|
||||
if (subpass_state.clip_coverage.back().coverage.has_value()) {
|
||||
FML_DCHECK(next_replay_index_ <=
|
||||
subpass_state.rendered_clip_entities.size());
|
||||
// https://github.com/flutter/flutter/issues/162172
|
||||
// This code is slightly wrong and should be popping more than one clip
|
||||
// entry.
|
||||
if (!subpass_state.rendered_clip_entities.empty()) {
|
||||
subpass_state.rendered_clip_entities.pop_back();
|
||||
|
||||
|
@ -3,6 +3,9 @@ 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_BackdropFilterOverUnclosedClip_Metal.png
|
||||
impeller_Play_AiksTest_BackdropFilterOverUnclosedClip_OpenGLES.png
|
||||
impeller_Play_AiksTest_BackdropFilterOverUnclosedClip_Vulkan.png
|
||||
impeller_Play_AiksTest_BackdropRestoreUsesCorrectCoverageForFirstRestoredClip_Metal.png
|
||||
impeller_Play_AiksTest_BackdropRestoreUsesCorrectCoverageForFirstRestoredClip_OpenGLES.png
|
||||
impeller_Play_AiksTest_BackdropRestoreUsesCorrectCoverageForFirstRestoredClip_Vulkan.png
|
||||
|
Loading…
x
Reference in New Issue
Block a user