Closed Bug 1578851 Opened 6 years ago Closed 6 years ago

WebVR immersive mode broken on android when e10s is enabled

Categories

(Core :: WebVR, defect, P1)

Unspecified
Android
defect

Tracking

()

RESOLVED FIXED
mozilla72
Tracking Status
firefox72 --- fixed

People

(Reporter: rbarker, Assigned: daoshengmu)

References

Details

Attachments

(1 file)

On android the following always returns false when e10s is enabled:
https://searchfox.org/mozilla-central/rev/e5327b05c822cdac24e233afa37d72c0552dbbaf/gfx/vr/VRManager.cpp#1049
This causes skipPaint to always be false here:
https://searchfox.org/mozilla-central/rev/e5327b05c822cdac24e233afa37d72c0552dbbaf/layout/base/nsRefreshDriver.cpp#2136

Because of this, the refresh driver bails out early and many callbacks are not invoked.

The priority flag is not set for this bug.
:kip, could you have a look please?

For more information, please visit auto_nag documentation.

Flags: needinfo?(kgilbert)

I am going to work on this.

Assignee: nobody → dmu
Flags: needinfo?(kgilbert)
Priority: -- → P1

(In reply to Randall Barker [:rbarker] from comment #0)

On android the following always returns false when e10s is enabled:
https://searchfox.org/mozilla-central/rev/e5327b05c822cdac24e233afa37d72c0552dbbaf/gfx/vr/VRManager.cpp#1049
This causes skipPaint to always be false here:
https://searchfox.org/mozilla-central/rev/e5327b05c822cdac24e233afa37d72c0552dbbaf/layout/base/nsRefreshDriver.cpp#2136

Because of this, the refresh driver bails out early and many callbacks are not invoked.

https://chromatic.funktroniclabs.com/ actually returns true when running https://searchfox.org/mozilla-central/rev/e5327b05c822cdac24e233afa37d72c0552dbbaf/gfx/vr/VRManager.cpp#1049 in e10s.

I am going to investigate other potential issues.

The difference between Android and desktop doing immersive mode is we don't use CompositorVsyncScheduler in Android.

For doing animation in WebVR, there are couple of ways can do the update. I have checked VRFrameData.Timestamp() is increased progressively, and VRManagerChild::RunFrameRequestCallbacks() also be executed properly, its timeStamp for running callbacks is increased as well.

So, one last place to do animation is nsGlobalWindowInner::RequestAnimationFrame(). I notice it doesn't call nsRefreshDriver::RunFrameRequestCallbacks() in e10s mode, non-e10s mode does. Both of e10s and non-e10s have HTMLCanvasElement::InvalidateCanvasContent that comes from WebGLContext::Clear()to call nsIFrame::InvalidateLayer(). It will ask mRootRefreshDrivers to repaint layers in nsRefreshDriver. I think this is the root cause.

We get stuck at nsRefreshDriver::IsWaitingForPaint() [1]. It looks like we spend too much time at LayerTransaction in e10s mode.

[1] https://searchfox.org/mozilla-central/source/layout/base/nsRefreshDriver.cpp#2377

There should not be any paint when in immersive mode. Please re-read the original comment in the bug.

(In reply to Randall Barker [:rbarker] from comment #6)

There should not be any paint when in immersive mode. Please re-read the original comment in the bug.

We can't use VRManager::Get() in the tab process. It is only able to be instanced in the parent process or GPU process in Windows. That is why it always returns false from IsPresenting().

We need an alternative then. We need to short circuit painting in the content process.

See Also: → 1586110

Move r? from :mattwoodrow to :mstange because the original skipPaint patch was reviewed by :mstange.

See Also: → 1586405

Sorry for the long delay. I'm trying to make sense of this bug.

The original purpose of the skipPaint check was an optimization: If we don't need to paint, skip the paint. It should not have affected correctness. If skipPaint is false more often than before, that should only cause extra work but be otherwise harmless. The only danger would be if skipPaint returned true in cases where it shouldn't. But that's not the case. So the description in comment 0 is not accurate.

The real description of what's broken here is given in comment 5: We don't run the refresh driver tick in immersive mode because we don't get notifications from the compositor that composites have happened; we keep waiting for those notifications. This is, as far as I can tell, a bug that's completely independent from the skipPaint check. Please let me know if that's not the case.

So now we have two reasons to check whether we're in immersive mode:

  1. Don't paint if we're in immersive mode. This is just an optimization.
  2. Don't wait for notifications from the compositor that we've composited. This is a correctness issue.

However, I think a better fix would be to deliver notifications correctly even during immersive mode. The IsWaitingForPaint(aNowTime) check is there to make sure that content doesn't get more than two frames ahead of what's on the screen. I think this method of back-pressure is useful even in immersive mode. But it can only work if content is notified when things end up on the screen in immersive mode.

Since this bug is time-critical and needs a fix now, I'm going to accept the current fix (but with a variable rename). But I think the better fix would be to make IsWaitingForPaint work correctly in immersive mode.

Pushed by dmu@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/d4b62d6f1e64 Using VRManagerChild to check isPresenting to skip painting in nsRefreshDriver. r=rbarker,imanol,mstange
Status: NEW → RESOLVED
Closed: 6 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla72

(In reply to Markus Stange [:mstange] from comment #12)

Sorry for the long delay. I'm trying to make sense of this bug.

The original purpose of the skipPaint check was an optimization: If we don't need to paint, skip the paint. It should not have affected correctness. If skipPaint is false more often than before, that should only cause extra work but be otherwise harmless. The only danger would be if skipPaint returned true in cases where it shouldn't. But that's not the case. So the description in comment 0 is not accurate.

The real description of what's broken here is given in comment 5: We don't run the refresh driver tick in immersive mode because we don't get notifications from the compositor that composites have happened; we keep waiting for those notifications. This is, as far as I can tell, a bug that's completely independent from the skipPaint check. Please let me know if that's not the case.

So now we have two reasons to check whether we're in immersive mode:

  1. Don't paint if we're in immersive mode. This is just an optimization.
  2. Don't wait for notifications from the compositor that we've composited. This is a correctness issue.

However, I think a better fix would be to deliver notifications correctly even during immersive mode. The IsWaitingForPaint(aNowTime) check is there to make sure that content doesn't get more than two frames ahead of what's on the screen. I think this method of back-pressure is useful even in immersive mode. But it can only work if content is notified when things end up on the screen in immersive mode.

Since this bug is time-critical and needs a fix now, I'm going to accept the current fix (but with a variable rename). But I think the better fix would be to make IsWaitingForPaint work correctly in immersive mode.

Agree. That makes senses with what I got from my investigation.

You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: