Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 0d79533

Browse files
authored
[Impeller] Fix back-to-back clip restoration (#38964)
1 parent d762142 commit 0d79533

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
@@ -270,6 +270,29 @@ TEST_P(AiksTest, CanRenderDifferenceClips) {
270270
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
271271
}
272272

273+
TEST_P(AiksTest, CanRenderWithContiguousClipRestores) {
274+
Canvas canvas;
275+
276+
// Cover the whole canvas with red.
277+
canvas.DrawPaint({.color = Color::Red()});
278+
279+
canvas.Save();
280+
281+
// Append two clips. First with empty coverage.
282+
canvas.ClipPath(
283+
PathBuilder{}.AddRect(Rect::MakeXYWH(100, 100, 100, 100)).TakePath());
284+
canvas.ClipPath(
285+
PathBuilder{}.AddRect(Rect::MakeXYWH(100, 100, 100, 100)).TakePath());
286+
287+
// Restore to no clips.
288+
canvas.Restore();
289+
290+
// Replace the whole canvas with green.
291+
canvas.DrawPaint({.color = Color::Green()});
292+
293+
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
294+
}
295+
273296
TEST_P(AiksTest, ClipsUseCurrentTransform) {
274297
std::array<Color, 5> colors = {Color::White(), Color::Black(),
275298
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)