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 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |