Open Bug 1799334 Opened 3 years ago Updated 11 days ago

backdrop-filter doesn't blur remote <browser> element

Categories

(Core :: Graphics: WebRender, defect, P2)

Firefox 106
Desktop
All
defect

Tracking

()

ASSIGNED

People

(Reporter: userChrome.css, Assigned: cheff)

References

(Blocks 2 open bugs)

Details

Attachments

(4 files)

  • Using userChrome.css custom file before backdrop-filter was disabled, fixed and re-enabled (around ver. 95.0), you could set this CSS property for firefox UI elements, like:
    -- absolute position bookmarks bar;
    -- search breakout megabar;
    -- tabs, etc.

  • Attached pictures - shows you could use backdrop-filter for UI elements before.

Is that a bug or is there a reason it was disabled for UI elements after re-enabling it?

Checked with Glenn, and this definitely appears to be a regression.

Severity: -- → S3
Priority: -- → P2

Just wanted to let you know that it still broken on Firefox v115/v117nightly.
One thing I noticed that blur rendering works in settings menu.

Forgot to mention that flag "layout.css.backdrop-filter.enabled" is used.

I was poking at some of these effects and found this issue.

Here's a patch that reproduces the issue:

diff --git a/browser/themes/shared/urlbar-searchbar.css b/browser/themes/shared/urlbar-searchbar.css
index b5684c5f6f4b9..a3ff1a8c2b3e4 100644
--- a/browser/themes/shared/urlbar-searchbar.css
+++ b/browser/themes/shared/urlbar-searchbar.css
@@ -242,6 +242,8 @@
 }

 #urlbar[breakout][breakout-extend] > #urlbar-background {
+  background-color: rgba(0, 0, 0, .3);
+  backdrop-filter: blur(10px);
   animation-name: urlbar-grow;
   animation-duration: 0s;
   animation-timing-function: var(--animation-easing-function);

What is going on is that blurring remote tabs (like the new tab page) doesn't work. However blurring same-process tabs like about:config does work.

I thought this could be more general but http://crisal.io/tmp/backdrop-filter-iframe.html indicates this works for content... Glenn, do you know the difference here off-hand? Are top level tabs treated specially by webrender vs. cross-origin iframes? I would've expected them to be somewhat similar from WR's side.

Flags: needinfo?(gwatson)
Summary: Backdrop-filter has not been working for firefox UI elements since it was re-enabled → backdrop-filter doesn't blur remote <browser> element

They will look quite different from WR side (remote tabs get an iframe display item, local tabs get embedded in parent display list). Having said that, I'm not sure why that would make any difference to whether backdrop-filter works on it, so it will need investigation.

Flags: needinfo?(gwatson)

