Commit 9ebbc362 authored by Klaus Weidner's avatar Klaus Weidner Committed by Commit Bot

Fix rAF handoff on exiting WebVR presentation

If there's an outstanding presenting VSync request when presentation exits,
it must be converted to a normal VSync request for magic window mode.

This fixes a regression introduced by crrev.com/c/817545.

BUG=794266

Change-Id: I93f0739facb702f68c29d8af7c77b669d6b54bda
Reviewed-on: https://chromium-review.googlesource.com/822985Reviewed-by: default avatarBill Orr <billorr@chromium.org>
Reviewed-by: default avatarMichael Thiessen <mthiesse@chromium.org>
Commit-Queue: Klaus Weidner <klausw@chromium.org>
Cr-Commit-Position: refs/heads/master@{#523612}
parent 582b4313
...@@ -200,7 +200,9 @@ void VRDisplay::RequestVSync() { ...@@ -200,7 +200,9 @@ void VRDisplay::RequestVSync() {
DVLOG(2) << __FUNCTION__ DVLOG(2) << __FUNCTION__
<< " start: pending_vrdisplay_raf_=" << pending_vrdisplay_raf_ << " start: pending_vrdisplay_raf_=" << pending_vrdisplay_raf_
<< " in_animation_frame_=" << in_animation_frame_ << " in_animation_frame_=" << in_animation_frame_
<< " did_submit_this_frame_=" << did_submit_this_frame_; << " did_submit_this_frame_=" << did_submit_this_frame_
<< " pending_magic_window_vsync_=" << pending_magic_window_vsync_
<< " pending_presenting_vsync_=" << pending_presenting_vsync_;
if (!pending_vrdisplay_raf_) if (!pending_vrdisplay_raf_)
return; return;
Document* doc = navigator_vr_->GetDocument(); Document* doc = navigator_vr_->GetDocument();
...@@ -208,20 +210,23 @@ void VRDisplay::RequestVSync() { ...@@ -208,20 +210,23 @@ void VRDisplay::RequestVSync() {
return; return;
// If we've switched from magic window to presenting, cancel the Document rAF // If we've switched from magic window to presenting, cancel the Document rAF
// and start the VrPresentationProvider VSync. // and start the VrPresentationProvider VSync.
if (is_presenting_ && pending_vsync_id_ != -1) { if (is_presenting_ && pending_magic_window_vsync_id_ != -1) {
doc->CancelAnimationFrame(pending_vsync_id_); doc->CancelAnimationFrame(pending_magic_window_vsync_id_);
pending_vsync_ = false; pending_magic_window_vsync_ = false;
pending_vsync_id_ = -1; pending_magic_window_vsync_id_ = -1;
} }
if (display_blurred_ || pending_vsync_) if (display_blurred_ || pending_magic_window_vsync_ ||
pending_presenting_vsync_)
return; return;
if (!is_presenting_) { if (!is_presenting_) {
magic_window_provider_->GetPose( magic_window_provider_->GetPose(
WTF::Bind(&VRDisplay::OnMagicWindowPose, WrapWeakPersistent(this))); WTF::Bind(&VRDisplay::OnMagicWindowPose, WrapWeakPersistent(this)));
pending_vsync_ = true; pending_magic_window_vsync_ = true;
pending_vsync_id_ = pending_magic_window_vsync_id_ =
doc->RequestAnimationFrame(new VRDisplayFrameRequestCallback(this)); doc->RequestAnimationFrame(new VRDisplayFrameRequestCallback(this));
DVLOG(2) << __FUNCTION__ << " done: pending_magic_window_vsync_="
<< pending_magic_window_vsync_;
return; return;
} }
DCHECK(vr_presentation_provider_.is_bound()); DCHECK(vr_presentation_provider_.is_bound());
...@@ -240,18 +245,19 @@ void VRDisplay::RequestVSync() { ...@@ -240,18 +245,19 @@ void VRDisplay::RequestVSync() {
// (d) from ProcessScheduledAnimations if a rAF callback finishes without // (d) from ProcessScheduledAnimations if a rAF callback finishes without
// submitting a frame. // submitting a frame.
// //
// These cases are mutually exclusive which prevents duplicate RequestVSync // These cases are mutually exclusive which prevents duplicate GetVSync
// calls. Case (a) only applies outside an animating context // calls. Case (a) only applies outside an animating context
// (in_animation_frame_ is false), and (b,c,d) all require an animating // (in_animation_frame_ is false), and (b,c,d) all require an animating
// context. While in an animating context, submitFrame is called either // context. While in an animating context, submitFrame is called either
// before rAF (b), after rAF (c), or not at all (d). If rAF isn't called at // before rAF (b), after rAF (c), or not at all (d). If rAF isn't called at
// all, there won't be future frames. // all, there won't be future frames.
pending_vsync_ = true; pending_presenting_vsync_ = true;
vr_presentation_provider_->GetVSync( vr_presentation_provider_->GetVSync(
WTF::Bind(&VRDisplay::OnPresentingVSync, WrapWeakPersistent(this))); WTF::Bind(&VRDisplay::OnPresentingVSync, WrapWeakPersistent(this)));
DVLOG(2) << __FUNCTION__ << " done: pending_vsync_=" << pending_vsync_; DVLOG(2) << __FUNCTION__
<< " done: pending_presenting_vsync_=" << pending_presenting_vsync_;
} }
int VRDisplay::requestAnimationFrame(V8FrameRequestCallback* callback) { int VRDisplay::requestAnimationFrame(V8FrameRequestCallback* callback) {
...@@ -265,7 +271,7 @@ int VRDisplay::requestAnimationFrame(V8FrameRequestCallback* callback) { ...@@ -265,7 +271,7 @@ int VRDisplay::requestAnimationFrame(V8FrameRequestCallback* callback) {
// arrive earlier than frame submission, but other than that we want to call // arrive earlier than frame submission, but other than that we want to call
// it as early as possible. See comments inside RequestVSync() for more // it as early as possible. See comments inside RequestVSync() for more
// details on the applicable cases. // details on the applicable cases.
if (!in_animation_frame_ || did_submit_this_frame_) { if (!is_presenting_ || !in_animation_frame_ || did_submit_this_frame_) {
RequestVSync(); RequestVSync();
} }
FrameRequestCallbackCollection::V8FrameCallback* frame_callback = FrameRequestCallbackCollection::V8FrameCallback* frame_callback =
...@@ -988,17 +994,18 @@ void VRDisplay::ProcessScheduledAnimations(double timestamp) { ...@@ -988,17 +994,18 @@ void VRDisplay::ProcessScheduledAnimations(double timestamp) {
pending_vrdisplay_raf_ = false; pending_vrdisplay_raf_ = false;
did_submit_this_frame_ = false; did_submit_this_frame_ = false;
scripted_animation_controller_->ServiceScriptedAnimations(timestamp); scripted_animation_controller_->ServiceScriptedAnimations(timestamp);
if (pending_vrdisplay_raf_ && !did_submit_this_frame_) { // requestAnimationFrame may have deferred RequestVSync, call it now to
DVLOG(2) << __FUNCTION__ << ": vrDisplay.rAF did not submit a frame"; // cover the case where no frame was submitted, or where presentation ended
RequestVSync(); // while servicing the scripted animation.
} RequestVSync();
} }
if (pending_pose_) if (pending_pose_)
frame_pose_ = std::move(pending_pose_); frame_pose_ = std::move(pending_pose_);
// Sanity check: If pending_vrdisplay_raf_ is true and the vsync provider // Sanity check: If pending_vrdisplay_raf_ is true and the vsync provider
// is connected, we must now have a pending vsync. // is connected, we must now have a pending vsync.
DCHECK(!pending_vrdisplay_raf_ || pending_vsync_); DCHECK(!pending_vrdisplay_raf_ || pending_magic_window_vsync_ ||
pending_presenting_vsync_);
} }
void VRDisplay::OnPresentingVSync( void VRDisplay::OnPresentingVSync(
...@@ -1013,7 +1020,7 @@ void VRDisplay::OnPresentingVSync( ...@@ -1013,7 +1020,7 @@ void VRDisplay::OnPresentingVSync(
case device::mojom::blink::VRPresentationProvider::VSyncStatus::CLOSING: case device::mojom::blink::VRPresentationProvider::VSyncStatus::CLOSING:
return; return;
} }
pending_vsync_ = false; pending_presenting_vsync_ = false;
frame_pose_ = std::move(pose); frame_pose_ = std::move(pose);
vr_frame_id_ = frame_id; vr_frame_id_ = frame_id;
...@@ -1034,8 +1041,8 @@ void VRDisplay::OnPresentingVSync( ...@@ -1034,8 +1041,8 @@ void VRDisplay::OnPresentingVSync(
void VRDisplay::OnMagicWindowVSync(double timestamp) { void VRDisplay::OnMagicWindowVSync(double timestamp) {
DVLOG(2) << __FUNCTION__; DVLOG(2) << __FUNCTION__;
pending_vsync_ = false; pending_magic_window_vsync_ = false;
pending_vsync_id_ = -1; pending_magic_window_vsync_id_ = -1;
vr_frame_id_ = -1; vr_frame_id_ = -1;
ProcessScheduledAnimations(timestamp); ProcessScheduledAnimations(timestamp);
} }
...@@ -1049,12 +1056,15 @@ void VRDisplay::OnMagicWindowPose(device::mojom::blink::VRPosePtr pose) { ...@@ -1049,12 +1056,15 @@ void VRDisplay::OnMagicWindowPose(device::mojom::blink::VRPosePtr pose) {
} }
void VRDisplay::OnPresentationProviderConnectionError() { void VRDisplay::OnPresentationProviderConnectionError() {
DVLOG(1) << __FUNCTION__ << ";;; is_presenting_=" << is_presenting_
<< " pending_magic_window_vsync_=" << pending_magic_window_vsync_
<< " pending_presenting_vsync_=" << pending_presenting_vsync_;
vr_presentation_provider_.reset(); vr_presentation_provider_.reset();
if (is_presenting_) { if (is_presenting_) {
ForceExitPresent(); ForceExitPresent();
pending_vsync_ = false;
RequestVSync();
} }
pending_presenting_vsync_ = false;
RequestVSync();
} }
ScriptedAnimationController& VRDisplay::EnsureScriptedAnimationController( ScriptedAnimationController& VRDisplay::EnsureScriptedAnimationController(
......
...@@ -194,11 +194,10 @@ class VRDisplay final : public EventTargetWithInlineData, ...@@ -194,11 +194,10 @@ class VRDisplay final : public EventTargetWithInlineData,
void ProcessScheduledAnimations(double timestamp); void ProcessScheduledAnimations(double timestamp);
void ProcessScheduledWindowAnimations(double timestamp); void ProcessScheduledWindowAnimations(double timestamp);
// In order to help the VR device with scheduling, never request a new VSync // Request delivery of a VSync event for either magic window mode or
// until the current frame is either submitted or abandoned. If vrDisplay.rAF // presenting mode as applicable. May be called more than once per frame, it
// is called earlier, defer the GetVSync until vrDisplay.submitFrame is // ensures that there's at most one VSync request active at a time.
// called. If the rAF callback exits without submitting a frame, call it at // Does nothing if the web application hasn't requested a rAF callback.
// that time.
void RequestVSync(); void RequestVSync();
Member<NavigatorVR> navigator_vr_; Member<NavigatorVR> navigator_vr_;
...@@ -244,8 +243,9 @@ class VRDisplay final : public EventTargetWithInlineData, ...@@ -244,8 +243,9 @@ class VRDisplay final : public EventTargetWithInlineData,
TraceWrapperMember<ScriptedAnimationController> TraceWrapperMember<ScriptedAnimationController>
scripted_animation_controller_; scripted_animation_controller_;
bool pending_vrdisplay_raf_ = false; bool pending_vrdisplay_raf_ = false;
bool pending_vsync_ = false; bool pending_presenting_vsync_ = false;
int pending_vsync_id_ = -1; bool pending_magic_window_vsync_ = false;
int pending_magic_window_vsync_id_ = -1;
bool in_animation_frame_ = false; bool in_animation_frame_ = false;
bool did_submit_this_frame_ = false; bool did_submit_this_frame_ = false;
bool display_blurred_ = false; bool display_blurred_ = false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment