Fix backdrop-filter with invalid mask image issue [chromium/src : main]

0 views
Skip to first unread message

Wangsong Jin (Gerrit)

unread,
Dec 18, 2025, 2:59:34 PM12/18/25
to Fredrik Söderquist, Kyle Charbonneau, Dirk Schulze, Stephen Chenney, Philip Rogers, Robert Flack, Olga Gerchikov, Michael Ludwig, Xianzhu Wang, Claire Chambers, Chromium LUCI CQ, AyeAye, chromium...@chromium.org, blink-rev...@chromium.org, fmalit...@chromium.org, fserb...@chromium.org, blink-reviews-p...@chromium.org, drott+bl...@chromium.org, blink-revi...@chromium.org, zol...@webkit.org, blink-rev...@chromium.org, kinuko...@chromium.org, jmedle...@chromium.org, blink-revie...@chromium.org, blink-...@chromium.org, cc-...@chromium.org, ipc-securi...@chromium.org, penghu...@chromium.org
Attention needed from Fredrik Söderquist

Wangsong Jin added 6 comments

Patchset-level comments
File-level comment, Patchset 28:
Philip Rogers . resolved

Sorry Wangsong but I didn't get to this today, and I am OOO for a couple weeks.

f...@opera.com, could you review this?

Wangsong Jin

No worries! Thanks for looping in Fredrik to review.

Commit Message
Line 28, Patchset 28:HandleInvalidMaskImageWithBackdropFilterruntime feature flag as a
Fredrik Söderquist . resolved

Missing space

Wangsong Jin

Marked as resolved.

File third_party/blink/renderer/core/layout/layout_box.cc
Line 2274, Patchset 28: !layer->GetImage()->ErrorOccurred() &&
Fredrik Söderquist . resolved

I would use `CanRender()` instead here.

Wangsong Jin

Marked as unresolved.