Right, but my point is that in the test-case above (http://crisal.io/tmp/backdrop-filter-iframe.html), I have a local iframe and a remote iframe, and those both work, right?

But yeah maybe there's something weird going on there on the top level display list or something.

I found on reddit that adding clip-path to :root element makes backdrop-filter blur work again on #urlbar-background element.

:root { clip-path: inset(0 round 8px); }

Any updates on this?

hey, so I looked into this because of Zen.

the backdrop-filter breaks when the content underneath it is in an OOP iframe. so the blur sees only the parent chrome background, ignoring the iframe's pixels.

cause:
in gfx/wr/webrender/src/scene_building.rs, the WebRender inserts a tile-cache barrier both before and after traversing a root (OOP) iframe. the post-iframe barrier splits chrome content into a separate tile-cache surface, and any subsequent backdrop-filter can't sample the iframe's pixels, since they're on a different surface.

fix:
remove the post-iframe barrier only (the pre-iframe barrier stays). this keeps chrome content in the same tile-cache slice as the iframe so backdrop-filter can reach across the boundary.

verified locally. [screenshot] (https://postimg.cc/xq82GbjJ) test with backdrop-filter:invert(1) inverts the OOP iframe's pixel colors. the clip-path workaround from Comment 8 (:root { clip-path: inset(0 round 8px) }) works because it forces a new tile cache slice that happens to include the iframe.

patch:

diff --git a/gfx/wr/webrender/src/scene_building.rs b/gfx/wr/webrender/src/scene_building.rs
--- a/gfx/wr/webrender/src/scene_building.rs
+++ b/gfx/wr/webrender/src/scene_building.rs
@@ -1083,7 +1083,6 @@
                     if self.iframe_size.is_empty() {
                         assert!(self.root_iframe_clip.is_some());
                         self.root_iframe_clip = None;
-                        self.add_tile_cache_barrier_if_needed(SliceFlags::empty());
                     }
 
                     self.id_to_index_mapper_stack.pop().unwrap();
@@ -1335,8 +1334,10 @@
             SpatialNodeUid::root_scroll_frame(iframe_pipeline_id, instance_id),
         );
 
-        // If this is a root iframe, force a new tile cache both before and after
-        // adding primitives for this iframe.
+        // If this is a root iframe, force a new tile cache before adding
+        // primitives for this iframe. Keep the post-iframe content in the same
+        // tile cache so backdrop-filters in chrome/parent content can read back
+        // pixels from the visually preceding remote iframe surface.
         if self.iframe_size.is_empty() {
             assert!(self.root_iframe_clip.is_none());
             self.root_iframe_clip = Some(ClipId::root(iframe_pipeline_id));
diff --git a/gfx/wr/wrench/reftests/filters/backdrop-filter-root-iframe.yaml b/gfx/wr/wrench/reftests/filters/backdrop-filter-root-iframe.yaml
new file mode 100644
--- /dev/null
+++ b/gfx/wr/wrench/reftests/filters/backdrop-filter-root-iframe.yaml
@@ -0,0 +1,19 @@
+# Verify that a backdrop-filter following a root iframe can sample the iframe's
+# rendered pixels.
+---
+root:
+  items:
+    - type: iframe
+      id: [1, 2]
+      bounds: [0, 0, 100, 100]
+      clip-rect: [0, 0, 100, 100]
+    - type: backdrop-filter
+      bounds: [0, 0, 100, 100]
+      filters: invert(1)
+
+pipelines:
+  - id: [1, 2]
+    items:
+      - type: rect
+        bounds: [0, 0, 100, 100]
+        color: red
diff --git a/gfx/wr/wrench/reftests/filters/backdrop-filter-root-iframe-ref.yaml b/gfx/wr/wrench/reftests/filters/backdrop-filter-root-iframe-ref.yaml
new file mode 100644
--- /dev/null
+++ b/gfx/wr/wrench/reftests/filters/backdrop-filter-root-iframe-ref.yaml
@@ -0,0 +1,6 @@
+---
+root:
+  items:
+    - type: rect
+      bounds: [0, 0, 100, 100]
+      color: cyan
diff --git a/gfx/wr/wrench/reftests/filters/reftest.list b/gfx/wr/wrench/reftests/filters/reftest.list
--- a/gfx/wr/wrench/reftests/filters/reftest.list
+++ b/gfx/wr/wrench/reftests/filters/reftest.list
@@ -64,6 +64,7 @@
 skip_on(android,device) skip_on(win) fuzzy(1,104) fuzzy-if(platform(swgl),4,18484) == filter-blur-scaled-xonly.yaml filter-blur-scaled-xonly.png  # fails on  Pixel2
 == svg-filter-flood.yaml svg-filter-flood-ref.yaml
 == backdrop-filter-basic.yaml backdrop-filter-basic-ref.yaml
+== backdrop-filter-root-iframe.yaml backdrop-filter-root-iframe-ref.yaml
 platform(linux,mac) == backdrop-filter-perspective.yaml backdrop-filter-perspective.png
 == backdrop-filter-on-child-surface.yaml backdrop-filter-on-child-surface-ref.yaml
 == backdrop-filter-clip-mask.yaml backdrop-filter-clip-mask-ref.yaml

But it is important for web content to be on its own cache slice for all sorts of things like scrolling performance, so doing that unconditionally is not a viable fix.

What's not very clear to me is how it does work across iframes but not for browser elements

Assignee: nobody → cheff
Attachment #9646447 - Attachment description: Bug 1799334 - Let backdrop-filter read back content from lower picture cache slices → Bug 1799334 - Let backdrop-filter read back content from lower picture cache slices. r?#gfx-reviewers
Status: UNCONFIRMED → ASSIGNED
Ever confirmed: true
Attachment #9646448 - Attachment description: Bug 1799334 - Add reftests for cross slices → Bug 1799334 - Add reftests for cross slices. r?#gfx-reviewers
Attachment #9646447 - Attachment description: Bug 1799334 - Let backdrop-filter read back content from lower picture cache slices. r?#gfx-reviewers → Bug 1799334 - Let backdrop-filter read back content from lower picture cache slices. r?#gfx-reviewers,gw
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: