Skip to content

[Impeller] Dilated saveLayer content disappears when its source is outside the clip #195666

Closed

Description

@ColdPaleLight

When a saveLayer uses a dilate image filter, Impeller drops content that is outside the parent clip even when the dilated result should extend into the visible area.

For example, on a 160 × 100 canvas:

  • Draw a black background.
  • Clip to (20, 20, 100, 60) in (x, y, width, height) notation.
  • Save a layer with a dilation radius of (10, 10).
  • Draw a white rectangle at (15, 45, 4, 10) and restore the layer.

The source rectangle is entirely to the left of the clip. After dilation, however, its right edge extends to x = 29, so a white strip should be visible inside the clip. Instead, the rectangle disappears.

This engine test reproduces the problem:

TEST_P(DlGoldenTest, DilatedContentOutsideClip) {
  SetWindowSize(impeller::ISize(160, 100));
  DisplayListBuilder builder;
  builder.DrawColor(DlColor::kBlack(), DlBlendMode::kSrc);
  builder.ClipRect(DlRect::MakeXYWH(20, 20, 100, 60));

  DlPaint layer_paint;
  layer_paint.setImageFilter(DlImageFilter::MakeDilate(10, 10));
  builder.SaveLayer(DlRect::MakeXYWH(0, 0, 160, 100), &layer_paint);
  // The rectangle is outside the clip, but its dilated right edge is inside.
  builder.DrawRect(DlRect::MakeXYWH(15, 45, 4, 10),
                   DlPaint().setColor(DlColor::kWhite()));
  builder.Restore();

  auto screenshot = MakeScreenshot(builder.Build());
  if (!screenshot) {
    GTEST_SKIP() << "making screenshots not supported.";
  }
  const uint8_t* row =
      screenshot->GetBytes() + 50 * screenshot->GetBytesPerRow();
  for (size_t channel = 0; channel < 3; channel++) {
    EXPECT_EQ(row[24 * 4 + channel], 255);
    EXPECT_EQ(row[15 * 4 + channel], 0);
  }
}

Pixel (24, 50) should be white because it is inside both the clip and the dilated rectangle. It is black with Impeller, and the test fails on both Metal and MetalSDF. Pixel (15, 50) is outside the clip and should remain black.

The same example renders as expected with Skia on both CPU and GPU:
https://fiddle.skia.org/c/86acbc9f1ca0a0a85db41a288e858498

Reproduced in native engine tests at revision 666d2c4e831d40738b8692464d57b4aaa9478acd, using host_debug_unopt_arm64 on macOS.

Activity

  1. added
    in triagePresently being triaged by the triage team
    engineflutter/engine related. See also e: labels.
    e: impellerImpeller rendering backend issues and features requests
    and removed
    in triagePresently being triaged by the triage team
    on Oct 30, 2026
  2. puneetkukreja98 commented on Oct 30, 2026

    @puneetkukreja98
    Contributor

    @ColdPaleLight Thanks for reporting this, routing this to team-engine for further investigation.

  3. added
    P2Important issues not at the top of the work list
    on Nov 2, 2026
  4. ColdPaleLight commented on Nov 5, 2026

    @ColdPaleLight
    MemberAuthor

    Fixed by the linked PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work liste: impellerImpeller rendering backend issues and features requestsengineflutter/engine related. See also e: labels.team-engineOwned by Engine teamtriaged-engineTriaged by Engine team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions