Bug 1476797 - Indicate VR session activity indepenently of layer presence r=daoshengmu

MozReview-Commit-ID: 4F0vclSj5gB

Differential Revision: https://phabricator.services.mozilla.com/D2451

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Kearwood Gilbert 2018-07-31 01:41:25 +00:00
Родитель 6da4b51b7b
Коммит 17fa5240f0
15 изменённых файлов: 197 добавлений и 39 удалений

Просмотреть файл

@ -2063,6 +2063,7 @@ nsGlobalWindowInner::PostHandleEvent(EventChainPostVisitor& aVisitor)
// forwards, navigating backwards, and on page reload.
for (const auto& display : mVRDisplays) {
if (display->IsPresenting()) {
display->StartVRNavigation();
// Save this VR display ID to trigger vrdisplayactivate event
// after the next load event.
nsGlobalWindowOuter* outer = GetOuterWindowInternal();

Просмотреть файл

@ -498,11 +498,24 @@ VRDisplay::ResetPose()
mClient->ZeroSensor();
}
void
VRDisplay::StartVRNavigation()
{
mClient->StartVRNavigation();
}
void
VRDisplay::StartHandlingVRNavigationEvent()
{
mHandlingVRNavigationEventStart = TimeStamp::Now();
++mVRNavigationEventDepth;
TimeDuration timeout = TimeDuration::FromMilliseconds(gfxPrefs::VRNavigationTimeout());
// A 0 or negative TimeDuration indicates that content may take
// as long as it wishes to respond to the event, as long as
// it happens before the event exits.
if (timeout.ToMilliseconds() > 0) {
mClient->StopVRNavigation(timeout);
}
}
void
@ -510,6 +523,9 @@ VRDisplay::StopHandlingVRNavigationEvent()
{
MOZ_ASSERT(mVRNavigationEventDepth > 0);
--mVRNavigationEventDepth;
if (mVRNavigationEventDepth == 0) {
mClient->StopVRNavigation(TimeDuration::FromMilliseconds(0));
}
}
bool
@ -522,7 +538,7 @@ VRDisplay::IsHandlingVRNavigationEvent()
return false;
}
TimeDuration timeout = TimeDuration::FromMilliseconds(gfxPrefs::VRNavigationTimeout());
return timeout <= TimeDuration(0) ||
return timeout.ToMilliseconds() <= 0 ||
(TimeStamp::Now() - mHandlingVRNavigationEventStart) <= timeout;
}

Просмотреть файл

@ -363,6 +363,7 @@ public:
int32_t RequestAnimationFrame(mozilla::dom::FrameRequestCallback& aCallback,
mozilla::ErrorResult& aError);
void CancelAnimationFrame(int32_t aHandle, mozilla::ErrorResult& aError);
void StartVRNavigation();
void StartHandlingVRNavigationEvent();
void StopHandlingVRNavigationEvent();
bool IsHandlingVRNavigationEvent();

Просмотреть файл

@ -297,3 +297,31 @@ VRDisplayClient::GetSubmitFrameResult(VRSubmitFrameResultInfo& aResult)
{
aResult = mSubmitFrameResult;
}
void
VRDisplayClient::StartVRNavigation()
{
/**
* A VR-to-VR site navigation has started, notify VRManager
* so we don't drop out of VR during the transition
*/
VRManagerChild *vm = VRManagerChild::Get();
vm->SendStartVRNavigation(mDisplayInfo.mDisplayID);
}
void
VRDisplayClient::StopVRNavigation(const TimeDuration& aTimeout)
{
/**
* A VR-to-VR site navigation has ended and the new site
* has received a vrdisplayactivate event.
* Don't actually consider the navigation transition over
* until aTimeout has elapsed.
* This may be called multiple times, in which case the timeout
* should be reset to aTimeout.
* When aTimeout is TimeDuration(0), we should consider the
* transition immediately ended.
*/
VRManagerChild *vm = VRManagerChild::Get();
vm->SendStopVRNavigation(mDisplayInfo.mDisplayID, aTimeout);
}

Просмотреть файл

@ -47,6 +47,9 @@ public:
bool IsPresentationGenerationCurrent() const;
void MakePresentationGenerationCurrent();
void StartVRNavigation();
void StopVRNavigation(const TimeDuration& aTimeout);
protected:
virtual ~VRDisplayClient();

Просмотреть файл

