OLD | NEW |
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 Loading... |
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 Loading... |
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 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
620 } | 664 } |
621 | 665 |
622 pending_previous_frame_render_ = true; | 666 pending_previous_frame_render_ = true; |
623 pending_submit_frame_ = true; | 667 pending_submit_frame_ = true; |
624 | 668 |
625 TRACE_EVENT_BEGIN0("gpu", "VRDisplay::SubmitFrame"); | 669 TRACE_EVENT_BEGIN0("gpu", "VRDisplay::SubmitFrame"); |
626 display_->SubmitFrame(vr_frame_id_, | 670 display_->SubmitFrame(vr_frame_id_, |
627 gpu::MailboxHolder(mailbox, sync_token, GL_TEXTURE_2D)); | 671 gpu::MailboxHolder(mailbox, sync_token, GL_TEXTURE_2D)); |
628 TRACE_EVENT_END0("gpu", "VRDisplay::SubmitFrame"); | 672 TRACE_EVENT_END0("gpu", "VRDisplay::SubmitFrame"); |
629 | 673 |
| 674 did_submit_this_frame_ = true; |
| 675 // If we were deferring a rAF-triggered vsync request, do this now. |
| 676 if (pending_vrdisplay_raf_) |
| 677 RequestVSync(); |
| 678 |
630 // If preserveDrawingBuffer is false, must clear now. Normally this | 679 // If preserveDrawingBuffer is false, must clear now. Normally this |
631 // happens as part of compositing, but that's not active while | 680 // happens as part of compositing, but that's not active while |
632 // presenting, so run the responsible code directly. | 681 // presenting, so run the responsible code directly. |
633 rendering_context_->MarkCompositedAndClearBackbufferIfNeeded(); | 682 rendering_context_->MarkCompositedAndClearBackbufferIfNeeded(); |
634 | 683 |
635 // If we're not deferring the wait for transferring the mailbox, | 684 // If we're not deferring the wait for transferring the mailbox, |
636 // we need to wait for it now to prevent the image going out of | 685 // we need to wait for it now to prevent the image going out of |
637 // scope before its mailbox is retrieved. | 686 // scope before its mailbox is retrieved. |
638 if (!wait_for_previous_transfer_to_finish) { | 687 if (!wait_for_previous_transfer_to_finish) { |
639 TRACE_EVENT0("gpu", "waitForCurrentTransferToFinish"); | 688 TRACE_EVENT0("gpu", "waitForCurrentTransferToFinish"); |
640 while (pending_submit_frame_) { | 689 while (pending_submit_frame_) { |
641 if (!submit_frame_client_binding_.WaitForIncomingMethodCall()) { | 690 if (!submit_frame_client_binding_.WaitForIncomingMethodCall()) { |
642 DLOG(ERROR) << "Failed to receive SubmitFrame response"; | 691 DLOG(ERROR) << "Failed to receive SubmitFrame response"; |
643 break; | 692 break; |
644 } | 693 } |
645 } | 694 } |
646 } | 695 } |
647 } | 696 } |
648 | 697 |
649 void VRDisplay::OnSubmitFrameTransferred() { | 698 void VRDisplay::OnSubmitFrameTransferred() { |
| 699 DVLOG(3) << __FUNCTION__; |
650 pending_submit_frame_ = false; | 700 pending_submit_frame_ = false; |
651 } | 701 } |
652 | 702 |
653 void VRDisplay::OnSubmitFrameRendered() { | 703 void VRDisplay::OnSubmitFrameRendered() { |
| 704 DVLOG(3) << __FUNCTION__; |
654 pending_previous_frame_render_ = false; | 705 pending_previous_frame_render_ = false; |
655 } | 706 } |
656 | 707 |
657 Document* VRDisplay::GetDocument() { | 708 Document* VRDisplay::GetDocument() { |
658 return navigator_vr_->GetDocument(); | 709 return navigator_vr_->GetDocument(); |
659 } | 710 } |
660 | 711 |
661 void VRDisplay::OnPresentChange() { | 712 void VRDisplay::OnPresentChange() { |
662 DVLOG(1) << __FUNCTION__ << ": is_presenting_=" << is_presenting_; | 713 DVLOG(1) << __FUNCTION__ << ": is_presenting_=" << is_presenting_; |
663 if (is_presenting_ && !is_valid_device_for_presenting_) { | 714 if (is_presenting_ && !is_valid_device_for_presenting_) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
705 // Record user action for stop presenting. Note that this could be | 756 // Record user action for stop presenting. Note that this could be |
706 // user-triggered or not. | 757 // user-triggered or not. |
707 Platform::Current()->RecordAction( | 758 Platform::Current()->RecordAction( |
708 UserMetricsAction("VR.WebVR.StopPresenting")); | 759 UserMetricsAction("VR.WebVR.StopPresenting")); |
709 } | 760 } |
710 | 761 |
711 rendering_context_ = nullptr; | 762 rendering_context_ = nullptr; |
712 context_gl_ = nullptr; | 763 context_gl_ = nullptr; |
713 pending_submit_frame_ = false; | 764 pending_submit_frame_ = false; |
714 pending_previous_frame_render_ = false; | 765 pending_previous_frame_render_ = false; |
| 766 did_submit_this_frame_ = false; |
715 } | 767 } |
716 | 768 |
717 void VRDisplay::OnActivate(device::mojom::blink::VRDisplayEventReason reason, | 769 void VRDisplay::OnActivate(device::mojom::blink::VRDisplayEventReason reason, |
718 const OnActivateCallback& on_handled) { | 770 const OnActivateCallback& on_handled) { |
719 AutoReset<bool> activating(&in_display_activate_, true); | 771 AutoReset<bool> activating(&in_display_activate_, true); |
720 navigator_vr_->DispatchVREvent(VRDisplayEvent::Create( | 772 navigator_vr_->DispatchVREvent(VRDisplayEvent::Create( |
721 EventTypeNames::vrdisplayactivate, true, false, this, reason)); | 773 EventTypeNames::vrdisplayactivate, true, false, this, reason)); |
722 on_handled.Run(pending_present_request_); | 774 on_handled.Run(pending_present_request_); |
723 } | 775 } |
724 | 776 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
769 } | 821 } |
770 | 822 |
771 TRACE_EVENT1("gpu", "VRDisplay::OnVSync", "frame", vr_frame_id_); | 823 TRACE_EVENT1("gpu", "VRDisplay::OnVSync", "frame", vr_frame_id_); |
772 | 824 |
773 if (pending_vrdisplay_raf_ && scripted_animation_controller_) { | 825 if (pending_vrdisplay_raf_ && scripted_animation_controller_) { |
774 // Run the callback, making sure that in_animation_frame_ is only | 826 // Run the callback, making sure that in_animation_frame_ is only |
775 // true for the vrDisplay rAF and not for a legacy window rAF | 827 // true for the vrDisplay rAF and not for a legacy window rAF |
776 // that may be called later. | 828 // that may be called later. |
777 AutoReset<bool> animating(&in_animation_frame_, true); | 829 AutoReset<bool> animating(&in_animation_frame_, true); |
778 pending_vrdisplay_raf_ = false; | 830 pending_vrdisplay_raf_ = false; |
| 831 did_submit_this_frame_ = false; |
779 scripted_animation_controller_->ServiceScriptedAnimations(timestamp); | 832 scripted_animation_controller_->ServiceScriptedAnimations(timestamp); |
| 833 if (pending_vrdisplay_raf_ && !did_submit_this_frame_) { |
| 834 DVLOG(2) << __FUNCTION__ << ": vrDisplay.rAF did not submit a frame"; |
| 835 RequestVSync(); |
| 836 } |
780 } | 837 } |
781 | 838 |
| 839 // Sanity check: If pending_vrdisplay_raf_ is true and the vsync provider |
| 840 // is connected, we must now have a pending vsync. |
| 841 DCHECK(!pending_vrdisplay_raf_ || !vr_v_sync_provider_.is_bound() || |
| 842 pending_vsync_); |
| 843 |
782 // For GVR, we shut down normal vsync processing during VR presentation. | 844 // For GVR, we shut down normal vsync processing during VR presentation. |
783 // Trigger any callbacks on window.rAF manually so that they run after | 845 // Trigger any callbacks on window.rAF manually so that they run after |
784 // completing the vrDisplay.rAF processing. | 846 // completing the vrDisplay.rAF processing. |
785 if (is_presenting_ && !capabilities_->hasExternalDisplay()) { | 847 if (is_presenting_ && !capabilities_->hasExternalDisplay()) { |
786 Platform::Current()->CurrentThread()->GetWebTaskRunner()->PostTask( | 848 Platform::Current()->CurrentThread()->GetWebTaskRunner()->PostTask( |
787 BLINK_FROM_HERE, WTF::Bind(&VRDisplay::ProcessScheduledWindowAnimations, | 849 BLINK_FROM_HERE, WTF::Bind(&VRDisplay::ProcessScheduledWindowAnimations, |
788 WrapWeakPersistent(this), timestamp)); | 850 WrapWeakPersistent(this), timestamp)); |
789 } | 851 } |
790 } | 852 } |
791 | 853 |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
901 visitor->Trace(stage_parameters_); | 963 visitor->Trace(stage_parameters_); |
902 visitor->Trace(eye_parameters_left_); | 964 visitor->Trace(eye_parameters_left_); |
903 visitor->Trace(eye_parameters_right_); | 965 visitor->Trace(eye_parameters_right_); |
904 visitor->Trace(layer_); | 966 visitor->Trace(layer_); |
905 visitor->Trace(rendering_context_); | 967 visitor->Trace(rendering_context_); |
906 visitor->Trace(scripted_animation_controller_); | 968 visitor->Trace(scripted_animation_controller_); |
907 visitor->Trace(pending_present_resolvers_); | 969 visitor->Trace(pending_present_resolvers_); |
908 } | 970 } |
909 | 971 |
910 } // namespace blink | 972 } // namespace blink |
OLD | NEW |