File third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc
Line 37, Patchset 28: if (!image->ErrorOccurred() && image->IsLoaded()) {
Fredrik Söderquist . resolved

Ditto here.

Wangsong Jin

Marked as resolved.

Line 35, Patchset 28: while (layer) {
if (StyleImage* image = layer->GetImage()) {
if (!image->ErrorOccurred() && image->IsLoaded()) {
return false;
}
}
layer = layer->Next();
}
Fredrik Söderquist . resolved

I think we should put this in `FillLayer` instead - with the negation removed (i.e more like `AllImagesAreAvailable`.

Wangsong Jin

Thanks, I've refactored to HasAnyImagesAvailable().

File third_party/blink/web_tests/external/wpt/css/css-masking/mask-image/mask-image-invalid-url-with-backdrop-filter.html
Line 14, Patchset 28: background-color: pink;
Fredrik Söderquist . resolved

Could we pick a background color that is not a tint of red? (Red is the color of failure.)

Wangsong Jin

Done!

Open in Gerrit

Related details

Attention is currently required from:
  • Fredrik Söderquist
Submit Requirements:
  • requirement satisfiedCode-Coverage
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: I77cd4907beb541325894eaa2a490401fbc1c05b4
Gerrit-Change-Number: 7004946
Gerrit-PatchSet: 30
Gerrit-Owner: Wangsong Jin <wangs...@microsoft.com>
Gerrit-Reviewer: Claire Chambers <clcha...@microsoft.com>
Gerrit-Reviewer: Fredrik Söderquist <f...@opera.com>
Gerrit-Reviewer: Michael Ludwig <michae...@google.com>
Gerrit-Reviewer: Philip Rogers <p...@chromium.org>
Gerrit-Reviewer: Wangsong Jin <wangs...@microsoft.com>
Gerrit-CC: Dirk Schulze <dsch...@chromium.org>
Gerrit-CC: Kyle Charbonneau <kyle...@chromium.org>
Gerrit-CC: Olga Gerchikov <gerc...@microsoft.com>
Gerrit-CC: Robert Flack <fla...@chromium.org>
Gerrit-CC: Stephen Chenney <sche...@chromium.org>
Gerrit-CC: Xianzhu Wang <wangx...@chromium.org>
Gerrit-Attention: Fredrik Söderquist <f...@opera.com>
Gerrit-Comment-Date: Thu, 18 Dec 2025 19:59:21 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: Philip Rogers <p...@chromium.org>
Comment-In-Reply-To: Fredrik Söderquist <f...@opera.com>
satisfied_requirement
unsatisfied_requirement
open
diffy

Philip Rogers (Gerrit)

unread,
Dec 18, 2025, 5:44:38 PM12/18/25
to Wangsong Jin, Fredrik Söderquist, Kyle Charbonneau, Dirk Schulze, Stephen Chenney, Robert Flack, Olga Gerchikov, Michael Ludwig, Xianzhu Wang, Claire Chambers, Chromium LUCI CQ, AyeAye, chromium...@chromium.org, blink-rev...@chromium.org, fmalit...@chromium.org, fserb...@chromium.org, blink-reviews-p...@chromium.org, drott+bl...@chromium.org, blink-revi...@chromium.org, zol...@webkit.org, blink-rev...@chromium.org, kinuko...@chromium.org, jmedle...@chromium.org, blink-revie...@chromium.org, blink-...@chromium.org, cc-...@chromium.org, ipc-securi...@chromium.org, penghu...@chromium.org
Attention needed from Fredrik Söderquist and Wangsong Jin

Philip Rogers added 1 comment

File third_party/blink/renderer/core/layout/layout_box.cc
Line 2265, Patchset 27: // on SVG content (see CSSMaskPainter), we need to update paint
Philip Rogers . resolved
The code in third_party/blink/renderer/core/paint/css_mask_painter.cc seems to be doing something very similar to what you're doing in this patch (see the "kludge" comment), and the effect is similar too (e.g., the mask clip will be null in FragmentPaintPropertyTreeBuilder::UpdateEffect). Are these doing the same thing? If so, maybe we can share code by basically just doing:
```
if (layer->GetImage()->IsMaskSource()) {
// Since an invalid <mask> reference does not yield a paint property,
// we need to update paint properties when a reference changes.
SetNeedsPaintPropertyUpdate();
}
```

And similarly, share code in css_mask_painter.cc?

Wangsong Jin

Thanks!

I don't think the special handling in HasSingleInvalidSVGMaskReferenceMaskLayer() do the same thing.

I found that HasSingleInvalidSVGMaskReferenceMaskLayer() creates special behavior for SVG with local mask resource - when a local reference is invalid, we return std::nullopt and don't apply any masking at all. Not really sure that's by design though.

In my test, the blue rectangle gets an exception (invalid local reference, but still visible), while the green circle remains hidden (invalid external resource).

```
<svg width="200" height="200">
<rect x="120" y="10" width="100" height="100"
fill="blue"
mask="url(#local-invalid-mask)" />
<circle cx="60" cy="150" r="40"
fill="green"
mask="url(remote-invalid-mask)" />
</svg>
```
Link: https://codepen.io/JosephJin0815/pen/ByjeXoL

Therefore, this function isn't meant to mask out the content. And regardless of whether the mask image is valid or invalid, the mask bounds themselves should still exist and not be null.

Wangsong Jin

Done

Philip Rogers

Hi Wangsong, I prototyped the idea I was suggesting for about unifying the svg and css codepaths in https://chromium-review.googlesource.com/c/chromium/src/+/7275621, and it seems to pass tests and matches Firefox and Safari in https://codepen.io/JosephJin0815/pen/ByjeXoL. WDYT of this approach vs the one in your latest patchset? If you want to go with it, feel free to copy the patch and land it (it builds on one of your patches here).

Open in Gerrit

Related details

Attention is currently required from:
  • Fredrik Söderquist
  • Wangsong Jin
Gerrit-Attention: Wangsong Jin <wangs...@microsoft.com>
Gerrit-Attention: Fredrik Söderquist <f...@opera.com>
Gerrit-Comment-Date: Thu, 18 Dec 2025 22:44:27 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: Philip Rogers <p...@chromium.org>
Comment-In-Reply-To: Wangsong Jin <wangs...@microsoft.com>
satisfied_requirement
unsatisfied_requirement
open
diffy

Wangsong Jin (Gerrit)

unread,
Dec 18, 2025, 8:19:44 PM12/18/25
to Fredrik Söderquist, Kyle Charbonneau, Dirk Schulze, Stephen Chenney, Philip Rogers, Robert Flack, Olga Gerchikov, Michael Ludwig, Xianzhu Wang, Claire Chambers, Chromium LUCI CQ, AyeAye, chromium...@chromium.org, blink-rev...@chromium.org, fmalit...@chromium.org, fserb...@chromium.org, blink-reviews-p...@chromium.org, drott+bl...@chromium.org, blink-revi...@chromium.org, zol...@webkit.org, blink-rev...@chromium.org, kinuko...@chromium.org, jmedle...@chromium.org, blink-revie...@chromium.org, blink-...@chromium.org, cc-...@chromium.org, ipc-securi...@chromium.org, penghu...@chromium.org
Attention needed from Fredrik Söderquist and Philip Rogers

Wangsong Jin added 1 comment

File third_party/blink/renderer/core/layout/layout_box.cc
Wangsong Jin

Hi Philip, thank you so much for your prototype! Sorry I was not quite understanding your suggestion initially—I was confused about SVG element behavior.

I prefer the approach you mentioned since it's more general, and I've updated the code accordingly.

One question about an edge case: With the current logic, if multiple mask images are specified and all are invalid, we won't mask out the content (maybe we should?). It seems we deliberate do that for SVG elements, but let me know if HTML elements should behave differently.

```
bool HasSingleInvalidMaskLayer(const LayoutObject& object,
const FillLayer& first_layer) {
if (first_layer.Next()) {
return false;
}
...
```
Open in Gerrit

Related details

Attention is currently required from:
  • Fredrik Söderquist
  • Philip Rogers
Submit Requirements:
  • requirement satisfiedCode-Coverage
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: I77cd4907beb541325894eaa2a490401fbc1c05b4
Gerrit-Change-Number: 7004946
Gerrit-PatchSet: 31
Gerrit-Owner: Wangsong Jin <wangs...@microsoft.com>
Gerrit-Reviewer: Claire Chambers <clcha...@microsoft.com>
Gerrit-Reviewer: Fredrik Söderquist <f...@opera.com>
Gerrit-Reviewer: Michael Ludwig <michae...@google.com>
Gerrit-Reviewer: Philip Rogers <p...@chromium.org>
Gerrit-Reviewer: Wangsong Jin <wangs...@microsoft.com>
Gerrit-CC: Dirk Schulze <dsch...@chromium.org>
Gerrit-CC: Kyle Charbonneau <kyle...@chromium.org>
Gerrit-CC: Olga Gerchikov <gerc...@microsoft.com>
Gerrit-CC: Robert Flack <fla...@chromium.org>
Gerrit-CC: Stephen Chenney <sche...@chromium.org>
Gerrit-CC: Xianzhu Wang <wangx...@chromium.org>
Gerrit-Attention: Philip Rogers <p...@chromium.org>
Gerrit-Attention: Fredrik Söderquist <f...@opera.com>
Gerrit-Comment-Date: Fri, 19 Dec 2025 01:19:33 +0000
satisfied_requirement
unsatisfied_requirement
open
diffy

Fredrik Söderquist (Gerrit)

unread,
Dec 19, 2025, 5:18:45 AM (14 days ago) 12/19/25
to Wangsong Jin, Kyle Charbonneau, Dirk Schulze, Stephen Chenney, Philip Rogers, Robert Flack, Olga Gerchikov, Michael Ludwig, Xianzhu Wang, Claire Chambers, Chromium LUCI CQ, AyeAye, chromium...@chromium.org, blink-rev...@chromium.org, fmalit...@chromium.org, fserb...@chromium.org, blink-reviews-p...@chromium.org, drott+bl...@chromium.org, blink-revi...@chromium.org, zol...@webkit.org, blink-rev...@chromium.org, kinuko...@chromium.org, jmedle...@chromium.org, blink-revie...@chromium.org, blink-...@chromium.org, cc-...@chromium.org, ipc-securi...@chromium.org, penghu...@chromium.org
Attention needed from Wangsong Jin

Fredrik Söderquist added 5 comments

Patchset-level comments
File-level comment, Patchset 31 (Latest):
Fredrik Söderquist . resolved

(I'll also be OOO after today)

File third_party/blink/renderer/core/layout/layout_box.cc
Line 2265, Patchset 27: // on SVG content (see CSSMaskPainter), we need to update paint
Philip Rogers . unresolved
Fredrik Söderquist

I think this could work, but just like Wangsong I think this won't work as-is if all mask are invalid. I think it's probably better to keep the SVG quirk separate (it's for backwards compat BTW - maybe we should add a use-counter for it?). So maybe add a "all layers are renderable" helper and return `nullopt` for that?

File third_party/blink/renderer/core/paint/css_mask_painter.cc
Line 30, Patchset 31 (Latest): if (style_image->IsMaskSource()) {
const auto* mask_source = DynamicTo<StyleMaskSourceImage>(style_image);
if (mask_source && mask_source->HasSVGMask()) {
Fredrik Söderquist . unresolved
These three (type-check, type-cast and null-check) should be merged. The way this is written it type-checks twice and then does an unnecessary null-check.
```suggestion
if (auto* mask_source = DynamicTo<StyleMaskSourceImage>(style_image);
mask_source && mask_source->HasSVGMask()) {
```
Line 36, Patchset 31 (Latest): return style_image->ErrorOccurred();
Fredrik Söderquist . unresolved

`CanRender()`

Line 46, Patchset 31 (Parent): // This is a kludge. The spec[1] says that a non-existent <mask>
// reference should yield an image layer of transparent black.
//
// [1] https://drafts.fxtf.org/css-masking/#the-mask-image
Fredrik Söderquist . unresolved

I would move this comment into `HasSingleInvalidMaskLayer()`, because it still applies.

Open in Gerrit

Related details

Attention is currently required from:
  • Wangsong Jin
Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement is not satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: I77cd4907beb541325894eaa2a490401fbc1c05b4
    Gerrit-Change-Number: 7004946
    Gerrit-PatchSet: 31
    Gerrit-Owner: Wangsong Jin <wangs...@microsoft.com>
    Gerrit-Reviewer: Claire Chambers <clcha...@microsoft.com>
    Gerrit-Reviewer: Fredrik Söderquist <f...@opera.com>
    Gerrit-Reviewer: Michael Ludwig <michae...@google.com>
    Gerrit-Reviewer: Philip Rogers <p...@chromium.org>
    Gerrit-Reviewer: Wangsong Jin <wangs...@microsoft.com>
    Gerrit-CC: Dirk Schulze <dsch...@chromium.org>
    Gerrit-CC: Kyle Charbonneau <kyle...@chromium.org>
    Gerrit-CC: Olga Gerchikov <gerc...@microsoft.com>
    Gerrit-CC: Robert Flack <fla...@chromium.org>
    Gerrit-CC: Stephen Chenney <sche...@chromium.org>
    Gerrit-CC: Xianzhu Wang <wangx...@chromium.org>
    Gerrit-Attention: Wangsong Jin <wangs...@microsoft.com>
    Gerrit-Comment-Date: Fri, 19 Dec 2025 10:18:31 +0000
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Wangsong Jin (Gerrit)

    unread,
    Dec 19, 2025, 7:21:45 PM (13 days ago) 12/19/25
    to Fredrik Söderquist, Kyle Charbonneau, Dirk Schulze, Stephen Chenney, Philip Rogers, Robert Flack, Olga Gerchikov, Michael Ludwig, Xianzhu Wang, Claire Chambers, Chromium LUCI CQ, AyeAye, chromium...@chromium.org, blink-rev...@chromium.org, fmalit...@chromium.org, fserb...@chromium.org, blink-reviews-p...@chromium.org, drott+bl...@chromium.org, blink-revi...@chromium.org, zol...@webkit.org, blink-rev...@chromium.org, kinuko...@chromium.org, jmedle...@chromium.org, blink-revie...@chromium.org, blink-...@chromium.org, cc-...@chromium.org, ipc-securi...@chromium.org, penghu...@chromium.org
    Attention needed from Fredrik Söderquist

    Wangsong Jin added 4 comments

    File third_party/blink/renderer/core/layout/layout_box.cc
    Line 2265, Patchset 27: // on SVG content (see CSSMaskPainter), we need to update paint
    Philip Rogers . resolved
    Wangsong Jin

    Thanks for the suggestion! I agree we should match Firefox and Safari behavior, where the element is masked out if all masks are invalid. In this case, combining SVG and other cases into a single path also feels a bit messy. I’ve added FillLayer::HasAnyImagesAvailable() back to handle multiple mask layers.
    And I add IsLoaded() alongside with CanRender() to avoid filtering with slow‑loading invalid mask images (Content appears briefly, then disappears).

    File third_party/blink/renderer/core/paint/css_mask_painter.cc
    Line 30, Patchset 31: if (style_image->IsMaskSource()) {

    const auto* mask_source = DynamicTo<StyleMaskSourceImage>(style_image);
    if (mask_source && mask_source->HasSVGMask()) {
    Fredrik Söderquist . resolved
    These three (type-check, type-cast and null-check) should be merged. The way this is written it type-checks twice and then does an unnecessary null-check.
    ```suggestion
    if (auto* mask_source = DynamicTo<StyleMaskSourceImage>(style_image);
    mask_source && mask_source->HasSVGMask()) {
    ```
    Wangsong Jin

    Done

    Line 36, Patchset 31: return style_image->ErrorOccurred();
    Fredrik Söderquist . resolved

    `CanRender()`

    Wangsong Jin

    Done

    Line 46, Patchset 31 (Parent): // This is a kludge. The spec[1] says that a non-existent <mask>
    // reference should yield an image layer of transparent black.
    //
    // [1] https://drafts.fxtf.org/css-masking/#the-mask-image
    Fredrik Söderquist . resolved

    I would move this comment into `HasSingleInvalidMaskLayer()`, because it still applies.

    Wangsong Jin

    Done

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Fredrik Söderquist
    Submit Requirements:
      • requirement satisfiedCode-Coverage
      • requirement is not satisfiedCode-Owners
      • requirement is not satisfiedCode-Review
      • requirement is not satisfiedReview-Enforcement
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: comment
      Gerrit-Project: chromium/src
      Gerrit-Branch: main
      Gerrit-Change-Id: I77cd4907beb541325894eaa2a490401fbc1c05b4
      Gerrit-Change-Number: 7004946
      Gerrit-PatchSet: 32
      Gerrit-Owner: Wangsong Jin <wangs...@microsoft.com>
      Gerrit-Reviewer: Claire Chambers <clcha...@microsoft.com>
      Gerrit-Reviewer: Fredrik Söderquist <f...@opera.com>
      Gerrit-Reviewer: Michael Ludwig <michae...@google.com>
      Gerrit-Reviewer: Philip Rogers <p...@chromium.org>
      Gerrit-Reviewer: Wangsong Jin <wangs...@microsoft.com>
      Gerrit-CC: Dirk Schulze <dsch...@chromium.org>
      Gerrit-CC: Kyle Charbonneau <kyle...@chromium.org>
      Gerrit-CC: Olga Gerchikov <gerc...@microsoft.com>
      Gerrit-CC: Robert Flack <fla...@chromium.org>
      Gerrit-CC: Stephen Chenney <sche...@chromium.org>
      Gerrit-CC: Xianzhu Wang <wangx...@chromium.org>
      Gerrit-Attention: Fredrik Söderquist <f...@opera.com>
      Gerrit-Comment-Date: Sat, 20 Dec 2025 00:21:27 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      Comment-In-Reply-To: Philip Rogers <p...@chromium.org>
      Comment-In-Reply-To: Wangsong Jin <wangs...@microsoft.com>
      Comment-In-Reply-To: Fredrik Söderquist <f...@opera.com>
      satisfied_requirement
      unsatisfied_requirement
      open
      diffy
      Reply all
      Reply to author
      Forward
      0 new messages