New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 840075 link

Starred by 2 users

Issue metadata

Status: Available
Owner: ----
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Linux
Pri: 2
Type: Bug



Sign in to add a comment

Display compositor stops with object-fit:contain on an animated 2d canvas

Reported by ajohn...@draster.com, May 5 2018

Issue description

UserAgent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36

Steps to reproduce the problem:
1. Go to: http://jsfiddle.net/uk7jvr6o/11/
2. Draw on the white canvas by making long, swirly strokes - do not release your mouse button for at least 10 seconds.

What is the expected behavior?
A line being drawn that does not lag behind the cursor more than 60ms or so.

What went wrong?
The line sometimes lags behind the cursor by one second or more.

Here is a video showing the issue:
https://youtu.be/RK8QKim4uWs

Did this work before? N/A 

Chrome version: 68.0.3409.2  Channel: canary
OS Version: Ubuntu 14.04
Flash Version: 

Please watch the video (2 minutes): https://youtu.be/RK8QKim4uWs

The code responsible for calling beginPath(), stroke(), etc for this jsfiddle can be found here around line 4281:
https://github.com/fabricjs/fabric.js/blob/v2.2.3/dist/fabric.js#L4281

The problem only seems to happen when using object-fit:contain (as shown in the video, I comment it out and the problem goes away) 

Disabling 2d accelerated canvas seems to work around the problem (and shown in the video).

The problem does not happen in Firefox.

I don't know whether this is a regression.

I have had colleagues confirm that the issue exists on Windows chrome as well.
 
I've had a chance to try this on windows and the results are even worse than they are on linux -- entire line segments appear to be missing, and they never show up even if you wait for many seconds. Basically, you get a corrupt result.

I've attached an animated gif showing a windows result.

fitContainLaptop.gif
143 KB View Download

Comment 2 Deleted

Just so you don't have to dig through the fabricjs code, here's a pure js repro with no libraries:
http://jsfiddle.net/n7nebbL8/16/

Expected behavior upon clicking 'Run':
Diagonal line should be slowly drawn from upper-left corner to lower right corner. There should be no gaps, lag, or stopages when the line is being drawn. The performance should be quite smooth.

Actual behavior:
The line drawing stops for long periods of time (500ms or more) part way through or is missing many segments.

Notes:
The bug happens slightly differently on windows than it does on linux, but there are similar problems on both platforms.
The bug doesn't happen if Hardware Accelerated 2D Canvas is disabled in chrome://flags
The bug doesn't happen in FF.
The bug appears sooner if the canvas is squeezed more.
So if a 1000px canvas is squeezed in a 200px container, you see it almost immediately.
Andrea updated the fiddlejs with a smaller container size to illustrate his point about smaller containers. If you have trouble reproducing the bug with the earlier examples, try this one:
http://jsfiddle.net/n7nebbL8/17/
Labels: Needs-Triage-M68

Comment 7 by bokan@chromium.org, May 7 2018

Components: -Blink Blink>Canvas
I can repro in 68.0.3418.2 on Linux. Trace attached.

Looks like mouse moves are getting to the renderer just fine. Around second 15, lasting for about 3.5 seconds, the browser stops drawing frames. Perhaps canvas is somehow not notifying the compositor that new frames need to be produced?
trace_canvasdraw.json.gz
6.2 MB Download

Comment 8 by bokan@chromium.org, May 7 2018

Cc: bokan@chromium.org
Status: Untriaged (was: Unconfirmed)
I should note that this exact issue is also present in webkit, which could mean that this bug has been around for quite a while. (blink forked webkit in 2013 correct?)
Cc: junov@chromium.org
Components: -Blink>Canvas Internals>Compositing
Summary: Display compositor stops with object-fit:contain on an animated 2d canvas (was: Canvas delayed drawing on stroke() call with object-fit:contain)
I notice that we also see image filtering flicker (jaggies!)
Also, the bug has nothing to do with path rendering.  I modified the fiddle to use fillRect instead -> same bug.  The bug is really just about animation + object-fit.

The trace shows that it is business as usual on the main thread of render process (Canvas2DLayerBridge continues to flush work to the GPU, and commit frames).  The blink compositor is also doing the same work as usual, but the display compositor stops.  Perhaps the display compositor scheduler is getting in a bad state? OR the layer tree is not processing invalidations correctly.  Someone from the compositing team needs to look at this.

Triaging to the compositing component for further investigation.