@ -345,6 +345,18 @@ VRDisplayHost::CheckClearDisplayInfoDirty()
return true;
}
void
VRDisplayHost::StartVRNavigation()
{
}
void
VRDisplayHost::StopVRNavigation(const TimeDuration& aTimeout)
{
}
VRControllerHost::VRControllerHost(VRDeviceType aType, dom::GamepadHand aHand,
uint32_t aDisplayID)
: mControllerInfo{}
@ -422,3 +434,4 @@ VRControllerHost::GetVibrateIndex()
{
return mVibrateIndex;
}

Просмотреть файл

@ -42,6 +42,8 @@ public:
virtual void ZeroSensor() = 0;
virtual void StartPresentation() = 0;
virtual void StopPresentation() = 0;
virtual void StartVRNavigation();
virtual void StopVRNavigation(const TimeDuration& aTimeout);
void NotifyVSync();
void StartFrame();

Просмотреть файл

@ -599,5 +599,23 @@ VRManager::DispatchSubmitFrameResult(uint32_t aDisplayID, const VRSubmitFrameRes
}
}
void
VRManager::StartVRNavigation(const uint32_t& aDisplayID)
{
RefPtr<VRDisplayHost> display = GetDisplay(aDisplayID);
if (display) {
display->StartVRNavigation();
}
}
void
VRManager::StopVRNavigation(const uint32_t& aDisplayID, const TimeDuration& aTimeout)
{
RefPtr<VRDisplayHost> display = GetDisplay(aDisplayID);
if (display) {
display->StopVRNavigation(aTimeout);
}
}
} // namespace gfx
} // namespace mozilla

Просмотреть файл

@ -60,6 +60,8 @@ public:
void StopVibrateHaptic(uint32_t aControllerIdx);
void NotifyVibrateHapticCompleted(const VRManagerPromise& aPromise);
void DispatchSubmitFrameResult(uint32_t aDisplayID, const VRSubmitFrameResultInfo& aResult);
void StartVRNavigation(const uint32_t& aDisplayID);
void StopVRNavigation(const uint32_t& aDisplayID, const TimeDuration& aTimeout);
protected:
VRManager();

Просмотреть файл

