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 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 int VRDisplay::requestAnimationFrame(FrameRequestCallback* callback) { |
133 DVLOG(2) << __FUNCTION__; | |
133 Document* doc = this->GetDocument(); | 134 Document* doc = this->GetDocument(); |
134 if (!doc) | 135 if (!doc) |
135 return 0; | 136 return 0; |
136 pending_raf_ = true; | 137 pending_vrdisplay_raf_ = true; |
137 if (!vr_v_sync_provider_.is_bound()) { | 138 if (!vr_v_sync_provider_.is_bound()) { |
138 ConnectVSyncProvider(); | 139 ConnectVSyncProvider(); |
139 } else if (!display_blurred_ && !pending_vsync_) { | 140 } else if (!display_blurred_ && !pending_vsync_) { |
140 pending_vsync_ = true; | 141 pending_vsync_ = true; |
141 vr_v_sync_provider_->GetVSync(ConvertToBaseCallback( | 142 vr_v_sync_provider_->GetVSync(ConvertToBaseCallback( |
142 WTF::Bind(&VRDisplay::OnVSync, WrapWeakPersistent(this)))); | 143 WTF::Bind(&VRDisplay::OnVSync, WrapWeakPersistent(this)))); |
143 } | 144 } |
144 callback->use_legacy_time_base_ = false; | 145 callback->use_legacy_time_base_ = false; |
145 return EnsureScriptedAnimationController(doc).RegisterCallback(callback); | 146 return EnsureScriptedAnimationController(doc).RegisterCallback(callback); |
146 } | 147 } |
147 | 148 |
148 void VRDisplay::cancelAnimationFrame(int id) { | 149 void VRDisplay::cancelAnimationFrame(int id) { |
150 DVLOG(2) << __FUNCTION__; | |
149 if (!scripted_animation_controller_) | 151 if (!scripted_animation_controller_) |
150 return; | 152 return; |
151 scripted_animation_controller_->CancelCallback(id); | 153 scripted_animation_controller_->CancelCallback(id); |
152 } | 154 } |
153 | 155 |
154 void VRDisplay::OnBlur() { | 156 void VRDisplay::OnBlur() { |
157 DVLOG(1) << __FUNCTION__; | |
155 display_blurred_ = true; | 158 display_blurred_ = true; |
156 vr_v_sync_provider_.reset(); | 159 vr_v_sync_provider_.reset(); |
157 navigator_vr_->EnqueueVREvent(VRDisplayEvent::Create( | 160 navigator_vr_->EnqueueVREvent(VRDisplayEvent::Create( |
158 EventTypeNames::vrdisplayblur, true, false, this, "")); | 161 EventTypeNames::vrdisplayblur, true, false, this, "")); |
159 } | 162 } |
160 | 163 |
161 void VRDisplay::OnFocus() { | 164 void VRDisplay::OnFocus() { |
165 DVLOG(1) << __FUNCTION__; | |
162 display_blurred_ = false; | 166 display_blurred_ = false; |
163 ConnectVSyncProvider(); | 167 ConnectVSyncProvider(); |
164 navigator_vr_->EnqueueVREvent(VRDisplayEvent::Create( | 168 navigator_vr_->EnqueueVREvent(VRDisplayEvent::Create( |
165 EventTypeNames::vrdisplayfocus, true, false, this, "")); | 169 EventTypeNames::vrdisplayfocus, true, false, this, "")); |
166 } | 170 } |
167 | 171 |
168 void ReportPresentationResult(PresentationResult result) { | 172 void ReportPresentationResult(PresentationResult result) { |
169 // Note that this is called twice for each call to requestPresent - | 173 // Note that this is called twice for each call to requestPresent - |
170 // one to declare that requestPresent was called, and one for the | 174 // one to declare that requestPresent was called, and one for the |
171 // result. | 175 // result. |
172 DEFINE_STATIC_LOCAL( | 176 DEFINE_STATIC_LOCAL( |
173 EnumerationHistogram, vr_presentation_result_histogram, | 177 EnumerationHistogram, vr_presentation_result_histogram, |
174 ("VRDisplayPresentResult", | 178 ("VRDisplayPresentResult", |
175 static_cast<int>(PresentationResult::kPresentationResultMax))); | 179 static_cast<int>(PresentationResult::kPresentationResultMax))); |
176 vr_presentation_result_histogram.Count(static_cast<int>(result)); | 180 vr_presentation_result_histogram.Count(static_cast<int>(result)); |
177 } | 181 } |
178 | 182 |
179 ScriptPromise VRDisplay::requestPresent(ScriptState* script_state, | 183 ScriptPromise VRDisplay::requestPresent(ScriptState* script_state, |
180 const HeapVector<VRLayer>& layers) { | 184 const HeapVector<VRLayer>& layers) { |
185 DVLOG(1) << __FUNCTION__; | |
181 ExecutionContext* execution_context = ExecutionContext::From(script_state); | 186 ExecutionContext* execution_context = ExecutionContext::From(script_state); |
182 UseCounter::Count(execution_context, UseCounter::kVRRequestPresent); | 187 UseCounter::Count(execution_context, UseCounter::kVRRequestPresent); |
183 if (!execution_context->IsSecureContext()) { | 188 if (!execution_context->IsSecureContext()) { |
184 UseCounter::Count(execution_context, | 189 UseCounter::Count(execution_context, |
185 UseCounter::kVRRequestPresentInsecureOrigin); | 190 UseCounter::kVRRequestPresentInsecureOrigin); |
186 } | 191 } |
187 | 192 |
188 ReportPresentationResult(PresentationResult::kRequested); | 193 ReportPresentationResult(PresentationResult::kRequested); |
189 | 194 |
190 ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); | 195 ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
313 kNotAllowedError, "Presentation request was denied."); | 318 kNotAllowedError, "Presentation request was denied."); |
314 | 319 |
315 while (!pending_present_resolvers_.IsEmpty()) { | 320 while (!pending_present_resolvers_.IsEmpty()) { |
316 ScriptPromiseResolver* resolver = pending_present_resolvers_.TakeFirst(); | 321 ScriptPromiseResolver* resolver = pending_present_resolvers_.TakeFirst(); |
317 resolver->Reject(exception); | 322 resolver->Reject(exception); |
318 } | 323 } |
319 } | 324 } |
320 } | 325 } |
321 | 326 |
322 ScriptPromise VRDisplay::exitPresent(ScriptState* script_state) { | 327 ScriptPromise VRDisplay::exitPresent(ScriptState* script_state) { |
328 DVLOG(1) << __FUNCTION__; | |
323 ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); | 329 ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state); |
324 ScriptPromise promise = resolver->Promise(); | 330 ScriptPromise promise = resolver->Promise(); |
325 | 331 |
326 if (!is_presenting_) { | 332 if (!is_presenting_) { |
327 // Can't stop presenting if we're not presenting. | 333 // Can't stop presenting if we're not presenting. |
328 DOMException* exception = DOMException::Create( | 334 DOMException* exception = DOMException::Create( |
329 kInvalidStateError, "VRDisplay is not presenting."); | 335 kInvalidStateError, "VRDisplay is not presenting."); |
330 resolver->Reject(exception); | 336 resolver->Reject(exception); |
331 return promise; | 337 return promise; |
332 } | 338 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
390 is_presenting_ = true; | 396 is_presenting_ = true; |
391 ReportPresentationResult(PresentationResult::kSuccess); | 397 ReportPresentationResult(PresentationResult::kSuccess); |
392 | 398 |
393 UpdateLayerBounds(); | 399 UpdateLayerBounds(); |
394 | 400 |
395 while (!pending_present_resolvers_.IsEmpty()) { | 401 while (!pending_present_resolvers_.IsEmpty()) { |
396 ScriptPromiseResolver* resolver = pending_present_resolvers_.TakeFirst(); | 402 ScriptPromiseResolver* resolver = pending_present_resolvers_.TakeFirst(); |
397 resolver->Resolve(); | 403 resolver->Resolve(); |
398 } | 404 } |
399 OnPresentChange(); | 405 OnPresentChange(); |
406 | |
407 // For GVR, we shut down normal vsync processing during VR presentation. | |
408 // Run window.rAF once manually so that applications get a chance to | |
409 // schedule a VRDisplay.rAF in case they do so only while presenting. | |
410 if (!pending_vrdisplay_raf_ && !capabilities_->hasExternalDisplay()) { | |
411 double timestamp = WTF::MonotonicallyIncreasingTime(); | |
412 Platform::Current()->CurrentThread()->GetWebTaskRunner()->PostTask( | |
413 BLINK_FROM_HERE, WTF::Bind(&VRDisplay::ProcessScheduledWindowAnimations, | |
414 WrapWeakPersistent(this), timestamp)); | |
415 } | |
400 } | 416 } |
401 | 417 |
402 // Need to close service if exists and then free rendering context. | 418 // Need to close service if exists and then free rendering context. |
403 void VRDisplay::ForceExitPresent() { | 419 void VRDisplay::ForceExitPresent() { |
404 if (display_) { | 420 if (display_) { |
405 display_->ExitPresent(); | 421 display_->ExitPresent(); |
406 } | 422 } |
407 StopPresenting(); | 423 StopPresenting(); |
408 } | 424 } |
409 | 425 |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
606 | 622 |
607 void VRDisplay::OnSubmitFrameRendered() { | 623 void VRDisplay::OnSubmitFrameRendered() { |
608 pending_previous_frame_render_ = false; | 624 pending_previous_frame_render_ = false; |
609 } | 625 } |
610 | 626 |
611 Document* VRDisplay::GetDocument() { | 627 Document* VRDisplay::GetDocument() { |
612 return navigator_vr_->GetDocument(); | 628 return navigator_vr_->GetDocument(); |
613 } | 629 } |
614 | 630 |
615 void VRDisplay::OnPresentChange() { | 631 void VRDisplay::OnPresentChange() { |
632 DVLOG(1) << __FUNCTION__ << ": is_presenting_=" << is_presenting_; | |
616 if (is_presenting_ && !is_valid_device_for_presenting_) { | 633 if (is_presenting_ && !is_valid_device_for_presenting_) { |
617 DVLOG(1) << __FUNCTION__ << ": device not valid, not sending event"; | 634 DVLOG(1) << __FUNCTION__ << ": device not valid, not sending event"; |
618 return; | 635 return; |
619 } | 636 } |
620 navigator_vr_->EnqueueVREvent(VRDisplayEvent::Create( | 637 navigator_vr_->EnqueueVREvent(VRDisplayEvent::Create( |
621 EventTypeNames::vrdisplaypresentchange, true, false, this, "")); | 638 EventTypeNames::vrdisplaypresentchange, true, false, this, "")); |
622 } | 639 } |
623 | 640 |
624 void VRDisplay::OnChanged(device::mojom::blink::VRDisplayInfoPtr display) { | 641 void VRDisplay::OnChanged(device::mojom::blink::VRDisplayInfoPtr display) { |
625 Update(display); | 642 Update(display); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
674 } | 691 } |
675 | 692 |
676 void VRDisplay::ProcessScheduledWindowAnimations(double timestamp) { | 693 void VRDisplay::ProcessScheduledWindowAnimations(double timestamp) { |
677 TRACE_EVENT1("gpu", "VRDisplay::window.rAF", "frame", vr_frame_id_); | 694 TRACE_EVENT1("gpu", "VRDisplay::window.rAF", "frame", vr_frame_id_); |
678 auto doc = navigator_vr_->GetDocument(); | 695 auto doc = navigator_vr_->GetDocument(); |
679 if (!doc) | 696 if (!doc) |
680 return; | 697 return; |
681 auto page = doc->GetPage(); | 698 auto page = doc->GetPage(); |
682 if (!page) | 699 if (!page) |
683 return; | 700 return; |
701 | |
702 bool had_pending_vrdisplay_raf = pending_vrdisplay_raf_; | |
684 // TODO(klausw): update timestamp based on scheduling delay? | 703 // TODO(klausw): update timestamp based on scheduling delay? |
685 page->Animator().ServiceScriptedAnimations(timestamp); | 704 page->Animator().ServiceScriptedAnimations(timestamp); |
705 | |
706 if (had_pending_vrdisplay_raf != pending_vrdisplay_raf_) { | |
707 DVLOG(1) << __FUNCTION__ | |
708 << ": window.rAF fallback successfully scheduled VRDisplay.rAF"; | |
709 } | |
710 | |
711 if (!pending_vrdisplay_raf_) { | |
712 // There wasn't any call to vrDisplay.rAF, so we will not be getting new | |
713 // frames from now on unless the application schedules one down the road in | |
714 // reaction to a separate event or timeout. TODO(klausw,crbug.com/716087): | |
715 // do something more useful here? | |
716 DVLOG(1) << __FUNCTION__ | |
717 << ": no scheduled VRDisplay.requestAnimationFrame, presentation " | |
718 "broken?"; | |
719 } | |
686 } | 720 } |
687 | 721 |
688 void VRDisplay::ProcessScheduledAnimations(double timestamp) { | 722 void VRDisplay::ProcessScheduledAnimations(double timestamp) { |
723 DVLOG(2) << __FUNCTION__; | |
689 // Check if we still have a valid context, the animation controller | 724 // Check if we still have a valid context, the animation controller |
690 // or document may have disappeared since we scheduled this. | 725 // or document may have disappeared since we scheduled this. |
691 Document* doc = this->GetDocument(); | 726 Document* doc = this->GetDocument(); |
692 if (!doc || display_blurred_ || !scripted_animation_controller_) | 727 if (!doc || display_blurred_) { |
728 DVLOG(2) << __FUNCTION__ << ": early exit, doc=" << doc | |
729 << " display_blurred_=" << display_blurred_; | |
693 return; | 730 return; |
731 } | |
694 | 732 |
695 TRACE_EVENT1("gpu", "VRDisplay::OnVSync", "frame", vr_frame_id_); | 733 TRACE_EVENT1("gpu", "VRDisplay::OnVSync", "frame", vr_frame_id_); |
696 | 734 |
697 AutoReset<bool> animating(&in_animation_frame_, true); | 735 if (pending_vrdisplay_raf_ && scripted_animation_controller_) { |
mthiesse
2017/04/28 20:35:39
nit: Checking pending_vrdisplay_raf_ is not really
klausw
2017/04/28 21:10:17
True, but seems a bit subtle and possibly fragile.
| |
698 pending_raf_ = false; | 736 // Run the callback, making sure that in_animation_frame_ is only |
699 | 737 // true for the vrDisplay rAF and not for a legacy window rAF |
700 scripted_animation_controller_->ServiceScriptedAnimations(timestamp); | 738 // that may be called later. |
739 AutoReset<bool> animating(&in_animation_frame_, true); | |
740 pending_vrdisplay_raf_ = false; | |
741 scripted_animation_controller_->ServiceScriptedAnimations(timestamp); | |
742 } | |
701 | 743 |
702 // For GVR, we shut down normal vsync processing during VR presentation. | 744 // For GVR, we shut down normal vsync processing during VR presentation. |
703 // Trigger any callbacks on window.rAF manually so that they run after | 745 // Trigger any callbacks on window.rAF manually so that they run after |
704 // completing the vrDisplay.rAF processing. | 746 // completing the vrDisplay.rAF processing. |
705 if (is_presenting_ && !capabilities_->hasExternalDisplay()) { | 747 if (is_presenting_ && !capabilities_->hasExternalDisplay()) { |
706 Platform::Current()->CurrentThread()->GetWebTaskRunner()->PostTask( | 748 Platform::Current()->CurrentThread()->GetWebTaskRunner()->PostTask( |
707 BLINK_FROM_HERE, WTF::Bind(&VRDisplay::ProcessScheduledWindowAnimations, | 749 BLINK_FROM_HERE, WTF::Bind(&VRDisplay::ProcessScheduledWindowAnimations, |
708 WrapWeakPersistent(this), timestamp)); | 750 WrapWeakPersistent(this), timestamp)); |
709 } | 751 } |
710 } | 752 } |
711 | 753 |
712 void VRDisplay::OnVSync(device::mojom::blink::VRPosePtr pose, | 754 void VRDisplay::OnVSync(device::mojom::blink::VRPosePtr pose, |
713 mojo::common::mojom::blink::TimeDeltaPtr time, | 755 mojo::common::mojom::blink::TimeDeltaPtr time, |
714 int16_t frame_id, | 756 int16_t frame_id, |
715 device::mojom::blink::VRVSyncProvider::Status error) { | 757 device::mojom::blink::VRVSyncProvider::Status error) { |
758 DVLOG(2) << __FUNCTION__; | |
716 v_sync_connection_failed_ = false; | 759 v_sync_connection_failed_ = false; |
717 switch (error) { | 760 switch (error) { |
718 case device::mojom::blink::VRVSyncProvider::Status::SUCCESS: | 761 case device::mojom::blink::VRVSyncProvider::Status::SUCCESS: |
719 break; | 762 break; |
720 case device::mojom::blink::VRVSyncProvider::Status::CLOSING: | 763 case device::mojom::blink::VRVSyncProvider::Status::CLOSING: |
721 return; | 764 return; |
722 } | 765 } |
723 pending_vsync_ = false; | 766 pending_vsync_ = false; |
724 | 767 |
725 WTF::TimeDelta time_delta = | 768 WTF::TimeDelta time_delta = |
(...skipping 19 matching lines...) Expand all Loading... | |
745 WTF::Bind(&VRDisplay::ProcessScheduledAnimations, | 788 WTF::Bind(&VRDisplay::ProcessScheduledAnimations, |
746 WrapWeakPersistent(this), timebase_ + time_delta.InSecondsF())); | 789 WrapWeakPersistent(this), timebase_ + time_delta.InSecondsF())); |
747 } | 790 } |
748 | 791 |
749 void VRDisplay::ConnectVSyncProvider() { | 792 void VRDisplay::ConnectVSyncProvider() { |
750 if (!navigator_vr_->IsFocused() || vr_v_sync_provider_.is_bound()) | 793 if (!navigator_vr_->IsFocused() || vr_v_sync_provider_.is_bound()) |
751 return; | 794 return; |
752 display_->GetVRVSyncProvider(mojo::MakeRequest(&vr_v_sync_provider_)); | 795 display_->GetVRVSyncProvider(mojo::MakeRequest(&vr_v_sync_provider_)); |
753 vr_v_sync_provider_.set_connection_error_handler(ConvertToBaseCallback( | 796 vr_v_sync_provider_.set_connection_error_handler(ConvertToBaseCallback( |
754 WTF::Bind(&VRDisplay::OnVSyncConnectionError, WrapWeakPersistent(this)))); | 797 WTF::Bind(&VRDisplay::OnVSyncConnectionError, WrapWeakPersistent(this)))); |
755 if (pending_raf_ && !display_blurred_) { | 798 if (pending_vrdisplay_raf_ && !display_blurred_) { |
756 pending_vsync_ = true; | 799 pending_vsync_ = true; |
757 vr_v_sync_provider_->GetVSync(ConvertToBaseCallback( | 800 vr_v_sync_provider_->GetVSync(ConvertToBaseCallback( |
758 WTF::Bind(&VRDisplay::OnVSync, WrapWeakPersistent(this)))); | 801 WTF::Bind(&VRDisplay::OnVSync, WrapWeakPersistent(this)))); |
759 } | 802 } |
760 } | 803 } |
761 | 804 |
762 void VRDisplay::OnVSyncConnectionError() { | 805 void VRDisplay::OnVSyncConnectionError() { |
763 vr_v_sync_provider_.reset(); | 806 vr_v_sync_provider_.reset(); |
764 if (v_sync_connection_failed_) | 807 if (v_sync_connection_failed_) |
765 return; | 808 return; |
(...skipping 28 matching lines...) Expand all Loading... | |
794 } | 837 } |
795 | 838 |
796 bool VRDisplay::HasPendingActivity() const { | 839 bool VRDisplay::HasPendingActivity() const { |
797 // Prevent V8 from garbage collecting the wrapper object if there are | 840 // Prevent V8 from garbage collecting the wrapper object if there are |
798 // event listeners attached to it. | 841 // event listeners attached to it. |
799 return GetExecutionContext() && HasEventListeners(); | 842 return GetExecutionContext() && HasEventListeners(); |
800 } | 843 } |
801 | 844 |
802 void VRDisplay::FocusChanged() { | 845 void VRDisplay::FocusChanged() { |
803 // TODO(mthiesse): Blur/focus the display. | 846 // TODO(mthiesse): Blur/focus the display. |
847 DVLOG(1) << __FUNCTION__; | |
804 vr_v_sync_provider_.reset(); | 848 vr_v_sync_provider_.reset(); |
805 ConnectVSyncProvider(); | 849 ConnectVSyncProvider(); |
806 } | 850 } |
807 | 851 |
808 DEFINE_TRACE(VRDisplay) { | 852 DEFINE_TRACE(VRDisplay) { |
809 EventTargetWithInlineData::Trace(visitor); | 853 EventTargetWithInlineData::Trace(visitor); |
810 ContextLifecycleObserver::Trace(visitor); | 854 ContextLifecycleObserver::Trace(visitor); |
811 visitor->Trace(navigator_vr_); | 855 visitor->Trace(navigator_vr_); |
812 visitor->Trace(capabilities_); | 856 visitor->Trace(capabilities_); |
813 visitor->Trace(stage_parameters_); | 857 visitor->Trace(stage_parameters_); |
814 visitor->Trace(eye_parameters_left_); | 858 visitor->Trace(eye_parameters_left_); |
815 visitor->Trace(eye_parameters_right_); | 859 visitor->Trace(eye_parameters_right_); |
816 visitor->Trace(layer_); | 860 visitor->Trace(layer_); |
817 visitor->Trace(rendering_context_); | 861 visitor->Trace(rendering_context_); |
818 visitor->Trace(scripted_animation_controller_); | 862 visitor->Trace(scripted_animation_controller_); |
819 visitor->Trace(pending_present_resolvers_); | 863 visitor->Trace(pending_present_resolvers_); |
820 } | 864 } |
821 | 865 |
822 } // namespace blink | 866 } // namespace blink |
OLD | NEW |