Components: Internals>Services>Viz
Owner: danakj@chromium.org
Status: Assigned (was: Untriaged)
Yup, definitely a display compositor scheduling issue.
Cc: sunn...@chromium.org briander...@chromium.org enne@chromium.org
I can reproduce also. During the window where the display stops drawing, DisplayScheduler::ProcessSurfaceDamage() is continually called but with |display_damaged|=false, so we don't trigger any begin frames for the display scheduler.
What I see in the trace, and locally, is that the renderer cc keeps trying to produce frames (LayerTreeHostImpl::PrepareToDraw), but early outs because of no damage, sends an ack to the display, which sees no damage and does not draw.

So damage isn't being generated/reported correctly to/in the renderer cc.
Cc: weiliangc@chromium.org
When it's working:

[1:1:0515/141022.325085:ERROR:layer.cc(1107)] SetNeedsDisplayRect 243,240 43x16
[1:1:0515/141022.325496:ERROR:texture_layer.cc(107)] SetTransferableResourceInternal
[1:1:0515/141022.325984:ERROR:texture_layer.cc(107)] SetTransferableResourceInternal
[1:9:0515/141022.327296:ERROR:layer_tree_host_impl.cc(936)] root damage 320,249 43x16
[1:9:0515/141022.327603:ERROR:layer_tree_host_impl.cc(1928)] DrawLayers with damage
[1:9:0515/141022.328304:ERROR:scheduler_state_machine.cc(1231)] $$ DidSubmitCompositorFrame


When it's not:

[1:1:0515/141022.791533:ERROR:layer.cc(1107)] SetNeedsDisplayRect 363,217 13x17
[1:1:0515/141022.791887:ERROR:texture_layer.cc(107)] SetTransferableResourceInternal
[1:1:0515/141022.792275:ERROR:texture_layer.cc(107)] SetTransferableResourceInternal
[1:9:0515/141022.793103:ERROR:layer_tree_host_impl.cc(936)] root damage 0,0 0x0
[1:9:0515/141022.793261:ERROR:layer_tree_host_impl.cc(1924)] DrawLayers no damage

The texture layer is setting damage every frame. But the damage tracker seems to not notice it sometimes?
Working:

[1:1:0515/142729.593077:ERROR:layer.cc(1107)] SetNeedsDisplayRect 329,159 19x27
[1:1:0515/142729.593342:ERROR:texture_layer.cc(107)] SetTransferableResourceInternal
[1:1:0515/142729.593608:ERROR:texture_layer.cc(107)] SetTransferableResourceInternal
[1:9:0515/142729.594276:ERROR:damage_tracker.cc(116)] 0x234f8cd1b200 contributes 0
[1:9:0515/142729.594402:ERROR:damage_tracker.cc(116)] 0x234f8cd1b500 contributes 0
[1:9:0515/142729.594505:ERROR:damage_tracker.cc(116)] 0x234f8cd1b800 contributes 1
[1:9:0515/142729.594620:ERROR:damage_tracker.cc(394)] maybe layer damage 0,0 0x0 for bounds 485x350
[1:9:0515/142729.594737:ERROR:damage_tracker.cc(116)] 0x234f8cd1a000 contributes 1
[1:9:0515/142729.594840:ERROR:damage_tracker.cc(394)] maybe layer damage 0,0 0x0 for bounds 471x336
[1:9:0515/142729.594918:ERROR:damage_tracker.cc(116)] 0x234f8cd19500 contributes 1
[1:9:0515/142729.594987:ERROR:damage_tracker.cc(394)] maybe layer damage 0,0 0x0 for bounds 334x334
[1:9:0515/142729.595051:ERROR:damage_tracker.cc(116)] 0x234f8cc92200 contributes 1
[1:9:0515/142729.595114:ERROR:damage_tracker.cc(394)] maybe layer damage 0,0 0x0 for bounds 471x336
[1:9:0515/142729.595178:ERROR:damage_tracker.cc(116)] 0x234f8cde9a80 contributes 1
[1:9:0515/142729.595239:ERROR:damage_tracker.cc(394)] maybe layer damage 329,159 19x27 for bounds 334x334   <------------
[1:9:0515/142729.595304:ERROR:damage_tracker.cc(398)] layer damage 329,159 5x27
[1:9:0515/142729.595364:ERROR:damage_tracker.cc(401)] layer damage in target 406,168 5x27
[1:9:0515/142729.595424:ERROR:damage_tracker.cc(116)] 0x234f8cd1a600 contributes 0
[1:9:0515/142729.595483:ERROR:damage_tracker.cc(116)] 0x234f8cd1a900 contributes 0
[1:9:0515/142729.595542:ERROR:damage_tracker.cc(116)] 0x234f8cd34600 contributes 1
[1:9:0515/142729.595602:ERROR:damage_tracker.cc(394)] maybe layer damage 0,0 0x0 for bounds 15x334
[1:9:0515/142729.595667:ERROR:layer_tree_host_impl.cc(936)] root damage 406,168 5x27
[1:9:0515/142729.595768:ERROR:layer_tree_host_impl.cc(1928)] DrawLayers with damage

