--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -41,16 +41,17 @@
#include "mozilla/dom/FlyWebService.h"
#include "mozilla/dom/Permissions.h"
#include "mozilla/dom/Presentation.h"
#include "mozilla/dom/ServiceWorkerContainer.h"
#include "mozilla/dom/StorageManager.h"
#include "mozilla/dom/TCPSocket.h"
#include "mozilla/dom/URLSearchParams.h"
#include "mozilla/dom/VRDisplay.h"
+#include "mozilla/dom/VRDisplayEvent.h"
#include "mozilla/dom/VRServiceTest.h"
#include "mozilla/dom/WebAuthentication.h"
#include "mozilla/dom/workers/RuntimeService.h"
#include "mozilla/Hal.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/SSE.h"
#include "mozilla/StaticPtr.h"
#include "Connection.h"
@@ -1562,16 +1563,37 @@ Navigator::RequestVRServiceTest()
win->NotifyVREventListenerAdded();
if (!mVRServiceTest) {
mVRServiceTest = VRServiceTest::CreateTestService(mWindow);
}
return mVRServiceTest;
}
+bool
+Navigator::IsWebVRContentDetected() const
+{
+ nsGlobalWindow* win = nsGlobalWindow::Cast(mWindow);
+ return win->IsVRContentDetected();
+}
+
+bool
+Navigator::IsWebVRContentPresenting() const
+{
+ nsGlobalWindow* win = nsGlobalWindow::Cast(mWindow);
+ return win->IsVRContentPresenting();
+}
+
+void
+Navigator::RequestVRPresentation(VRDisplay& aDisplay)
+{
+ nsGlobalWindow* win = nsGlobalWindow::Cast(mWindow);
+ win->DispatchVRDisplayActivate(aDisplay.DisplayId(), VRDisplayEventReason::Requested);
+}
+
//*****************************************************************************
// Navigator::nsIMozNavigatorNetwork
//*****************************************************************************
NS_IMETHODIMP
Navigator::GetProperties(nsINetworkProperties** aProperties)
{
ErrorResult rv;
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -193,16 +193,19 @@ public:
network::Connection* GetConnection(ErrorResult& aRv);
MediaDevices* GetMediaDevices(ErrorResult& aRv);
void GetGamepads(nsTArray<RefPtr<Gamepad> >& aGamepads, ErrorResult& aRv);
GamepadServiceTest* RequestGamepadServiceTest();
already_AddRefed<Promise> GetVRDisplays(ErrorResult& aRv);
void GetActiveVRDisplays(nsTArray<RefPtr<VRDisplay>>& aDisplays) const;
VRServiceTest* RequestVRServiceTest();
+ bool IsWebVRContentDetected() const;
+ bool IsWebVRContentPresenting() const;
+ void RequestVRPresentation(VRDisplay& aDisplay);
#ifdef MOZ_TIME_MANAGER
time::TimeManager* GetMozTime(ErrorResult& aRv);
#endif // MOZ_TIME_MANAGER
Presentation* GetPresentation(ErrorResult& aRv);
bool SendBeacon(const nsAString& aUrl,
const Nullable<fetch::BodyInit>& aData,
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -198,16 +198,17 @@
#include "mozilla/dom/IDBFactory.h"
#include "mozilla/dom/MessageChannel.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/Gamepad.h"
#include "mozilla/dom/GamepadManager.h"
+#include "gfxVR.h"
#include "mozilla/dom/VRDisplay.h"
#include "mozilla/dom/VRDisplayEvent.h"
#include "mozilla/dom/VRDisplayEventBinding.h"
#include "mozilla/dom/VREventObserver.h"
#include "nsRefreshDriver.h"
#include "Layers.h"
@@ -1567,16 +1568,17 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalW
mIsChrome(false),
mCleanMessageManager(false),
mNeedsFocus(true),
mHasFocus(false),
mShowFocusRingForContent(false),
mFocusByKeyOccurred(false),
mHasGamepad(false),
mHasVREvents(false),
+ mHasVRDisplayActivateEvents(false),
mHasSeenGamepadInput(false),
mNotifiedIDDestroyed(false),
mAllowScriptsToClose(false),
mTopLevelOuterContentWindow(false),
mSuspendDepth(0),
mFreezeDepth(0),
mFocusMethod(0),
mSerial(0),
@@ -1996,23 +1998,25 @@ nsGlobalWindow::CleanUp()
}
}
if (IsInnerWindow()) {
DisableGamepadUpdates();
mHasGamepad = false;
DisableVRUpdates();
mHasVREvents = false;
+ mHasVRDisplayActivateEvents = false;
#ifdef MOZ_B2G
DisableTimeChangeNotifications();
#endif
DisableIdleCallbackRequests();
} else {
MOZ_ASSERT(!mHasGamepad);
MOZ_ASSERT(!mHasVREvents);
+ MOZ_ASSERT(!mHasVRDisplayActivateEvents);
}
if (mCleanMessageManager) {
MOZ_ASSERT(mIsChrome, "only chrome should have msg manager cleaned");
nsGlobalChromeWindow *asChrome = static_cast<nsGlobalChromeWindow*>(this);
if (asChrome->mMessageManager) {
static_cast<nsFrameMessageManager*>(
asChrome->mMessageManager.get())->Disconnect();
@@ -2165,16 +2169,17 @@ nsGlobalWindow::FreeInnerObjects()
}
mAudioContexts.Clear();
DisableGamepadUpdates();
mHasGamepad = false;
mGamepads.Clear();
DisableVRUpdates();
mHasVREvents = false;
+ mHasVRDisplayActivateEvents = false;
mVRDisplays.Clear();
if (mTabChild) {
while (mBeforeUnloadListenerCount-- > 0) {
mTabChild->BeforeUnloadRemoved();
}
}
}
@@ -13518,16 +13523,20 @@ nsGlobalWindow::EventListenerAdded(nsIAt
if (aType == nsGkAtoms::onvrdisplayactivate ||
aType == nsGkAtoms::onvrdisplayconnect ||
aType == nsGkAtoms::onvrdisplaydeactivate ||
aType == nsGkAtoms::onvrdisplaydisconnect ||
aType == nsGkAtoms::onvrdisplaypresentchange) {
NotifyVREventListenerAdded();
}
+ if (aType == nsGkAtoms::onvrdisplayactivate) {
+ mHasVRDisplayActivateEvents = true;
+ }
+
if (aType == nsGkAtoms::onbeforeunload &&
mTabChild &&
(!mDoc || !(mDoc->GetSandboxFlags() & SANDBOXED_MODALS))) {
MOZ_ASSERT(IsInnerWindow());
mBeforeUnloadListenerCount++;
MOZ_ASSERT(mBeforeUnloadListenerCount > 0);
mTabChild->BeforeUnloadAdded();
}
@@ -13561,19 +13570,42 @@ nsGlobalWindow::NotifyVREventListenerAdd
EnableVRUpdates();
}
bool
nsGlobalWindow::HasUsedVR() const
{
MOZ_ASSERT(IsInnerWindow());
+ // Returns true only if any WebVR API call or related event
+ // has been used
return mHasVREvents;
}
+bool
+nsGlobalWindow::IsVRContentDetected() const
+{
+ MOZ_ASSERT(IsInnerWindow());
+
+ // Returns true only if the content will respond to
+ // the VRDisplayActivate event.
+ return mHasVRDisplayActivateEvents;
+}
+
+bool
+nsGlobalWindow::IsVRContentPresenting() const
+{
+ for (auto display : mVRDisplays) {
+ if (display->IsAnyPresenting(gfx::kVRGroupAll)) {
+ return true;
+ }
+ }
+ return false;
+}
+
void
nsGlobalWindow::EnableTimeChangeNotifications()
{
mozilla::time::AddWindowListener(AsInner());
}
void
nsGlobalWindow::DisableTimeChangeNotifications()
@@ -13758,17 +13790,17 @@ void
nsGlobalWindow::DispatchVRDisplayActivate(uint32_t aDisplayID,
mozilla::dom::VRDisplayEventReason aReason)
{
// Search for the display identified with aDisplayID and fire the
// event if found.
for (auto display : mVRDisplays) {
if (display->DisplayId() == aDisplayID) {
if (aReason != VRDisplayEventReason::Navigation &&
- display->IsAnyPresenting()) {
+ display->IsAnyPresenting(gfx::kVRGroupContent)) {
// We only want to trigger this event if nobody is presenting to the
// display already or when a page is loaded by navigating away
// from a page with an active VR Presentation.
continue;
}
VRDisplayEventInit init;
init.mBubbles = false;
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -452,16 +452,18 @@ public:
bool SetWidgetFullscreen(FullscreenReason aReason, bool aIsFullscreen,
nsIWidget* aWidget, nsIScreen* aScreen);
bool FullScreen() const;
// Inner windows only.
virtual void SetHasGamepadEventListener(bool aHasGamepad = true) override;
void NotifyVREventListenerAdded();
bool HasUsedVR() const;
+ bool IsVRContentDetected() const;
+ bool IsVRContentPresenting() const;
using EventTarget::EventListenerAdded;
virtual void EventListenerAdded(nsIAtom* aType) override;
using EventTarget::EventListenerRemoved;
virtual void EventListenerRemoved(nsIAtom* aType) override;
// nsIInterfaceRequestor
NS_DECL_NSIINTERFACEREQUESTOR
@@ -1902,16 +1904,20 @@ protected:
// Inner windows only.
// Indicates whether this window wants gamepad input events
bool mHasGamepad : 1;
// Inner windows only.
// Indicates whether this window wants VR events
bool mHasVREvents : 1;
+
+ // Inner windows only.
+ // Indicates whether this window wants VRDisplayActivate events
+ bool mHasVRDisplayActivateEvents : 1;
nsCheapSet<nsUint32HashKey> mGamepadIndexSet;
nsRefPtrHashtable<nsUint32HashKey, mozilla::dom::Gamepad> mGamepads;
bool mHasSeenGamepadInput;
// whether we've sent the destroy notification for our window id
bool mNotifiedIDDestroyed : 1;
// whether scripts may close the window,
// even if "dom.allow_scripts_to_close_windows" is false.
--- a/dom/vr/VRDisplay.cpp
+++ b/dom/vr/VRDisplay.cpp
@@ -530,34 +530,42 @@ VRDisplay::RequestPresent(const nsTArray
if (!global) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
RefPtr<Promise> promise = Promise::Create(global, aRv);
NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
+ bool isChromePresentation = aCallerType == CallerType::System;
+ uint32_t presentationGroup = isChromePresentation ? gfx::kVRGroupChrome : gfx::kVRGroupContent;
+
if (!EventStateManager::IsHandlingUserInput() &&
- aCallerType != CallerType::System &&
+ !isChromePresentation &&
!IsHandlingVRNavigationEvent() &&
gfxPrefs::VRRequireGesture()) {
// The WebVR API states that if called outside of a user gesture, the
// promise must be rejected. We allow VR presentations to start within
// trusted events such as vrdisplayactivate, which triggers in response to
// HMD proximity sensors and when navigating within a VR presentation.
+ // This user gesture requirement is not enforced for chrome/system code.
promise->MaybeRejectWithUndefined();
- } else if (!IsPresenting() && IsAnyPresenting()) {
- // Only one presentation allowed per VRDisplay
- // on a first-come-first-serve basis.
+ } else if (!IsPresenting() && IsAnyPresenting(presentationGroup)) {
+ // Only one presentation allowed per VRDisplay on a
+ // first-come-first-serve basis.
// If this Javascript context is presenting, then we can replace our
// presentation with a new one containing new layers but we should never
// replace the presentation of another context.
+ // Simultaneous presentations in other groups are allowed in separate
+ // Javascript contexts to enable browser UI from chrome/system contexts.
+ // Eventually, this restriction will be loosened to enable multitasking
+ // use cases.
promise->MaybeRejectWithUndefined();
} else {
- mPresentation = mClient->BeginPresentation(aLayers);
+ mPresentation = mClient->BeginPresentation(aLayers, presentationGroup);
mFrameInfo.Clear();
promise->MaybeResolve(JS::UndefinedHandleValue);
}
return promise.forget();
}
NS_IMETHODIMP
VRDisplay::Observe(nsISupports* aSubject, const char* aTopic,
@@ -672,29 +680,54 @@ bool
VRDisplay::IsPresenting() const
{
// IsPresenting returns true only if this Javascript context is presenting
// and will return false if another context is presenting.
return mPresentation != nullptr;
}
bool
-VRDisplay::IsAnyPresenting() const
+VRDisplay::IsAnyPresenting(uint32_t aGroupMask) const
{
- // IsAnyPresenting returns true if any Javascript context is presenting
- // even if this context is not presenting.
- return IsPresenting() || mClient->GetIsPresenting();
+ // IsAnyPresenting returns true if either this VRDisplay object or any other
+ // from anther Javascript context is presenting with a group matching
+ // aGroupMask.
+ if (mPresentation && (mPresentation->GetGroup() & aGroupMask)) {
+ return true;
+ }
+ if (mClient->GetDisplayInfo().GetPresentingGroups() & aGroupMask) {
+ return true;
+ }
+ return false;
}
bool
VRDisplay::IsConnected() const
{
return mClient->GetIsConnected();
}
+uint32_t
+VRDisplay::PresentingGroups() const
+{
+ return mClient->GetDisplayInfo().GetPresentingGroups();
+}
+
+uint32_t
+VRDisplay::GroupMask() const
+{
+ return mClient->GetDisplayInfo().GetGroupMask();
+}
+
+void
+VRDisplay::SetGroupMask(const uint32_t& aGroupMask)
+{
+ mClient->SetGroupMask(aGroupMask);
+}
+
NS_IMPL_CYCLE_COLLECTION_INHERITED(VRDisplay, DOMEventTargetHelper, mCapabilities, mStageParameters)
NS_IMPL_ADDREF_INHERITED(VRDisplay, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(VRDisplay, DOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(VRDisplay)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, DOMEventTargetHelper)
--- a/dom/vr/VRDisplay.h
+++ b/dom/vr/VRDisplay.h
@@ -303,18 +303,21 @@ class VRDisplay final : public DOMEventT
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIOBSERVER
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(VRDisplay, DOMEventTargetHelper)
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
+ uint32_t PresentingGroups() const;
+ uint32_t GroupMask() const;
+ void SetGroupMask(const uint32_t& aGroupMask);
+ bool IsAnyPresenting(uint32_t aGroupMask) const;
bool IsPresenting() const;
- bool IsAnyPresenting() const;
bool IsConnected() const;
VRDisplayCapabilities* Capabilities();
VRStageParameters* GetStageParameters();
uint32_t DisplayId() const { return mDisplayId; }
void GetDisplayName(nsAString& aDisplayName) const { aDisplayName = mDisplayName; }
--- a/dom/webidl/Navigator.webidl
+++ b/dom/webidl/Navigator.webidl
@@ -268,16 +268,22 @@ partial interface Navigator {
};
partial interface Navigator {
[Throws, Pref="dom.vr.enabled"]
Promise<sequence<VRDisplay>> getVRDisplays();
// TODO: Use FrozenArray once available. (Bug 1236777)
[Frozen, Cached, Pure, Pref="dom.vr.enabled"]
readonly attribute sequence<VRDisplay> activeVRDisplays;
+ [ChromeOnly, Pref="dom.vr.enabled"]
+ readonly attribute boolean isWebVRContentDetected;
+ [ChromeOnly, Pref="dom.vr.enabled"]
+ readonly attribute boolean isWebVRContentPresenting;
+ [ChromeOnly, Pref="dom.vr.enabled"]
+ void requestVRPresentation(VRDisplay display);
};
partial interface Navigator {
[Pref="dom.vr.test.enabled"]
VRServiceTest requestVRServiceTest();
};
#ifdef MOZ_TIME_MANAGER
// nsIDOMMozNavigatorTime
--- a/dom/webidl/VRDisplay.webidl
+++ b/dom/webidl/VRDisplay.webidl
@@ -178,16 +178,36 @@ interface VREyeParameters {
*/
[Constant] readonly attribute unsigned long renderWidth;
[Constant] readonly attribute unsigned long renderHeight;
};
[Pref="dom.vr.enabled",
HeaderFile="mozilla/dom/VRDisplay.h"]
interface VRDisplay : EventTarget {
+ /**
+ * presentingGroups is a bitmask indicating which VR session groups
+ * have an active VR presentation.
+ */
+ [ChromeOnly] readonly attribute unsigned long presentingGroups;
+ /**
+ * Setting groupMask causes submitted frames by VR sessions that
+ * aren't included in the bitmasked groups to be ignored.
+ * Non-chrome content is not aware of the value of groupMask.
+ * VRDisplay.RequestAnimationFrame will still fire for VR sessions
+ * that are hidden by groupMask, enabling their performance to be
+ * measured by chrome UI that is presented in other groups.
+ * This is expected to be used in cases where chrome UI is presenting
+ * information during link traversal or presenting options when content
+ * performance is too low for comfort.
+ * The VR refresh / VSync cycle is driven by the visible content
+ * and the non-visible content may have a throttled refresh rate.
+ */
+ [ChromeOnly] attribute unsigned long groupMask;
+
readonly attribute boolean isConnected;
readonly attribute boolean isPresenting;
/**
* Dictionary of capabilities describing the VRDisplay.
*/
[Constant] readonly attribute VRDisplayCapabilities capabilities;
--- a/gfx/vr/VRDisplayClient.cpp
+++ b/gfx/vr/VRDisplayClient.cpp
@@ -27,83 +27,67 @@
using namespace mozilla;
using namespace mozilla::gfx;
VRDisplayClient::VRDisplayClient(const VRDisplayInfo& aDisplayInfo)
: mDisplayInfo(aDisplayInfo)
, bLastEventWasMounted(false)
, bLastEventWasPresenting(false)
, mPresentationCount(0)
+ , mLastEventFrameId(0)
{
MOZ_COUNT_CTOR(VRDisplayClient);
}
VRDisplayClient::~VRDisplayClient() {
MOZ_COUNT_DTOR(VRDisplayClient);
}
void
VRDisplayClient::UpdateDisplayInfo(const VRDisplayInfo& aDisplayInfo)
{
mDisplayInfo = aDisplayInfo;
+ FireEvents();
}
already_AddRefed<VRDisplayPresentation>
-VRDisplayClient::BeginPresentation(const nsTArray<mozilla::dom::VRLayer>& aLayers)
+VRDisplayClient::BeginPresentation(const nsTArray<mozilla::dom::VRLayer>& aLayers,
+ uint32_t aGroup)
{
++mPresentationCount;
- RefPtr<VRDisplayPresentation> presentation = new VRDisplayPresentation(this, aLayers);
+ RefPtr<VRDisplayPresentation> presentation = new VRDisplayPresentation(this, aLayers, aGroup);
return presentation.forget();
}
void
VRDisplayClient::PresentationDestroyed()
{
--mPresentationCount;
}
void
VRDisplayClient::ZeroSensor()
{
VRManagerChild *vm = VRManagerChild::Get();
vm->SendResetSensor(mDisplayInfo.mDisplayID);
}
-VRHMDSensorState
-VRDisplayClient::GetSensorState()
-{
- VRHMDSensorState sensorState;
- VRManagerChild *vm = VRManagerChild::Get();
- Unused << vm->SendGetSensorState(mDisplayInfo.mDisplayID, &sensorState);
- return sensorState;
-}
-
-const double kVRDisplayRAFMaxDuration = 32; // milliseconds
-
void
-VRDisplayClient::NotifyVsync()
+VRDisplayClient::SetGroupMask(uint32_t aGroupMask)
{
VRManagerChild *vm = VRManagerChild::Get();
-
- bool isPresenting = GetIsPresenting();
+ vm->SendSetGroupMask(mDisplayInfo.mDisplayID, aGroupMask);
+}
- bool bShouldCallback = !isPresenting;
- if (mLastVSyncTime.IsNull()) {
- bShouldCallback = true;
- } else {
- TimeDuration duration = TimeStamp::Now() - mLastVSyncTime;
- if (duration.ToMilliseconds() > kVRDisplayRAFMaxDuration) {
- bShouldCallback = true;
- }
- }
-
- if (bShouldCallback) {
- vm->RunFrameRequestCallbacks();
- mLastVSyncTime = TimeStamp::Now();
- }
+void
+VRDisplayClient::FireEvents()
+{
+ VRManagerChild *vm = VRManagerChild::Get();
+ // Only fire these events for non-chrome VR sessions
+ bool isPresenting = (mDisplayInfo.mPresentingGroups & kVRGroupContent) != 0;
// Check if we need to trigger onVRDisplayPresentChange event
if (bLastEventWasPresenting != isPresenting) {
bLastEventWasPresenting = isPresenting;
vm->FireDOMVRDisplayPresentChangeEvent(mDisplayInfo.mDisplayID);
}
// Check if we need to trigger onvrdisplayactivate event
@@ -116,38 +100,36 @@ VRDisplayClient::NotifyVsync()
// Check if we need to trigger onvrdisplaydeactivate event
if (bLastEventWasMounted && !mDisplayInfo.mIsMounted) {
bLastEventWasMounted = false;
if (gfxPrefs::VRAutoActivateEnabled()) {
vm->FireDOMVRDisplayUnmountedEvent(mDisplayInfo.mDisplayID);
}
}
+
+ // Check if we need to trigger VRDisplay.requestAnimationFrame
+ if (mLastEventFrameId != mDisplayInfo.mFrameId) {
+ mLastEventFrameId = mDisplayInfo.mFrameId;
+ vm->RunFrameRequestCallbacks();
+ }
}
-void
-VRDisplayClient::NotifyVRVsync()
+VRHMDSensorState
+VRDisplayClient::GetSensorState()
{
- VRManagerChild *vm = VRManagerChild::Get();
- vm->RunFrameRequestCallbacks();
- mLastVSyncTime = TimeStamp::Now();
+ return mDisplayInfo.GetSensorState();
}
bool
VRDisplayClient::GetIsConnected() const
{
return mDisplayInfo.GetIsConnected();
}
-bool
-VRDisplayClient::GetIsPresenting() const
-{
- return mDisplayInfo.GetIsPresenting();
-}
-
void
VRDisplayClient::NotifyDisconnected()
{
mDisplayInfo.mIsConnected = false;
}
void
VRDisplayClient::UpdateSubmitFrameResult(const VRSubmitFrameResultInfo& aResult)
--- a/gfx/vr/VRDisplayClient.h
+++ b/gfx/vr/VRDisplayClient.h
@@ -29,38 +29,37 @@ public:
void UpdateSubmitFrameResult(const VRSubmitFrameResultInfo& aResult);
const VRDisplayInfo& GetDisplayInfo() const { return mDisplayInfo; }
virtual VRHMDSensorState GetSensorState();
void GetSubmitFrameResult(VRSubmitFrameResultInfo& aResult);
virtual void ZeroSensor();
- already_AddRefed<VRDisplayPresentation> BeginPresentation(const nsTArray<dom::VRLayer>& aLayers);
+ already_AddRefed<VRDisplayPresentation> BeginPresentation(const nsTArray<dom::VRLayer>& aLayers,
+ uint32_t aGroup);
void PresentationDestroyed();
- void NotifyVsync();
- void NotifyVRVsync();
-
bool GetIsConnected() const;
- bool GetIsPresenting() const;
void NotifyDisconnected();
+ void SetGroupMask(uint32_t aGroupMask);
protected:
virtual ~VRDisplayClient();
+ void FireEvents();
+
VRDisplayInfo mDisplayInfo;
bool bLastEventWasMounted;
bool bLastEventWasPresenting;
- TimeStamp mLastVSyncTime;
int mPresentationCount;
-
+ uint32_t mLastEventFrameId;
private:
VRSubmitFrameResultInfo mSubmitFrameResult;
};
} // namespace gfx
} // namespace mozilla
#endif /* GFX_VR_DISPLAY_CLIENT_H */
--- a/gfx/vr/VRDisplayHost.cpp
+++ b/gfx/vr/VRDisplayHost.cpp
@@ -1,101 +1,165 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "VRDisplayHost.h"
#include "gfxVR.h"
+#include "ipc/VRLayerParent.h"
#if defined(XP_WIN)
#include <d3d11.h>
#include "gfxWindowsPlatform.h"
#include "../layers/d3d11/CompositorD3D11.h"
#include "mozilla/layers/TextureD3D11.h"
#endif
using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::layers;
VRDisplayHost::VRDisplayHost(VRDeviceType aType)
- : mInputFrameID(0)
{
MOZ_COUNT_CTOR(VRDisplayHost);
mDisplayInfo.mType = aType;
mDisplayInfo.mDisplayID = VRSystemManager::AllocateDisplayID();
- mDisplayInfo.mIsPresenting = false;
+ mDisplayInfo.mPresentingGroups = 0;
+ mDisplayInfo.mGroupMask = kVRGroupContent;
+ mDisplayInfo.mFrameId = 0;
}
VRDisplayHost::~VRDisplayHost()
{
MOZ_COUNT_DTOR(VRDisplayHost);
}
void
+VRDisplayHost::SetGroupMask(uint32_t aGroupMask)
+{
+ mDisplayInfo.mGroupMask = aGroupMask;
+}
+
+void
VRDisplayHost::AddLayer(VRLayerParent *aLayer)
{
mLayers.AppendElement(aLayer);
+ mDisplayInfo.mPresentingGroups |= aLayer->GetGroup();
if (mLayers.Length() == 1) {
StartPresentation();
}
- mDisplayInfo.mIsPresenting = mLayers.Length() > 0;
// Ensure that the content process receives the change immediately
VRManager* vm = VRManager::Get();
vm->RefreshVRDisplays();
}
void
VRDisplayHost::RemoveLayer(VRLayerParent *aLayer)
{
mLayers.RemoveElement(aLayer);
if (mLayers.Length() == 0) {
StopPresentation();
}
- mDisplayInfo.mIsPresenting = mLayers.Length() > 0;
+ mDisplayInfo.mPresentingGroups = 0;
+ for (auto layer : mLayers) {
+ mDisplayInfo.mPresentingGroups |= layer->GetGroup();
+ }
// Ensure that the content process receives the change immediately
VRManager* vm = VRManager::Get();
vm->RefreshVRDisplays();
}
+void
+VRDisplayHost::StartFrame()
+{
+ mLastFrameStart = TimeStamp::Now();
+ ++mDisplayInfo.mFrameId;
+ mDisplayInfo.mLastSensorState[mDisplayInfo.mFrameId % kVRMaxLatencyFrames] = GetSensorState();
+}
+
+void
+VRDisplayHost::NotifyVSync()
+{
+ /**
+ * We will trigger a new frame immediately after a successful frame texture
+ * submission. If content fails to call VRDisplay.submitFrame after
+ * kVRDisplayRAFMaxDuration milliseconds has elapsed since the last
+ * VRDisplay.requestAnimationFrame, we act as a "watchdog" and kick-off
+ * a new VRDisplay.requestAnimationFrame to avoid a render loop stall and
+ * to give content a chance to recover.
+ *
+ * If the lower level VR platform API's are rejecting submitted frames,
+ * such as when the Oculus "Health and Safety Warning" is displayed,
+ * we will not kick off the next frame immediately after VRDisplay.submitFrame
+ * as it would result in an unthrottled render loop that would free run at
+ * potentially extreme frame rates. To ensure that content has a chance to
+ * resume its presentation when the frames are accepted once again, we rely
+ * on this "watchdog" to act as a VR refresh driver cycling at a rate defined
+ * by kVRDisplayRAFMaxDuration.
+ *
+ * kVRDisplayRAFMaxDuration is the number of milliseconds since last frame
+ * start before triggering a new frame. When content is failing to submit
+ * frames on time or the lower level VR platform API's are rejecting frames,
+ * kVRDisplayRAFMaxDuration determines the rate at which RAF callbacks
+ * will be called.
+ *
+ * This number must be larger than the slowest expected frame time during
+ * normal VR presentation, but small enough not to break content that
+ * makes assumptions of reasonably minimal VSync rate.
+ *
+ * The slowest expected refresh rate for a VR display currently is an
+ * Oculus CV1 when ASW (Asynchronous Space Warp) is enabled, at 45hz.
+ * A kVRDisplayRAFMaxDuration value of 50 milliseconds results in a 20hz
+ * rate, which avoids inadvertent triggering of the watchdog during
+ * Oculus ASW even if every second frame is dropped.
+ */
+ const double kVRDisplayRAFMaxDuration = 50;
+
+ bool bShouldStartFrame = false;
+
+ if (mDisplayInfo.mPresentingGroups == 0) {
+ // If this display isn't presenting, refresh the sensors and trigger
+ // VRDisplay.requestAnimationFrame at the normal 2d display refresh rate.
+ bShouldStartFrame = true;
+ } else {
+ // If content fails to call VRDisplay.submitFrame, we must eventually
+ // time-out and trigger a new frame.
+ if (mLastFrameStart.IsNull()) {
+ bShouldStartFrame = true;
+ } else {
+ TimeDuration duration = TimeStamp::Now() - mLastFrameStart;
+ if (duration.ToMilliseconds() > kVRDisplayRAFMaxDuration) {
+ bShouldStartFrame = true;
+ }
+ }
+ }
+
+ if (bShouldStartFrame) {
+ VRManager *vm = VRManager::Get();
+ MOZ_ASSERT(vm);
+ vm->NotifyVRVsync(mDisplayInfo.mDisplayID);
+ }
+}
+
#if defined(XP_WIN)
void
-VRDisplayHost::SubmitFrame(VRLayerParent* aLayer, const int32_t& aInputFrameID,
- PTextureParent* aTexture, const gfx::Rect& aLeftEyeRect,
- const gfx::Rect& aRightEyeRect)
+VRDisplayHost::SubmitFrame(VRLayerParent* aLayer, PTextureParent* aTexture,
+ const gfx::Rect& aLeftEyeRect,
+ const gfx::Rect& aRightEyeRect)
{
- // aInputFrameID is no longer controlled by content with the WebVR 1.1 API
- // update; however, we will later use this code to enable asynchronous
- // submission of multiple layers to be composited. This will enable
- // us to build browser UX that remains responsive even when content does
- // not consistently submit frames.
-
- int32_t inputFrameID = aInputFrameID;
- if (inputFrameID == 0) {
- inputFrameID = mInputFrameID;
+ if ((mDisplayInfo.mGroupMask & aLayer->GetGroup()) == 0) {
+ // Suppress layers hidden by the group mask
+ return;
}
- if (inputFrameID < 0) {
- // Sanity check to prevent invalid memory access on builds with assertions
- // disabled.
- inputFrameID = 0;
- }
-
- VRHMDSensorState sensorState = mLastSensorState[inputFrameID % kMaxLatencyFrames];
- // It is possible to get a cache miss on mLastSensorState if latency is
- // longer than kMaxLatencyFrames. An optimization would be to find a frame
- // that is closer than the one selected with the modulus.
- // If we hit this; however, latency is already so high that the site is
- // un-viewable and a more accurate pose prediction is not likely to
- // compensate.
TextureHost* th = TextureHost::AsTextureHost(aTexture);
// WebVR doesn't use the compositor to compose the frame, so use
// AutoLockTextureHostWithoutCompositor here.
AutoLockTextureHostWithoutCompositor autoLock(th);
if (autoLock.Failed()) {
NS_WARNING("Failed to lock the VR layer texture");
return;
@@ -111,25 +175,41 @@ VRDisplayHost::SubmitFrame(VRLayerParent
IntSize texSize = source->GetSize();
TextureSourceD3D11* sourceD3D11 = source->AsSourceD3D11();
if (!sourceD3D11) {
NS_WARNING("WebVR support currently only implemented for D3D11");
return;
}
- SubmitFrame(sourceD3D11, texSize, sensorState, aLeftEyeRect, aRightEyeRect);
+ if (!SubmitFrame(sourceD3D11, texSize, aLeftEyeRect, aRightEyeRect)) {
+ return;
+ }
+
+ /**
+ * Trigger the next VSync immediately after we are successfully
+ * submitting frames. As SubmitFrame is responsible for throttling
+ * the render loop, if we don't successfully call it, we shouldn't trigger
+ * NotifyVRVsync immediately, as it will run unbounded.
+ * If NotifyVRVsync is not called here due to SubmitFrame failing, the
+ * fallback "watchdog" code in VRDisplayHost::NotifyVSync() will cause
+ * frames to continue at a lower refresh rate until frame submission
+ * succeeds again.
+ */
+ VRManager *vm = VRManager::Get();
+ MOZ_ASSERT(vm);
+ vm->NotifyVRVsync(mDisplayInfo.mDisplayID);
}
#else
void
-VRDisplayHost::SubmitFrame(VRLayerParent* aLayer, const int32_t& aInputFrameID,
- PTextureParent* aTexture, const gfx::Rect& aLeftEyeRect,
- const gfx::Rect& aRightEyeRect)
+VRDisplayHost::SubmitFrame(VRLayerParent* aLayer, PTextureParent* aTexture,
+ const gfx::Rect& aLeftEyeRect,
+ const gfx::Rect& aRightEyeRect)
{
NS_WARNING("WebVR only supported in Windows.");
}
#endif
bool
VRDisplayHost::CheckClearDisplayInfoDirty()
--- a/gfx/vr/VRDisplayHost.h
+++ b/gfx/vr/VRDisplayHost.h
@@ -32,60 +32,57 @@ class VRDisplayHost {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRDisplayHost)
const VRDisplayInfo& GetDisplayInfo() const { return mDisplayInfo; }
void AddLayer(VRLayerParent* aLayer);
void RemoveLayer(VRLayerParent* aLayer);
- virtual VRHMDSensorState GetSensorState() = 0;
virtual void ZeroSensor() = 0;
virtual void StartPresentation() = 0;
virtual void StopPresentation() = 0;
- virtual void NotifyVSync() { };
+ virtual void NotifyVSync();
+ void StartFrame();
void SubmitFrame(VRLayerParent* aLayer,
- const int32_t& aInputFrameID,
mozilla::layers::PTextureParent* aTexture,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect);
bool CheckClearDisplayInfoDirty();
+ void SetGroupMask(uint32_t aGroupMask);
protected:
explicit VRDisplayHost(VRDeviceType aType);
virtual ~VRDisplayHost();
#if defined(XP_WIN)
- virtual void SubmitFrame(mozilla::layers::TextureSourceD3D11* aSource,
+ // Subclasses should override this SubmitFrame function.
+ // Returns true if the SubmitFrame call will block as necessary
+ // to control timing of the next frame and throttle the render loop
+ // for the needed framerate.
+ virtual bool SubmitFrame(mozilla::layers::TextureSourceD3D11* aSource,
const IntSize& aSize,
- const VRHMDSensorState& aSensorState,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect) = 0;
#endif
VRDisplayInfo mDisplayInfo;
nsTArray<RefPtr<VRLayerParent>> mLayers;
- // Weak reference to mLayers entries are cleared in VRLayerParent destructor
+ // Weak reference to mLayers entries are cleared in
+ // VRLayerParent destructor
- // The maximum number of frames of latency that we would expect before we
- // should give up applying pose prediction.
- // If latency is greater than one second, then the experience is not likely
- // to be corrected by pose prediction. Setting this value too
- // high may result in unnecessary memory allocation.
- // As the current fastest refresh rate is 90hz, 100 is selected as a
- // conservative value.
- static const int kMaxLatencyFrames = 100;
- VRHMDSensorState mLastSensorState[kMaxLatencyFrames];
- int32_t mInputFrameID;
+protected:
+ virtual VRHMDSensorState GetSensorState() = 0;
private:
VRDisplayInfo mLastUpdateDisplayInfo;
+ TimeStamp mLastFrameStart;
};
class VRControllerHost {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRControllerHost)
const VRControllerInfo& GetControllerInfo() const;
void SetButtonPressed(uint64_t aBit);
--- a/gfx/vr/VRDisplayPresentation.cpp
+++ b/gfx/vr/VRDisplayPresentation.cpp
@@ -9,23 +9,31 @@
#include "mozilla/Unused.h"
#include "VRDisplayClient.h"
#include "VRLayerChild.h"
using namespace mozilla;
using namespace mozilla::gfx;
VRDisplayPresentation::VRDisplayPresentation(VRDisplayClient *aDisplayClient,
- const nsTArray<mozilla::dom::VRLayer>& aLayers)
+ const nsTArray<mozilla::dom::VRLayer>& aLayers,
+ uint32_t aGroup)
: mDisplayClient(aDisplayClient)
, mDOMLayers(aLayers)
+ , mGroup(aGroup)
{
CreateLayers();
}
+uint32_t
+VRDisplayPresentation::GetGroup() const
+{
+ return mGroup;
+}
+
void
VRDisplayPresentation::CreateLayers()
{
if (mLayers.Length()) {
return;
}
for (dom::VRLayer& layer : mDOMLayers) {
@@ -75,17 +83,18 @@ VRDisplayPresentation::CreateLayers()
nsIDocument* doc;
doc = canvasElement->OwnerDoc();
if (doc) {
target = doc->EventTargetFor(TaskCategory::Other);
}
RefPtr<VRLayerChild> vrLayer =
static_cast<VRLayerChild*>(manager->CreateVRLayer(mDisplayClient->GetDisplayInfo().GetDisplayID(),
- leftBounds, rightBounds, target));
+ leftBounds, rightBounds, target,
+ mGroup));
if (!vrLayer) {
NS_WARNING("CreateVRLayer returned null!");
continue;
}
vrLayer->Initialize(canvasElement);
mLayers.AppendElement(vrLayer);
--- a/gfx/vr/VRDisplayPresentation.h
+++ b/gfx/vr/VRDisplayPresentation.h
@@ -14,26 +14,30 @@ namespace gfx {
class VRDisplayClient;
class VRLayerChild;
class VRDisplayPresentation final
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRDisplayPresentation)
public:
- VRDisplayPresentation(VRDisplayClient *aDisplayClient, const nsTArray<dom::VRLayer>& aLayers);
+ VRDisplayPresentation(VRDisplayClient *aDisplayClient,
+ const nsTArray<dom::VRLayer>& aLayers,
+ uint32_t aGroup);
void SubmitFrame();
void GetDOMLayers(nsTArray<dom::VRLayer>& result);
+ uint32_t GetGroup() const;
private:
~VRDisplayPresentation();
void CreateLayers();
void DestroyLayers();
RefPtr<VRDisplayClient> mDisplayClient;
nsTArray<dom::VRLayer> mDOMLayers;
nsTArray<RefPtr<VRLayerChild>> mLayers;
+ uint32_t mGroup;
};
} // namespace gfx
} // namespace mozilla
#endif /* GFX_VR_DISPLAY_PRESENTAITON_H */
--- a/gfx/vr/VRManager.cpp
+++ b/gfx/vr/VRManager.cpp
@@ -163,25 +163,27 @@ VRManager::NotifyVsync(const TimeStamp&
const double kVRDisplayRefreshMaxDuration = 5000; // milliseconds
const double kVRDisplayInactiveMaxDuration = 30000; // milliseconds
bool bHaveEventListener = false;
bool bHaveControllerListener = false;
for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) {
VRManagerParent *vmp = iter.Get()->GetKey();
- if (mVRDisplays.Count()) {
- Unused << vmp->SendNotifyVSync();
- }
bHaveEventListener |= vmp->HaveEventListener();
bHaveControllerListener |= vmp->HaveControllerListener();
}
+ // VRDisplayHost::NotifyVSync may modify mVRDisplays, so we iterate
+ // through a local copy here.
+ nsTArray<RefPtr<VRDisplayHost>> displays;
for (auto iter = mVRDisplays.Iter(); !iter.Done(); iter.Next()) {
- gfx::VRDisplayHost* display = iter.UserData();
+ displays.AppendElement(iter.UserData());
+ }
+ for (const auto& display: displays) {
display->NotifyVSync();
}
if (bHaveEventListener) {
// If content has set an EventHandler to be notified of VR display events
// we must continually refresh the VR display enumeration to check
// for events that we must fire such as Window.onvrdisplayconnect
// Note that enumeration itself may activate display hardware, such
@@ -234,19 +236,22 @@ void
VRManager::NotifyVRVsync(const uint32_t& aDisplayID)
{
for (const auto& manager: mManagers) {
if (manager->GetIsPresenting()) {
manager->HandleInput();
}
}
- for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) {
- Unused << iter.Get()->GetKey()->SendNotifyVRVSync(aDisplayID);
+ RefPtr<VRDisplayHost> display = GetDisplay(aDisplayID);
+ if (display) {
+ display->StartFrame();
}
+
+ RefreshVRDisplays();
}
void
VRManager::RefreshVRDisplays(bool aMustDispatch)
{
nsTArray<RefPtr<gfx::VRDisplayHost> > displays;
/** We don't wish to enumerate the same display from multiple managers,
@@ -334,17 +339,17 @@ void
VRManager::SubmitFrame(VRLayerParent* aLayer, layers::PTextureParent* aTexture,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect)
{
TextureHost* th = TextureHost::AsTextureHost(aTexture);
mLastFrame = th;
RefPtr<VRDisplayHost> display = GetDisplay(aLayer->GetDisplayID());
if (display) {
- display->SubmitFrame(aLayer, 0, aTexture, aLeftEyeRect, aRightEyeRect);
+ display->SubmitFrame(aLayer, aTexture, aLeftEyeRect, aRightEyeRect);
}
}
RefPtr<gfx::VRControllerHost>
VRManager::GetController(const uint32_t& aControllerID)
{
RefPtr<gfx::VRControllerHost> controller;
if (mVRControllers.Get(aControllerID, getter_AddRefs(controller))) {
--- a/gfx/vr/gfxVR.h
+++ b/gfx/vr/gfxVR.h
@@ -127,90 +127,138 @@ struct VRFieldOfView {
Matrix4x4 ConstructProjectionMatrix(float zNear, float zFar, bool rightHanded) const;
double upDegrees;
double rightDegrees;
double downDegrees;
double leftDegrees;
};
+struct VRHMDSensorState {
+ VRHMDSensorState()
+ {
+ Clear();
+ }
+ int32_t inputFrameID;
+ double timestamp;
+ VRDisplayCapabilityFlags flags;
+
+ // These members will only change with inputFrameID:
+ float orientation[4];
+ float position[3];
+ float angularVelocity[3];
+ float angularAcceleration[3];
+ float linearVelocity[3];
+ float linearAcceleration[3];
+
+ void Clear() {
+ memset(this, 0, sizeof(VRHMDSensorState));
+ }
+
+ bool operator==(const VRHMDSensorState& other) const {
+ return inputFrameID == other.inputFrameID &&
+ timestamp == other.timestamp;
+ }
+
+ bool operator!=(const VRHMDSensorState& other) const {
+ return !(*this == other);
+ }
+};
+
+// The maximum number of frames of latency that we would expect before we
+// should give up applying pose prediction.
+// If latency is greater than one second, then the experience is not likely
+// to be corrected by pose prediction. Setting this value too
+// high may result in unnecessary memory allocation.
+// As the current fastest refresh rate is 90hz, 100 is selected as a
+// conservative value.
+static const int kVRMaxLatencyFrames = 100;
+
+// We assign VR presentations to groups with a bitmask.
+// Currently, we will only display either content or chrome.
+// Later, we will have more groups to support VR home spaces and
+// multitasking environments.
+// These values are not exposed to regular content and only affect
+// chrome-only API's. They may be changed at any time.
+static const uint32_t kVRGroupNone = 0;
+static const uint32_t kVRGroupContent = 1 << 0;
+static const uint32_t kVRGroupChrome = 1 << 1;
+static const uint32_t kVRGroupAll = 0xffffffff;
+
struct VRDisplayInfo
{
VRDeviceType GetType() const { return mType; }
uint32_t GetDisplayID() const { return mDisplayID; }
const nsCString& GetDisplayName() const { return mDisplayName; }
VRDisplayCapabilityFlags GetCapabilities() const { return mCapabilityFlags; }
const IntSize& SuggestedEyeResolution() const { return mEyeResolution; }
const Point3D& GetEyeTranslation(uint32_t whichEye) const { return mEyeTranslation[whichEye]; }
const VRFieldOfView& GetEyeFOV(uint32_t whichEye) const { return mEyeFOV[whichEye]; }
bool GetIsConnected() const { return mIsConnected; }
bool GetIsMounted() const { return mIsMounted; }
- bool GetIsPresenting() const { return mIsPresenting; }
+ uint32_t GetPresentingGroups() const { return mPresentingGroups; }
+ uint32_t GetGroupMask() const { return mGroupMask; }
const Size& GetStageSize() const { return mStageSize; }
const Matrix4x4& GetSittingToStandingTransform() const { return mSittingToStandingTransform; }
+ uint32_t GetFrameId() const { return mFrameId; }
enum Eye {
Eye_Left,
Eye_Right,
NumEyes
};
uint32_t mDisplayID;
VRDeviceType mType;
nsCString mDisplayName;
VRDisplayCapabilityFlags mCapabilityFlags;
VRFieldOfView mEyeFOV[VRDisplayInfo::NumEyes];
Point3D mEyeTranslation[VRDisplayInfo::NumEyes];
IntSize mEyeResolution;
bool mIsConnected;
bool mIsMounted;
- bool mIsPresenting;
+ uint32_t mPresentingGroups;
+ uint32_t mGroupMask;
Size mStageSize;
Matrix4x4 mSittingToStandingTransform;
+ uint32_t mFrameId;
+ VRHMDSensorState mLastSensorState[kVRMaxLatencyFrames];
bool operator==(const VRDisplayInfo& other) const {
+ for (size_t i = 0; i < kVRMaxLatencyFrames; i++) {
+ if (mLastSensorState[i] != other.mLastSensorState[i]) {
+ return false;
+ }
+ }
return mType == other.mType &&
mDisplayID == other.mDisplayID &&
mDisplayName == other.mDisplayName &&
mCapabilityFlags == other.mCapabilityFlags &&
mEyeResolution == other.mEyeResolution &&
mIsConnected == other.mIsConnected &&
mIsMounted == other.mIsMounted &&
- mIsPresenting == other.mIsPresenting &&
+ mPresentingGroups == other.mPresentingGroups &&
+ mGroupMask == other.mGroupMask &&
mEyeFOV[0] == other.mEyeFOV[0] &&
mEyeFOV[1] == other.mEyeFOV[1] &&
mEyeTranslation[0] == other.mEyeTranslation[0] &&
mEyeTranslation[1] == other.mEyeTranslation[1] &&
mStageSize == other.mStageSize &&
- mSittingToStandingTransform == other.mSittingToStandingTransform;
+ mSittingToStandingTransform == other.mSittingToStandingTransform &&
+ mFrameId == other.mFrameId;
}
bool operator!=(const VRDisplayInfo& other) const {
return !(*this == other);
}
-};
-struct VRHMDSensorState {
- VRHMDSensorState()
+ const VRHMDSensorState& GetSensorState() const
{
- Clear();
- }
- double timestamp;
- int32_t inputFrameID;
- VRDisplayCapabilityFlags flags;
- float orientation[4];
- float position[3];
- float angularVelocity[3];
- float angularAcceleration[3];
- float linearVelocity[3];
- float linearAcceleration[3];
-
- void Clear() {
- memset(this, 0, sizeof(VRHMDSensorState));
+ return mLastSensorState[mFrameId % kVRMaxLatencyFrames];
}
};
struct VRSubmitFrameResultInfo
{
VRSubmitFrameResultInfo()
: mFrameNum(0),
mWidth(0),
--- a/gfx/vr/gfxVROSVR.cpp
+++ b/gfx/vr/gfxVROSVR.cpp
@@ -294,16 +294,17 @@ VRDisplayOSVR::GetSensorState()
OSVR_TimeValue timestamp;
OSVR_OrientationState orientation;
OSVR_ReturnCode ret =
osvr_GetOrientationState(*m_iface, ×tamp, &orientation);
result.timestamp = timestamp.seconds;
+ result.inputFrameID = mDisplayInfo.mFrameId;
if (ret == OSVR_RETURN_SUCCESS) {
result.flags |= VRDisplayCapabilityFlags::Cap_Orientation;
result.orientation[0] = orientation.data[1];
result.orientation[1] = orientation.data[2];
result.orientation[2] = orientation.data[3];
result.orientation[3] = orientation.data[0];
}
@@ -317,24 +318,24 @@ VRDisplayOSVR::GetSensorState()
result.position[2] = position.data[2];
}
return result;
}
#if defined(XP_WIN)
-void
+bool
VRDisplayOSVR::SubmitFrame(TextureSourceD3D11* aSource,
const IntSize& aSize,
- const VRHMDSensorState& aSensorState,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect)
{
// XXX Add code to submit frame
+ return false;
}
#endif
void
VRDisplayOSVR::StartPresentation()
{
// XXX Add code to start VR Presentation
@@ -531,17 +532,17 @@ VRSystemManagerOSVR::GetHMDs(nsTArray<Re
}
}
bool
VRSystemManagerOSVR::GetIsPresenting()
{
if (mHMDInfo) {
VRDisplayInfo displayInfo(mHMDInfo->GetDisplayInfo());
- return displayInfo.GetIsPresenting();
+ return displayInfo.GetPresentingGroups() != kVRGroupNone;
}
return false;
}
void
VRSystemManagerOSVR::HandleInput()
{
--- a/gfx/vr/gfxVROSVR.h
+++ b/gfx/vr/gfxVROSVR.h
@@ -20,27 +20,26 @@
namespace mozilla {
namespace gfx {
namespace impl {
class VRDisplayOSVR : public VRDisplayHost
{
public:
- VRHMDSensorState GetSensorState() override;
void ZeroSensor() override;
protected:
+ VRHMDSensorState GetSensorState() override;
virtual void StartPresentation() override;
virtual void StopPresentation() override;
#if defined(XP_WIN)
- virtual void SubmitFrame(TextureSourceD3D11* aSource,
+ virtual bool SubmitFrame(TextureSourceD3D11* aSource,
const IntSize& aSize,
- const VRHMDSensorState& aSensorState,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect) override;
#endif
public:
explicit VRDisplayOSVR(OSVR_ClientContext* context,
OSVR_ClientInterface* iface,
OSVR_DisplayConfig* display);
--- a/gfx/vr/gfxVROculus.cpp
+++ b/gfx/vr/gfxVROculus.cpp
@@ -433,30 +433,28 @@ VRDisplayOculus::ZeroSensor()
{
ovr_RecenterTrackingOrigin(mSession);
UpdateStageParameters();
}
VRHMDSensorState
VRDisplayOculus::GetSensorState()
{
- mInputFrameID++;
-
VRHMDSensorState result;
double frameDelta = 0.0f;
if (gfxPrefs::VRPosePredictionEnabled()) {
// XXX We might need to call ovr_GetPredictedDisplayTime even if we don't use the result.
// If we don't call it, the Oculus driver will spew out many warnings...
double predictedFrameTime = ovr_GetPredictedDisplayTime(mSession, 0);
frameDelta = predictedFrameTime - ovr_GetTimeInSeconds();
}
result = GetSensorState(frameDelta);
- result.inputFrameID = mInputFrameID;
- mLastSensorState[result.inputFrameID % kMaxLatencyFrames] = result;
+ result.inputFrameID = mDisplayInfo.mFrameId;
result.position[1] -= mEyeHeight;
+ mDisplayInfo.mLastSensorState[result.inputFrameID % kVRMaxLatencyFrames] = result;
return result;
}
VRHMDSensorState
VRDisplayOculus::GetSensorState(double timeOffset)
{
VRHMDSensorState result;
@@ -690,36 +688,35 @@ VRDisplayOculus::UpdateConstantBuffers()
ID3D11Buffer *buffer = mVSConstantBuffer;
mContext->VSSetConstantBuffers(0, 1, &buffer);
buffer = mPSConstantBuffer;
mContext->PSSetConstantBuffers(0, 1, &buffer);
return true;
}
-void
+bool
VRDisplayOculus::SubmitFrame(TextureSourceD3D11* aSource,
const IntSize& aSize,
- const VRHMDSensorState& aSensorState,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect)
{
if (!mIsPresenting) {
- return;
+ return false;
}
if (mRenderTargets.IsEmpty()) {
/**
* XXX - We should resolve fail the promise returned by
* VRDisplay.requestPresent() when the DX11 resources fail allocation
* in VRDisplayOculus::StartPresentation().
* Bailing out here prevents the crash but content should be aware
* that frames are not being presented.
* See Bug 1299309.
**/
- return;
+ return false;
}
MOZ_ASSERT(mDevice);
MOZ_ASSERT(mContext);
RefPtr<CompositingRenderTargetD3D11> surface = GetNextRenderTarget();
surface->BindRenderTarget(mContext);
@@ -770,25 +767,25 @@ VRDisplayOculus::SubmitFrame(TextureSour
mContext->PSSetShaderResources(0 /* 0 == TexSlot::RGB */, 1, &srView);
// XXX Use Constant from TexSlot in CompositorD3D11.cpp?
ID3D11SamplerState *sampler = mLinearSamplerState;
mContext->PSSetSamplers(0, 1, &sampler);
if (!UpdateConstantBuffers()) {
NS_WARNING("Failed to update constant buffers for Oculus");
- return;
+ return false;
}
mContext->Draw(4, 0);
ovrResult orv = ovr_CommitTextureSwapChain(mSession, mTextureSet);
if (orv != ovrSuccess) {
NS_WARNING("ovr_CommitTextureSwapChain failed.\n");
- return;
+ return false;
}
ovrLayerEyeFov layer;
memset(&layer, 0, sizeof(layer));
layer.Header.Type = ovrLayerType_EyeFov;
layer.Header.Flags = 0;
layer.ColorTexture[0] = mTextureSet;
layer.ColorTexture[1] = nullptr;
@@ -803,51 +800,62 @@ VRDisplayOculus::SubmitFrame(TextureSour
layer.Viewport[1].Size.w = aSize.width * aRightEyeRect.width;
layer.Viewport[1].Size.h = aSize.height * aRightEyeRect.height;
const Point3D& l = mDisplayInfo.mEyeTranslation[0];
const Point3D& r = mDisplayInfo.mEyeTranslation[1];
const ovrVector3f hmdToEyeViewOffset[2] = { { l.x, l.y, l.z },
{ r.x, r.y, r.z } };
+ const VRHMDSensorState& sensorState = mDisplayInfo.GetSensorState();
+
for (uint32_t i = 0; i < 2; ++i) {
- Quaternion o(aSensorState.orientation[0],
- aSensorState.orientation[1],
- aSensorState.orientation[2],
- aSensorState.orientation[3]);
+ Quaternion o(sensorState.orientation[0],
+ sensorState.orientation[1],
+ sensorState.orientation[2],
+ sensorState.orientation[3]);
Point3D vo(hmdToEyeViewOffset[i].x, hmdToEyeViewOffset[i].y, hmdToEyeViewOffset[i].z);
Point3D p = o.RotatePoint(vo);
layer.RenderPose[i].Orientation.x = o.x;
layer.RenderPose[i].Orientation.y = o.y;
layer.RenderPose[i].Orientation.z = o.z;
layer.RenderPose[i].Orientation.w = o.w;
- layer.RenderPose[i].Position.x = p.x + aSensorState.position[0];
- layer.RenderPose[i].Position.y = p.y + aSensorState.position[1];
- layer.RenderPose[i].Position.z = p.z + aSensorState.position[2];
+ layer.RenderPose[i].Position.x = p.x + sensorState.position[0];
+ layer.RenderPose[i].Position.y = p.y + sensorState.position[1];
+ layer.RenderPose[i].Position.z = p.z + sensorState.position[2];
}
ovrLayerHeader *layers = &layer.Header;
- orv = ovr_SubmitFrame(mSession, aSensorState.inputFrameID, nullptr, &layers, 1);
+ orv = ovr_SubmitFrame(mSession, mDisplayInfo.mFrameId, nullptr, &layers, 1);
+ // ovr_SubmitFrame will fail during the Oculus health and safety warning.
+ // and will start succeeding once the warning has been dismissed by the user.
- if (orv != ovrSuccess) {
- printf_stderr("ovr_SubmitFrame failed.\n");
+ if (!OVR_UNQUALIFIED_SUCCESS(orv)) {
+ /**
+ * We wish to throttle the framerate for any case that the rendered
+ * result is not visible. In some cases, such as during the Oculus
+ * "health and safety warning", orv will be > 0 (OVR_SUCCESS but not
+ * OVR_UNQUALIFIED_SUCCESS) and ovr_SubmitFrame will not block.
+ * In this case, returning true would have resulted in an unthrottled
+ * render loop hiting excessive frame rates and consuming resources.
+ */
+ return false;
}
- // Trigger the next VSync immediately
- VRManager *vm = VRManager::Get();
- MOZ_ASSERT(vm);
- vm->NotifyVRVsync(mDisplayInfo.mDisplayID);
+ return true;
}
void
VRDisplayOculus::NotifyVSync()
{
ovrSessionStatus sessionStatus;
ovrResult ovr = ovr_GetSessionStatus(mSession, &sessionStatus);
mDisplayInfo.mIsConnected = (ovr == ovrSuccess && sessionStatus.HmdPresent);
+
+ VRDisplayHost::NotifyVSync();
}
VRControllerOculus::VRControllerOculus(dom::GamepadHand aHand)
: VRControllerHost(VRDeviceType::Oculus)
, mIndexTrigger(0.0f)
, mHandTrigger(0.0f)
, mVibrateThread(nullptr)
, mIsVibrateStopped(false)
@@ -1162,17 +1170,17 @@ VRSystemManagerOculus::GetHMDs(nsTArray<
}
}
bool
VRSystemManagerOculus::GetIsPresenting()
{
if (mHMDInfo) {
VRDisplayInfo displayInfo(mHMDInfo->GetDisplayInfo());
- return displayInfo.GetIsPresenting();
+ return displayInfo.GetPresentingGroups() != 0;
}
return false;
}
void
VRSystemManagerOculus::HandleInput()
{
--- a/gfx/vr/gfxVROculus.h
+++ b/gfx/vr/gfxVROculus.h
@@ -32,25 +32,24 @@ enum class OculusControllerAxisType : ui
ThumbstickYAxis,
NumVRControllerAxisType
};
class VRDisplayOculus : public VRDisplayHost
{
public:
virtual void NotifyVSync() override;
- virtual VRHMDSensorState GetSensorState() override;
void ZeroSensor() override;
protected:
+ virtual VRHMDSensorState GetSensorState() override;
virtual void StartPresentation() override;
virtual void StopPresentation() override;
- virtual void SubmitFrame(mozilla::layers::TextureSourceD3D11* aSource,
+ virtual bool SubmitFrame(mozilla::layers::TextureSourceD3D11* aSource,
const IntSize& aSize,
- const VRHMDSensorState& aSensorState,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect) override;
void UpdateStageParameters();
public:
explicit VRDisplayOculus(ovrSession aSession);
protected:
--- a/gfx/vr/gfxVROpenVR.cpp
+++ b/gfx/vr/gfxVROpenVR.cpp
@@ -168,22 +168,16 @@ VRDisplayOpenVR::UpdateStageParameters()
void
VRDisplayOpenVR::ZeroSensor()
{
mVRSystem->ResetSeatedZeroPose();
UpdateStageParameters();
}
-VRHMDSensorState
-VRDisplayOpenVR::GetSensorState()
-{
- return GetSensorState(0.0f);
-}
-
void
VRDisplayOpenVR::PollEvents()
{
::vr::VREvent_t event;
while (mVRSystem->PollNextEvent(&event, sizeof(event))) {
if (event.trackedDeviceIndex == ::vr::k_unTrackedDeviceIndex_Hmd) {
switch (event.eventType) {
case ::vr::VREvent_TrackedDeviceUserInteractionStarted:
@@ -196,17 +190,17 @@ VRDisplayOpenVR::PollEvents()
// ignore
break;
}
}
}
}
VRHMDSensorState
-VRDisplayOpenVR::GetSensorState(double timeOffset)
+VRDisplayOpenVR::GetSensorState()
{
PollEvents();
::vr::TrackedDevicePose_t poses[::vr::k_unMaxTrackedDeviceCount];
// Note: We *must* call WaitGetPoses in order for any rendering to happen at all
mVRCompositor->WaitGetPoses(poses, ::vr::k_unMaxTrackedDeviceCount, nullptr, 0);
VRHMDSensorState result;
@@ -251,16 +245,17 @@ VRDisplayOpenVR::GetSensorState(double t
result.position[0] = m._41;
result.position[1] = m._42;
result.position[2] = m._43;
result.linearVelocity[0] = pose.vVelocity.v[0];
result.linearVelocity[1] = pose.vVelocity.v[1];
result.linearVelocity[2] = pose.vVelocity.v[2];
}
+ result.inputFrameID = mDisplayInfo.mFrameId;
return result;
}
void
VRDisplayOpenVR::StartPresentation()
{
if (mIsPresenting) {
return;
@@ -278,25 +273,24 @@ VRDisplayOpenVR::StopPresentation()
mVRCompositor->ClearLastSubmittedFrame();
mIsPresenting = false;
}
#if defined(XP_WIN)
-void
+bool
VRDisplayOpenVR::SubmitFrame(TextureSourceD3D11* aSource,
const IntSize& aSize,
- const VRHMDSensorState& aSensorState,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect)
{
if (!mIsPresenting) {
- return;
+ return false;
}
::vr::Texture_t tex;
tex.handle = (void *)aSource->GetD3D11Texture();
tex.eType = ::vr::ETextureType::TextureType_DirectX;
tex.eColorSpace = ::vr::EColorSpace::ColorSpace_Auto;
::vr::VRTextureBounds_t bounds;
@@ -318,32 +312,31 @@ VRDisplayOpenVR::SubmitFrame(TextureSour
err = mVRCompositor->Submit(::vr::EVREye::Eye_Right, &tex, &bounds);
if (err != ::vr::EVRCompositorError::VRCompositorError_None) {
printf_stderr("OpenVR Compositor Submit() failed.\n");
}
mVRCompositor->PostPresentHandoff();
- // Trigger the next VSync immediately
- VRManager *vm = VRManager::Get();
- MOZ_ASSERT(vm);
- vm->NotifyVRVsync(mDisplayInfo.mDisplayID);
+ return true;
}
#endif
void
VRDisplayOpenVR::NotifyVSync()
{
// We update mIsConneced once per frame.
mDisplayInfo.mIsConnected = ::vr::VR_IsHmdPresent();
// Make sure we respond to OpenVR events even when not presenting
PollEvents();
+
+ VRDisplayHost::NotifyVSync();
}
VRControllerOpenVR::VRControllerOpenVR(dom::GamepadHand aHand, uint32_t aNumButtons,
uint32_t aNumAxes, ::vr::ETrackedDeviceClass aDeviceType)
: VRControllerHost(VRDeviceType::OpenVR)
, mTrigger(0)
, mAxisMove(aNumAxes)
, mVibrateThread(nullptr)
@@ -590,17 +583,17 @@ VRSystemManagerOpenVR::GetHMDs(nsTArray<
}
}
bool
VRSystemManagerOpenVR::GetIsPresenting()
{
if (mOpenVRHMD) {
VRDisplayInfo displayInfo(mOpenVRHMD->GetDisplayInfo());
- return displayInfo.GetIsPresenting();
+ return displayInfo.GetPresentingGroups() != kVRGroupNone;
}
return false;
}
void
VRSystemManagerOpenVR::HandleInput()
{
--- a/gfx/vr/gfxVROpenVR.h
+++ b/gfx/vr/gfxVROpenVR.h
@@ -21,41 +21,38 @@
namespace mozilla {
namespace gfx {
namespace impl {
class VRDisplayOpenVR : public VRDisplayHost
{
public:
virtual void NotifyVSync() override;
- virtual VRHMDSensorState GetSensorState() override;
void ZeroSensor() override;
protected:
+ virtual VRHMDSensorState GetSensorState() override;
virtual void StartPresentation() override;
virtual void StopPresentation() override;
#if defined(XP_WIN)
- virtual void SubmitFrame(mozilla::layers::TextureSourceD3D11* aSource,
+ virtual bool SubmitFrame(mozilla::layers::TextureSourceD3D11* aSource,
const IntSize& aSize,
- const VRHMDSensorState& aSensorState,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect) override;
#endif
public:
explicit VRDisplayOpenVR(::vr::IVRSystem *aVRSystem,
::vr::IVRChaperone *aVRChaperone,
::vr::IVRCompositor *aVRCompositor);
protected:
virtual ~VRDisplayOpenVR();
void Destroy();
- VRHMDSensorState GetSensorState(double timeOffset);
-
// not owned by us; global from OpenVR
::vr::IVRSystem *mVRSystem;
::vr::IVRChaperone *mVRChaperone;
::vr::IVRCompositor *mVRCompositor;
bool mIsPresenting;
void UpdateStageParameters();
--- a/gfx/vr/gfxVRPuppet.cpp
+++ b/gfx/vr/gfxVRPuppet.cpp
@@ -51,17 +51,16 @@ static const uint32_t kPuppetAxes[] = {
static const uint32_t kNumPuppetAxis = sizeof(kPuppetAxes) /
sizeof(uint32_t);
static const uint32_t kNumPuppetHaptcs = 1;
VRDisplayPuppet::VRDisplayPuppet()
: VRDisplayHost(VRDeviceType::Puppet)
, mIsPresenting(false)
- , mFrameNum(0)
{
MOZ_COUNT_CTOR_INHERITED(VRDisplayPuppet, VRDisplayHost);
mDisplayInfo.mDisplayName.AssignLiteral("Puppet HMD");
mDisplayInfo.mIsConnected = true;
mDisplayInfo.mIsMounted = false;
mDisplayInfo.mCapabilityFlags = VRDisplayCapabilityFlags::Cap_None |
VRDisplayCapabilityFlags::Cap_Orientation |
@@ -149,22 +148,17 @@ VRDisplayPuppet::Destroy()
void
VRDisplayPuppet::ZeroSensor()
{
}
VRHMDSensorState
VRDisplayPuppet::GetSensorState()
{
- return GetSensorState(0.0f);
-}
-
-VRHMDSensorState
-VRDisplayPuppet::GetSensorState(double timeOffset)
-{
+ mSensorState.inputFrameID = mDisplayInfo.mFrameId;
return mSensorState;
}
void
VRDisplayPuppet::SetSensorState(const VRHMDSensorState& aSensorState)
{
memcpy(&mSensorState, &aSensorState, sizeof(mSensorState));
}
@@ -290,25 +284,24 @@ VRDisplayPuppet::UpdateConstantBuffers()
ID3D11Buffer *buffer = mVSConstantBuffer;
mContext->VSSetConstantBuffers(0, 1, &buffer);
buffer = mPSConstantBuffer;
mContext->PSSetConstantBuffers(0, 1, &buffer);
return true;
}
-void
+bool
VRDisplayPuppet::SubmitFrame(TextureSourceD3D11* aSource,
const IntSize& aSize,
- const VRHMDSensorState& aSensorState,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect)
{
if (!mIsPresenting) {
- return;
+ return false;
}
VRManager *vm = VRManager::Get();
MOZ_ASSERT(vm);
switch (gfxPrefs::VRPuppetSubmitFrame()) {
case 0:
// The VR frame is not displayed.
@@ -344,49 +337,48 @@ VRDisplayPuppet::SubmitFrame(TextureSour
desc2.BindFlags = 0;
desc2.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
desc2.MiscFlags = 0;
ID3D11Texture2D* stagingTexture = nullptr;
hr = mDevice->CreateTexture2D(&desc2, nullptr, &stagingTexture);
if (FAILED(hr)) {
MOZ_ASSERT(false, "Failed to create a staging texture");
- return;
+ return false;
}
// Copy the texture to a staging resource
mContext->CopyResource(stagingTexture, texture);
// Map the staging resource
hr = mContext->Map(stagingTexture,
0, // Subsource
D3D11_MAP_READ,
0, // MapFlags
&mapInfo);
if (FAILED(hr)) {
MOZ_ASSERT(false, "Failed to map staging texture");
}
mappedTexture = stagingTexture;
- }
- else {
+ } else {
MOZ_ASSERT(false, "Failed to map staging texture");
- return;
+ return false;
}
} else {
mappedTexture = texture;
}
// Ideally, we should convert the srcData to a PNG image and decode it
// to a Base64 string here, but the GPU process does not have the privilege to
// access the image library. So, we have to convert the RAW image data
// to a base64 string and forward it to let the content process to
// do the image conversion.
char* srcData = static_cast<char*>(mapInfo.pData);
VRSubmitFrameResultInfo result;
result.mFormat = SurfaceFormat::B8G8R8A8;
result.mWidth = desc.Width;
result.mHeight = desc.Height;
- result.mFrameNum = mFrameNum;
+ result.mFrameNum = mDisplayInfo.mFrameId;
nsCString rawString(Substring((char*)srcData, mapInfo.RowPitch * desc.Height));
if (Base64Encode(rawString, result.mBase64Image) != NS_OK) {
MOZ_ASSERT(false, "Failed to encode base64 images.");
}
mContext->Unmap(mappedTexture, 0);
// Dispatch the base64 encoded string to the DOM side, and it will be decoded
// and convert to a PNG image there.
@@ -445,55 +437,56 @@ VRDisplayPuppet::SubmitFrame(TextureSour
mContext->PSSetShaderResources(0 /* 0 == TexSlot::RGB */, 1, &srView);
// XXX Use Constant from TexSlot in CompositorD3D11.cpp?
ID3D11SamplerState *sampler = mLinearSamplerState;
mContext->PSSetSamplers(0, 1, &sampler);
if (!UpdateConstantBuffers()) {
NS_WARNING("Failed to update constant buffers for Puppet");
- return;
+ return false;
}
mContext->Draw(4, 0);
break;
}
}
- // Trigger the next VSync immediately
- vm->NotifyVRVsync(mDisplayInfo.mDisplayID);
- ++mFrameNum;
+ // We will always return false for gfxVRPuppet to ensure that the fallback "watchdog"
+ // code in VRDisplayHost::NotifyVSync() throttles the render loop. This "watchdog" will
+ // result in a refresh rate that is quite low compared to real hardware, but should be
+ // sufficient for non-performance oriented tests. If we wish to simulate realistic frame
+ // rates with VRDisplayPuppet, we should block here for the appropriate amount of time and
+ // return true to indicate that we have blocked.
+ return false;
}
#else
-void
+bool
VRDisplayPuppet::SubmitFrame(TextureSourceOGL* aSource,
const IntSize& aSize,
- const VRHMDSensorState& aSensorState,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect)
{
if (!mIsPresenting) {
- return;
+ return false;
}
// TODO: Bug 1343730, Need to block until the next simulated
// vblank interval and capture frames for use in reftests.
- // Trigger the next VSync immediately
- VRManager *vm = VRManager::Get();
- MOZ_ASSERT(vm);
- vm->NotifyVRVsync(mDisplayInfo.mDisplayID);
- ++mFrameNum;
+ return false;
}
#endif
void
VRDisplayPuppet::NotifyVSync()
{
// We update mIsConneced once per frame.
mDisplayInfo.mIsConnected = true;
+
+ VRDisplayHost::NotifyVSync();
}
VRControllerPuppet::VRControllerPuppet(dom::GamepadHand aHand)
: VRControllerHost(VRDeviceType::Puppet)
, mButtonPressState(0)
{
MOZ_COUNT_CTOR_INHERITED(VRControllerPuppet, VRControllerHost);
mControllerInfo.mControllerName.AssignLiteral("Puppet Gamepad");
@@ -630,17 +623,17 @@ VRSystemManagerPuppet::GetHMDs(nsTArray<
aHMDResult.AppendElement(mPuppetHMD);
}
bool
VRSystemManagerPuppet::GetIsPresenting()
{
if (mPuppetHMD) {
VRDisplayInfo displayInfo(mPuppetHMD->GetDisplayInfo());
- return displayInfo.GetIsPresenting();
+ return displayInfo.GetPresentingGroups() != kVRGroupNone;
}
return false;
}
void
VRSystemManagerPuppet::HandleInput()
{
--- a/gfx/vr/gfxVRPuppet.h
+++ b/gfx/vr/gfxVRPuppet.h
@@ -15,46 +15,42 @@ namespace mozilla {
namespace gfx {
namespace impl {
class VRDisplayPuppet : public VRDisplayHost
{
public:
void SetDisplayInfo(const VRDisplayInfo& aDisplayInfo);
virtual void NotifyVSync() override;
- virtual VRHMDSensorState GetSensorState() override;
void SetSensorState(const VRHMDSensorState& aSensorState);
void ZeroSensor() override;
protected:
+ virtual VRHMDSensorState GetSensorState() override;
virtual void StartPresentation() override;
virtual void StopPresentation() override;
#if defined(XP_WIN)
- virtual void SubmitFrame(mozilla::layers::TextureSourceD3D11* aSource,
+ virtual bool SubmitFrame(mozilla::layers::TextureSourceD3D11* aSource,
const IntSize& aSize,
- const VRHMDSensorState& aSensorState,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect) override;
#else
- virtual void SubmitFrame(mozilla::layers::TextureSourceOGL* aSource,
+ virtual bool SubmitFrame(mozilla::layers::TextureSourceOGL* aSource,
const IntSize& aSize,
- const VRHMDSensorState& aSensorState,
const gfx::Rect& aLeftEyeRect,
const gfx::Rect& aRightEyeRect);
#endif // XP_WIN
public:
explicit VRDisplayPuppet();
protected:
virtual ~VRDisplayPuppet();
void Destroy();
- VRHMDSensorState GetSensorState(double timeOffset);
-
bool mIsPresenting;
private:
#if defined(XP_WIN)
bool UpdateConstantBuffers();
RefPtr<ID3D11Device> mDevice;
RefPtr<ID3D11DeviceContext> mContext;
@@ -65,17 +61,16 @@ private:
layers::PixelShaderConstants mPSConstants;
RefPtr<ID3D11Buffer> mVSConstantBuffer;
RefPtr<ID3D11Buffer> mPSConstantBuffer;
RefPtr<ID3D11Buffer> mVertexBuffer;
RefPtr<ID3D11InputLayout> mInputLayout;
#endif
VRHMDSensorState mSensorState;
- uint32_t mFrameNum;
};
class VRControllerPuppet : public VRControllerHost
{
public:
explicit VRControllerPuppet(dom::GamepadHand aHand);
void SetButtonPressState(uint32_t aButton, bool aPressed);
uint64_t GetButtonPressState();
--- a/gfx/vr/ipc/PVRManager.ipdl
+++ b/gfx/vr/ipc/PVRManager.ipdl
@@ -35,27 +35,30 @@ sync protocol PVRManager
{
manages PTexture;
manages PVRLayer;
parent:
async PTexture(SurfaceDescriptor aSharedData, LayersBackend aBackend,
TextureFlags aTextureFlags, uint64_t aSerial);
- async PVRLayer(uint32_t aDisplayID, float aLeftEyeX, float aLeftEyeY, float aLeftEyeWidth, float aLeftEyeHeight, float aRightEyeX, float aRightEyeY, float aRightEyeWidth, float aRightEyeHeight);
+ async PVRLayer(uint32_t aDisplayID, float aLeftEyeX, float aLeftEyeY,
+ float aLeftEyeWidth, float aLeftEyeHeight, float aRightEyeX,
+ float aRightEyeY, float aRightEyeWidth, float aRightEyeHeight,
+ uint32_t aGroup);
// (Re)Enumerate VR Displays. An updated list of VR displays will be returned
// asynchronously to children via UpdateDisplayInfo.
async RefreshDisplays();
// Reset the sensor of the display identified by aDisplayID so that the current
// sensor state is the "Zero" position.
async ResetSensor(uint32_t aDisplayID);
- sync GetSensorState(uint32_t aDisplayID) returns(VRHMDSensorState aState);
+ async SetGroupMask(uint32_t aDisplayID, uint32_t aGroupMask);
async SetHaveEventListener(bool aHaveEventListener);
async ControllerListenerAdded();
async ControllerListenerRemoved();
async VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
double aIntensity, double aDuration, uint32_t aPromiseID);
async StopVibrateHaptic(uint32_t aControllerIdx);
@@ -76,18 +79,16 @@ child:
async ParentAsyncMessages(AsyncParentMessageData[] aMessages);
// Notify children of updated VR display enumeration and details. This will
// be sent to all children when the parent receives RefreshDisplays, even
// if no changes have been detected. This ensures that Promises exposed
// through DOM calls are always resolved.
async UpdateDisplayInfo(VRDisplayInfo[] aDisplayUpdates);
- async NotifyVSync();
- async NotifyVRVSync(uint32_t aDisplayID);
async DispatchSubmitFrameResult(uint32_t aDisplayID, VRSubmitFrameResultInfo aResult);
async GamepadUpdate(GamepadChangeEvent aGamepadEvent);
async ReplyGamepadVibrateHaptic(uint32_t aPromiseID);
async ReplyCreateVRServiceTestDisplay(nsCString aID, uint32_t aPromiseID,
uint32_t aDeviceID);
async ReplyCreateVRServiceTestController(nsCString aID, uint32_t aPromiseID,
uint32_t aDeviceID);
--- a/gfx/vr/ipc/VRLayerParent.cpp
+++ b/gfx/vr/ipc/VRLayerParent.cpp
@@ -5,21 +5,22 @@
#include "VRLayerParent.h"
#include "mozilla/Unused.h"
namespace mozilla {
namespace gfx {
-VRLayerParent::VRLayerParent(uint32_t aVRDisplayID, const Rect& aLeftEyeRect, const Rect& aRightEyeRect)
+VRLayerParent::VRLayerParent(uint32_t aVRDisplayID, const Rect& aLeftEyeRect, const Rect& aRightEyeRect, const uint32_t aGroup)
: mIPCOpen(true)
, mVRDisplayID(aVRDisplayID)
, mLeftEyeRect(aLeftEyeRect)
, mRightEyeRect(aRightEyeRect)
+ , mGroup(aGroup)
{
}
VRLayerParent::~VRLayerParent()
{
MOZ_COUNT_DTOR(VRLayerParent);
}
--- a/gfx/vr/ipc/VRLayerParent.h
+++ b/gfx/vr/ipc/VRLayerParent.h
@@ -14,30 +14,33 @@
namespace mozilla {
namespace gfx {
class VRLayerParent : public PVRLayerParent {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRLayerParent)
public:
- VRLayerParent(uint32_t aVRDisplayID, const Rect& aLeftEyeRect, const Rect& aRightEyeRect);
+ VRLayerParent(uint32_t aVRDisplayID, const Rect& aLeftEyeRect,
+ const Rect& aRightEyeRect, const uint32_t aGroup);
virtual mozilla::ipc::IPCResult RecvSubmitFrame(PTextureParent* texture) override;
virtual mozilla::ipc::IPCResult RecvDestroy() override;
uint32_t GetDisplayID() const { return mVRDisplayID; }
+ uint32_t GetGroup() const { return mGroup; }
protected:
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
virtual ~VRLayerParent();
void Destroy();
bool mIPCOpen;
uint32_t mVRDisplayID;
gfx::IntSize mSize;
gfx::Rect mLeftEyeRect;
gfx::Rect mRightEyeRect;
+ uint32_t mGroup;
};
} // namespace gfx
} // namespace mozilla
#endif
--- a/gfx/vr/ipc/VRManagerChild.cpp
+++ b/gfx/vr/ipc/VRManagerChild.cpp
@@ -35,17 +35,16 @@ static StaticRefPtr<VRManagerParent> sVR
void ReleaseVRManagerParentSingleton() {
sVRManagerParentSingleton = nullptr;
}
VRManagerChild::VRManagerChild()
: TextureForwarder()
, mDisplaysInitialized(false)
- , mInputFrameID(-1)
, mMessageLoop(MessageLoop::current())
, mFrameRequestCallbackCounter(0)
, mBackend(layers::LayersBackend::LAYERS_NONE)
, mPromiseID(0)
, mVRMockDisplay(nullptr)
{
MOZ_ASSERT(NS_IsMainThread());
@@ -185,17 +184,18 @@ PVRLayerChild*
VRManagerChild::AllocPVRLayerChild(const uint32_t& aDisplayID,
const float& aLeftEyeX,
const float& aLeftEyeY,
const float& aLeftEyeWidth,
const float& aLeftEyeHeight,
const float& aRightEyeX,
const float& aRightEyeY,
const float& aRightEyeWidth,
- const float& aRightEyeHeight)
+ const float& aRightEyeHeight,
+ const uint32_t& aGroup)
{
RefPtr<VRLayerChild> layer = new VRLayerChild(aDisplayID, this);
return layer.forget().take();
}
bool
VRManagerChild::DeallocPVRLayerChild(PVRLayerChild* actor)
{
@@ -317,22 +317,16 @@ VRManagerChild::CreateVRServiceTestDispl
void
VRManagerChild::CreateVRServiceTestController(const nsCString& aID, dom::Promise* aPromise)
{
SendCreateVRServiceTestController(aID, mPromiseID);
mPromiseList.Put(mPromiseID, aPromise);
++mPromiseID;
}
-int
-VRManagerChild::GetInputFrameID()
-{
- return mInputFrameID;
-}
-
mozilla::ipc::IPCResult
VRManagerChild::RecvParentAsyncMessages(InfallibleTArray<AsyncParentMessageData>&& aMessages)
{
for (InfallibleTArray<AsyncParentMessageData>::index_type i = 0; i < aMessages.Length(); ++i) {
const AsyncParentMessageData& message = aMessages[i];
switch (message.type()) {
case AsyncParentMessageData::TOpNotifyNotUsed: {
@@ -400,33 +394,36 @@ VRManagerChild::DeallocShmem(ipc::Shmem&
{
return PVRManagerChild::DeallocShmem(aShmem);
}
PVRLayerChild*
VRManagerChild::CreateVRLayer(uint32_t aDisplayID,
const Rect& aLeftEyeRect,
const Rect& aRightEyeRect,
- nsIEventTarget* aTarget)
+ nsIEventTarget* aTarget,
+ uint32_t aGroup)
{
PVRLayerChild* vrLayerChild = AllocPVRLayerChild(aDisplayID, aLeftEyeRect.x,
aLeftEyeRect.y, aLeftEyeRect.width,
aLeftEyeRect.height, aRightEyeRect.x,
aRightEyeRect.y, aRightEyeRect.width,
- aRightEyeRect.height);
+ aRightEyeRect.height,
+ aGroup);
// Do the DOM labeling.
if (aTarget) {
SetEventTargetForActor(vrLayerChild, aTarget);
MOZ_ASSERT(vrLayerChild->GetActorEventTarget());
}
return SendPVRLayerConstructor(vrLayerChild, aDisplayID, aLeftEyeRect.x,
aLeftEyeRect.y, aLeftEyeRect.width,
aLeftEyeRect.height, aRightEyeRect.x,
aRightEyeRect.y, aRightEyeRect.width,
- aRightEyeRect.height);
+ aRightEyeRect.height,
+ aGroup);
}
// XXX TODO - VRManagerChild::FrameRequest is the same as nsIDocument::FrameRequest, should we consolodate these?
struct VRManagerChild::FrameRequest
{
FrameRequest(mozilla::dom::FrameRequestCallback& aCallback,
int32_t aHandle) :
@@ -474,38 +471,16 @@ VRManagerChild::ScheduleFrameRequestCall
void
VRManagerChild::CancelFrameRequestCallback(int32_t aHandle)
{
// mFrameRequestCallbacks is stored sorted by handle
mFrameRequestCallbacks.RemoveElementSorted(aHandle);
}
mozilla::ipc::IPCResult
-VRManagerChild::RecvNotifyVSync()
-{
- for (auto& display : mDisplays) {
- display->NotifyVsync();
- }
-
- return IPC_OK();
-}
-
-mozilla::ipc::IPCResult
-VRManagerChild::RecvNotifyVRVSync(const uint32_t& aDisplayID)
-{
- for (auto& display : mDisplays) {
- if (display->GetDisplayInfo().GetDisplayID() == aDisplayID) {
- display->NotifyVRVsync();
- }
- }
-
- return IPC_OK();
-}
-
-mozilla::ipc::IPCResult
VRManagerChild::RecvGamepadUpdate(const GamepadChangeEvent& aGamepadEvent)
{
// VRManagerChild could be at other processes, but GamepadManager
// only exists at the content process or the same process
// in non-e10s mode.
MOZ_ASSERT(XRE_IsContentProcess() || IsSameProcess());
RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
--- a/gfx/vr/ipc/VRManagerChild.h
+++ b/gfx/vr/ipc/VRManagerChild.h
@@ -43,17 +43,16 @@ public:
static VRManagerChild* Get();
// Indicate that an observer wants to receive VR events.
void AddListener(dom::VREventObserver* aObserver);
// Indicate that an observer should no longer receive VR events.
void RemoveListener(dom::VREventObserver* aObserver);
- int GetInputFrameID();
bool GetVRDisplays(nsTArray<RefPtr<VRDisplayClient> >& aDisplays);
bool RefreshVRDisplaysWithCallback(uint64_t aWindowId);
void AddPromise(const uint32_t& aID, dom::Promise* aPromise);
void CreateVRServiceTestDisplay(const nsCString& aID, dom::Promise* aPromise);
void CreateVRServiceTestController(const nsCString& aID, dom::Promise* aPromise);
static void InitSameProcess();
@@ -71,17 +70,18 @@ public:
uint64_t aSerial,
wr::MaybeExternalImageId& aExternalImageId,
nsIEventTarget* aTarget = nullptr) override;
virtual void CancelWaitForRecycle(uint64_t aTextureId) override;
PVRLayerChild* CreateVRLayer(uint32_t aDisplayID,
const Rect& aLeftEyeRect,
const Rect& aRightEyeRect,
- nsIEventTarget* aTarget);
+ nsIEventTarget* aTarget,
+ uint32_t aGroup);
static void IdentifyTextureHost(const layers::TextureFactoryIdentifier& aIdentifier);
layers::LayersBackend GetBackendType() const;
layers::SyncObject* GetSyncObject() { return mSyncObject; }
virtual MessageLoop* GetMessageLoop() const override { return mMessageLoop; }
virtual base::ProcessId GetParentPid() const override { return OtherPid(); }
@@ -114,25 +114,24 @@ protected:
virtual PVRLayerChild* AllocPVRLayerChild(const uint32_t& aDisplayID,
const float& aLeftEyeX,
const float& aLeftEyeY,
const float& aLeftEyeWidth,
const float& aLeftEyeHeight,
const float& aRightEyeX,
const float& aRightEyeY,
const float& aRightEyeWidth,
- const float& aRightEyeHeight) override;
+ const float& aRightEyeHeight,
+ const uint32_t& aGroup) override;
virtual bool DeallocPVRLayerChild(PVRLayerChild* actor) override;
virtual mozilla::ipc::IPCResult RecvUpdateDisplayInfo(nsTArray<VRDisplayInfo>&& aDisplayUpdates) override;
virtual mozilla::ipc::IPCResult RecvParentAsyncMessages(InfallibleTArray<AsyncParentMessageData>&& aMessages) override;
- virtual mozilla::ipc::IPCResult RecvNotifyVSync() override;
- virtual mozilla::ipc::IPCResult RecvNotifyVRVSync(const uint32_t& aDisplayID) override;
virtual mozilla::ipc::IPCResult RecvDispatchSubmitFrameResult(const uint32_t& aDisplayID, const VRSubmitFrameResultInfo& aResult) override;
virtual mozilla::ipc::IPCResult RecvGamepadUpdate(const GamepadChangeEvent& aGamepadEvent) override;
virtual mozilla::ipc::IPCResult RecvReplyGamepadVibrateHaptic(const uint32_t& aPromiseID) override;
virtual mozilla::ipc::IPCResult RecvReplyCreateVRServiceTestDisplay(const nsCString& aID,
const uint32_t& aPromiseID,
const uint32_t& aDeviceID) override;
virtual mozilla::ipc::IPCResult RecvReplyCreateVRServiceTestController(const nsCString& aID,
@@ -170,18 +169,16 @@ private:
* make sure if there is no newer usage.
*/
void NotifyNotUsed(uint64_t aTextureId, uint64_t aFwdTransactionId);
nsTArray<RefPtr<VRDisplayClient> > mDisplays;
bool mDisplaysInitialized;
nsTArray<uint64_t> mNavigatorCallbacks;
- int32_t mInputFrameID;
-
MessageLoop* mMessageLoop;
struct FrameRequest;
nsTArray<FrameRequest> mFrameRequestCallbacks;
/**
* The current frame request callback handle
*/
--- a/gfx/vr/ipc/VRManagerParent.cpp
+++ b/gfx/vr/ipc/VRManagerParent.cpp
@@ -60,22 +60,24 @@ PVRLayerParent*
VRManagerParent::AllocPVRLayerParent(const uint32_t& aDisplayID,
const float& aLeftEyeX,
const float& aLeftEyeY,
const float& aLeftEyeWidth,
const float& aLeftEyeHeight,
const float& aRightEyeX,
const float& aRightEyeY,
const float& aRightEyeWidth,
- const float& aRightEyeHeight)
+ const float& aRightEyeHeight,
+ const uint32_t& aGroup)
{
RefPtr<VRLayerParent> layer;
layer = new VRLayerParent(aDisplayID,
Rect(aLeftEyeX, aLeftEyeY, aLeftEyeWidth, aLeftEyeHeight),
- Rect(aRightEyeX, aRightEyeY, aRightEyeWidth, aRightEyeHeight));
+ Rect(aRightEyeX, aRightEyeY, aRightEyeWidth, aRightEyeHeight),
+ aGroup);
VRManager* vm = VRManager::Get();
RefPtr<gfx::VRDisplayHost> display = vm->GetDisplay(aDisplayID);
if (display) {
display->AddLayer(layer);
}
return layer.forget().take();
}
@@ -249,22 +251,22 @@ VRManagerParent::RecvResetSensor(const u
if (display != nullptr) {
display->ZeroSensor();
}
return IPC_OK();
}
mozilla::ipc::IPCResult
-VRManagerParent::RecvGetSensorState(const uint32_t& aDisplayID, VRHMDSensorState* aState)
+VRManagerParent::RecvSetGroupMask(const uint32_t& aDisplayID, const uint32_t& aGroupMask)
{
VRManager* vm = VRManager::Get();
RefPtr<gfx::VRDisplayHost> display = vm->GetDisplay(aDisplayID);
if (display != nullptr) {
- *aState = display->GetSensorState();
+ display->SetGroupMask(aGroupMask);
}
return IPC_OK();
}
bool
VRManagerParent::HaveEventListener()
{
return mHaveEventListener;
--- a/gfx/vr/ipc/VRManagerParent.h
+++ b/gfx/vr/ipc/VRManagerParent.h
@@ -75,32 +75,32 @@ protected:
virtual PVRLayerParent* AllocPVRLayerParent(const uint32_t& aDisplayID,
const float& aLeftEyeX,
const float& aLeftEyeY,
const float& aLeftEyeWidth,
const float& aLeftEyeHeight,
const float& aRightEyeX,
const float& aRightEyeY,
const float& aRightEyeWidth,
- const float& aRightEyeHeight) override;
+ const float& aRightEyeHeight,
+ const uint32_t& aGroup) override;
virtual bool DeallocPVRLayerParent(PVRLayerParent* actor) override;
virtual void ActorDestroy(ActorDestroyReason why) override;
void OnChannelConnected(int32_t pid) override;
virtual mozilla::ipc::IPCResult RecvRefreshDisplays() override;
virtual mozilla::ipc::IPCResult RecvResetSensor(const uint32_t& aDisplayID) override;
- virtual mozilla::ipc::IPCResult RecvGetSensorState(const uint32_t& aDisplayID, VRHMDSensorState* aState) override;
+ virtual mozilla::ipc::IPCResult RecvSetGroupMask(const uint32_t& aDisplayID, const uint32_t& aGroupMask) override;
virtual mozilla::ipc::IPCResult RecvSetHaveEventListener(const bool& aHaveEventListener) override;
virtual mozilla::ipc::IPCResult RecvControllerListenerAdded() override;
virtual mozilla::ipc::IPCResult RecvControllerListenerRemoved() override;
virtual mozilla::ipc::IPCResult RecvVibrateHaptic(const uint32_t& aControllerIdx, const uint32_t& aHapticIndex,
const double& aIntensity, const double& aDuration, const uint32_t& aPromiseID) override;
virtual mozilla::ipc::IPCResult RecvStopVibrateHaptic(const uint32_t& aControllerIdx) override;
-
virtual mozilla::ipc::IPCResult RecvCreateVRTestSystem() override;
virtual mozilla::ipc::IPCResult RecvCreateVRServiceTestDisplay(const nsCString& aID, const uint32_t& aPromiseID) override;
virtual mozilla::ipc::IPCResult RecvCreateVRServiceTestController(const nsCString& aID, const uint32_t& aPromiseID) override;
virtual mozilla::ipc::IPCResult RecvSetDisplayInfoToMockDisplay(const uint32_t& aDeviceID,
const VRDisplayInfo& aDisplayInfo) override;
virtual mozilla::ipc::IPCResult RecvSetSensorStateToMockDisplay(const uint32_t& aDeviceID,
const VRHMDSensorState& aSensorState) override;
virtual mozilla::ipc::IPCResult RecvNewButtonEventToMockController(const uint32_t& aDeviceID, const long& aButton,
--- a/gfx/vr/ipc/VRMessageUtils.h
+++ b/gfx/vr/ipc/VRMessageUtils.h
@@ -35,45 +35,57 @@ struct ParamTraits<mozilla::gfx::VRDispl
{
WriteParam(aMsg, aParam.mType);
WriteParam(aMsg, aParam.mDisplayID);
WriteParam(aMsg, aParam.mDisplayName);
WriteParam(aMsg, aParam.mCapabilityFlags);
WriteParam(aMsg, aParam.mEyeResolution);
WriteParam(aMsg, aParam.mIsConnected);
WriteParam(aMsg, aParam.mIsMounted);
- WriteParam(aMsg, aParam.mIsPresenting);
+ WriteParam(aMsg, aParam.mPresentingGroups);
+ WriteParam(aMsg, aParam.mGroupMask);
WriteParam(aMsg, aParam.mStageSize);
WriteParam(aMsg, aParam.mSittingToStandingTransform);
+ WriteParam(aMsg, aParam.mFrameId);
for (int i = 0; i < mozilla::gfx::VRDisplayInfo::NumEyes; i++) {
WriteParam(aMsg, aParam.mEyeFOV[i]);
WriteParam(aMsg, aParam.mEyeTranslation[i]);
}
+ for (int i = 0; i < mozilla::gfx::kVRMaxLatencyFrames; i++) {
+ WriteParam(aMsg, aParam.mLastSensorState[i]);
+ }
}
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
{
if (!ReadParam(aMsg, aIter, &(aResult->mType)) ||
!ReadParam(aMsg, aIter, &(aResult->mDisplayID)) ||
!ReadParam(aMsg, aIter, &(aResult->mDisplayName)) ||
!ReadParam(aMsg, aIter, &(aResult->mCapabilityFlags)) ||
!ReadParam(aMsg, aIter, &(aResult->mEyeResolution)) ||
!ReadParam(aMsg, aIter, &(aResult->mIsConnected)) ||
!ReadParam(aMsg, aIter, &(aResult->mIsMounted)) ||
- !ReadParam(aMsg, aIter, &(aResult->mIsPresenting)) ||
+ !ReadParam(aMsg, aIter, &(aResult->mPresentingGroups)) ||
+ !ReadParam(aMsg, aIter, &(aResult->mGroupMask)) ||
!ReadParam(aMsg, aIter, &(aResult->mStageSize)) ||
- !ReadParam(aMsg, aIter, &(aResult->mSittingToStandingTransform))) {
+ !ReadParam(aMsg, aIter, &(aResult->mSittingToStandingTransform)) ||
+ !ReadParam(aMsg, aIter, &(aResult->mFrameId))) {
return false;
}
for (int i = 0; i < mozilla::gfx::VRDisplayInfo::NumEyes; i++) {
if (!ReadParam(aMsg, aIter, &(aResult->mEyeFOV[i])) ||
!ReadParam(aMsg, aIter, &(aResult->mEyeTranslation[i]))) {
return false;
}
}
+ for (int i = 0; i < mozilla::gfx::kVRMaxLatencyFrames; i++) {
+ if (!ReadParam(aMsg, aIter, &(aResult->mLastSensorState[i]))) {
+ return false;
+ }
+ }
return true;
}
};
template <>
struct ParamTraits<mozilla::gfx::VRHMDSensorState>
{
--- a/gfx/vr/ovr_capi_dynamic.h
+++ b/gfx/vr/ovr_capi_dynamic.h
@@ -718,14 +718,26 @@ typedef ovrResult (OVR_PFN* pfn_ovr_Crea
typedef ovrResult (OVR_PFN* pfn_ovr_GetMirrorTextureBufferGL)(ovrSession session,
ovrMirrorTexture mirrorTexture,
unsigned int* out_TexId);
#define OVR_KEY_EYE_HEIGHT "EyeHeight" // float meters
#define OVR_DEFAULT_EYE_HEIGHT 1.675f
+#if !defined(OVR_SUCCESS)
+#define OVR_SUCCESS(result) (result >= 0)
+#endif
+
+#if !defined(OVR_UNQUALIFIED_SUCCESS)
+#define OVR_UNQUALIFIED_SUCCESS(result) (result == ovrSuccess)
+#endif
+
+#if !defined(OVR_FAILURE)
+#define OVR_FAILURE(result) (!OVR_SUCCESS(result))
+#endif
+
#ifdef __cplusplus
}
#endif
#endif /* mozilla_ovr_capi_dynamic_h_ */
#endif /* OVR_CAPI_h */
--- a/ipc/ipdl/sync-messages.ini
+++ b/ipc/ipdl/sync-messages.ini
@@ -1045,18 +1045,16 @@ description =
[PWebRenderBridge::DPSyncEnd]
description =
[PWebRenderBridge::DPGetSnapshot]
description =
[PWebRenderBridge::SetAsyncScrollOffset]
description = test only
[PWebRenderBridge::SetAsyncZoom]
description = test only
-[PVRManager::GetSensorState]
-description =
[PHal::GetCurrentBatteryInformation]
description =
[PHal::GetCurrentNetworkInformation]
description =
[PHal::GetScreenEnabled]
description =
[PHal::GetKeyLightEnabled]
description =