| 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 |