Bug 233421

Summary: Compositing/paint invalidation with transforms
Product: WebKit Reporter: Sam Sneddon [:gsnedders] <gsnedders>
Component: CompositingAssignee: Simon Fraser (smfr) <simon.fraser>
Status: RESOLVED FIXED    
Severity: Normal CC: changseok, esprehn+autocc, ews-watchlist, fred.wang, glenn, kondapallykalyan, pdr, simon.fraser, webkit-bug-importer, zalan
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: Unspecified   
OS: Unspecified   
URL: https://codepen.io/BrianCross/pen/wvqZPEq
Attachments:
Description Flags
Simple testcase
none
Patch
zalan: review+, ews-feeder: commit-queue-
Patch none

Description Sam Sneddon [:gsnedders] 2021-11-22 06:52:01 PST
Noticed on Twitter, and I've not actually verified this on iOS myself, but apparently the above doesn't work properly on iOS 15.
Comment 1 Radar WebKit Bug Importer 2021-11-29 06:52:24 PST
<rdar://problem/85814854>
Comment 2 Simon Fraser (smfr) 2022-02-22 15:03:08 PST
I can reproduce on iPad and iPhone, but not on macOS.
Comment 3 Simon Fraser (smfr) 2022-02-23 14:58:35 PST
Created attachment 453033 [details]
Simple testcase
Comment 4 Simon Fraser (smfr) 2022-02-23 15:29:41 PST
The bug is that when the layer becomes composited due to the translate3d(), we repaint the layer it used to paint into, but do so using the new scale, thus using a repaint rect that is too small.
Comment 5 Simon Fraser (smfr) 2022-02-23 21:36:32 PST
Trying to use the cached repaint rects on RenderLayer fixes this bug, but exposes an issue in compositing/shared-backing/repaint-into-shared-backing.html where we've cached a bad repaint rect.

This happens during a RenderLayerCompositor::computeCompositingRequirements() traversal where we have some backing sharing going on. In that test, the layer paint order tree looks like:

S---------C-c-- -- -b---- -g---s 4 4 0x685058cf0 (0,0) width=990 height=820 [SA 0x68507c7c0] (layerID 47) {sc 5} RenderView 0x6870007d0
S-----------c-- -- -b---- -g---- 4 4   + 0x685059670 (0,0) width=990 height=444 [SA 0x68507c900] RenderBlock 0x687001680 HTML 0x687001000
-NO-------CP--- -- ------ ---c-- 4 5     n 0x6850597a0 (18,10) width=524 height=424 [SA 0x68507c9a0] (layerID 53) {sc 6} RenderBlock 0x687004350 DIV 0x687006c10 class='container'
S----------p-s- -- -b---- -g---- 5 5     + 0x6850598d0 (12,12) width=2000 height=0 RenderBlock (relative positioned) 0x687004470 DIV 0x687006ca0 class='wrapper'
S-O----------s- -- -b---- -gkcx- 5 5       + 0x685059a00 (0,0) width=2040 height=290 [SA 0x68507ca40] RenderBlock (positioned) 0x687004590 DIV 0x687006e10 class='positioned'
S-----T------s- -- ------ --k-x- 5 5         + 0x685059b30 (20,38) width=300 height=200 RenderBlock (relative positioned) 0x687004720 DIV 0x687006ea0 class='inner'

Note that 0x6850597a0 Provides backing (P), and 0x6850598d0 shares it (p). During the traversal, this is temporarily undone so 0x6850598d0 appears non-composited.

Now style changes so that 0x685059a00 becomes non-composited; we recompute its repaint rects (computeRepaintRectsIncludingDescendants()), finding the RenderView as the repaint container, so compute repaint rects relative to it. So 0x685059a00 and 0x685059b30 get cached repaint rects relative to the root.

Now we end the backing sharing sequence, 0x6850598d0 shares backing once again, so becomes the repaint container for 0x685059a00 and 0x685059b30. But in RenderLayerBacking::setBackingSharingLayers() we don't think the backing sharing config has actually changed, so we don't recompute repaint rects.
Comment 6 Simon Fraser (smfr) 2022-02-24 16:10:06 PST
Created attachment 453148 [details]
Patch
Comment 7 Simon Fraser (smfr) 2022-02-28 15:39:19 PST
Created attachment 453442 [details]
Patch
Comment 8 EWS 2022-02-28 20:55:31 PST
Committed r290628 (247901@main): <https://commits.webkit.org/247901@main>

All reviewed patches have been landed. Closing bug and clearing flags on attachment 453442 [details].