| Index: third_party/WebKit/Source/modules/vr/VRDisplay.cpp
|
| diff --git a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
|
| index 5122c99d42d313daa98f7a7ad95c259908966e61..6aa007eae2a43caa9969d659f94681f2c565cf41 100644
|
| --- a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
|
| +++ b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
|
| @@ -129,12 +129,33 @@ VREyeParameters* VRDisplay::getEyeParameters(const String& which_eye) {
|
| }
|
| }
|
|
|
| -int VRDisplay::requestAnimationFrame(FrameRequestCallback* callback) {
|
| - DVLOG(2) << __FUNCTION__;
|
| - Document* doc = this->GetDocument();
|
| - if (!doc)
|
| - return 0;
|
| - pending_vrdisplay_raf_ = true;
|
| +void VRDisplay::RequestVSync() {
|
| + DVLOG(2) << __FUNCTION__
|
| + << " start: pending_vrdisplay_raf_=" << pending_vrdisplay_raf_
|
| + << " in_animation_frame_=" << in_animation_frame_
|
| + << " did_submit_this_frame_=" << did_submit_this_frame_;
|
| +
|
| + // The logic here is a bit subtle. We get called from one of the following
|
| + // four contexts:
|
| + //
|
| + // (a) from requestAnimationFrame if outside an animating context (i.e. the
|
| + // first rAF call from inside a getVRDisplays() promise)
|
| + //
|
| + // (b) from requestAnimationFrame in an animating context if the JS code
|
| + // calls rAF after submitFrame.
|
| + //
|
| + // (c) from submitFrame if that is called after rAF.
|
| + //
|
| + // (d) from ProcessScheduledAnimations if a rAF callback finishes without
|
| + // submitting a frame.
|
| + //
|
| + // These cases are mutually exclusive which prevents duplicate RequestVSync
|
| + // calls. Case (a) only applies outside an animating context
|
| + // (in_animation_frame_ is false), and (b,c,d) all require an animating
|
| + // 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
|
| + // all, there won't be future frames.
|
| +
|
| if (!vr_v_sync_provider_.is_bound()) {
|
| ConnectVSyncProvider();
|
| } else if (!display_blurred_ && !pending_vsync_) {
|
| @@ -142,6 +163,27 @@ int VRDisplay::requestAnimationFrame(FrameRequestCallback* callback) {
|
| vr_v_sync_provider_->GetVSync(ConvertToBaseCallback(
|
| WTF::Bind(&VRDisplay::OnVSync, WrapWeakPersistent(this))));
|
| }
|
| +
|
| + DVLOG(2) << __FUNCTION__ << " done:"
|
| + << " vr_v_sync_provider_.is_bound()="
|
| + << vr_v_sync_provider_.is_bound()
|
| + << " pending_vsync_=" << pending_vsync_;
|
| +}
|
| +
|
| +int VRDisplay::requestAnimationFrame(FrameRequestCallback* callback) {
|
| + DVLOG(2) << __FUNCTION__;
|
| + Document* doc = this->GetDocument();
|
| + if (!doc)
|
| + return 0;
|
| + pending_vrdisplay_raf_ = true;
|
| +
|
| + // We want to delay the GetVSync call while presenting to ensure it doesn't
|
| + // arrive earlier than frame submission, but other than that we want to call
|
| + // it as early as possible. See comments inside RequestVSync() for more
|
| + // details on the applicable cases.
|
| + if (!in_animation_frame_ || did_submit_this_frame_) {
|
| + RequestVSync();
|
| + }
|
| callback->use_legacy_time_base_ = false;
|
| return EnsureScriptedAnimationController(doc).RegisterCallback(callback);
|
| }
|
| @@ -487,6 +529,8 @@ HeapVector<VRLayer> VRDisplay::getLayers() {
|
| }
|
|
|
| void VRDisplay::submitFrame() {
|
| + DVLOG(2) << __FUNCTION__;
|
| +
|
| if (!display_)
|
| return;
|
| TRACE_EVENT1("gpu", "submitFrame", "frame", vr_frame_id_);
|
| @@ -606,6 +650,10 @@ void VRDisplay::submitFrame() {
|
| vr_frame_id_,
|
| gpu::MailboxHolder(static_image->GetMailbox(),
|
| static_image->GetSyncToken(), GL_TEXTURE_2D));
|
| + did_submit_this_frame_ = true;
|
| + // If we were deferring a rAF-triggered vsync request, do this now.
|
| + if (pending_vrdisplay_raf_)
|
| + RequestVSync();
|
|
|
| // If preserveDrawingBuffer is false, must clear now. Normally this
|
| // happens as part of compositing, but that's not active while
|
| @@ -627,10 +675,12 @@ void VRDisplay::submitFrame() {
|
| }
|
|
|
| void VRDisplay::OnSubmitFrameTransferred() {
|
| + DVLOG(3) << __FUNCTION__;
|
| pending_submit_frame_ = false;
|
| }
|
|
|
| void VRDisplay::OnSubmitFrameRendered() {
|
| + DVLOG(3) << __FUNCTION__;
|
| pending_previous_frame_render_ = false;
|
| }
|
|
|
| @@ -692,6 +742,7 @@ void VRDisplay::StopPresenting() {
|
| context_gl_ = nullptr;
|
| pending_submit_frame_ = false;
|
| pending_previous_frame_render_ = false;
|
| + did_submit_this_frame_ = false;
|
| }
|
|
|
| void VRDisplay::OnActivate(device::mojom::blink::VRDisplayEventReason reason,
|
| @@ -756,9 +807,19 @@ void VRDisplay::ProcessScheduledAnimations(double timestamp) {
|
| // that may be called later.
|
| AutoReset<bool> animating(&in_animation_frame_, true);
|
| pending_vrdisplay_raf_ = false;
|
| + did_submit_this_frame_ = false;
|
| scripted_animation_controller_->ServiceScriptedAnimations(timestamp);
|
| + if (pending_vrdisplay_raf_ && !did_submit_this_frame_) {
|
| + DVLOG(2) << __FUNCTION__ << ": vrDisplay.rAF did not submit a frame";
|
| + RequestVSync();
|
| + }
|
| }
|
|
|
| + // Sanity check: If pending_vrdisplay_raf_ is true and the vsync provider
|
| + // is connected, we must now have a pending vsync.
|
| + DCHECK(!pending_vrdisplay_raf_ || !vr_v_sync_provider_.is_bound() ||
|
| + pending_vsync_);
|
| +
|
| // For GVR, we shut down normal vsync processing during VR presentation.
|
| // Trigger any callbacks on window.rAF manually so that they run after
|
| // completing the vrDisplay.rAF processing.
|
|
|