Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(896)

Unified Diff: third_party/WebKit/Source/modules/vr/VRDisplay.cpp

Issue 2888313002: WebVR: Defer GetVSync calls until the current frame is submitted. (Closed)
Patch Set: Tweak test to run a few frames in magic window mode Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 3201ab4b09aef52ea62219a363d4ac17c5b6a456..7296ffccc326d9a1ee3b610f0237ca7789686bb0 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_);
@@ -627,6 +671,11 @@ void VRDisplay::submitFrame() {
gpu::MailboxHolder(mailbox, sync_token, GL_TEXTURE_2D));
TRACE_EVENT_END0("gpu", "VRDisplay::SubmitFrame");
+ 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
// presenting, so run the responsible code directly.
@@ -647,10 +696,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;
}
@@ -712,6 +763,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,
@@ -776,9 +828,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.
« no previous file with comments | « third_party/WebKit/Source/modules/vr/VRDisplay.h ('k') | third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698