Bug 270567 - Incorrect filter primitive area with tiling
Summary: Incorrect filter primitive area with tiling
Status: NEW
Alias: None
Product: WebKit
Classification: Unclassified
Component: SVG (show other bugs)
Version: Other
Hardware: Unspecified All
: P2 Normal
Assignee: Nobody
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2024-03-06 01:54 PST by ana.tudor.lhnh
Modified: 2024-09-07 11:58 PDT (History)
6 users (show)

See Also:


Attachments
The result in a demo after also applying a feTile in Epiphany (left) vs. Chrome (right) (73.27 KB, image/png)
2024-03-06 01:54 PST, ana.tudor.lhnh
no flags Details
What happens on resizing the viewport. (232.85 KB, image/gif)
2024-03-06 02:02 PST, ana.tudor.lhnh
no flags Details
Test (668 bytes, text/html)
2024-09-06 17:24 PDT, Simon Fraser (smfr)
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description ana.tudor.lhnh 2024-03-06 01:54:29 PST
Created attachment 470200 [details]
The result in a demo after also applying a feTile in Epiphany (left) vs. Chrome (right)

Consider a square element (which also gets a checkerboard background pattern to make things more obvious).

Consider an SVG filter applied on it, the only primitive being a `feComposite` with a `height` attribute set to a quarter of the filter area.

```
  <svg width="0" height="0">
    <filter id="f" primitiveUnits="objectBoundingBox" x="0" y="0" width="100%" height="100%">
      <feComposite height="0.25"/>
    </filter>
  </svg>
```

Live test https://codepen.io/thebabydino/pen/ExJVgLo?editors=1000

I would expect the output to be the top quarter of the filter area, but that's not what happens.

Note that I've only tested via Epiphany on Ubuntu and asking around (one https://twitter.com/anatudor/status/1765305940977336376 + two https://bsky.app/profile/anatudor.bsky.social/post/3kmze7a3hrk2p) about what it looks like in actual Safari, the results are all over the place: no filter applied, same result as in Chrome and Firefox or same result as I'm getting in Epiphany.

This is a very big problem if I want to have a `feTile` after that `feComposite` (see atachment).

After refresh and resize, Epiphany also shows me the same result as in Chrome and Firefox. However, if I switch to a different CodePen view, I see the same broken result as at first.
Comment 1 ana.tudor.lhnh 2024-03-06 02:02:23 PST
Created attachment 470201 [details]
What happens on resizing the viewport.

The problem seems to depend on the viewport.
Comment 2 Alexey Proskuryakov 2024-03-06 09:12:58 PST
I sometimes see the bad rendering in Safari on first load, or when switching back to the codepen tab. Once it's drawn properly, resizing doesn't break it.
Comment 3 Radar WebKit Bug Importer 2024-03-06 09:13:07 PST
<rdar://problem/124145301>
Comment 4 Said Abou-Hallawa 2024-03-12 18:12:32 PDT
This is fixed by the PR of bug 265465. This PR sets the geometry of the referenced SVG filter correctly.

*** This bug has been marked as a duplicate of bug 265465 ***
Comment 5 Said Abou-Hallawa 2024-04-10 13:14:53 PDT
The final https://github.com/WebKit/WebKit/pull/25512 does not fix this bug.
Comment 6 Simon Fraser (smfr) 2024-09-06 17:24:10 PDT
Created attachment 472484 [details]
Test
Comment 7 Simon Fraser (smfr) 2024-09-06 17:28:24 PDT
The test case shows that we're re-applying the effect at the top of a lower tile, because we've got the clip rect confused with the effect rect.
Comment 8 Simon Fraser (smfr) 2024-09-06 21:56:54 PDT
This happens on various different operators (feBlend, feOffset, feComposited) when the height attribute is specified.
Comment 9 Simon Fraser (smfr) 2024-09-07 11:39:46 PDT
Also reproduces with a simple feImage filter split across tile boundaries. This only reproduces with SVG filters referenced from CSS, not in pure SVG.

The fundamental problem is that some clipped rectangle is feeding into the computation of the primitiveSubregion.
Comment 10 Simon Fraser (smfr) 2024-09-07 11:57:25 PDT
We conflate the dirty rect with the primitiveSubregion in:
RenderLayerFilters::beginFilterEffect:
  m_filterRegion is clipped to the dirty rect, and feeds into filter.setFilterRegion() and GraphicsContextSwitcher::create()'s sourceImageRect

createReferenceFilter():
  filterRegion.intersect(inflatedDirtyRect)
Comment 11 Simon Fraser (smfr) 2024-09-07 11:58:30 PDT
We need a really surgical separation of clipping rects vs. filter regions. Even `Filter` probably needs to track them separately.