@ -29,7 +29,7 @@ namespace dom {
#endif // MOZILLA_INTERNAL_API
namespace gfx {
static const int32_t kVRExternalVersion = 1;
static const int32_t kVRExternalVersion = 2;
// We assign VR presentations to groups with a bitmask.
// Currently, we will only display either content or chrome.
@ -359,6 +359,8 @@ struct VRBrowserState
#if defined(__ANDROID__)
bool shutdown;
#endif // defined(__ANDROID__)
bool presentationActive;
bool navigationTransitionActive;
VRLayerState layerState[kVRLayerMaxCount];
};

Просмотреть файл

@ -56,7 +56,7 @@ int VRDisplayExternal::sPushIndex = 0;
VRDisplayExternal::VRDisplayExternal(const VRDisplayState& aDisplayState)
: VRDisplayHost(VRDeviceType::External)
, mIsPresenting(false)
, mBrowserState{}
, mLastSensorState{}
{
MOZ_COUNT_CTOR_INHERITED(VRDisplayExternal, VRDisplayHost);
@ -86,10 +86,14 @@ VRDisplayExternal::ZeroSensor()
void
VRDisplayExternal::Refresh()
{
VRManager *vm = VRManager::Get();
VRSystemManagerExternal* manager = vm->GetExternalManager();
manager->PullState(&mDisplayInfo.mDisplayState, &mLastSensorState, mDisplayInfo.mControllerState);
if (!mVRNavigationTransitionEnd.IsNull() &&
TimeStamp::Now() > mVRNavigationTransitionEnd) {
mBrowserState.navigationTransitionActive = false;
}
PullState();
PushState();
}
VRHMDSensorState
@ -101,21 +105,17 @@ VRDisplayExternal::GetSensorState()
void
VRDisplayExternal::StartPresentation()
{
if (mIsPresenting) {
if (mBrowserState.presentationActive) {
return;
}
sPushIndex = 0;
mIsPresenting = true;
mTelemetry.Clear();
mTelemetry.mPresentationStart = TimeStamp::Now();
// Indicate that we are ready to start immersive mode
VRBrowserState state;
memset(&state, 0, sizeof(VRBrowserState));
state.layerState[0].type = VRLayerType::LayerType_Stereo_Immersive;
VRManager *vm = VRManager::Get();
VRSystemManagerExternal* manager = vm->GetExternalManager();
manager->PushState(&state);
mBrowserState.presentationActive = true;
mBrowserState.layerState[0].type = VRLayerType::LayerType_Stereo_Immersive;
PushState();
// TODO - Implement telemetry:
@ -125,18 +125,16 @@ VRDisplayExternal::StartPresentation()
void
VRDisplayExternal::StopPresentation()
{
if (!mIsPresenting) {
if (!mBrowserState.presentationActive) {
return;
}
mIsPresenting = false;
sPushIndex = 0;
// Indicate that we have stopped immersive mode
VRBrowserState state;
memset(&state, 0, sizeof(VRBrowserState));
VRManager *vm = VRManager::Get();
VRSystemManagerExternal* manager = vm->GetExternalManager();
manager->PushState(&state, true);
mBrowserState.presentationActive = false;
memset(mBrowserState.layerState, 0, sizeof(VRLayerState) * mozilla::ArrayLength(mBrowserState.layerState));
PushState(true);
// TODO - Implement telemetry:
@ -154,6 +152,25 @@ VRDisplayExternal::StopPresentation()
*/
}
void
VRDisplayExternal::StartVRNavigation()
{
mBrowserState.navigationTransitionActive = true;
mVRNavigationTransitionEnd = TimeStamp();
PushState();
}
void
VRDisplayExternal::StopVRNavigation(const TimeDuration& aTimeout)
{
if (aTimeout.ToMilliseconds() <= 0) {
mBrowserState.navigationTransitionActive = false;
mVRNavigationTransitionEnd = TimeStamp();
PushState();
}
mVRNavigationTransitionEnd = TimeStamp::Now() + aTimeout;
}
bool
VRDisplayExternal::PopulateLayerTexture(const layers::SurfaceDescriptor& aTexture,
VRLayerTextureType* aTextureType,
@ -207,10 +224,8 @@ VRDisplayExternal::SubmitFrame(const layers::SurfaceDescriptor& aTexture,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect)
{
VRBrowserState state;
memset(&state, 0, sizeof(VRBrowserState));
state.layerState[0].type = VRLayerType::LayerType_Stereo_Immersive;
VRLayer_Stereo_Immersive& layer = state.layerState[0].layer_stereo_immersive;
MOZ_ASSERT(mBrowserState.layerState[0].type == VRLayerType::LayerType_Stereo_Immersive);
VRLayer_Stereo_Immersive& layer = mBrowserState.layerState[0].layer_stereo_immersive;
if (!PopulateLayerTexture(aTexture, &layer.mTextureType, &layer.mTextureHandle)) {
return false;
}
@ -226,26 +241,24 @@ VRDisplayExternal::SubmitFrame(const layers::SurfaceDescriptor& aTexture,
layer.mRightEyeRect.width = aRightEyeRect.width;
layer.mRightEyeRect.height = aRightEyeRect.height;
VRManager *vm = VRManager::Get();
VRSystemManagerExternal* manager = vm->GetExternalManager();
manager->PushState(&state, true);
PushState(true);
sPushIndex++;
VRDisplayState displayState;
memset(&displayState, 0, sizeof(VRDisplayState));
#if defined(MOZ_WIDGET_ANDROID)
manager->PullState(&displayState, &mLastSensorState, mDisplayInfo.mControllerState, [&]() {
return (displayState.mLastSubmittedFrameId >= aFrameId) || displayState.mSuppressFrames || !displayState.mIsConnected;
PullState([&]() {
return (mDisplayInfo.mDisplayState.mLastSubmittedFrameId >= aFrameId) ||
mDisplayInfo.mDisplayState.mSuppressFrames ||
!mDisplayInfo.mDisplayState.mIsConnected;
});
if (displayState.mSuppressFrames || !displayState.mIsConnected) {
if (mDisplayInfo.mDisplayState.mSuppressFrames || !mDisplayInfo.mDisplayState.mIsConnected) {
// External implementation wants to supress frames, service has shut down or hardware has been disconnected.
return false;
}
#else
while (displayState.mLastSubmittedFrameId < aFrameId) {
if (manager->PullState(&displayState, &mLastSensorState, mDisplayInfo.mControllerState)) {
if (displayState.mSuppressFrames || !displayState.mIsConnected) {
while (mDisplayInfo.mDisplayState.mLastSubmittedFrameId < aFrameId) {
if (PullState()) {
if (mDisplayInfo.mDisplayState.mSuppressFrames || !mDisplayInfo.mDisplayState.mIsConnected) {
// External implementation wants to supress frames, service has shut down or hardware has been disconnected.
return false;
}
@ -258,9 +271,40 @@ VRDisplayExternal::SubmitFrame(const layers::SurfaceDescriptor& aTexture,
}
#endif // defined(MOZ_WIDGET_ANDROID)
return displayState.mLastSubmittedFrameSuccessful;
return mDisplayInfo.mDisplayState.mLastSubmittedFrameSuccessful;
}
void
VRDisplayExternal::PushState(bool aNotifyCond)
{
VRManager *vm = VRManager::Get();
VRSystemManagerExternal* manager = vm->GetExternalManager();
manager->PushState(&mBrowserState, aNotifyCond);
}
#if defined(MOZ_WIDGET_ANDROID)
bool
VRDisplayExternal::PullState(const std::function<bool()>& aWaitCondition)
{
VRManager *vm = VRManager::Get();
VRSystemManagerExternal* manager = vm->GetExternalManager();
return manager->PullState(&mDisplayInfo.mDisplayState,
&mLastSensorState,
mDisplayInfo.mControllerState,
aWaitCondition);
}
#else
bool
VRDisplayExternal::PullState()
{
VRManager *vm = VRManager::Get();
VRSystemManagerExternal* manager = vm->GetExternalManager();
return manager->PullState(&mDisplayInfo.mDisplayState,
&mLastSensorState,
mDisplayInfo.mControllerState);
}
#endif
VRSystemManagerExternal::VRSystemManagerExternal(VRExternalShmem* aAPIShmem /* = nullptr*/)
: mExternalShmem(aAPIShmem)
#if !defined(MOZ_WIDGET_ANDROID)

Просмотреть файл

@ -37,6 +37,8 @@ protected:
VRHMDSensorState GetSensorState() override;
void StartPresentation() override;
void StopPresentation() override;
void StartVRNavigation() override;
void StopVRNavigation(const TimeDuration& aTimeout) override;
bool SubmitFrame(const layers::SurfaceDescriptor& aTexture,
uint64_t aFrameId,
@ -55,9 +57,16 @@ private:
bool PopulateLayerTexture(const layers::SurfaceDescriptor& aTexture,
VRLayerTextureType* aTextureType,
VRLayerTextureHandle* aTextureHandle);
void PushState(bool aNotifyCond = false);
#if defined(MOZ_WIDGET_ANDROID)
bool PullState(const std::function<bool()>& aWaitCondition = nullptr);
#else
bool PullState();
#endif
VRTelemetry mTelemetry;
bool mIsPresenting;
TimeStamp mVRNavigationTransitionEnd;
VRBrowserState mBrowserState;
VRHMDSensorState mLastSensorState;
};

Просмотреть файл

@ -65,6 +65,8 @@ parent:
async NewAxisMoveEventToMockController(uint32_t aDeviceID, long aAxis,
double aValue);
async NewPoseMoveToMockController(uint32_t aDeviceID, GamepadPoseState aPose);
async StartVRNavigation(uint32_t aDeviceID);
async StopVRNavigation(uint32_t aDeviceID, TimeDuration aDuration);
child:
// Notify children of updated VR display enumeration and details. This will

Просмотреть файл

@ -434,5 +434,21 @@ VRManagerParent::SendReplyGamepadVibrateHaptic(const uint32_t& aPromiseID)
return true;
}
mozilla::ipc::IPCResult
VRManagerParent::RecvStartVRNavigation(const uint32_t& aDeviceID)
{
VRManager* vm = VRManager::Get();
vm->StartVRNavigation(aDeviceID);
return IPC_OK();
}
mozilla::ipc::IPCResult
VRManagerParent::RecvStopVRNavigation(const uint32_t& aDeviceID, const TimeDuration& aTimeout)
{
VRManager* vm = VRManager::Get();
vm->StopVRNavigation(aDeviceID, aTimeout);
return IPC_OK();
}
} // namespace gfx
} // namespace mozilla

Просмотреть файл

@ -73,7 +73,8 @@ protected:
virtual mozilla::ipc::IPCResult RecvNewAxisMoveEventToMockController(const uint32_t& aDeviceID, const long& aAxis,
const double& aValue) override;
virtual mozilla::ipc::IPCResult RecvNewPoseMoveToMockController(const uint32_t& aDeviceID, const GamepadPoseState& pose) override;
virtual mozilla::ipc::IPCResult RecvStartVRNavigation(const uint32_t& aDeviceID) override;
virtual mozilla::ipc::IPCResult RecvStopVRNavigation(const uint32_t& aDeviceID, const TimeDuration& aTimeout) override;
private:
void RegisterWithManager();
void UnregisterFromManager();