Not working, next frame:

[1:1:0515/142729.610036:ERROR:layer.cc(1107)] SetNeedsDisplayRect 346,134 32x26
[1:1:0515/142729.610378:ERROR:texture_layer.cc(107)] SetTransferableResourceInternal
[1:1:0515/142729.610756:ERROR:texture_layer.cc(107)] SetTransferableResourceInternal
[1:9:0515/142729.611529:ERROR:damage_tracker.cc(116)] 0x234f8cd1b200 contributes 0
[1:9:0515/142729.611701:ERROR:damage_tracker.cc(116)] 0x234f8cd1b500 contributes 0
[1:9:0515/142729.611792:ERROR:damage_tracker.cc(116)] 0x234f8cd1b800 contributes 1
[1:9:0515/142729.611882:ERROR:damage_tracker.cc(394)] maybe layer damage 0,0 0x0 for bounds 485x350
[1:9:0515/142729.611966:ERROR:damage_tracker.cc(116)] 0x234f8cd1a000 contributes 1
[1:9:0515/142729.612046:ERROR:damage_tracker.cc(394)] maybe layer damage 0,0 0x0 for bounds 471x336
[1:9:0515/142729.612119:ERROR:damage_tracker.cc(116)] 0x234f8cd19500 contributes 1
[1:9:0515/142729.612189:ERROR:damage_tracker.cc(394)] maybe layer damage 0,0 0x0 for bounds 334x334
[1:9:0515/142729.612253:ERROR:damage_tracker.cc(116)] 0x234f8cc92200 contributes 1
[1:9:0515/142729.612317:ERROR:damage_tracker.cc(394)] maybe layer damage 0,0 0x0 for bounds 471x336
[1:9:0515/142729.612381:ERROR:damage_tracker.cc(116)] 0x234f8cde9a80 contributes 1
[1:9:0515/142729.612445:ERROR:damage_tracker.cc(394)] maybe layer damage 346,134 32x26 for bounds 334x334  <-----------------
[1:9:0515/142729.612508:ERROR:damage_tracker.cc(116)] 0x234f8cd1a600 contributes 0
[1:9:0515/142729.612570:ERROR:damage_tracker.cc(116)] 0x234f8cd1a900 contributes 0
[1:9:0515/142729.612633:ERROR:damage_tracker.cc(116)] 0x234f8cd34600 contributes 1
[1:9:0515/142729.612696:ERROR:damage_tracker.cc(394)] maybe layer damage 0,0 0x0 for bounds 15x334
[1:9:0515/142729.612764:ERROR:layer_tree_host_impl.cc(936)] root damage 0,0 0x0
[1:9:0515/142729.612856:ERROR:layer_tree_host_impl.cc(1924)] DrawLayers no damage

Then, in a later bad frame:

[1:1:0515/142730.177432:ERROR:layer.cc(1107)] SetNeedsDisplayRect 397,286 5x5
[1:1:0515/142730.177722:ERROR:texture_layer.cc(107)] SetTransferableResourceInternal
[1:1:0515/142730.178035:ERROR:texture_layer.cc(107)] SetTransferableResourceInternal
[1:9:0515/142730.178826:ERROR:damage_tracker.cc(116)] 0x234f8cd1b200 contributes 0
[1:9:0515/142730.178976:ERROR:damage_tracker.cc(116)] 0x234f8cd1b500 contributes 0
[1:9:0515/142730.179060:ERROR:damage_tracker.cc(116)] 0x234f8cd1b800 contributes 1
[1:9:0515/142730.179139:ERROR:damage_tracker.cc(394)] maybe layer damage 0,0 0x0 for bounds 485x350
[1:9:0515/142730.179219:ERROR:damage_tracker.cc(116)] 0x234f8cd1a000 contributes 1
[1:9:0515/142730.179302:ERROR:damage_tracker.cc(394)] maybe layer damage 0,0 0x0 for bounds 471x336
[1:9:0515/142730.179382:ERROR:damage_tracker.cc(116)] 0x234f8cd19500 contributes 1
[1:9:0515/142730.179453:ERROR:damage_tracker.cc(394)] maybe layer damage 0,0 0x0 for bounds 334x334
[1:9:0515/142730.179516:ERROR:damage_tracker.cc(116)] 0x234f8cc92200 contributes 1
[1:9:0515/142730.179579:ERROR:damage_tracker.cc(394)] maybe layer damage 0,0 0x0 for bounds 471x336
[1:9:0515/142730.179643:ERROR:damage_tracker.cc(116)] 0x234f8cde9a80 contributes 1
[1:9:0515/142730.179704:ERROR:damage_tracker.cc(394)] maybe layer damage 346,116 122x176 for bounds 334x334   <------
[1:9:0515/142730.179768:ERROR:damage_tracker.cc(116)] 0x234f8cd1a600 contributes 0
[1:9:0515/142730.179829:ERROR:damage_tracker.cc(116)] 0x234f8cd1a900 contributes 0
[1:9:0515/142730.179890:ERROR:damage_tracker.cc(116)] 0x234f8cd34600 contributes 1
[1:9:0515/142730.179955:ERROR:damage_tracker.cc(394)] maybe layer damage 0,0 0x0 for bounds 15x334

