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

Side by Side Diff: third_party/WebKit/Source/modules/vr/VRDisplay.cpp

Issue 2888313002: WebVR: Defer GetVSync calls until the current frame is submitted. (Closed)
Patch Set: Refactor RequestVSync, add comments and test 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "modules/vr/VRDisplay.h" 5 #include "modules/vr/VRDisplay.h"
6 6
7 #include "core/css/StylePropertySet.h" 7 #include "core/css/StylePropertySet.h"
8 #include "core/dom/DOMException.h" 8 #include "core/dom/DOMException.h"
9 #include "core/dom/FrameRequestCallback.h" 9 #include "core/dom/FrameRequestCallback.h"
10 #include "core/dom/ScriptedAnimationController.h" 10 #include "core/dom/ScriptedAnimationController.h"
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 switch (StringToVREye(which_eye)) { 122 switch (StringToVREye(which_eye)) {
123 case kVREyeLeft: 123 case kVREyeLeft:
124 return eye_parameters_left_; 124 return eye_parameters_left_;
125 case kVREyeRight: 125 case kVREyeRight:
126 return eye_parameters_right_; 126 return eye_parameters_right_;
127 default: 127 default:
128 return nullptr; 128 return nullptr;
129 } 129 }
130 } 130 }
131 131
132 int VRDisplay::requestAnimationFrame(FrameRequestCallback* callback) { 132 void VRDisplay::RequestVSync() {
133 DVLOG(2) << __FUNCTION__; 133 DVLOG(2) << __FUNCTION__
134 Document* doc = this->GetDocument(); 134 << " start: pending_vrdisplay_raf_=" << pending_vrdisplay_raf_
135 if (!doc) 135 << " in_animation_frame_=" << in_animation_frame_
136 return 0; 136 << " did_submit_this_frame_=" << did_submit_this_frame_;
137 pending_vrdisplay_raf_ = true; 137
138 // The logic here is a bit subtle. We get called from one of the following
139 // four contexts:
140 //
141 // (a) from requestAnimationFrame if outside an animating context (i.e. the
142 // first rAF call from inside a getVRDisplays() promise)
143 //
144 // (b) from requestAnimationFrame in an animating context if the JS code
145 // calls rAF after submitFrame.
146 //
147 // (c) from submitFrame if that is called after rAF.
148 //
149 // (d) from ProcessScheduledAnimations if a rAF callback finishes without
150 // submitting a frame.
151 //
152 // These cases are mutually exclusive which prevents duplicate RequestVSync
153 // calls. Case (a) only applies outside an animating context
154 // (in_animation_frame_ is false), and (b,c,d) all require an animating
155 // context. While in an animating context, submitFrame is called either
156 // before rAF (b), after rAF (c), or not at all (d). If rAF isn't called at
157 // all, there won't be future frames.
158
138 if (!vr_v_sync_provider_.is_bound()) { 159 if (!vr_v_sync_provider_.is_bound()) {
139 ConnectVSyncProvider(); 160 ConnectVSyncProvider();
140 } else if (!display_blurred_ && !pending_vsync_) { 161 } else if (!display_blurred_ && !pending_vsync_) {
141 pending_vsync_ = true; 162 pending_vsync_ = true;
142 vr_v_sync_provider_->GetVSync(ConvertToBaseCallback( 163 vr_v_sync_provider_->GetVSync(ConvertToBaseCallback(
143 WTF::Bind(&VRDisplay::OnVSync, WrapWeakPersistent(this)))); 164 WTF::Bind(&VRDisplay::OnVSync, WrapWeakPersistent(this))));
144 } 165 }
166
167 DVLOG(2) << __FUNCTION__ << " done:"
168 << " vr_v_sync_provider_.is_bound()="
169 << vr_v_sync_provider_.is_bound()
170 << " pending_vsync_=" << pending_vsync_;
171 }
172
173 int VRDisplay::requestAnimationFrame(FrameRequestCallback* callback) {
174 DVLOG(2) << __FUNCTION__;
175 Document* doc = this->GetDocument();
176 if (!doc)
177 return 0;
178 pending_vrdisplay_raf_ = true;
179
180 // We want to delay the GetVSync call while presenting to ensure it doesn't
181 // arrive earlier than frame submission, but other than that we want to call
182 // it as early as possible. See comments inside RequestVSync() for more
183 // details on the applicable cases.
184 if (!in_animation_frame_ || did_submit_this_frame_) {
185 RequestVSync();
186 }
145 callback->use_legacy_time_base_ = false; 187 callback->use_legacy_time_base_ = false;
146 return EnsureScriptedAnimationController(doc).RegisterCallback(callback); 188 return EnsureScriptedAnimationController(doc).RegisterCallback(callback);
147 } 189 }
148 190
149 void VRDisplay::cancelAnimationFrame(int id) { 191 void VRDisplay::cancelAnimationFrame(int id) {
150 DVLOG(2) << __FUNCTION__; 192 DVLOG(2) << __FUNCTION__;
151 if (!scripted_animation_controller_) 193 if (!scripted_animation_controller_)
152 return; 194 return;
153 scripted_animation_controller_->CancelCallback(id); 195 scripted_animation_controller_->CancelCallback(id);
154 } 196 }
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 HeapVector<VRLayer> layers; 522 HeapVector<VRLayer> layers;
481 523
482 if (is_presenting_) { 524 if (is_presenting_) {
483 layers.push_back(layer_); 525 layers.push_back(layer_);
484 } 526 }
485 527
486 return layers; 528 return layers;
487 } 529 }
488 530
489 void VRDisplay::submitFrame() { 531 void VRDisplay::submitFrame() {
532 DVLOG(2) << __FUNCTION__;
533
490 if (!display_) 534 if (!display_)
491 return; 535 return;
492 TRACE_EVENT1("gpu", "submitFrame", "frame", vr_frame_id_); 536 TRACE_EVENT1("gpu", "submitFrame", "frame", vr_frame_id_);
493 537
494 Document* doc = this->GetDocument(); 538 Document* doc = this->GetDocument();
495 if (!is_presenting_) { 539 if (!is_presenting_) {
496 if (doc) { 540 if (doc) {
497 doc->AddConsoleMessage(ConsoleMessage::Create( 541 doc->AddConsoleMessage(ConsoleMessage::Create(
498 kRenderingMessageSource, kWarningMessageLevel, 542 kRenderingMessageSource, kWarningMessageLevel,
499 "submitFrame has no effect when the VRDisplay is not presenting.")); 543 "submitFrame has no effect when the VRDisplay is not presenting."));
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
599 } 643 }
600 } 644 }
601 } 645 }
602 646
603 pending_previous_frame_render_ = true; 647 pending_previous_frame_render_ = true;
604 pending_submit_frame_ = true; 648 pending_submit_frame_ = true;
605 display_->SubmitFrame( 649 display_->SubmitFrame(
606 vr_frame_id_, 650 vr_frame_id_,
607 gpu::MailboxHolder(static_image->GetMailbox(), 651 gpu::MailboxHolder(static_image->GetMailbox(),
608 static_image->GetSyncToken(), GL_TEXTURE_2D)); 652 static_image->GetSyncToken(), GL_TEXTURE_2D));
653 did_submit_this_frame_ = true;
654 // If we were deferring a rAF-triggered vsync request, do this now.
655 if (pending_vrdisplay_raf_)
656 RequestVSync();
609 657
610 // If preserveDrawingBuffer is false, must clear now. Normally this 658 // If preserveDrawingBuffer is false, must clear now. Normally this
611 // happens as part of compositing, but that's not active while 659 // happens as part of compositing, but that's not active while
612 // presenting, so run the responsible code directly. 660 // presenting, so run the responsible code directly.
613 rendering_context_->MarkCompositedAndClearBackbufferIfNeeded(); 661 rendering_context_->MarkCompositedAndClearBackbufferIfNeeded();
614 662
615 // If we're not deferring the wait for transferring the mailbox, 663 // If we're not deferring the wait for transferring the mailbox,
616 // we need to wait for it now to prevent the image going out of 664 // we need to wait for it now to prevent the image going out of
617 // scope before its mailbox is retrieved. 665 // scope before its mailbox is retrieved.
618 if (!wait_for_previous_transfer_to_finish) { 666 if (!wait_for_previous_transfer_to_finish) {
619 TRACE_EVENT0("gpu", "waitForCurrentTransferToFinish"); 667 TRACE_EVENT0("gpu", "waitForCurrentTransferToFinish");
620 while (pending_submit_frame_) { 668 while (pending_submit_frame_) {
621 if (!submit_frame_client_binding_.WaitForIncomingMethodCall()) { 669 if (!submit_frame_client_binding_.WaitForIncomingMethodCall()) {
622 DLOG(ERROR) << "Failed to receive SubmitFrame response"; 670 DLOG(ERROR) << "Failed to receive SubmitFrame response";
623 break; 671 break;
624 } 672 }
625 } 673 }
626 } 674 }
627 } 675 }
628 676
629 void VRDisplay::OnSubmitFrameTransferred() { 677 void VRDisplay::OnSubmitFrameTransferred() {
678 DVLOG(3) << __FUNCTION__;
630 pending_submit_frame_ = false; 679 pending_submit_frame_ = false;
631 } 680 }
632 681
633 void VRDisplay::OnSubmitFrameRendered() { 682 void VRDisplay::OnSubmitFrameRendered() {
683 DVLOG(3) << __FUNCTION__;
634 pending_previous_frame_render_ = false; 684 pending_previous_frame_render_ = false;
635 } 685 }
636 686
637 Document* VRDisplay::GetDocument() { 687 Document* VRDisplay::GetDocument() {
638 return navigator_vr_->GetDocument(); 688 return navigator_vr_->GetDocument();
639 } 689 }
640 690
641 void VRDisplay::OnPresentChange() { 691 void VRDisplay::OnPresentChange() {
642 DVLOG(1) << __FUNCTION__ << ": is_presenting_=" << is_presenting_; 692 DVLOG(1) << __FUNCTION__ << ": is_presenting_=" << is_presenting_;
643 if (is_presenting_ && !is_valid_device_for_presenting_) { 693 if (is_presenting_ && !is_valid_device_for_presenting_) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
685 // Record user action for stop presenting. Note that this could be 735 // Record user action for stop presenting. Note that this could be
686 // user-triggered or not. 736 // user-triggered or not.
687 Platform::Current()->RecordAction( 737 Platform::Current()->RecordAction(
688 UserMetricsAction("VR.WebVR.StopPresenting")); 738 UserMetricsAction("VR.WebVR.StopPresenting"));
689 } 739 }
690 740
691 rendering_context_ = nullptr; 741 rendering_context_ = nullptr;
692 context_gl_ = nullptr; 742 context_gl_ = nullptr;
693 pending_submit_frame_ = false; 743 pending_submit_frame_ = false;
694 pending_previous_frame_render_ = false; 744 pending_previous_frame_render_ = false;
745 did_submit_this_frame_ = false;
695 } 746 }
696 747
697 void VRDisplay::OnActivate(device::mojom::blink::VRDisplayEventReason reason, 748 void VRDisplay::OnActivate(device::mojom::blink::VRDisplayEventReason reason,
698 const OnActivateCallback& on_handled) { 749 const OnActivateCallback& on_handled) {
699 AutoReset<bool> activating(&in_display_activate_, true); 750 AutoReset<bool> activating(&in_display_activate_, true);
700 navigator_vr_->DispatchVREvent(VRDisplayEvent::Create( 751 navigator_vr_->DispatchVREvent(VRDisplayEvent::Create(
701 EventTypeNames::vrdisplayactivate, true, false, this, reason)); 752 EventTypeNames::vrdisplayactivate, true, false, this, reason));
702 on_handled.Run(pending_present_request_); 753 on_handled.Run(pending_present_request_);
703 } 754 }
704 755
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
749 } 800 }
750 801
751 TRACE_EVENT1("gpu", "VRDisplay::OnVSync", "frame", vr_frame_id_); 802 TRACE_EVENT1("gpu", "VRDisplay::OnVSync", "frame", vr_frame_id_);
752 803
753 if (pending_vrdisplay_raf_ && scripted_animation_controller_) { 804 if (pending_vrdisplay_raf_ && scripted_animation_controller_) {
754 // Run the callback, making sure that in_animation_frame_ is only 805 // Run the callback, making sure that in_animation_frame_ is only
755 // true for the vrDisplay rAF and not for a legacy window rAF 806 // true for the vrDisplay rAF and not for a legacy window rAF
756 // that may be called later. 807 // that may be called later.
757 AutoReset<bool> animating(&in_animation_frame_, true); 808 AutoReset<bool> animating(&in_animation_frame_, true);
758 pending_vrdisplay_raf_ = false; 809 pending_vrdisplay_raf_ = false;
810 did_submit_this_frame_ = false;
759 scripted_animation_controller_->ServiceScriptedAnimations(timestamp); 811 scripted_animation_controller_->ServiceScriptedAnimations(timestamp);
812 if (pending_vrdisplay_raf_ && !did_submit_this_frame_) {
813 DVLOG(2) << __FUNCTION__ << ": vrDisplay.rAF did not submit a frame";
814 RequestVSync();
815 }
760 } 816 }
761 817
818 // Sanity check: If pending_vrdisplay_raf_ is true and the vsync provider
819 // is connected, we must now have a pending vsync.
820 DCHECK(!pending_vrdisplay_raf_ || !vr_v_sync_provider_.is_bound() ||
821 pending_vsync_);
822
762 // For GVR, we shut down normal vsync processing during VR presentation. 823 // For GVR, we shut down normal vsync processing during VR presentation.
763 // Trigger any callbacks on window.rAF manually so that they run after 824 // Trigger any callbacks on window.rAF manually so that they run after
764 // completing the vrDisplay.rAF processing. 825 // completing the vrDisplay.rAF processing.
765 if (is_presenting_ && !capabilities_->hasExternalDisplay()) { 826 if (is_presenting_ && !capabilities_->hasExternalDisplay()) {
766 Platform::Current()->CurrentThread()->GetWebTaskRunner()->PostTask( 827 Platform::Current()->CurrentThread()->GetWebTaskRunner()->PostTask(
767 BLINK_FROM_HERE, WTF::Bind(&VRDisplay::ProcessScheduledWindowAnimations, 828 BLINK_FROM_HERE, WTF::Bind(&VRDisplay::ProcessScheduledWindowAnimations,
768 WrapWeakPersistent(this), timestamp)); 829 WrapWeakPersistent(this), timestamp));
769 } 830 }
770 } 831 }
771 832
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
881 visitor->Trace(stage_parameters_); 942 visitor->Trace(stage_parameters_);
882 visitor->Trace(eye_parameters_left_); 943 visitor->Trace(eye_parameters_left_);
883 visitor->Trace(eye_parameters_right_); 944 visitor->Trace(eye_parameters_right_);
884 visitor->Trace(layer_); 945 visitor->Trace(layer_);
885 visitor->Trace(rendering_context_); 946 visitor->Trace(rendering_context_);
886 visitor->Trace(scripted_animation_controller_); 947 visitor->Trace(scripted_animation_controller_);
887 visitor->Trace(pending_present_resolvers_); 948 visitor->Trace(pending_present_resolvers_);
888 } 949 }
889 950
890 } // namespace blink 951 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698