Animation of composited layer triggers repaint of page background. |
||||
Issue descriptionChrome Version: 69.0.3493.3 (Official Build) dev (64-bit) OS: All What steps will reproduce the problem? (1) Load http://output.jsbin.com/fakihoq/quiet (2) Click either of the buttons to either do a JS animation or CSS animation of the #cover element offscreen and back. What is the expected result? Expect a smooth animation without repaints. What happens instead? Instead, the background is repainted every frame, which causes expensive raster work.
,
Aug 2
,
Aug 2
This is affecting us on the Cast team, it would be great if someone could look at this.
,
Nov 29
The reason the background of the root re-rasters on every frame is that you can't apply overflow clip to the ViewportDefiningElement: https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/layout/layout_block.cc?type=cs&q=allowsoverflowclip&sq=package:chromium&g=0&l=304 However, you can put contain:layout on the body element, which will remove the re-raster of the background. The reason the raster is gone with this property is that contain:layout prevents layout overflow from being propagated to the root canvas of the webview. The change of the root canvas's layout overflow is what prevents this.
,
Nov 30
Thanks! That's a great tip for anyone running into the issue. How hard would it be / how often do you think we could not grow the root canvas in the presence of overflow: hidden without containment? It think it's a common pattern for application like interfaces and visually usually doesn't change the screen.
,
Dec 3
I looked into this exact question last week and again this morning. The invalidation in the testcase at https://output.jsbin.com/gofoposeme comes from the fact that the generated image for the radial gradient depends on layout overflow, because the background fill layer for the gradient has background-attachment:local (i.e. relative to contents) and has width:auto. I also thought about the optimization you describe: not invalidating if the root has overflow:hidden and also the top-left offset of the background fill layer has not changed. To do this we'd have to plumb whether this condition holds to the invalidation code. Scroll offset (which is possible with overflow:hidden) is I think already invalidated elsewhere, in PaintLayerScrollableArea). Aside regarding scroll: one problem is that overflow:hidden does not actually disallow scroll. e.g. using scrollBy on the element with overflow: hidden does scroll it. scrollBy on the LayoutView directly is not possible because the LayoutView is not in the DOM, but window.scrollBy does scroll it. This is true even if the body is contain: paint. :( It appears there is no way to get rid of layout overflow on the LayoutView completely, or prevent scrolling of it programmatically. This seems quite bad for UIs that don't want scrolling.
,
Dec 3
I tried to prototype this optimization. I don't think it's a reasonable amount of complexity to handle the case of complicated fill backgrounds that sometimes don't depend on the width of the layout overflow, but in general do depend on it. There are just too many performance cliffs and corner cases that the approach fails in. Instead, applying contain:layout to the elements which contain the background and moving them around without invalidating them is the right approach for developers. This gets rid of layout overflow and its associated costs (*). (*) Right now layout overflow is still computed, even under contain:paint, but I don't think it is used for anything. Also, I think the accompanying invalidation machinery incorrectly depends on these layout overflows. Will follow up on that independently.
,
Dec 31
Note: applying overflow:hidden to both <html> and <body> as well as background:white to the <html> also achieves good performance. http://rendering.chrishtr.org/2018/12/ensuring-performance-of-non-scrolled.html |
||||
►
Sign in to add a comment |
||||
Comment 1 by flackr@chromium.org
, Jul 20