| Index: third_party/WebKit/Source/modules/vr/VRDisplay.cpp
|
| diff --git a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
|
| index 900b0a264af724c97a8e73086f945556ab30f406..829d1de2363f59e714247639ccf0e184825fe3b7 100644
|
| --- a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
|
| +++ b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
|
| @@ -29,6 +29,7 @@
|
| #include "platform/UserGestureIndicator.h"
|
| #include "public/platform/Platform.h"
|
| #include "wtf/AutoReset.h"
|
| +#include "wtf/Time.h"
|
|
|
| #include <array>
|
|
|
| @@ -48,33 +49,6 @@ VREye stringToVREye(const String& whichEye) {
|
| return VREyeNone;
|
| }
|
|
|
| -class VRDisplayFrameRequestCallback : public FrameRequestCallback {
|
| - public:
|
| - VRDisplayFrameRequestCallback(VRDisplay* vrDisplay) : m_vrDisplay(vrDisplay) {
|
| - m_useLegacyTimeBase = true;
|
| - }
|
| - ~VRDisplayFrameRequestCallback() override {}
|
| - void handleEvent(double highResTimeMs) override {
|
| - Document* doc = m_vrDisplay->document();
|
| - if (!doc)
|
| - return;
|
| -
|
| - // Need to divide by 1000 here because serviceScriptedAnimations expects
|
| - // time to be given in seconds.
|
| - m_vrDisplay->serviceScriptedAnimations(
|
| - doc->loader()->timing().pseudoWallTimeToMonotonicTime(highResTimeMs /
|
| - 1000.0));
|
| - }
|
| -
|
| - DEFINE_INLINE_VIRTUAL_TRACE() {
|
| - visitor->trace(m_vrDisplay);
|
| -
|
| - FrameRequestCallback::trace(visitor);
|
| - }
|
| -
|
| - Member<VRDisplay> m_vrDisplay;
|
| -};
|
| -
|
| } // namespace
|
|
|
| VRDisplay::VRDisplay(NavigatorVR* navigatorVR,
|
| @@ -82,25 +56,16 @@ VRDisplay::VRDisplay(NavigatorVR* navigatorVR,
|
| device::mojom::blink::VRDisplayClientRequest request)
|
| : ContextLifecycleObserver(navigatorVR->document()),
|
| m_navigatorVR(navigatorVR),
|
| - m_isConnected(false),
|
| - m_isPresenting(false),
|
| - m_isValidDeviceForPresenting(true),
|
| - m_canUpdateFramePose(true),
|
| m_capabilities(new VRDisplayCapabilities()),
|
| m_eyeParametersLeft(new VREyeParameters()),
|
| m_eyeParametersRight(new VREyeParameters()),
|
| - m_depthNear(0.01),
|
| - m_depthFar(10000.0),
|
| m_fullscreenCheckTimer(
|
| TaskRunnerHelper::get(TaskType::UnspecedTimer,
|
| navigatorVR->document()->frame()),
|
| this,
|
| &VRDisplay::onFullscreenCheck),
|
| - m_contextGL(nullptr),
|
| - m_animationCallbackRequested(false),
|
| - m_inAnimationFrame(false),
|
| m_display(std::move(display)),
|
| - m_binding(this, std::move(request)) {}
|
| + m_displayClientBinding(this, std::move(request)) {}
|
|
|
| VRDisplay::~VRDisplay() {}
|
|
|
| @@ -149,9 +114,7 @@ void VRDisplay::disconnected() {
|
| }
|
|
|
| bool VRDisplay::getFrameData(VRFrameData* frameData) {
|
| - updatePose();
|
| -
|
| - if (!m_framePose)
|
| + if (!m_framePose || m_displayBlurred)
|
| return false;
|
|
|
| if (!frameData)
|
| @@ -165,9 +128,7 @@ bool VRDisplay::getFrameData(VRFrameData* frameData) {
|
| }
|
|
|
| VRPose* VRDisplay::getPose() {
|
| - updatePose();
|
| -
|
| - if (!m_framePose)
|
| + if (!m_framePose || m_displayBlurred)
|
| return nullptr;
|
|
|
| VRPose* pose = VRPose::create();
|
| @@ -175,23 +136,6 @@ VRPose* VRDisplay::getPose() {
|
| return pose;
|
| }
|
|
|
| -void VRDisplay::updatePose() {
|
| - if (m_displayBlurred) {
|
| - // WebVR spec says to return a null pose when the display is blurred.
|
| - m_framePose = nullptr;
|
| - return;
|
| - }
|
| - if (m_canUpdateFramePose) {
|
| - if (!m_display)
|
| - return;
|
| - device::mojom::blink::VRPosePtr pose;
|
| - m_display->GetPose(&pose);
|
| - m_framePose = std::move(pose);
|
| - if (m_isPresenting)
|
| - m_canUpdateFramePose = false;
|
| - }
|
| -}
|
| -
|
| void VRDisplay::resetPose() {
|
| if (!m_display)
|
| return;
|
| @@ -214,12 +158,13 @@ int VRDisplay::requestAnimationFrame(FrameRequestCallback* callback) {
|
| Document* doc = this->document();
|
| if (!doc)
|
| return 0;
|
| -
|
| - if (!m_animationCallbackRequested) {
|
| - doc->requestAnimationFrame(new VRDisplayFrameRequestCallback(this));
|
| - m_animationCallbackRequested = true;
|
| + m_pendingRaf = true;
|
| + if (!m_vrVSyncProvider.is_bound()) {
|
| + ConnectVSyncProvider();
|
| + } else if (!m_displayBlurred) {
|
| + m_vrVSyncProvider->GetVSync(convertToBaseCallback(
|
| + WTF::bind(&VRDisplay::OnVSync, wrapWeakPersistent(this))));
|
| }
|
| -
|
| callback->m_useLegacyTimeBase = false;
|
| return ensureScriptedAnimationController(doc).registerCallback(callback);
|
| }
|
| @@ -232,44 +177,18 @@ void VRDisplay::cancelAnimationFrame(int id) {
|
|
|
| void VRDisplay::OnBlur() {
|
| m_displayBlurred = true;
|
| -
|
| + m_vrVSyncProvider.reset();
|
| m_navigatorVR->enqueueVREvent(VRDisplayEvent::create(
|
| EventTypeNames::vrdisplayblur, true, false, this, ""));
|
| }
|
|
|
| void VRDisplay::OnFocus() {
|
| m_displayBlurred = false;
|
| - // Restart our internal doc requestAnimationFrame callback, if it fired while
|
| - // the display was blurred.
|
| - // TODO(bajones): Don't use doc->requestAnimationFrame() at all. Animation
|
| - // frames should be tied to the presenting VR display (e.g. should be serviced
|
| - // by GVR library callbacks on Android), and not the doc frame rate.
|
| - if (!m_animationCallbackRequested) {
|
| - Document* doc = this->document();
|
| - if (!doc)
|
| - return;
|
| - doc->requestAnimationFrame(new VRDisplayFrameRequestCallback(this));
|
| - }
|
| + ConnectVSyncProvider();
|
| m_navigatorVR->enqueueVREvent(VRDisplayEvent::create(
|
| EventTypeNames::vrdisplayfocus, true, false, this, ""));
|
| }
|
|
|
| -void VRDisplay::serviceScriptedAnimations(double monotonicAnimationStartTime) {
|
| - if (!m_scriptedAnimationController)
|
| - return;
|
| - AutoReset<bool> animating(&m_inAnimationFrame, true);
|
| - m_animationCallbackRequested = false;
|
| -
|
| - // We use an internal rAF callback to run the animation loop at the display
|
| - // speed, and run the user's callback after our internal callback fires.
|
| - // However, when the display is blurred, we want to pause the animation loop,
|
| - // so we don't fire the user's callback until the display is focused.
|
| - if (m_displayBlurred)
|
| - return;
|
| - m_scriptedAnimationController->serviceScriptedAnimations(
|
| - monotonicAnimationStartTime);
|
| -}
|
| -
|
| void ReportPresentationResult(PresentationResult result) {
|
| // Note that this is called twice for each call to requestPresent -
|
| // one to declare that requestPresent was called, and one for the
|
| @@ -655,7 +574,6 @@ void VRDisplay::submitFrame() {
|
| m_renderingContext->restoreClearColor();
|
|
|
| m_display->SubmitFrame(m_framePose.Clone());
|
| - m_canUpdateFramePose = true;
|
| }
|
|
|
| Document* VRDisplay::document() {
|
| @@ -700,6 +618,47 @@ void VRDisplay::OnDeactivate(
|
| EventTypeNames::vrdisplaydeactivate, true, false, this, reason));
|
| }
|
|
|
| +void VRDisplay::OnVSync(device::mojom::blink::VRPosePtr pose,
|
| + mojo::common::mojom::blink::TimeDeltaPtr time) {
|
| + WTF::TimeDelta timeDelta =
|
| + WTF::TimeDelta::FromMicroseconds(time->microseconds);
|
| + // The VSync provider cannot shut down before replying to pending callbacks,
|
| + // so it will send a null pose with no timestamp to be ignored.
|
| + if (pose.is_null() && timeDelta.is_zero()) {
|
| + // We need to keep the VSync loop going because we haven't responded to the
|
| + // previous rAF yet.
|
| + m_vrVSyncProvider->GetVSync(convertToBaseCallback(
|
| + WTF::bind(&VRDisplay::OnVSync, wrapWeakPersistent(this))));
|
| + return;
|
| + }
|
| + if (m_displayBlurred)
|
| + return;
|
| + if (!m_scriptedAnimationController)
|
| + return;
|
| + Document* doc = this->document();
|
| + if (!doc)
|
| + return;
|
| +
|
| + // Ensure a consistent timebase with document rAF.
|
| + if (m_timebase < 0) {
|
| + m_timebase = WTF::monotonicallyIncreasingTime() - timeDelta.InSecondsF();
|
| + }
|
| +
|
| + AutoReset<bool> animating(&m_inAnimationFrame, true);
|
| + m_framePose = std::move(pose);
|
| + m_pendingRaf = false;
|
| + m_scriptedAnimationController->serviceScriptedAnimations(
|
| + m_timebase + timeDelta.InSecondsF());
|
| +}
|
| +
|
| +void VRDisplay::ConnectVSyncProvider() {
|
| + m_display->GetVRVSyncProvider(mojo::MakeRequest(&m_vrVSyncProvider));
|
| + if (m_pendingRaf && !m_displayBlurred) {
|
| + m_vrVSyncProvider->GetVSync(convertToBaseCallback(
|
| + WTF::bind(&VRDisplay::OnVSync, wrapWeakPersistent(this))));
|
| + }
|
| +}
|
| +
|
| void VRDisplay::onFullscreenCheck(TimerBase*) {
|
| if (!m_isPresenting) {
|
| m_fullscreenCheckTimer.stop();
|
| @@ -745,7 +704,8 @@ ScriptedAnimationController& VRDisplay::ensureScriptedAnimationController(
|
| }
|
|
|
| void VRDisplay::dispose() {
|
| - m_binding.Close();
|
| + m_displayClientBinding.Close();
|
| + m_vrVSyncProvider.reset();
|
| }
|
|
|
| ExecutionContext* VRDisplay::getExecutionContext() const {
|
|
|