Skip to content

Commit 0c6155f

Browse files
bderozanderso
authored andcommitted
[Impeller] Fix back-to-back clip restoration (flutter#38964)
1 parent ac5c83d commit 0c6155f

File tree

2 files changed

+29
-3
lines changed

2 files changed

+29
-3
lines changed

impeller/aiks/aiks_unittests.cc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,29 @@ TEST_P(AiksTest, CanRenderDifferenceClips) {
265265
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
266266
}
267267

268+
TEST_P(AiksTest, CanRenderWithContiguousClipRestores) {
269+
Canvas canvas;
270+
271+
// Cover the whole canvas with red.
272+
canvas.DrawPaint({.color = Color::Red()});
273+
274+
canvas.Save();
275+
276+
// Append two clips. First with empty coverage.
277+
canvas.ClipPath(
278+
PathBuilder{}.AddRect(Rect::MakeXYWH(100, 100, 100, 100)).TakePath());
279+
canvas.ClipPath(
280+
PathBuilder{}.AddRect(Rect::MakeXYWH(100, 100, 100, 100)).TakePath());
281+
282+
// Restore to no clips.
283+
canvas.Restore();
284+
285+
// Replace the whole canvas with green.
286+
canvas.DrawPaint({.color = Color::Green()});
287+
288+
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
289+
}
290+
268291
TEST_P(AiksTest, ClipsUseCurrentTransform) {
269292
std::array<Color, 5> colors = {Color::White(), Color::Black(),
270293
Color::SkyBlue(), Color::Red(),

impeller/entity/entity_pass.cc

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -456,11 +456,14 @@ bool EntityPass::OnRender(
456456
return true;
457457
}
458458

459-
FML_DCHECK(stencil_stack.size() > 1);
459+
auto restoration_depth =
460+
element_entity.GetStencilDepth() - stencil_depth_floor;
461+
FML_DCHECK(restoration_depth < stencil_stack.size());
460462

461-
stencil_stack.pop_back();
463+
auto restored_coverage = stencil_stack.back().coverage;
464+
stencil_stack.resize(restoration_depth + 1);
462465

463-
if (!stencil_stack.back().coverage.has_value()) {
466+
if (!restored_coverage.has_value()) {
464467
// Running this restore op won't make anything renderable, so skip it.
465468
return true;
466469
}

0 commit comments

Comments
 (0)