We've been continuing to union the damage rects from the main thread, but they aren't in the layer's bounds so we don't use them.

Wait actually.. if you just try to draw in the right 1/4 of the canvas or so, it doesn't appear until your mouse moves into the left 3/4. Because the that's outside of the cc layer bounds... but somehow not outside of what we see on screen.

So this doesn't appear to be related to time or anything, merely the position and after ~10s of drawing you eventually end up in the right side of the canvas.
Cc: danakj@chromium.org
Components: -Internals>Compositing -Internals>Services>Viz Blink>Canvas Blink>Compositing
Owner: junov@chromium.org
The web inspector shows me a canvas of size, eg 480x392 px. But the cc layer being damaged by blink will always be exactly a square: 392x392 in this case.

Another size example: The inspector shows a 480x530 px canvas. But the cc layer is 480x480 px.

So in the first case, damage on the right does not cause redraws. In the second case, damage on the bottom does not cause redraws.

Here's an example, with the layer ids. The 11 layer is the size the inspector shows, and is where we are drawing the lines. But the 12 layer is where we are setting damage. The 11 layer gets some initial damage and then none as we draw, only layer 12 gets it.

[1:1:0515/145202.999013:ERROR:layer.cc(289)] 11 SetBounds 494x446
[1:1:0515/145202.999275:ERROR:layer.cc(289)] 12 SetBounds 444x444
[1:1:0515/145202.999390:ERROR:layer.cc(1109)] 11 SetNeedsDisplayRect 0,0 494x446 for bounds 0,0 494x446
[1:1:0515/145202.999499:ERROR:layer.cc(1109)] 11 SetNeedsDisplayRect 0,0 494x446 for bounds 0,0 494x446
[1:1:0515/145203.000108:ERROR:layer.cc(1109)] 12 SetNeedsDisplayRect 267,272 2x2 for bounds 0,0 444x444
[1:1:0515/145203.095197:ERROR:layer.cc(1109)] 12 SetNeedsDisplayRect 265,272 4x2 for bounds 0,0 444x444
[1:1:0515/145203.123943:ERROR:layer.cc(1109)] 12 SetNeedsDisplayRect 257,272 10x8 for bounds 0,0 444x444
[1:1:0515/145203.141135:ERROR:layer.cc(1109)] 12 SetNeedsDisplayRect 237,279 22x15 for bounds 0,0 444x444

There are 2 canvas's in the inspector so I thought maybe one is each of these layers, but they both have identical bounds in the inspector.

I think it's clear something weird is happening in blink at this point. junov would you like to look further?
It's been over two months and I thought I'd check in... any news?

I tried this again http://jsfiddle.net/n7nebbL8/17/ in Chrome Canary 69.0.3493.3 on linux and windows and the problem does still exist.


Owner: fs...@chromium.org
-> fserb@ since this is canvas related
Cc: -junov@chromium.org
I don't know how much Blink has changed since forking from Webkit, but in case it's relevant:

Webkit has this same bug -- at least in terms of how it manifests -- and it was reported here:
https://bugs.webkit.org/show_bug.cgi?id=187840

They've made a patch here:
https://trac.webkit.org/changeset/234187/webkit
Cc: fs...@chromium.org
Owner: ----
Status: Available (was: Assigned)
Any news?
Components: -Blink>Compositing Internals>Compositing

Sign in to add a comment