Bug 1250244 - (WIP, Don't commit) Implement WebVR 1.0 API draft
authorKearwood (Kip) Gilbert <kgilbert@mozilla.com>
Wed, 24 Feb 2016 15:54:50 -0800
changeset 340037 f3126bf6c31e39f7e7f65e18f76e396b9b4a8399
parent 339874 f0c0480732d36153e8839c7f17394d45f679f87d
child 516129 c426f66968c1b28b81e0e4258a03da37cf134b9b
push id12890
push userkgilbert@mozilla.com
push dateMon, 14 Mar 2016 22:39:46 +0000
bugs1250244
milestone48.0a1
Bug 1250244 - (WIP, Don't commit) Implement WebVR 1.0 API MozReview-Commit-ID: JTOmaWePlJq
dom/base/Element.cpp
dom/base/Element.h
dom/base/Navigator.cpp
dom/base/Navigator.h
dom/base/nsDocument.cpp
dom/base/nsDocument.h
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/base/nsPIDOMWindow.h
dom/bindings/Bindings.conf
dom/gamepad/Gamepad.h
dom/tests/mochitest/general/test_interfaces.html
dom/vr/VRDevice.cpp
dom/vr/VRDevice.h
dom/vr/VRDisplay.cpp
dom/vr/VRDisplay.h
dom/vr/moz.build
dom/webidl/Element.webidl
dom/webidl/Gamepad.webidl
dom/webidl/Navigator.webidl
dom/webidl/VRDevice.webidl
dom/webidl/VRDisplay.webidl
dom/webidl/moz.build
gfx/2d/BasePoint.h
gfx/2d/BasePoint3D.h
gfx/2d/BasePoint4D.h
gfx/2d/BaseSize.h
gfx/2d/Matrix.h
gfx/layers/Layers.cpp
gfx/layers/Layers.h
gfx/layers/composite/ContainerLayerComposite.cpp
gfx/layers/ipc/LayerTransactionParent.cpp
gfx/vr/VRDeviceProxy.cpp
gfx/vr/VRDeviceProxy.h
gfx/vr/VRDeviceProxyOrientationFallBack.cpp
gfx/vr/VRDeviceProxyOrientationFallBack.h
gfx/vr/VRDisplayProxy.cpp
gfx/vr/VRDisplayProxy.h
gfx/vr/VRDisplayProxyOrientationFallBack.cpp
gfx/vr/VRDisplayProxyOrientationFallBack.h
gfx/vr/VRManager.cpp
gfx/vr/VRManager.h
gfx/vr/gfxVR.h
gfx/vr/gfxVRCardboard.cpp
gfx/vr/gfxVROculus.cpp
gfx/vr/gfxVROculus050.cpp
gfx/vr/ipc/PVRManager.ipdl
gfx/vr/ipc/VRManagerChild.cpp
gfx/vr/ipc/VRManagerChild.h
gfx/vr/ipc/VRManagerParent.cpp
gfx/vr/ipc/VRMessageUtils.h
gfx/vr/moz.build
layout/base/nsDisplayList.cpp
layout/base/nsDisplayList.h
layout/generic/nsFrame.cpp
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -137,17 +137,17 @@
 #include "nsITextControlElement.h"
 #include "nsITextControlFrame.h"
 #include "nsISupportsImpl.h"
 #include "mozilla/dom/CSSPseudoElement.h"
 #include "mozilla/dom/DocumentFragment.h"
 #include "mozilla/dom/KeyframeEffectBinding.h"
 #include "mozilla/dom/WindowBinding.h"
 #include "mozilla/dom/ElementBinding.h"
-#include "mozilla/dom/VRDevice.h"
+#include "mozilla/dom/VRDisplay.h"
 #include "mozilla/IntegerPrintfMacros.h"
 #include "mozilla/Preferences.h"
 #include "nsComputedDOMStyle.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 nsIAtom*
@@ -3247,35 +3247,39 @@ GetFullScreenError(nsIDocument* aDoc)
   if (!nsContentUtils::IsRequestFullScreenAllowed()) {
     return "FullscreenDeniedNotInputDriven";
   }
 
   return nullptr;
 }
 
 void
-Element::RequestFullscreen(JSContext* aCx, JS::Handle<JS::Value> aOptions,
-                           ErrorResult& aError)
+Element::RequestFullscreen(ErrorResult& aError)
 {
-  MOZ_ASSERT_IF(!aCx, aOptions.isNullOrUndefined());
   // Only grant full-screen requests if this is called from inside a trusted
   // event handler (i.e. inside an event handler for a user initiated event).
   // This stops the full-screen from being abused similar to the popups of old,
   // and it also makes it harder for bad guys' script to go full-screen and
   // spoof the browser chrome/window and phish logins etc.
   // Note that requests for fullscreen inside a web app's origin are exempt
   // from this restriction.
   if (const char* error = GetFullScreenError(OwnerDoc())) {
     OwnerDoc()->DispatchFullscreenError(error);
     return;
   }
 
   auto request = MakeUnique<FullscreenRequest>(this);
   request->mIsCallerChrome = nsContentUtils::IsCallerChrome();
 
+  /*
+  
+  //  FINDME!!! KIP!!! HACK!!!  Need to move this to match the WebVR 1.0 API
+  
+  
+
   RequestFullscreenOptions fsOptions;
   // We need to check if options is convertible to a dict first before
   // trying to init fsOptions; otherwise Init() would throw, and we want to
   // silently ignore non-dictionary values
   if (aCx) {
     bool convertible;
     if (!IsConvertibleToDictionary(aCx, aOptions, &convertible)) {
       aError.Throw(NS_ERROR_FAILURE);
@@ -3288,16 +3292,17 @@ Element::RequestFullscreen(JSContext* aC
         return;
       }
 
       if (fsOptions.mVrDisplay) {
         request->mVRHMDDevice = fsOptions.mVrDisplay->GetHMD();
       }
     }
   }
+  */
 
   OwnerDoc()->AsyncRequestFullScreen(Move(request));
 }
 
 void
 Element::MozRequestPointerLock()
 {
   OwnerDoc()->RequestPointerLock(this);
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -725,19 +725,17 @@ public:
   }
   void ReleaseCapture()
   {
     if (nsIPresShell::GetCapturingContent() == this) {
       nsIPresShell::SetCapturingContent(nullptr, 0);
     }
   }
 
-  // aCx == nullptr is allowed only if aOptions.isNullOrUndefined()
-  void RequestFullscreen(JSContext* aCx, JS::Handle<JS::Value> aOptions,
-                         ErrorResult& aError);
+  void RequestFullscreen(ErrorResult& aError);
   void MozRequestPointerLock();
   Attr* GetAttributeNode(const nsAString& aName);
   already_AddRefed<Attr> SetAttributeNode(Attr& aNewAttr,
                                           ErrorResult& aError);
   already_AddRefed<Attr> RemoveAttributeNode(Attr& aOldAttr,
                                              ErrorResult& aError);
   Attr* GetAttributeNodeNS(const nsAString& aNamespaceURI,
                            const nsAString& aLocalName);
@@ -1816,17 +1814,17 @@ NS_IMETHOD SetCapture(bool retargetToEle
 NS_IMETHOD ReleaseCapture(void) final override                                \
 {                                                                             \
   Element::ReleaseCapture();                                                  \
   return NS_OK;                                                               \
 }                                                                             \
 NS_IMETHOD MozRequestFullScreen(void) final override                          \
 {                                                                             \
   mozilla::ErrorResult rv;                                                    \
-  Element::RequestFullscreen(nullptr, JS::UndefinedHandleValue, rv);          \
+  Element::RequestFullscreen(rv);                                    \
   return rv.StealNSResult();                                                  \
 }                                                                             \
 NS_IMETHOD MozRequestPointerLock(void) final override                         \
 {                                                                             \
   Element::MozRequestPointerLock();                                           \
   return NS_OK;                                                               \
 }                                                                             \
 using nsINode::QuerySelector;                                                 \
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -42,17 +42,17 @@
 #include "mozilla/dom/MobileMessageManager.h"
 #include "mozilla/dom/Permissions.h"
 #include "mozilla/dom/Presentation.h"
 #include "mozilla/dom/ServiceWorkerContainer.h"
 #include "mozilla/dom/TCPSocket.h"
 #include "mozilla/dom/Telephony.h"
 #include "mozilla/dom/Voicemail.h"
 #include "mozilla/dom/TVManager.h"
-#include "mozilla/dom/VRDevice.h"
+#include "mozilla/dom/VRDisplay.h"
 #include "mozilla/Hal.h"
 #include "nsISiteSpecificUserAgent.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/StaticPtr.h"
 #include "Connection.h"
 #include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
 #include "nsGlobalWindow.h"
 #ifdef MOZ_B2G
@@ -220,17 +220,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCachedResolveResults)
 #ifdef MOZ_EME
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeySystemAccessManager)
 #endif
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDeviceStorageAreaListener)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPresentation)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRGetDevicesPromises)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRGetDisplaysPromises)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(Navigator)
 
 void
 Navigator::Invalidate()
 {
@@ -362,17 +362,17 @@ Navigator::Invalidate()
     mMediaKeySystemAccessManager = nullptr;
   }
 #endif
 
   if (mDeviceStorageAreaListener) {
     mDeviceStorageAreaListener = nullptr;
   }
 
-  mVRGetDevicesPromises.Clear();
+  mVRGetDisplaysPromises.Clear();
 }
 
 //*****************************************************************************
 //    Navigator::nsIDOMNavigator
 //*****************************************************************************
 
 NS_IMETHODIMP
 Navigator::GetUserAgent(nsAString& aUserAgent)
@@ -1930,58 +1930,58 @@ Navigator::GetGamepads(nsTArray<RefPtr<G
   NS_ENSURE_TRUE_VOID(mWindow->GetDocShell());
   nsGlobalWindow* win = nsGlobalWindow::Cast(mWindow);
   win->SetHasGamepadEventListener(true);
   win->GetGamepads(aGamepads);
 }
 #endif
 
 already_AddRefed<Promise>
-Navigator::GetVRDevices(ErrorResult& aRv)
+Navigator::GetVRDisplays(ErrorResult& aRv)
 {
   if (!mWindow || !mWindow->GetDocShell()) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
   nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(mWindow);
   RefPtr<Promise> p = Promise::Create(go, aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
-  // We pass ourself to RefreshVRDevices, so NotifyVRDevicesUpdated will
-  // be called asynchronously, resolving the promises in mVRGetDevicesPromises.
-  if (!VRDevice::RefreshVRDevices(this)) {
+  // We pass ourself to RefreshVRDisplays, so NotifyVRDisplaysUpdated will
+  // be called asynchronously, resolving the promises in mVRGetDisplaysPromises.
+  if (!VRDisplay::RefreshVRDisplays(this)) {
     p->MaybeReject(NS_ERROR_FAILURE);
     return p.forget();
   }
 
-  mVRGetDevicesPromises.AppendElement(p);
+  mVRGetDisplaysPromises.AppendElement(p);
   return p.forget();
 }
 
 void
-Navigator::NotifyVRDevicesUpdated()
+Navigator::NotifyVRDisplaysUpdated()
 {
   // Synchronize the VR devices and resolve the promises in
-  // mVRGetDevicesPromises
+  // mVRGetDisplaysPromises
   nsGlobalWindow* win = nsGlobalWindow::Cast(mWindow);
 
-  nsTArray<RefPtr<VRDevice>> vrDevs;
-  if (win->UpdateVRDevices(vrDevs)) {
-    for (auto p: mVRGetDevicesPromises) {
-      p->MaybeResolve(vrDevs);
+  nsTArray<RefPtr<VRDisplay>> vrDisplays;
+  if (win->UpdateVRDisplays(vrDisplays)) {
+    for (auto p: mVRGetDisplaysPromises) {
+      p->MaybeResolve(vrDisplays);
     }
   } else {
-    for (auto p: mVRGetDevicesPromises) {
+    for (auto p: mVRGetDisplaysPromises) {
       p->MaybeReject(NS_ERROR_FAILURE);
     }
   }
-  mVRGetDevicesPromises.Clear();
+  mVRGetDisplaysPromises.Clear();
 }
 
 //*****************************************************************************
 //    Navigator::nsIMozNavigatorNetwork
 //*****************************************************************************
 
 NS_IMETHODIMP
 Navigator::GetProperties(nsINetworkProperties** aProperties)
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -263,18 +263,18 @@ public:
                                                  ErrorResult& aRv);
 #endif
 #ifdef MOZ_B2G_RIL
   MobileConnectionArray* GetMozMobileConnections(ErrorResult& aRv);
 #endif // MOZ_B2G_RIL
 #ifdef MOZ_GAMEPAD
   void GetGamepads(nsTArray<RefPtr<Gamepad> >& aGamepads, ErrorResult& aRv);
 #endif // MOZ_GAMEPAD
-  already_AddRefed<Promise> GetVRDevices(ErrorResult& aRv);
-  void NotifyVRDevicesUpdated();
+  already_AddRefed<Promise> GetVRDisplays(ErrorResult& aRv);
+  void NotifyVRDisplaysUpdated();
 #ifdef MOZ_B2G_FM
   FMRadio* GetMozFMRadio(ErrorResult& aRv);
 #endif
 #ifdef MOZ_B2G_BT
   bluetooth::BluetoothManager* GetMozBluetooth(ErrorResult& aRv);
 #endif // MOZ_B2G_BT
 #ifdef MOZ_TIME_MANAGER
   time::TimeManager* GetMozTime(ErrorResult& aRv);
@@ -419,15 +419,15 @@ private:
 
   // Hashtable for saving cached objects DoResolve created, so we don't create
   // the object twice if asked for it twice, whether due to use of "delete" or
   // due to Xrays.  We could probably use a nsJSThingHashtable here, but then
   // we'd need to figure out exactly how to trace that, and that seems to be
   // rocket science.  :(
   nsInterfaceHashtable<nsStringHashKey, nsISupports> mCachedResolveResults;
 
-  nsTArray<RefPtr<Promise> > mVRGetDevicesPromises;
+  nsTArray<RefPtr<Promise> > mVRGetDisplaysPromises;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_Navigator_h
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -247,16 +247,17 @@
 #include "mozilla/StyleSetHandle.h"
 #include "mozilla/StyleSetHandleInlines.h"
 #include "mozilla/StyleSheetHandle.h"
 #include "mozilla/StyleSheetHandleInlines.h"
 
 #include "mozilla/DocLoadingTimelineMarker.h"
 
 #include "nsISpeculativeConnect.h"
+#include "VRDisplayProxy.h"
 
 #ifdef MOZ_MEDIA_NAVIGATOR
 #include "mozilla/MediaManager.h"
 #endif // MOZ_MEDIA_NAVIGATOR
 #ifdef MOZ_WEBRTC
 #include "IPeerConnection.h"
 #endif // MOZ_WEBRTC
 
@@ -11625,20 +11626,20 @@ nsresult nsDocument::RemoteFrameFullscre
 
 nsresult nsDocument::RemoteFrameFullscreenReverted()
 {
   RestorePreviousFullScreenState();
   return NS_OK;
 }
 
 static void
-ReleaseVRDeviceProxyRef(void *, nsIAtom*, void *aPropertyValue, void *)
+ReleaseVRDisplayProxyRef(void *, nsIAtom*, void *aPropertyValue, void *)
 {
   if (aPropertyValue) {
-    static_cast<gfx::VRDeviceProxy*>(aPropertyValue)->Release();
+    static_cast<gfx::VRDisplayProxy*>(aPropertyValue)->Release();
   }
 }
 
 static bool
 HasFullScreenSubDocument(nsIDocument* aDoc)
 {
   uint32_t count = CountFullscreenSubDocuments(aDoc);
   NS_ASSERTION(count <= 1, "Fullscreen docs should have at most 1 fullscreen child!");
@@ -11989,19 +11990,19 @@ nsDocument::ApplyFullscreen(const Fullsc
   nsIDocument* fullScreenRootDoc = nsContentUtils::GetRootDocument(this);
 
   // If a document is already in fullscreen, then unlock the mouse pointer
   // before setting a new document to fullscreen
   UnlockPointer();
 
   // Process options -- in this case, just HMD
   if (aRequest.mVRHMDDevice) {
-    RefPtr<gfx::VRDeviceProxy> hmdRef = aRequest.mVRHMDDevice;
+    RefPtr<gfx::VRDisplayProxy> hmdRef = aRequest.mVRHMDDevice;
     elem->SetProperty(nsGkAtoms::vr_state, hmdRef.forget().take(),
-                      ReleaseVRDeviceProxyRef, true);
+                      ReleaseVRDisplayProxyRef, true);
   }
 
   // Set the full-screen element. This sets the full-screen style on the
   // element, and the full-screen-ancestor styles on ancestors of the element
   // in this document.
   DebugOnly<bool> x = FullScreenStackPush(elem);
   NS_ASSERTION(x, "Full-screen state of requesting doc should always change!");
   // Set the iframe fullscreen flag.
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -106,17 +106,17 @@ struct FullscreenRequest : public Linked
   Element* GetElement() const { return mElement; }
   nsDocument* GetDocument() const { return mDocument; }
 
 private:
   RefPtr<Element> mElement;
   RefPtr<nsDocument> mDocument;
 
 public:
-  RefPtr<gfx::VRDeviceProxy> mVRHMDDevice;
+  RefPtr<gfx::VRDisplayProxy> mVRHMDDevice;
   // This value should be true if the fullscreen request is
   // originated from chrome code.
   bool mIsCallerChrome = false;
   // This value denotes whether we should trigger a NewOrigin event if
   // requesting fullscreen in its document causes the origin which is
   // fullscreen to change. We may want *not* to trigger that event if
   // we're calling RequestFullScreen() as part of a continuation of a
   // request in a subdocument in different process, whereupon the caller
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -188,17 +188,17 @@
 #include "mozilla/dom/MessageChannel.h"
 #include "mozilla/dom/Promise.h"
 
 #ifdef MOZ_GAMEPAD
 #include "mozilla/dom/Gamepad.h"
 #include "mozilla/dom/GamepadService.h"
 #endif
 
-#include "mozilla/dom/VRDevice.h"
+#include "mozilla/dom/VRDisplay.h"
 
 #include "nsRefreshDriver.h"
 #include "Layers.h"
 
 #include "mozilla/AddonPathService.h"
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/Services.h"
 #include "mozilla/Telemetry.h"
@@ -1862,17 +1862,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingStorageEvents)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleObservers)
 
 #ifdef MOZ_GAMEPAD
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepads)
 #endif
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCacheStorage)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRDevices)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRDisplays)
 
   // Traverse stuff from nsPIDOMWindow
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeEventHandler)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentTarget)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameElement)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFocusedNode)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMenubar)
@@ -1937,17 +1937,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingStorageEvents)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleObservers)
 
 #ifdef MOZ_GAMEPAD
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mGamepads)
 #endif
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCacheStorage)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mVRDevices)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mVRDisplays)
 
   // Unlink stuff from nsPIDOMWindow
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeEventHandler)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mParentTarget)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mFrameElement)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mFocusedNode)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mMenubar)
@@ -6023,17 +6023,17 @@ FullscreenTransitionTask::Observer::Obse
     obs->RemoveObserver(this, kPaintedTopic);
     mTask->mTimer = nullptr;
     mTask->Run();
   }
   return NS_OK;
 }
 
 static bool
-MakeWidgetFullscreen(nsGlobalWindow* aWindow, gfx::VRDeviceProxy* aHMD,
+MakeWidgetFullscreen(nsGlobalWindow* aWindow, gfx::VRDisplayProxy* aHMD,
                      FullscreenReason aReason, bool aFullscreen)
 {
   nsCOMPtr<nsIWidget> widget = aWindow->GetMainWidget();
   if (!widget) {
     return false;
   }
 
   FullscreenTransitionDuration duration;
@@ -6056,17 +6056,17 @@ MakeWidgetFullscreen(nsGlobalWindow* aWi
     task->Run();
     return true;
   }
 }
 
 nsresult
 nsGlobalWindow::SetFullscreenInternal(FullscreenReason aReason,
                                       bool aFullScreen,
-                                      gfx::VRDeviceProxy* aHMD)
+                                      gfx::VRDisplayProxy* aHMD)
 {
   MOZ_ASSERT(IsOuterWindow());
   MOZ_ASSERT(nsContentUtils::IsSafeToRunScript(),
              "Requires safe to run script as it "
              "may call FinishDOMFullscreenChange");
 
   NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
 
@@ -13081,22 +13081,22 @@ nsGlobalWindow::SyncGamepadState()
     for (auto iter = mGamepads.Iter(); !iter.Done(); iter.Next()) {
       gamepadsvc->SyncGamepadState(iter.Key(), iter.UserData());
     }
   }
 }
 #endif // MOZ_GAMEPAD
 
 bool
-nsGlobalWindow::UpdateVRDevices(nsTArray<RefPtr<mozilla::dom::VRDevice>>& aDevices)
-{
-  FORWARD_TO_INNER(UpdateVRDevices, (aDevices), false);
-
-  VRDevice::UpdateVRDevices(mVRDevices, ToSupports(this));
-  aDevices = mVRDevices;
+nsGlobalWindow::UpdateVRDisplays(nsTArray<RefPtr<mozilla::dom::VRDisplay>>& aDevices)
+{
+  FORWARD_TO_INNER(UpdateVRDisplays, (aDevices), false);
+
+  VRDisplay::UpdateVRDisplays(mVRDisplays, ToSupports(this));
+  aDevices = mVRDisplays;
   return true;
 }
 
 // nsGlobalChromeWindow implementation
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalChromeWindow)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGlobalChromeWindow,
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -112,28 +112,28 @@ class Navigator;
 class OwningExternalOrWindowProxy;
 class Promise;
 class PostMessageEvent;
 struct RequestInit;
 class RequestOrUSVString;
 class Selection;
 class SpeechSynthesis;
 class U2F;
-class VRDevice;
+class VRDisplay;
 class WakeLock;
 #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
 class WindowOrientationObserver;
 #endif
 namespace cache {
 class CacheStorage;
 } // namespace cache
 class IDBFactory;
 } // namespace dom
 namespace gfx {
-class VRDeviceProxy;
+class VRDisplayProxy;
 } // namespace gfx
 } // namespace mozilla
 
 extern already_AddRefed<nsIScriptTimeoutHandler>
 NS_CreateJSTimeoutHandler(JSContext* aCx, nsGlobalWindow *aWindow,
                           mozilla::dom::Function& aFunction,
                           const mozilla::dom::Sequence<JS::Value>& aArguments,
                           mozilla::ErrorResult& aError);
@@ -483,17 +483,17 @@ public:
   void RefreshCompartmentPrincipal();
 
   // For accessing protected field mFullScreen
   friend class FullscreenTransitionTask;
 
   // Outer windows only.
   virtual nsresult SetFullscreenInternal(
     FullscreenReason aReason, bool aIsFullscreen,
-    mozilla::gfx::VRDeviceProxy *aHMD = nullptr) override final;
+    mozilla::gfx::VRDisplayProxy *aHMD = nullptr) override final;
   virtual void FinishFullscreenChange(bool aIsFullscreen) override final;
   bool SetWidgetFullscreen(FullscreenReason aReason, bool aIsFullscreen,
                            nsIWidget* aWidget, nsIScreen* aScreen);
   bool FullScreen() const;
 
   // Inner windows only.
   virtual void SetHasGamepadEventListener(bool aHasGamepad = true) override;
 
@@ -772,17 +772,17 @@ public:
 #endif
 
   // Inner windows only.
   // Enable/disable updates for gamepad input.
   void EnableGamepadUpdates();
   void DisableGamepadUpdates();
 
   // Update the VR devices for this window
-  bool UpdateVRDevices(nsTArray<RefPtr<mozilla::dom::VRDevice>>& aDevices);
+  bool UpdateVRDisplays(nsTArray<RefPtr<mozilla::dom::VRDisplay>>& aDevices);
 
 #define EVENT(name_, id_, type_, struct_)                                     \
   mozilla::dom::EventHandlerNonNull* GetOn##name_()                           \
   {                                                                           \
     mozilla::EventListenerManager* elm = GetExistingListenerManager();        \
     return elm ? elm->GetEventHandler(nsGkAtoms::on##name_, EmptyString())    \
                : nullptr;                                                     \
   }                                                                           \
@@ -1870,17 +1870,17 @@ protected:
   // mSpeechSynthesis is only used on inner windows.
   RefPtr<mozilla::dom::SpeechSynthesis> mSpeechSynthesis;
 #endif
 
   // This is the CC generation the last time we called CanSkip.
   uint32_t mCanSkipCCGeneration;
 
   // The VRDevies for this window
-  nsTArray<RefPtr<mozilla::dom::VRDevice>> mVRDevices;
+  nsTArray<RefPtr<mozilla::dom::VRDisplay>> mVRDisplays;
 
   friend class nsDOMScriptableHelper;
   friend class nsDOMWindowUtils;
   friend class mozilla::dom::PostMessageEvent;
   friend class DesktopNotification;
 
   static WindowByIdTable* sWindowsById;
   static bool sWarnedAboutWindowInternal;
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -40,17 +40,17 @@ struct nsTimeout;
 
 namespace mozilla {
 namespace dom {
 class AudioContext;
 class Element;
 class ServiceWorkerRegistrationMainThread;
 } // namespace dom
 namespace gfx {
-class VRDeviceProxy;
+class VRDisplayProxy;
 } // namespace gfx
 } // namespace mozilla
 
 // Popup control state enum. The values in this enum must go from most
 // permissive to least permissive so that it's safe to push state in
 // all situations. Pushing popup state onto the stack never makes the
 // current popup state less permissive (see
 // nsGlobalWindow::PushPopupControlState()).
@@ -332,17 +332,17 @@ public:
    *
    * If aHMD is not null, the window is made full screen on the given VR HMD
    * device instead of its currrent display.
    *
    * Outer windows only.
    */
   virtual nsresult SetFullscreenInternal(
     FullscreenReason aReason, bool aIsFullscreen,
-    mozilla::gfx::VRDeviceProxy *aHMD = nullptr) = 0;
+    mozilla::gfx::VRDisplayProxy *aHMD = nullptr) = 0;
 
   /**
    * This function should be called when the fullscreen state is flipped.
    * If no widget is involved the fullscreen change, this method is called
    * by SetFullscreenInternal, otherwise, it is called when the widget
    * finishes its change to or from fullscreen.
    *
    * @param aIsFullscreen indicates whether the widget is in fullscreen.
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1322,20 +1322,16 @@ DOMInterfaces = {
     'implicitJSContext' : [ 'undo', 'redo', 'transact' ],
 },
 
 'URL' : [{},
 {
     'workers': True,
 }],
 
-'VRDevice': {
-    'concrete': False
-},
-
 'VTTCue': {
     'nativeType': 'mozilla::dom::TextTrackCue'
 },
 
 'VTTRegion': {
   'nativeType': 'mozilla::dom::TextTrackRegion',
 },
 
--- a/dom/gamepad/Gamepad.h
+++ b/dom/gamepad/Gamepad.h
@@ -93,16 +93,28 @@ public:
     aButtons = mButtons;
   }
 
   void GetAxes(nsTArray<double>& aAxes) const
   {
     aAxes = mAxes;
   }
 
+  uint32_t DisplayId() const
+  {
+    /**
+     * XXX When we implement motion controller support for WebVR, we should
+     * return the DisplayID associated with the HMD that the controllers
+     * belong to.
+     *
+     * Returning 0 indicates that there is no associated VRDisplay.
+     */
+    return 0;
+  }
+
 private:
   virtual ~Gamepad() {}
   void UpdateTimestamp();
 
 protected:
   nsCOMPtr<nsISupports> mParent;
   nsString mID;
   uint32_t mIndex;
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -511,18 +511,16 @@ var interfaceNamesInGlobalScope =
     "HashChangeEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Headers",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "History",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "HDMIInputPort", b2g: true, permission: ["inputport"]},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "HMDVRDevice", release: false},
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLAllCollection",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLAnchorElement",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLAppletElement",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "HTMLAreaElement",
 // IMPORTANT: Do not change this list without review from a DOM peer!
@@ -939,18 +937,16 @@ var interfaceNamesInGlobalScope =
     {name: "PointerEvent", nightly: true, desktop: true, disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PopStateEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PopupBlockedEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "PopupBoxObject", xbl: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "PositionSensorVRDevice", release: false},
-// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "PresentationDeviceInfoManager",
      disabled: true,
      permission: ["presentation-device-manage"]},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "Presentation", disabled: true, permission: ["presentation"]},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "PresentationAvailability", disabled: true, permission: ["presentation"]},
 // IMPORTANT: Do not change this list without review from a DOM peer!
@@ -1395,26 +1391,21 @@ var interfaceNamesInGlobalScope =
     "UserProximityEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "ValidityState",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "VideoPlaybackQuality",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "VideoStreamTrack",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "VRDevice", release: false},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "VRPositionState", release: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "VREyeParameters", release: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "VRFieldOfView", release: false},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "VRFieldOfViewReadOnly", release: false},
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "VTTCue",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "VTTRegion", disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "WaveShaperNode",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "WebGLActiveInfo",
 // IMPORTANT: Do not change this list without review from a DOM peer!
deleted file mode 100644
--- a/dom/vr/VRDevice.cpp
+++ /dev/null
@@ -1,367 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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 "nsWrapperCache.h"
-
-#include "mozilla/dom/Element.h"
-#include "mozilla/dom/VRDeviceBinding.h"
-#include "mozilla/dom/ElementBinding.h"
-#include "mozilla/dom/VRDevice.h"
-#include "Navigator.h"
-#include "gfxVR.h"
-#include "VRDeviceProxy.h"
-#include "VRManagerChild.h"
-#include "nsIFrame.h"
-
-using namespace mozilla::gfx;
-
-namespace mozilla {
-namespace dom {
-
-/*static*/ bool
-VRDevice::RefreshVRDevices(dom::Navigator* aNavigator)
-{
-  gfx::VRManagerChild* vm = gfx::VRManagerChild::Get();
-  return vm && vm->RefreshVRDevicesWithCallback(aNavigator);
-}
-
-/*static*/ void
-VRDevice::UpdateVRDevices(nsTArray<RefPtr<VRDevice>>& aDevices, nsISupports* aParent)
-{
-  nsTArray<RefPtr<VRDevice>> devices;
-
-  gfx::VRManagerChild* vm = gfx::VRManagerChild::Get();
-  nsTArray<RefPtr<gfx::VRDeviceProxy>> proxyDevices;
-  if (vm && vm->GetVRDevices(proxyDevices)) {
-    for (size_t i = 0; i < proxyDevices.Length(); i++) {
-      RefPtr<gfx::VRDeviceProxy> proxyDevice = proxyDevices[i];
-      bool isNewDevice = true;
-      for (size_t j = 0; j < aDevices.Length(); j++) {
-        if (aDevices[j]->GetHMD()->GetDeviceInfo() == proxyDevice->GetDeviceInfo()) {
-          devices.AppendElement(aDevices[j]);
-          isNewDevice = false;
-        }
-      }
-
-      if (isNewDevice) {
-        gfx::VRStateValidFlags sensorBits = proxyDevice->GetDeviceInfo().GetSupportedSensorStateBits();
-        devices.AppendElement(new HMDInfoVRDevice(aParent, proxyDevice));
-        if (sensorBits & (gfx::VRStateValidFlags::State_Position |
-            gfx::VRStateValidFlags::State_Orientation))
-        {
-          devices.AppendElement(new HMDPositionVRDevice(aParent, proxyDevice));
-        }
-      }
-    }
-  }
-
-  aDevices = devices;
-}
-
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VRFieldOfViewReadOnly, mParent)
-NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRFieldOfViewReadOnly, AddRef)
-NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRFieldOfViewReadOnly, Release)
-
-JSObject*
-VRFieldOfViewReadOnly::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
-  return VRFieldOfViewReadOnlyBinding::Wrap(aCx, this, aGivenProto);
-}
-
-already_AddRefed<VRFieldOfView>
-VRFieldOfView::Constructor(const GlobalObject& aGlobal, const VRFieldOfViewInit& aParams,
-                           ErrorResult& aRV)
-{
-  RefPtr<VRFieldOfView> fov =
-    new VRFieldOfView(aGlobal.GetAsSupports(),
-                      aParams.mUpDegrees, aParams.mRightDegrees,
-                      aParams.mDownDegrees, aParams.mLeftDegrees);
-  return fov.forget();
-}
-
-already_AddRefed<VRFieldOfView>
-VRFieldOfView::Constructor(const GlobalObject& aGlobal,
-                           double aUpDegrees, double aRightDegrees,
-                           double aDownDegrees, double aLeftDegrees,
-                           ErrorResult& aRV)
-{
-  RefPtr<VRFieldOfView> fov =
-    new VRFieldOfView(aGlobal.GetAsSupports(),
-                      aUpDegrees, aRightDegrees, aDownDegrees,
-                      aLeftDegrees);
-  return fov.forget();
-}
-
-JSObject*
-VRFieldOfView::WrapObject(JSContext* aCx,
-                          JS::Handle<JSObject*> aGivenProto)
-{
-  return VRFieldOfViewBinding::Wrap(aCx, this, aGivenProto);
-}
-
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VREyeParameters, mParent, mMinFOV, mMaxFOV, mRecFOV, mCurFOV, mEyeTranslation, mRenderRect)
-NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VREyeParameters, AddRef)
-NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VREyeParameters, Release)
-
-VREyeParameters::VREyeParameters(nsISupports* aParent,
-                                 const gfx::VRFieldOfView& aMinFOV,
-                                 const gfx::VRFieldOfView& aMaxFOV,
-                                 const gfx::VRFieldOfView& aRecFOV,
-                                 const gfx::Point3D& aEyeTranslation,
-                                 const gfx::VRFieldOfView& aCurFOV,
-                                 const gfx::IntRect& aRenderRect)
-  : mParent(aParent)
-{
-  mMinFOV = new VRFieldOfView(aParent, aMinFOV);
-  mMaxFOV = new VRFieldOfView(aParent, aMaxFOV);
-  mRecFOV = new VRFieldOfView(aParent, aRecFOV);
-  mCurFOV = new VRFieldOfView(aParent, aCurFOV);
-
-  mEyeTranslation = new DOMPoint(aParent, aEyeTranslation.x, aEyeTranslation.y, aEyeTranslation.z, 0.0);
-  mRenderRect = new DOMRect(aParent, aRenderRect.x, aRenderRect.y, aRenderRect.width, aRenderRect.height);
-}
-
-VRFieldOfView*
-VREyeParameters::MinimumFieldOfView()
-{
-  return mMinFOV;
-}
-
-VRFieldOfView*
-VREyeParameters::MaximumFieldOfView()
-{
-  return mMaxFOV;
-}
-
-VRFieldOfView*
-VREyeParameters::RecommendedFieldOfView()
-{
-  return mRecFOV;
-}
-
-VRFieldOfView*
-VREyeParameters::CurrentFieldOfView()
-{
-  return mCurFOV;
-}
-
-DOMPoint*
-VREyeParameters::EyeTranslation()
-{
-  return mEyeTranslation;
-}
-
-DOMRect*
-VREyeParameters::RenderRect()
-{
-  return mRenderRect;
-}
-
-JSObject*
-VREyeParameters::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
-  return VREyeParametersBinding::Wrap(aCx, this, aGivenProto);
-}
-
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VRPositionState, mParent)
-NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRPositionState, AddRef)
-NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRPositionState, Release)
-
-VRPositionState::VRPositionState(nsISupports* aParent, const gfx::VRHMDSensorState& aState)
-  : mParent(aParent)
-  , mVRState(aState)
-{
-  mTimeStamp = aState.timestamp;
-
-  if (aState.flags & gfx::VRStateValidFlags::State_Position) {
-    mPosition = new DOMPoint(mParent, aState.position[0], aState.position[1], aState.position[2], 0.0);
-  }
-
-  if (aState.flags & gfx::VRStateValidFlags::State_Orientation) {
-    mOrientation = new DOMPoint(mParent, aState.orientation[0], aState.orientation[1], aState.orientation[2], aState.orientation[3]);
-  }
-}
-
-DOMPoint*
-VRPositionState::GetLinearVelocity()
-{
-  if (!mLinearVelocity) {
-    mLinearVelocity = new DOMPoint(mParent, mVRState.linearVelocity[0], mVRState.linearVelocity[1], mVRState.linearVelocity[2], 0.0);
-  }
-  return mLinearVelocity;
-}
-
-DOMPoint*
-VRPositionState::GetLinearAcceleration()
-{
-  if (!mLinearAcceleration) {
-    mLinearAcceleration = new DOMPoint(mParent, mVRState.linearAcceleration[0], mVRState.linearAcceleration[1], mVRState.linearAcceleration[2], 0.0);
-  }
-  return mLinearAcceleration;
-}
-
-DOMPoint*
-VRPositionState::GetAngularVelocity()
-{
-  if (!mAngularVelocity) {
-    mAngularVelocity = new DOMPoint(mParent, mVRState.angularVelocity[0], mVRState.angularVelocity[1], mVRState.angularVelocity[2], 0.0);
-  }
-  return mAngularVelocity;
-}
-
-DOMPoint*
-VRPositionState::GetAngularAcceleration()
-{
-  if (!mAngularAcceleration) {
-    mAngularAcceleration = new DOMPoint(mParent, mVRState.angularAcceleration[0], mVRState.angularAcceleration[1], mVRState.angularAcceleration[2], 0.0);
-  }
-  return mAngularAcceleration;
-}
-
-JSObject*
-VRPositionState::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
-  return VRPositionStateBinding::Wrap(aCx, this, aGivenProto);
-}
-
-NS_IMPL_CYCLE_COLLECTING_ADDREF(VRDevice)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(VRDevice)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(VRDevice)
-  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VRDevice, mParent)
-
-/* virtual */ JSObject*
-HMDVRDevice::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
-  return HMDVRDeviceBinding::Wrap(aCx, this, aGivenProto);
-}
-
-/* virtual */ JSObject*
-PositionSensorVRDevice::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
-  return PositionSensorVRDeviceBinding::Wrap(aCx, this, aGivenProto);
-}
-
-HMDInfoVRDevice::HMDInfoVRDevice(nsISupports* aParent, gfx::VRDeviceProxy* aHMD)
-  : HMDVRDevice(aParent, aHMD)
-{
-  MOZ_COUNT_CTOR_INHERITED(HMDInfoVRDevice, HMDVRDevice);
-  uint64_t hmdid = aHMD->GetDeviceInfo().GetDeviceID() << 8;
-  uint64_t devid = hmdid | 0x00; // we generate a devid with low byte 0 for the HMD, 1 for the position sensor
-
-  mHWID.Truncate();
-  mHWID.AppendPrintf("0x%llx", hmdid);
-
-  mDeviceId.Truncate();
-  mDeviceId.AppendPrintf("0x%llx", devid);
-
-  mDeviceName.Truncate();
-  mDeviceName.Append(NS_ConvertASCIItoUTF16(aHMD->GetDeviceInfo().GetDeviceName()));
-  mDeviceName.AppendLiteral(" (HMD)");
-
-  mValid = true;
-}
-
-HMDInfoVRDevice::~HMDInfoVRDevice()
-{
-  MOZ_COUNT_DTOR_INHERITED(HMDInfoVRDevice, HMDVRDevice);
-}
-
-/* If a field of view that is set to all 0's is passed in,
- * the recommended field of view for that eye is used.
- */
-void
-HMDInfoVRDevice::SetFieldOfView(const VRFieldOfViewInit& aLeftFOV,
-                                const VRFieldOfViewInit& aRightFOV,
-                                double zNear, double zFar)
-{
-  gfx::VRFieldOfView left = gfx::VRFieldOfView(aLeftFOV.mUpDegrees, aLeftFOV.mRightDegrees,
-                                               aLeftFOV.mDownDegrees, aLeftFOV.mLeftDegrees);
-  gfx::VRFieldOfView right = gfx::VRFieldOfView(aRightFOV.mUpDegrees, aRightFOV.mRightDegrees,
-                                                aRightFOV.mDownDegrees, aRightFOV.mLeftDegrees);
-
-  if (left.IsZero()) {
-    left = mHMD->GetDeviceInfo().GetRecommendedEyeFOV(VRDeviceInfo::Eye_Left);
-  }
-
-  if (right.IsZero()) {
-    right = mHMD->GetDeviceInfo().GetRecommendedEyeFOV(VRDeviceInfo::Eye_Right);
-  }
-
-  mHMD->SetFOV(left, right, zNear, zFar);
-}
-
-already_AddRefed<VREyeParameters> HMDInfoVRDevice::GetEyeParameters(VREye aEye)
-{
-  gfx::IntSize sz(mHMD->GetDeviceInfo().SuggestedEyeResolution());
-  gfx::VRDeviceInfo::Eye eye = aEye == VREye::Left ? gfx::VRDeviceInfo::Eye_Left : gfx::VRDeviceInfo::Eye_Right;
-  RefPtr<VREyeParameters> params =
-    new VREyeParameters(mParent,
-                        gfx::VRFieldOfView(15, 15, 15, 15), // XXX min?
-                        mHMD->GetDeviceInfo().GetMaximumEyeFOV(eye),
-                        mHMD->GetDeviceInfo().GetRecommendedEyeFOV(eye),
-                        mHMD->GetDeviceInfo().GetEyeTranslation(eye),
-                        mHMD->GetDeviceInfo().GetEyeFOV(eye),
-                        gfx::IntRect((aEye == VREye::Left) ? 0 : sz.width, 0, sz.width, sz.height));
-  return params.forget();
-}
-
-HMDPositionVRDevice::HMDPositionVRDevice(nsISupports* aParent, gfx::VRDeviceProxy* aHMD)
-  : PositionSensorVRDevice(aParent, aHMD)
-{
-  MOZ_COUNT_CTOR_INHERITED(HMDPositionVRDevice, PositionSensorVRDevice);
-
-  uint64_t hmdid = aHMD->GetDeviceInfo().GetDeviceID() << 8;
-  uint64_t devid = hmdid | 0x01; // we generate a devid with low byte 0 for the HMD, 1 for the position sensor
-
-  mHWID.Truncate();
-  mHWID.AppendPrintf("0x%llx", hmdid);
-
-  mDeviceId.Truncate();
-  mDeviceId.AppendPrintf("0x%llx", devid);
-
-  mDeviceName.Truncate();
-  mDeviceName.Append(NS_ConvertASCIItoUTF16(aHMD->GetDeviceInfo().GetDeviceName()));
-  mDeviceName.AppendLiteral(" (Sensor)");
-
-  mValid = true;
-}
-
-HMDPositionVRDevice::~HMDPositionVRDevice()
-{
-  MOZ_COUNT_DTOR_INHERITED(HMDPositionVRDevice, PositionSensorVRDevice);
-}
-
-already_AddRefed<VRPositionState>
-HMDPositionVRDevice::GetState()
-{
-  gfx::VRHMDSensorState state = mHMD->GetSensorState();
-  RefPtr<VRPositionState> obj = new VRPositionState(mParent, state);
-
-  return obj.forget();
-}
-
-already_AddRefed<VRPositionState>
-HMDPositionVRDevice::GetImmediateState()
-{
-  gfx::VRHMDSensorState state = mHMD->GetImmediateSensorState();
-  RefPtr<VRPositionState> obj = new VRPositionState(mParent, state);
-
-  return obj.forget();
-}
-
-void
-HMDPositionVRDevice::ResetSensor()
-{
-  mHMD->ZeroSensor();
-}
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/vr/VRDevice.h
+++ /dev/null
@@ -1,317 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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/. */
-
-#ifndef mozilla_dom_VRDevice_h_
-#define mozilla_dom_VRDevice_h_
-
-#include <stdint.h>
-
-#include "mozilla/ErrorResult.h"
-#include "mozilla/dom/TypedArray.h"
-#include "mozilla/dom/VRDeviceBinding.h"
-#include "mozilla/dom/DOMPoint.h"
-#include "mozilla/dom/DOMRect.h"
-
-#include "nsCOMPtr.h"
-#include "nsString.h"
-#include "nsTArray.h"
-#include "nsWrapperCache.h"
-
-#include "gfxVR.h"
-#include "VRDeviceProxy.h"
-
-namespace mozilla {
-namespace dom {
-class Navigator;
-
-class VRFieldOfViewReadOnly : public nsWrapperCache
-{
-public:
-  VRFieldOfViewReadOnly(nsISupports* aParent,
-                        double aUpDegrees, double aRightDegrees,
-                        double aDownDegrees, double aLeftDegrees)
-    : mParent(aParent)
-    , mUpDegrees(aUpDegrees)
-    , mRightDegrees(aRightDegrees)
-    , mDownDegrees(aDownDegrees)
-    , mLeftDegrees(aLeftDegrees)
-  {
-  }
-
-  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRFieldOfViewReadOnly)
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VRFieldOfViewReadOnly)
-
-  double UpDegrees() const { return mUpDegrees; }
-  double RightDegrees() const { return mRightDegrees; }
-  double DownDegrees() const { return mDownDegrees; }
-  double LeftDegrees() const { return mLeftDegrees; }
-
-  nsISupports* GetParentObject() const { return mParent; }
-  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
-
-protected:
-  virtual ~VRFieldOfViewReadOnly() {}
-
-  nsCOMPtr<nsISupports> mParent;
-
-  double mUpDegrees;
-  double mRightDegrees;
-  double mDownDegrees;
-  double mLeftDegrees;
-};
-
-class VRFieldOfView final : public VRFieldOfViewReadOnly
-{
-public:
-  VRFieldOfView(nsISupports* aParent, const gfx::VRFieldOfView& aSrc)
-    : VRFieldOfViewReadOnly(aParent,
-                            aSrc.upDegrees, aSrc.rightDegrees,
-                            aSrc.downDegrees, aSrc.leftDegrees)
-  {}
-
-  explicit VRFieldOfView(nsISupports* aParent,
-                         double aUpDegrees = 0.0, double aRightDegrees = 0.0,
-                         double aDownDegrees = 0.0, double aLeftDegrees = 0.0)
-    : VRFieldOfViewReadOnly(aParent,
-                            aUpDegrees, aRightDegrees, aDownDegrees, aLeftDegrees)
-  {}
-
-  static already_AddRefed<VRFieldOfView>
-  Constructor(const GlobalObject& aGlobal, const VRFieldOfViewInit& aParams,
-              ErrorResult& aRv);
-
-  static already_AddRefed<VRFieldOfView>
-  Constructor(const GlobalObject& aGlobal,
-              double aUpDegrees, double aRightDegrees,
-              double aDownDegrees, double aLeftDegrees,
-              ErrorResult& aRv);
-
-  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
-
-  void SetUpDegrees(double aVal) { mUpDegrees = aVal; }
-  void SetRightDegrees(double aVal) { mRightDegrees = aVal; }
-  void SetDownDegrees(double aVal) { mDownDegrees = aVal; }
-  void SetLeftDegrees(double aVal) { mLeftDegrees = aVal; }
-};
-
-class VRPositionState final : public nsWrapperCache
-{
-  ~VRPositionState() {}
-public:
-  VRPositionState(nsISupports* aParent, const gfx::VRHMDSensorState& aState);
-
-  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRPositionState)
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VRPositionState)
-
-  double TimeStamp() const { return mTimeStamp; }
-
-  bool HasPosition() const { return mPosition != nullptr; }
-  DOMPoint* GetPosition() const { return mPosition; }
-
-  bool HasOrientation() const { return mOrientation != nullptr; }
-  DOMPoint* GetOrientation() const { return mOrientation; }
-
-  // these are created lazily
-  DOMPoint* GetLinearVelocity();
-  DOMPoint* GetLinearAcceleration();
-  DOMPoint* GetAngularVelocity();
-  DOMPoint* GetAngularAcceleration();
-
-  nsISupports* GetParentObject() const { return mParent; }
-  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
-
-protected:
-  nsCOMPtr<nsISupports> mParent;
-
-  double mTimeStamp;
-  gfx::VRHMDSensorState mVRState;
-
-  RefPtr<DOMPoint> mPosition;
-  RefPtr<DOMPoint> mLinearVelocity;
-  RefPtr<DOMPoint> mLinearAcceleration;
-
-  RefPtr<DOMPoint> mOrientation;
-  RefPtr<DOMPoint> mAngularVelocity;
-  RefPtr<DOMPoint> mAngularAcceleration;
-};
-
-class VREyeParameters final : public nsWrapperCache
-{
-public:
-  VREyeParameters(nsISupports* aParent,
-                  const gfx::VRFieldOfView& aMinFOV,
-                  const gfx::VRFieldOfView& aMaxFOV,
-                  const gfx::VRFieldOfView& aRecFOV,
-                  const gfx::Point3D& aEyeTranslation,
-                  const gfx::VRFieldOfView& aCurFOV,
-                  const gfx::IntRect& aRenderRect);
-
-  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VREyeParameters)
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VREyeParameters)
-
-  VRFieldOfView* MinimumFieldOfView();
-  VRFieldOfView* MaximumFieldOfView();
-  VRFieldOfView* RecommendedFieldOfView();
-  DOMPoint* EyeTranslation();
-
-  VRFieldOfView* CurrentFieldOfView();
-  DOMRect* RenderRect();
-
-  nsISupports* GetParentObject() const { return mParent; }
-  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
-protected:
-  ~VREyeParameters() {}
-
-  nsCOMPtr<nsISupports> mParent;
-
-  RefPtr<VRFieldOfView> mMinFOV;
-  RefPtr<VRFieldOfView> mMaxFOV;
-  RefPtr<VRFieldOfView> mRecFOV;
-  RefPtr<DOMPoint> mEyeTranslation;
-  RefPtr<VRFieldOfView> mCurFOV;
-  RefPtr<DOMRect> mRenderRect;
-};
-
-class VRDevice : public nsISupports,
-                 public nsWrapperCache
-{
-public:
-
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(VRDevice)
-
-  void GetHardwareUnitId(nsAString& aHWID) const { aHWID = mHWID; }
-  void GetDeviceId(nsAString& aDeviceId) const { aDeviceId = mDeviceId; }
-  void GetDeviceName(nsAString& aDeviceName) const { aDeviceName = mDeviceName; }
-
-  bool IsValid() { return mValid; }
-
-  nsISupports* GetParentObject() const
-  {
-    return mParent;
-  }
-
-  enum VRDeviceType {
-    HMD,
-    PositionSensor
-  };
-
-  VRDeviceType GetType() const { return mType; }
-
-  static bool RefreshVRDevices(dom::Navigator* aNavigator);
-  static void UpdateVRDevices(nsTArray<RefPtr<VRDevice> >& aDevices,
-                              nsISupports* aParent);
-
-  gfx::VRDeviceProxy *GetHMD() {
-    return mHMD;
-  }
-
-protected:
-  VRDevice(nsISupports* aParent,
-           gfx::VRDeviceProxy* aHMD,
-           VRDeviceType aType)
-    : mParent(aParent)
-    , mHMD(aHMD)
-    , mType(aType)
-    , mValid(false)
-  {
-    MOZ_COUNT_CTOR(VRDevice);
-    mHWID.AssignLiteral("uknown");
-    mDeviceId.AssignLiteral("unknown");
-    mDeviceName.AssignLiteral("unknown");
-  }
-
-  virtual ~VRDevice()
-  {
-    MOZ_COUNT_DTOR(VRDevice);
-  }
-
-  nsCOMPtr<nsISupports> mParent;
-  RefPtr<gfx::VRDeviceProxy> mHMD;
-  nsString mHWID;
-  nsString mDeviceId;
-  nsString mDeviceName;
-
-  VRDeviceType mType;
-
-  bool mValid;
-};
-
-class HMDVRDevice : public VRDevice
-{
-public:
-  virtual already_AddRefed<VREyeParameters> GetEyeParameters(VREye aEye) = 0;
-
-  virtual void SetFieldOfView(const VRFieldOfViewInit& aLeftFOV,
-                              const VRFieldOfViewInit& aRightFOV,
-                              double zNear, double zFar) = 0;
-
-  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
-
-protected:
-  HMDVRDevice(nsISupports* aParent, gfx::VRDeviceProxy* aHMD)
-    : VRDevice(aParent, aHMD, VRDevice::HMD)
-  {
-    MOZ_COUNT_CTOR_INHERITED(HMDVRDevice, VRDevice);
-  }
-
-  virtual ~HMDVRDevice()
-  {
-    MOZ_COUNT_DTOR_INHERITED(HMDVRDevice, VRDevice);
-  }
-};
-
-class HMDInfoVRDevice : public HMDVRDevice
-{
-public:
-  HMDInfoVRDevice(nsISupports* aParent, gfx::VRDeviceProxy* aHMD);
-  virtual ~HMDInfoVRDevice();
-
-  /* If a field of view that is set to all 0's is passed in,
-   * the recommended field of view for that eye is used.
-   */
-  virtual void SetFieldOfView(const VRFieldOfViewInit& aLeftFOV,
-                              const VRFieldOfViewInit& aRightFOV,
-                              double zNear, double zFar) override;
-  virtual already_AddRefed<VREyeParameters> GetEyeParameters(VREye aEye) override;
-};
-
-class PositionSensorVRDevice : public VRDevice
-{
-public:
-  virtual already_AddRefed<VRPositionState> GetState() = 0;
-  virtual already_AddRefed<VRPositionState> GetImmediateState() = 0;
-  virtual void ResetSensor() = 0;
-  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
-
-protected:
-  explicit PositionSensorVRDevice(nsISupports* aParent, gfx::VRDeviceProxy* aHMD)
-    : VRDevice(aParent, aHMD, VRDevice::PositionSensor)
-  {
-    MOZ_COUNT_CTOR_INHERITED(PositionSensorVRDevice, VRDevice);
-  }
-
-  virtual ~PositionSensorVRDevice()
-  {
-    MOZ_COUNT_DTOR_INHERITED(PositionSensorVRDevice, VRDevice);
-  }
-};
-
-class HMDPositionVRDevice : public PositionSensorVRDevice
-{
-public:
-  HMDPositionVRDevice(nsISupports* aParent, gfx::VRDeviceProxy* aHMD);
-  ~HMDPositionVRDevice();
-
-  virtual already_AddRefed<VRPositionState> GetState() override;
-  virtual already_AddRefed<VRPositionState> GetImmediateState() override;
-  virtual void ResetSensor() override;
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif
new file mode 100644
--- /dev/null
+++ b/dom/vr/VRDisplay.cpp
@@ -0,0 +1,386 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 "nsWrapperCache.h"
+
+#include "mozilla/dom/Element.h"
+#include "mozilla/dom/VRDisplayBinding.h"
+#include "mozilla/dom/ElementBinding.h"
+#include "mozilla/dom/VRDisplay.h"
+#include "Navigator.h"
+#include "gfxVR.h"
+#include "VRDisplayProxy.h"
+#include "VRManagerChild.h"
+#include "nsIFrame.h"
+
+using namespace mozilla::gfx;
+
+namespace mozilla {
+namespace dom {
+
+/*static*/ bool
+VRDisplay::RefreshVRDisplays(dom::Navigator* aNavigator)
+{
+  gfx::VRManagerChild* vm = gfx::VRManagerChild::Get();
+  return vm && vm->RefreshVRDisplaysWithCallback(aNavigator);
+}
+
+/*static*/ void
+VRDisplay::UpdateVRDisplays(nsTArray<RefPtr<VRDisplay>>& aDevices, nsISupports* aParent)
+{
+  nsTArray<RefPtr<VRDisplay>> devices;
+
+  gfx::VRManagerChild* vm = gfx::VRManagerChild::Get();
+  nsTArray<RefPtr<gfx::VRDisplayProxy>> proxyDevices;
+  if (vm && vm->GetVRDisplays(proxyDevices)) {
+    for (size_t i = 0; i < proxyDevices.Length(); i++) {
+      RefPtr<gfx::VRDisplayProxy> proxyDevice = proxyDevices[i];
+      bool isNewDevice = true;
+      for (size_t j = 0; j < aDevices.Length(); j++) {
+        if (aDevices[j]->GetHMD()->GetDeviceInfo() == proxyDevice->GetDeviceInfo()) {
+          devices.AppendElement(aDevices[j]);
+          isNewDevice = false;
+        }
+      }
+
+      if (isNewDevice) {
+        devices.AppendElement(new VRDisplay(aParent, proxyDevice));
+      }
+    }
+  }
+
+  aDevices = devices;
+}
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VRFieldOfView, mParent)
+NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRFieldOfView, AddRef)
+NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRFieldOfView, Release)
+
+
+JSObject*
+VRFieldOfView::WrapObject(JSContext* aCx,
+                          JS::Handle<JSObject*> aGivenProto)
+{
+  return VRFieldOfViewBinding::Wrap(aCx, this, aGivenProto);
+}
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VREyeParameters, mParent, mFOV)
+NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VREyeParameters, AddRef)
+NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VREyeParameters, Release)
+
+VREyeParameters::VREyeParameters(nsISupports* aParent,
+                                 const gfx::Point3D& aEyeTranslation,
+                                 const gfx::VRFieldOfView& aFOV,
+                                 const gfx::IntSize& aRenderSize)
+  : mParent(aParent)
+  , mEyeTranslation(aEyeTranslation)
+  , mRenderSize(aRenderSize)
+{
+  mFOV = new VRFieldOfView(aParent, aFOV);
+}
+
+VRFieldOfView*
+VREyeParameters::FieldOfView()
+{
+  return mFOV;
+}
+
+void
+VREyeParameters::GetOffset(JSContext* aCx, JS::MutableHandle<JSObject*> aRetval)
+{
+  if (mOffset == nullptr) {
+    // Lazily create the Float32Array
+    mOffset = dom::Float32Array::Create(aCx, this, 3, mEyeTranslation.components);
+  }
+  JS::ExposeObjectToActiveJS(mOffset);
+  aRetval.set(mOffset);
+}
+
+JSObject*
+VREyeParameters::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
+{
+  return VREyeParametersBinding::Wrap(aCx, this, aGivenProto);
+}
+
+JSObject*
+VRStageParameters::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
+{
+  return VRStageParametersBinding::Wrap(aCx, this, aGivenProto);
+}
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VRStageParameters, mParent)
+NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRStageParameters, AddRef)
+NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRStageParameters, Release)
+
+void
+VRStageParameters::GetSittingToStandingTransform(JSContext* aCx, JS::MutableHandle<JSObject*> aRetval)
+{
+  if (mSittingToStandingTransformArray == nullptr) {
+    // Lazily create the Float32Array
+    mSittingToStandingTransformArray = dom::Float32Array::Create(aCx, this, 16,
+      mSittingToStandingTransform.components);
+  }
+  JS::ExposeObjectToActiveJS(mSittingToStandingTransformArray);
+  aRetval.set(mSittingToStandingTransformArray);
+}
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VRDisplayCapabilities, mParent)
+NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRDisplayCapabilities, AddRef)
+NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRDisplayCapabilities, Release)
+
+JSObject*
+VRDisplayCapabilities::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
+{
+  return VRDisplayCapabilitiesBinding::Wrap(aCx, this, aGivenProto);
+}
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VRPose, mParent)
+NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(VRPose, AddRef)
+NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(VRPose, Release)
+
+
+/*
+
+XXX - FINDME!! HACK!! KIP!!  Do we need to do this?
+
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(VRPose)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mPosition)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mLinearVelocity)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mLinearAcceleration)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mOrientation)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mAngularVelocity)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mAngularAcceleration)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mPosition)
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+*/
+
+VRPose::VRPose(nsISupports* aParent, const gfx::VRHMDSensorState& aState)
+  : mParent(aParent)
+  , mVRState(aState)
+  , mPosition(nullptr)
+  , mLinearVelocity(nullptr)
+  , mLinearAcceleration(nullptr)
+  , mOrientation(nullptr)
+  , mAngularVelocity(nullptr)
+  , mAngularAcceleration(nullptr)
+{
+  mTimeStamp = aState.timestamp * 1000.0f; // Converting from seconds to ms
+  mFrameId = aState.inputFrameID;
+}
+
+void
+VRPose::GetPosition(JSContext* aCx, JS::MutableHandle<JSObject*> aRetval)
+{
+  if (mPosition == nullptr && mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Position) {
+    // Lazily create the Float32Array
+    mPosition = dom::Float32Array::Create(aCx, this, 3, mVRState.position);
+  }
+  if (mPosition) {
+    JS::ExposeObjectToActiveJS(mPosition);
+  }
+  aRetval.set(mPosition);
+}
+
+void
+VRPose::GetLinearVelocity(JSContext* aCx, JS::MutableHandle<JSObject*> aRetval)
+{
+  if (mLinearVelocity == nullptr && mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Position) {
+    // Lazily create the Float32Array
+    mLinearVelocity = dom::Float32Array::Create(aCx, this, 3, mVRState.linearVelocity);
+  }
+  if (mLinearVelocity) {
+    JS::ExposeObjectToActiveJS(mLinearVelocity);
+  }
+  aRetval.set(mLinearVelocity);
+}
+
+void
+VRPose::GetLinearAcceleration(JSContext* aCx, JS::MutableHandle<JSObject*> aRetval)
+{
+  if (mLinearAcceleration == nullptr && mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Position) {
+    // Lazily create the Float32Array
+    mLinearAcceleration = dom::Float32Array::Create(aCx, this, 3, mVRState.linearAcceleration);
+  }
+  if (mLinearAcceleration) {
+    JS::ExposeObjectToActiveJS(mLinearAcceleration);
+  }
+  aRetval.set(mLinearAcceleration);
+}
+
+void
+VRPose::GetOrientation(JSContext* aCx, JS::MutableHandle<JSObject*> aRetval)
+{
+  if (mOrientation == nullptr && mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Orientation) {
+    // Lazily create the Float32Array
+    mOrientation = dom::Float32Array::Create(aCx, this, 4, mVRState.orientation);
+  }
+  if (mOrientation) {
+    JS::ExposeObjectToActiveJS(mOrientation);
+  }
+  aRetval.set(mOrientation);
+}
+
+void
+VRPose::GetAngularVelocity(JSContext* aCx, JS::MutableHandle<JSObject*> aRetval)
+{
+  if (mAngularVelocity == nullptr && mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Orientation) {
+    // Lazily create the Float32Array
+    mAngularVelocity = dom::Float32Array::Create(aCx, this, 3, mVRState.angularVelocity);
+  }
+  if (mAngularVelocity) {
+    JS::ExposeObjectToActiveJS(mAngularVelocity);
+  }
+  aRetval.set(mAngularVelocity);
+}
+
+void
+VRPose::GetAngularAcceleration(JSContext* aCx, JS::MutableHandle<JSObject*> aRetval)
+{
+  if (mAngularAcceleration == nullptr && mVRState.flags & gfx::VRDisplayCapabilityFlags::Cap_Orientation) {
+    // Lazily create the Float32Array
+    mAngularAcceleration = dom::Float32Array::Create(aCx, this, 3, mVRState.angularAcceleration);
+  }
+  if (mAngularAcceleration) {
+    JS::ExposeObjectToActiveJS(mAngularAcceleration);
+  }
+  aRetval.set(mAngularAcceleration);
+}
+
+JSObject*
+VRPose::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
+{
+  return VRPoseBinding::Wrap(aCx, this, aGivenProto);
+}
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(VRDisplay)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(VRDisplay)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(VRDisplay)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(VRDisplay, mParent)
+
+/* virtual */ JSObject*
+VRDisplay::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
+{
+  return VRDisplayBinding::Wrap(aCx, this, aGivenProto);
+}
+
+VRDisplay::VRDisplay(nsISupports* aParent, gfx::VRDisplayProxy* aHMD)
+  : mParent(aParent)
+  , mHMD(aHMD)
+  , mDepthNear(0.01f)
+  , mDepthFar(10000.0f)
+{
+  MOZ_COUNT_CTOR(VRDisplay);
+  mDisplayId = aHMD->GetDeviceInfo().GetDeviceID();
+  mDisplayName = NS_ConvertASCIItoUTF16(aHMD->GetDeviceInfo().GetDeviceName());
+  mCapabilities = new VRDisplayCapabilities(aParent, aHMD->GetDeviceInfo().GetCapabilities());
+}
+
+VRDisplay::~VRDisplay()
+{
+  MOZ_COUNT_DTOR(VRDisplay);
+}
+
+already_AddRefed<VREyeParameters>
+VRDisplay::GetEyeParameters(VREye aEye)
+{
+  gfx::VRDisplayInfo::Eye eye = aEye == VREye::Left ? gfx::VRDisplayInfo::Eye_Left : gfx::VRDisplayInfo::Eye_Right;
+  RefPtr<VREyeParameters> params =
+    new VREyeParameters(mParent,
+                        mHMD->GetDeviceInfo().GetEyeTranslation(eye),
+                        mHMD->GetDeviceInfo().GetEyeFOV(eye),
+                        mHMD->GetDeviceInfo().SuggestedEyeResolution());
+  return params.forget();
+}
+
+VRDisplayCapabilities*
+VRDisplay::Capabilities()
+{
+  return mCapabilities;
+}
+
+VRStageParameters*
+VRDisplay::GetStageParameters()
+{
+  // XXX When we implement room scale experiences for OpenVR, we should return
+  // something here.
+  return nullptr;
+}
+
+already_AddRefed<VRPose>
+VRDisplay::GetPose()
+{
+  gfx::VRHMDSensorState state = mHMD->GetSensorState();
+  RefPtr<VRPose> obj = new VRPose(mParent, state);
+
+  return obj.forget();
+}
+
+already_AddRefed<VRPose>
+VRDisplay::GetImmediatePose()
+{
+  gfx::VRHMDSensorState state = mHMD->GetImmediateSensorState();
+  RefPtr<VRPose> obj = new VRPose(mParent, state);
+
+  return obj.forget();
+}
+
+void
+VRDisplay::ResetPose()
+{
+  mHMD->ZeroSensor();
+}
+
+already_AddRefed<Promise>
+VRDisplay::RequestPresent(const VRLayer& aLayer, ErrorResult& aRv)
+{
+  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
+  if (!global) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
+
+  RefPtr<Promise> promise = Promise::Create(global, aRv);
+  NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
+
+  promise->MaybeResolve(JS::UndefinedHandleValue);
+  return promise.forget();
+}
+
+already_AddRefed<Promise>
+VRDisplay::ExitPresent(ErrorResult& aRv)
+{
+  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
+  if (!global) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
+  }
+
+  RefPtr<Promise> promise = Promise::Create(global, aRv);
+  NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
+
+  promise->MaybeResolve(JS::UndefinedHandleValue);
+  return promise.forget();
+}
+
+void
+VRDisplay::GetLayers(Nullable<nsTArray<VRLayer>>& result)
+{
+}
+
+void
+VRDisplay::SubmitFrame(const Optional<NonNull<VRPose>>& aPose)
+{
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/vr/VRDisplay.h
@@ -0,0 +1,299 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef mozilla_dom_VRDisplay_h_
+#define mozilla_dom_VRDisplay_h_
+
+#include <stdint.h>
+
+#include "mozilla/ErrorResult.h"
+#include "mozilla/dom/TypedArray.h"
+#include "mozilla/dom/VRDisplayBinding.h"
+#include "mozilla/dom/DOMPoint.h"
+#include "mozilla/dom/DOMRect.h"
+
+#include "nsCOMPtr.h"
+#include "nsString.h"
+#include "nsTArray.h"
+#include "nsWrapperCache.h"
+
+#include "gfxVR.h"
+#include "VRDisplayProxy.h"
+
+namespace mozilla {
+namespace dom {
+class Navigator;
+
+class VRFieldOfView final : public nsWrapperCache
+{
+public:
+  VRFieldOfView(nsISupports* aParent,
+                double aUpDegrees, double aRightDegrees,
+                double aDownDegrees, double aLeftDegrees)
+    : mParent(aParent)
+    , mUpDegrees(aUpDegrees)
+    , mRightDegrees(aRightDegrees)
+    , mDownDegrees(aDownDegrees)
+    , mLeftDegrees(aLeftDegrees)
+  {
+  }
+
+  VRFieldOfView(nsISupports* aParent, const gfx::VRFieldOfView& aSrc)
+    : mParent(aParent)
+    , mUpDegrees(aSrc.upDegrees)
+    , mRightDegrees(aSrc.rightDegrees)
+    , mDownDegrees(aSrc.downDegrees)
+    , mLeftDegrees(aSrc.leftDegrees)
+  {
+  }
+
+  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRFieldOfView)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VRFieldOfView)
+
+  double UpDegrees() const { return mUpDegrees; }
+  double RightDegrees() const { return mRightDegrees; }
+  double DownDegrees() const { return mDownDegrees; }
+  double LeftDegrees() const { return mLeftDegrees; }
+
+  nsISupports* GetParentObject() const { return mParent; }
+  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
+
+protected:
+  virtual ~VRFieldOfView() {}
+
+  nsCOMPtr<nsISupports> mParent;
+
+  double mUpDegrees;
+  double mRightDegrees;
+  double mDownDegrees;
+  double mLeftDegrees;
+};
+
+class VRDisplayCapabilities final : public nsWrapperCache
+{
+public:
+  VRDisplayCapabilities(nsISupports* aParent, const gfx::VRDisplayCapabilityFlags& aFlags)
+    : mParent(aParent)
+    , mFlags(aFlags)
+  {
+  }
+
+  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRDisplayCapabilities)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VRDisplayCapabilities)
+
+  nsISupports* GetParentObject() const
+  {
+    return mParent;
+  }
+
+  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
+
+  bool HasPosition() const
+  {
+    return bool(mFlags & gfx::VRDisplayCapabilityFlags::Cap_Position);
+  }
+
+  bool HasOrientation() const
+  {
+    return bool(mFlags & gfx::VRDisplayCapabilityFlags::Cap_Orientation);
+  }
+
+  bool HasExternalDisplay() const
+  {
+    return bool(mFlags & gfx::VRDisplayCapabilityFlags::Cap_External);
+  }
+
+  bool CanPresent() const
+  {
+    return bool(mFlags & gfx::VRDisplayCapabilityFlags::Cap_Present);
+  }
+
+protected:
+  ~VRDisplayCapabilities() {}
+  nsCOMPtr<nsISupports> mParent;
+  gfx::VRDisplayCapabilityFlags mFlags;
+};
+
+class VRPose final : public nsWrapperCache
+{
+
+public:
+  VRPose(nsISupports* aParent, const gfx::VRHMDSensorState& aState);
+
+  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRPose)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VRPose)
+
+  double Timestamp() const { return mTimeStamp; }
+  uint32_t FrameID() const { return mFrameId; }
+
+  void GetPosition(JSContext* aCx, JS::MutableHandle<JSObject*> aRetval);
+  void GetLinearVelocity(JSContext* aCx, JS::MutableHandle<JSObject*> aRetval);
+  void GetLinearAcceleration(JSContext* aCx, JS::MutableHandle<JSObject*> aRetval);
+  void GetOrientation(JSContext* aCx, JS::MutableHandle<JSObject*> aRetval);
+  void GetAngularVelocity(JSContext* aCx, JS::MutableHandle<JSObject*> aRetval);
+  void GetAngularAcceleration(JSContext* aCx, JS::MutableHandle<JSObject*> aRetval);
+
+  nsISupports* GetParentObject() const { return mParent; }
+  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
+
+protected:
+  ~VRPose() {}
+  nsCOMPtr<nsISupports> mParent;
+
+  double mTimeStamp;
+  uint32_t mFrameId;
+  gfx::VRHMDSensorState mVRState;
+
+  JS::Heap<JSObject*> mPosition;
+  JS::Heap<JSObject*> mLinearVelocity;
+  JS::Heap<JSObject*> mLinearAcceleration;
+  JS::Heap<JSObject*> mOrientation;
+  JS::Heap<JSObject*> mAngularVelocity;
+  JS::Heap<JSObject*> mAngularAcceleration;
+
+};
+
+class VRStageParameters final : public nsWrapperCache
+{
+public:
+  VRStageParameters(nsISupports* aParent,
+                    const gfx::Matrix4x4& aSittingToStandingTransform,
+                    const gfx::Size& aSize)
+    : mParent(aParent)
+    , mSittingToStandingTransform(aSittingToStandingTransform)
+    , mSittingToStandingTransformArray(nullptr)
+    , mSize(aSize)
+  {
+  }
+
+  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VRStageParameters)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VRStageParameters)
+
+  void GetSittingToStandingTransform(JSContext* aCx, JS::MutableHandle<JSObject*> aRetval);
+  float SizeX() const { return mSize.width; }
+  float SizeZ() const { return mSize.height; }
+
+  nsISupports* GetParentObject() const { return mParent; }
+  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
+
+protected:
+  ~VRStageParameters() {}
+
+  nsCOMPtr<nsISupports> mParent;
+
+  gfx::Matrix4x4 mSittingToStandingTransform;
+  JS::Heap<JSObject*> mSittingToStandingTransformArray;
+  gfx::Size mSize;
+};
+
+class VREyeParameters final : public nsWrapperCache
+{
+public:
+  VREyeParameters(nsISupports* aParent,
+                  const gfx::Point3D& aEyeTranslation,
+                  const gfx::VRFieldOfView& aFOV,
+                  const gfx::IntSize& aRenderSize);
+
+  NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(VREyeParameters)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(VREyeParameters)
+
+  void GetOffset(JSContext* aCx, JS::MutableHandle<JSObject*> aRetval);
+
+  VRFieldOfView* FieldOfView();
+
+  uint32_t RenderWidth() const { return mRenderSize.width; }
+  uint32_t RenderHeight() const { return mRenderSize.height; }
+
+  nsISupports* GetParentObject() const { return mParent; }
+  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
+protected:
+  ~VREyeParameters() {}
+
+  nsCOMPtr<nsISupports> mParent;
+
+
+  gfx::Point3D mEyeTranslation;
+  gfx::IntSize mRenderSize;
+  JS::Heap<JSObject*> mOffset;
+  RefPtr<VRFieldOfView> mFOV;
+};
+
+class VRDisplay final : public nsISupports,
+                        public nsWrapperCache
+{
+public:
+
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(VRDisplay)
+
+  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
+
+  VRDisplayCapabilities* Capabilities();
+  VRStageParameters* GetStageParameters();
+
+  uint32_t DisplayId() const { return mDisplayId; }
+  void GetDisplayName(nsAString& aDisplayName) const { aDisplayName = mDisplayName; }
+
+  nsISupports* GetParentObject() const
+  {
+    return mParent;
+  }
+
+  static bool RefreshVRDisplays(dom::Navigator* aNavigator);
+  static void UpdateVRDisplays(nsTArray<RefPtr<VRDisplay> >& aDevices,
+                              nsISupports* aParent);
+
+  gfx::VRDisplayProxy *GetHMD() {
+    return mHMD;
+  }
+
+  virtual already_AddRefed<VREyeParameters> GetEyeParameters(VREye aEye);
+
+  already_AddRefed<VRPose> GetPose();
+  already_AddRefed<VRPose> GetImmediatePose();
+  void ResetPose();
+
+  double DepthNear() {
+    return mDepthNear;
+  }
+
+  double DepthFar() {
+    return mDepthFar;
+  }
+
+  void SetDepthNear(double aDepthNear) {
+    mDepthNear = aDepthNear;
+  }
+
+  void SetDepthFar(double aDepthFar) {
+    mDepthFar = aDepthFar;
+  }
+
+  already_AddRefed<Promise> RequestPresent(const VRLayer& aLayer, ErrorResult& aRv);
+  already_AddRefed<Promise> ExitPresent(ErrorResult& aRv);
+  void GetLayers(Nullable<nsTArray<VRLayer>>& result);
+  void SubmitFrame(const Optional<NonNull<VRPose>>& aPose);
+
+protected:
+  VRDisplay(nsISupports* aParent, gfx::VRDisplayProxy* aHMD);
+  virtual ~VRDisplay();
+
+  nsCOMPtr<nsISupports> mParent;
+  RefPtr<gfx::VRDisplayProxy> mHMD;
+
+  uint32_t mDisplayId;
+  nsString mDisplayName;
+
+  RefPtr<VRDisplayCapabilities> mCapabilities;
+
+  double mDepthNear;
+  double mDepthFar;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif
--- a/dom/vr/moz.build
+++ b/dom/vr/moz.build
@@ -1,20 +1,20 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 EXPORTS.mozilla.dom += [
-    'VRDevice.h',
+    'VRDisplay.h',
     ]
 
 UNIFIED_SOURCES = [
-    'VRDevice.cpp',
+    'VRDisplay.cpp',
     ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/dom/base'
 ]
--- a/dom/webidl/Element.webidl
+++ b/dom/webidl/Element.webidl
@@ -236,26 +236,15 @@ partial interface Element {
 };
 
 Element implements ChildNode;
 Element implements NonDocumentTypeChildNode;
 Element implements ParentNode;
 Element implements Animatable;
 Element implements GeometryUtils;
 
-// non-standard: allows passing options to Element.requestFullscreen
-dictionary RequestFullscreenOptions {
-  // Which HMDVRDevice to go full screen on; also enables VR rendering.
-  // If null, normal fullscreen is entered.
-  HMDVRDevice? vrDisplay = null;
-};
-
 // https://fullscreen.spec.whatwg.org/#api
 partial interface Element {
-  /**
-   * The options parameter is non-standard. In Gecko, it can be:
-   *  a RequestFullscreenOptions object
-   */
   [Throws, UnsafeInPrerendering]
-  void requestFullscreen(optional any options);
+  void requestFullscreen();
   [Throws, UnsafeInPrerendering, BinaryName="requestFullscreen", Deprecated="PrefixedFullscreenAPI"]
-  void mozRequestFullScreen(optional any options);
+  void mozRequestFullScreen();
 };
--- a/dom/webidl/Gamepad.webidl
+++ b/dom/webidl/Gamepad.webidl
@@ -52,8 +52,18 @@ interface Gamepad {
   [Pure, Cached, Frozen]
   readonly attribute sequence<double> axes;
 
   /**
    * Timestamp from when the data of this device was last updated.
    */
   readonly attribute DOMHighResTimeStamp timestamp;
 };
+
+
+partial interface Gamepad {
+  /**
+   * If non-zero, this gamepad is associated with a VRDisplay with
+   * an equal displayId.
+   */
+  [Pref="dom.vr.enabled"]
+  readonly attribute unsigned long displayId;
+};
--- a/dom/webidl/Navigator.webidl
+++ b/dom/webidl/Navigator.webidl
@@ -344,17 +344,17 @@ partial interface Navigator {
 partial interface Navigator {
   [Throws, Pref="dom.gamepad.enabled"]
   sequence<Gamepad?> getGamepads();
 };
 #endif // MOZ_GAMEPAD
 
 partial interface Navigator {
   [Throws, Pref="dom.vr.enabled"]
-  Promise<sequence<VRDevice>> getVRDevices();
+  Promise<sequence<VRDisplay>> getVRDisplays();
 };
 
 #ifdef MOZ_B2G_BT
 partial interface Navigator {
   [Throws, CheckAnyPermissions="bluetooth", UnsafeInPrerendering]
   readonly attribute BluetoothManager mozBluetooth;
 };
 #endif // MOZ_B2G_BT
deleted file mode 100644
--- a/dom/webidl/VRDevice.webidl
+++ /dev/null
@@ -1,130 +0,0 @@
-/* -*- Mode: IDL; 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/. */
-
-enum VREye {
-  "left",
-  "right"
-};
-
-[Pref="dom.vr.enabled",
- HeaderFile="mozilla/dom/VRDevice.h"]
-interface VRFieldOfViewReadOnly {
-  readonly attribute double upDegrees;
-  readonly attribute double rightDegrees;
-  readonly attribute double downDegrees;
-  readonly attribute double leftDegrees;
-};
-
-[Pref="dom.vr.enabled",
- HeaderFile="mozilla/dom/VRDevice.h",
- Constructor(optional VRFieldOfViewInit fov),
- Constructor(double upDegrees, double rightDegrees, double downDegrees, double leftDegrees)]
-interface VRFieldOfView : VRFieldOfViewReadOnly {
-  inherit attribute double upDegrees;
-  inherit attribute double rightDegrees;
-  inherit attribute double downDegrees;
-  inherit attribute double leftDegrees;
-};
-
-dictionary VRFieldOfViewInit {
-  double upDegrees = 0.0;
-  double rightDegrees = 0.0;
-  double downDegrees = 0.0;
-  double leftDegrees = 0.0;
-};
-
-[Pref="dom.vr.enabled",
- HeaderFile="mozilla/dom/VRDevice.h"]
-interface VRPositionState {
-  readonly attribute double timeStamp;
-
-  readonly attribute boolean hasPosition;
-  readonly attribute DOMPoint? position;
-  readonly attribute DOMPoint? linearVelocity;
-  readonly attribute DOMPoint? linearAcceleration;
-
-  readonly attribute boolean hasOrientation;
-  // XXX should be DOMQuaternion as soon as we add that
-  readonly attribute DOMPoint? orientation;
-  readonly attribute DOMPoint? angularVelocity;
-  readonly attribute DOMPoint? angularAcceleration;
-};
-
-[Pref="dom.vr.enabled",
- HeaderFile="mozilla/dom/VRDevice.h"]
-interface VREyeParameters {
-  /* These values are expected to be static per-device/per-user */
-  [Constant, Cached] readonly attribute VRFieldOfView minimumFieldOfView;
-  [Constant, Cached] readonly attribute VRFieldOfView maximumFieldOfView;
-  [Constant, Cached] readonly attribute VRFieldOfView recommendedFieldOfView;
-  [Constant, Cached] readonly attribute DOMPoint eyeTranslation;
-
-  /* These values will vary after a FOV has been set */
-  [Constant, Cached] readonly attribute VRFieldOfView currentFieldOfView;
-  [Constant, Cached] readonly attribute DOMRect renderRect;
-};
-
-[Pref="dom.vr.enabled"]
-interface VRDevice {
-  /**
-   * An identifier for the distinct hardware unit that this
-   * VR Device is a part of.  All VRDevice/Sensors that come
-   * from the same hardware will have the same hardwareId
-   */
-  [Constant] readonly attribute DOMString hardwareUnitId;
-
-  /**
-   * An identifier for this distinct sensor/device on a physical
-   * hardware device.  This shouldn't change across browser
-   * restrats, allowing configuration data to be saved based on it.
-   */
-  [Constant] readonly attribute DOMString deviceId;
-
-  /**
-   * a device name, a user-readable name identifying it
-   */
-  [Constant] readonly attribute DOMString deviceName;
-};
-
-[Pref="dom.vr.enabled",
- HeaderFile="mozilla/dom/VRDevice.h"]
-interface HMDVRDevice : VRDevice {
-  // Return the current VREyeParameters for the given eye
-  VREyeParameters getEyeParameters(VREye whichEye);
-
-  // Set a field of view.  If either of the fields of view is null,
-  // or if their values are all zeros, then the recommended field of view
-  // for that eye will be used.
-  void setFieldOfView(optional VRFieldOfViewInit leftFOV,
-                      optional VRFieldOfViewInit rightFOV,
-                      optional double zNear = 0.01,
-                      optional double zFar = 10000.0);
-};
-
-[Pref="dom.vr.enabled" ,
- HeaderFile="mozilla/dom/VRDevice.h"]
-interface PositionSensorVRDevice : VRDevice {
-  /*
-   * Return a VRPositionState dictionary containing the state of this position sensor
-   * for the current frame if within a requestAnimationFrame callback, or for the
-   * previous frame if not.
-   *
-   * The VRPositionState will contain the position, orientation, and velocity
-   * and acceleration of each of these properties.  Use "hasPosition" and "hasOrientation"
-   * to check if the associated members are valid; if these are false, those members
-   * will be null.
-   */
-  [NewObject] VRPositionState getState();
-
-  /*
-   * Return the current instantaneous sensor state.
-   */
-  [NewObject] VRPositionState getImmediateState();
-
-  /* Reset this sensor, treating its current position and orientation
-   * as the "origin/zero" values.
-   */
-  void resetSensor();
-};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/VRDisplay.webidl
@@ -0,0 +1,259 @@
+/* -*- Mode: IDL; 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/. */
+
+enum VREye {
+  "left",
+  "right"
+};
+
+[Pref="dom.vr.enabled",
+ HeaderFile="mozilla/dom/VRDisplay.h"]
+interface VRFieldOfView {
+  readonly attribute double upDegrees;
+  readonly attribute double rightDegrees;
+  readonly attribute double downDegrees;
+  readonly attribute double leftDegrees;
+};
+
+typedef (HTMLCanvasElement or OffscreenCanvas) VRSource;
+
+dictionary VRLayer {
+  /**
+   * The canvas to be presented to the VRDisplay.
+   */
+  HTMLCanvasElement? source = null;
+
+  /**
+   * The left and right viewports contain 4 values defining the viewport
+   * rectangles within the canvas to present to the eye in UV space.
+   * [0] left offset of the viewport (0.0 - 1.0)
+   * [1] top offset of the viewport (0.0 - 1.0)
+   * [2] width of the viewport (0.0 - 1.0)
+   * [3] height of the viewport (0.0 - 1.0)
+   */
+  sequence<float>? leftBounds = null;
+  sequence<float>? rightBounds = null;
+};
+
+/**
+ * Values describing the capabilities of a VRDisplay.
+ * These are expected to be static per-device/per-user.
+ */
+[Pref="dom.vr.enabled",
+ HeaderFile="mozilla/dom/VRDisplay.h"]
+interface VRDisplayCapabilities {
+  /**
+   * hasPosition is true if the VRDisplay is capable of tracking its position.
+   */
+  readonly attribute boolean hasPosition;
+
+  /**
+   * hasOrientation is true if the VRDisplay is capable of tracking its orientation.
+   */
+  readonly attribute boolean hasOrientation;
+  
+  /**
+   * Whether or not the VRDisplay is separate from the device’s
+   * primary display. If presenting VR content will obscure
+   * other content on the device, this should be false. When
+   * false, the application should not attempt to mirror VR content
+   * or update non-VR UI because that content will not be visible.
+   */
+  readonly attribute boolean hasExternalDisplay;
+  
+  /**
+   * Whether or not the VRDisplay is capable of presenting content to an HMD or similar device.
+   * Can be used to indicate “magic window” devices that are capable of 6DoF tracking but for
+   * which requestPresent is not meaningful. If false then calls to requestPresent should
+   * always fail, and getEyeParameters should return null. 
+   */
+  readonly attribute boolean canPresent;
+};
+
+/**
+ * Values describing the the stage / play area for devices
+ * that support room-scale experiences.
+ */
+[Pref="dom.vr.enabled",
+ HeaderFile="mozilla/dom/VRDisplay.h"]
+interface VRStageParameters {
+  /**
+   * A 16-element array containing the components of a 4x4 transform
+   * matrix. This matrix transforms the sitting-space position
+   * returned by get{Immediate}Pose() to a standing-space position.
+   */
+  readonly attribute Float32Array sittingToStandingTransform;
+
+  /**
+   * Dimensions of the play-area bounds. The bounds are defined
+   * as an axis-aligned rectangle on the floor.
+   * The center of the rectangle is at (0,0,0) in standing-space
+   * coordinates.
+   * These bounds are defined for safety purposes.
+   * Content should not require the user to move beyond these
+   * bounds; however, it is possible for the user to ignore
+   * the bounds resulting in position values outside of
+   * this rectangle.
+   */
+  readonly attribute float sizeX;
+  readonly attribute float sizeZ;
+};
+
+[Pref="dom.vr.enabled",
+ HeaderFile="mozilla/dom/VRDisplay.h"]
+interface VRPose {
+  readonly attribute DOMHighResTimeStamp timestamp;
+
+  /* Unique identifier of the frame that will be rendered with this pose. */
+  readonly attribute unsigned long frameID;
+
+  /**
+   * position, linearVelocity, and linearAcceleration are 3-component vectors.
+   * position is relative to a sitting space. Transforming this point with
+   * VRStageParameters.sittingToStandingTransform converts this to standing space.
+   */
+  readonly attribute Float32Array? position;
+  readonly attribute Float32Array? linearVelocity;
+  readonly attribute Float32Array? linearAcceleration;
+
+  /* orientation is a 4-entry array representing the components of a quaternion. */
+  readonly attribute Float32Array? orientation;
+  /* angularVelocity and angularAcceleration are the components of 3-dimensional vectors. */
+  readonly attribute Float32Array? angularVelocity;
+  readonly attribute Float32Array? angularAcceleration;
+};
+
+[Pref="dom.vr.enabled",
+ HeaderFile="mozilla/dom/VRDisplay.h"]
+interface VREyeParameters {
+  /**
+   * offset is a 3-component vector representing an offset to
+   * translate the eye. This value may vary from frame
+   * to frame if the user adjusts their headset ipd.
+   */
+  [Constant, Cached] readonly attribute Float32Array offset;
+
+  /* These values may vary as the user adjusts their headset ipd. */
+  [Constant, Cached] readonly attribute VRFieldOfView fieldOfView;
+
+  /**
+   * renderWidth and renderHeight specify the recommended render target
+   * size of each eye viewport, in pixels. If multiple eyes are rendered
+   * in a single render target, then the render target should be made large
+   * enough to fit both viewports.
+   */
+  [Constant, Cached] readonly attribute unsigned long renderWidth;
+  [Constant, Cached] readonly attribute unsigned long renderHeight;
+};
+
+[Pref="dom.vr.enabled",
+ HeaderFile="mozilla/dom/VRDisplay.h"]
+interface VRDisplay {
+  /**
+   * Dictionary of capabilities describing the VRDisplay.
+   */
+  [Constant] readonly attribute VRDisplayCapabilities capabilities;
+
+  /**
+   * If this VRDisplay supports room-scale experiences, the optional
+   * stage attribute contains details on the room-scale parameters.
+   */
+  readonly attribute VRStageParameters? stageParameters;
+
+  /**
+   * Return the current VREyeParameters for the given eye.
+   */
+  VREyeParameters getEyeParameters(VREye whichEye);
+
+  /**
+   * An identifier for this distinct VRDisplay. Used as an
+   * association point in the Gamepad API.
+   */
+  [Constant] readonly attribute unsigned long displayId;
+
+  /**
+   * A display name, a user-readable name identifying it.
+   */
+  [Constant] readonly attribute DOMString displayName;
+
+  /**
+   * Return a VRPose containing the future predicted pose of the VRDisplay when the
+   * current frame will be presented. The value returned will not change until javascript
+   * has returned control to the browser.
+   *
+   * The VRPose will contain the position, orientation, velocity,
+   * and acceleration of each of these properties.
+   */
+  [NewObject] VRPose getPose();
+
+  /**
+   * Return the current instantaneous pose of the VRDisplay, with no
+   * prediction applied.
+   */
+  [NewObject] VRPose getImmediatePose();
+
+  /**
+   * Reset this sensor, treating its current position and orientation
+   * as the "origin/zero" values. VRPose.position,
+   * VRPose.orientation, and VRStageParameters.sittingToStandingTransform
+   * may be updated when calling resetPose(). This should only
+   * be called in a sitting space experience.
+   */
+  void resetPose();
+
+  /**
+   * z-depth defining the near plane of the eye view frustum
+   * enables mapping of values in the render target depth
+   * attachment to scene coordinates. Initially set to 0.01.
+   */
+  attribute double depthNear;
+
+  /**
+   * z-depth defining the far plane of the eye view frustum
+   * enables mapping of values in the render target depth
+   * attachment to scene coordinates. Initially set to 10000.0.
+   */
+  attribute double depthFar;
+
+  /**
+   * Begin presenting to the VRDisplay. Must be called in response to a user gesture.
+   * Repeat calls while already presenting will update the VRLayer being displayed.
+   */
+  [Throws]
+  Promise<void> requestPresent(optional VRLayer layer);
+  /**
+   * FINDME!!! KIP!! HACK!!  added "optional" to requestPresent above due to WebIDL spec:
+   *
+   *    If the type of an argument is a dictionary type or a union type that has a
+   *    dictionary type as one of its flattened member types, and that dictionary
+   *    type and its ancestors have no required members, and the argument is either
+   *    the final argument or is followed only by optional arguments, then the
+   *    argument MUST be specified as optional. Such arguments are always
+   *    considered to have a default value of an empty dictionary, unless otherwise
+   *    specified.
+   *
+   * FINDME!! KIP!! HACK!! Added [throws] to requestPresent, maybe this won't
+   * be needed?  Otherwise, need to update the spec.
+   */
+
+  /**
+   * Stops presenting to the VRDisplay.
+   */
+  [Throws]
+  Promise<void> exitPresent();
+
+  /**
+   * Get the sources currently being presented.
+   */
+  sequence<VRLayer>? getLayers();
+
+  /**
+   * The VRLayer provided to the VRDisplay will be captured and presented
+   * in the HMD. Calling this function has the same effect on the source
+   * canvas as any other operation that uses its source image, and canvases
+   * created without preserveDrawingBuffer set to true will be cleared.
+   */
+  void submitFrame(optional VRPose pose);
+};
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -580,17 +580,17 @@ WEBIDL_FILES = [
     'URL.webidl',
     'URLSearchParams.webidl',
     'USSDSession.webidl',
     'ValidityState.webidl',
     'VideoPlaybackQuality.webidl',
     'VideoStreamTrack.webidl',
     'VideoTrack.webidl',
     'VideoTrackList.webidl',
-    'VRDevice.webidl',
+    'VRDisplay.webidl',
     'VTTCue.webidl',
     'VTTRegion.webidl',
     'WaveShaperNode.webidl',
     'WebComponents.webidl',
     'WebGL2RenderingContext.webidl',
     'WebGLRenderingContext.webidl',
     'WebKitCSSMatrix.webidl',
     'WebSocket.webidl',
--- a/gfx/2d/BasePoint.h
+++ b/gfx/2d/BasePoint.h
@@ -17,17 +17,22 @@ namespace gfx {
 
 /**
  * Do not use this class directly. Subclass it, pass that subclass as the
  * Sub parameter, and only use that subclass. This allows methods to safely
  * cast 'this' to 'Sub*'.
  */
 template <class T, class Sub, class Coord = T>
 struct BasePoint {
-  T x, y;
+  union {
+    struct {
+      T x, y;
+    };
+    T components[2];
+  };
 
   // Constructors
   MOZ_CONSTEXPR BasePoint() : x(0), y(0) {}
   MOZ_CONSTEXPR BasePoint(Coord aX, Coord aY) : x(aX), y(aY) {}
 
   void MoveTo(T aX, T aY) { x = aX; y = aY; }
   void MoveBy(T aDx, T aDy) { x += aDx; y += aDy; }
 
--- a/gfx/2d/BasePoint3D.h
+++ b/gfx/2d/BasePoint3D.h
@@ -13,17 +13,22 @@ namespace gfx {
 
 /**
  * Do not use this class directly. Subclass it, pass that subclass as the
  * Sub parameter, and only use that subclass. This allows methods to safely
  * cast 'this' to 'Sub*'.
  */
 template <class T, class Sub>
 struct BasePoint3D {
-  T x, y, z;
+  union {
+    struct {
+      T x, y, z;
+    };
+    T components[3];
+  };
 
   // Constructors
   BasePoint3D() : x(0), y(0), z(0) {}
   BasePoint3D(T aX, T aY, T aZ) : x(aX), y(aY), z(aZ) {}
 
   void MoveTo(T aX, T aY, T aZ) { x = aX; y = aY; z = aZ; }
   void MoveBy(T aDx, T aDy, T aDz) { x += aDx; y += aDy; z += aDz; }
 
--- a/gfx/2d/BasePoint4D.h
+++ b/gfx/2d/BasePoint4D.h
@@ -13,17 +13,22 @@ namespace gfx {
 
 /**
  * Do not use this class directly. Subclass it, pass that subclass as the
  * Sub parameter, and only use that subclass. This allows methods to safely
  * cast 'this' to 'Sub*'.
  */
 template <class T, class Sub>
 struct BasePoint4D {
-  T x, y, z, w;
+  union {
+    struct {
+      T x, y, z, w;
+    };
+    T components[4];
+  };
 
   // Constructors
   BasePoint4D() : x(0), y(0), z(0), w(0) {}
   BasePoint4D(T aX, T aY, T aZ, T aW) : x(aX), y(aY), z(aZ), w(aW) {}
 
   void MoveTo(T aX, T aY, T aZ, T aW) { x = aX; y = aY; z = aZ; w = aW; }
   void MoveBy(T aDx, T aDy, T aDz, T aDw) { x += aDx; y += aDy; z += aDz; w += aDw; }
 
--- a/gfx/2d/BaseSize.h
+++ b/gfx/2d/BaseSize.h
@@ -13,17 +13,22 @@ namespace gfx {
 
 /**
  * Do not use this class directly. Subclass it, pass that subclass as the
  * Sub parameter, and only use that subclass. This allows methods to safely
  * cast 'this' to 'Sub*'.
  */
 template <class T, class Sub>
 struct BaseSize {
-  T width, height;
+  union {
+    struct {
+      T width, height;
+    };
+    T components[2];
+  };
 
   // Constructors
   MOZ_CONSTEXPR BaseSize() : width(0), height(0) {}
   MOZ_CONSTEXPR BaseSize(T aWidth, T aHeight) : width(aWidth), height(aHeight) {}
 
   void SizeTo(T aWidth, T aHeight) { width = aWidth; height = aHeight; }
 
   bool IsEmpty() const {
--- a/gfx/2d/Matrix.h
+++ b/gfx/2d/Matrix.h
@@ -32,19 +32,24 @@ public:
     , _21(0), _22(1.0f)
     , _31(0), _32(0)
   {}
   Matrix(Float a11, Float a12, Float a21, Float a22, Float a31, Float a32)
     : _11(a11), _12(a12)
     , _21(a21), _22(a22)
     , _31(a31), _32(a32)
   {}
-  Float _11, _12;
-  Float _21, _22;
-  Float _31, _32;
+  union {
+    struct {
+      Float _11, _12;
+      Float _21, _22;
+      Float _31, _32;
+    };
+    Float components[6];
+  };
 
   MOZ_ALWAYS_INLINE Matrix Copy() const
   {
     return Matrix(*this);
   }
 
   friend std::ostream& operator<<(std::ostream& aStream, const Matrix& aMatrix);
 
@@ -456,20 +461,25 @@ public:
     , _41(a41), _42(a42), _43(a43), _44(a44)
   {}
 
   Matrix4x4Typed(const Matrix4x4Typed& aOther)
   {
     memcpy(this, &aOther, sizeof(*this));
   }
 
-  Float _11, _12, _13, _14;
-  Float _21, _22, _23, _24;
-  Float _31, _32, _33, _34;
-  Float _41, _42, _43, _44;
+  union {
+    struct {
+      Float _11, _12, _13, _14;
+      Float _21, _22, _23, _24;
+      Float _31, _32, _33, _34;
+      Float _41, _42, _43, _44;
+    };
+    Float components[16];
+  };
 
   friend std::ostream& operator<<(std::ostream& aStream, const Matrix4x4Typed& aMatrix)
   {
     const Float *f = &aMatrix._11;
     aStream << "[ " << f[0] << " "  << f[1] << " " << f[2] << " " << f[3] << " ;" << std::endl; f += 4;
     aStream << "  " << f[0] << " "  << f[1] << " " << f[2] << " " << f[3] << " ;" << std::endl; f += 4;
     aStream << "  " << f[0] << " "  << f[1] << " " << f[2] << " " << f[3] << " ;" << std::endl; f += 4;
     aStream << "  " << f[0] << " "  << f[1] << " " << f[2] << " " << f[3] << " ]" << std::endl;
@@ -1631,19 +1641,24 @@ public:
   }
 
   Matrix5x4& operator*=(const Matrix5x4 &aMatrix)
   {
     *this = *this * aMatrix;
     return *this;
   }
 
-  Float _11, _12, _13, _14;
-  Float _21, _22, _23, _24;
-  Float _31, _32, _33, _34;
-  Float _41, _42, _43, _44;
-  Float _51, _52, _53, _54;
+  union {
+    struct {
+      Float _11, _12, _13, _14;
+      Float _21, _22, _23, _24;
+      Float _31, _32, _33, _34;
+      Float _41, _42, _43, _44;
+      Float _51, _52, _53, _54;
+    };
+    Float components[20];
+  };
 };
 
 } // namespace gfx
 } // namespace mozilla
 
 #endif /* MOZILLA_GFX_MATRIX_H_ */
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -1114,17 +1114,17 @@ ContainerLayer::ContainerLayer(LayerMana
     mInheritedYScale(1.0f),
     mPresShellResolution(1.0f),
     mScaleToResolution(false),
     mUseIntermediateSurface(false),
     mSupportsComponentAlphaChildren(false),
     mMayHaveReadbackChild(false),
     mChildrenChanged(false),
     mEventRegionsOverride(EventRegionsOverride::NoOverride),
-    mVRDeviceID(0),
+    mVRDisplayID(0),
     mInputFrameID(0)
 {
   MOZ_COUNT_CTOR(ContainerLayer);
   mContentFlags = 0; // Clear NO_TEXT, NO_TEXT_OVER_TRANSPARENT
 }
 
 ContainerLayer::~ContainerLayer()
 {
@@ -1277,17 +1277,17 @@ ContainerLayer::RepositionChild(Layer* a
 
 void
 ContainerLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
 {
   aAttrs = ContainerLayerAttributes(mPreXScale, mPreYScale,
                                     mInheritedXScale, mInheritedYScale,
                                     mPresShellResolution, mScaleToResolution,
                                     mEventRegionsOverride,
-                                    mVRDeviceID,
+                                    mVRDisplayID,
                                     mInputFrameID);
 }
 
 bool
 ContainerLayer::Creates3DContextWithExtendingChildren()
 {
   if (Extend3DContext()) {
     return false;
@@ -2144,18 +2144,18 @@ ContainerLayer::PrintInfo(std::stringstr
     aStream << nsPrintfCString(" [presShellResolution=%g]", mPresShellResolution).get();
   }
   if (mEventRegionsOverride & EventRegionsOverride::ForceDispatchToContent) {
     aStream << " [force-dtc]";
   }
   if (mEventRegionsOverride & EventRegionsOverride::ForceEmptyHitRegion) {
     aStream << " [force-ehr]";
   }
-  if (mVRDeviceID) {
-    aStream << nsPrintfCString(" [hmd=%lu] [hmdframe=%l]", mVRDeviceID, mInputFrameID).get();
+  if (mVRDisplayID) {
+    aStream << nsPrintfCString(" [hmd=%lu] [hmdframe=%l]", mVRDisplayID, mInputFrameID).get();
   }
 }
 
 void
 ContainerLayer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
 {
   Layer::DumpPacket(aPacket, aParent);
   // Get this layer data
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -2127,22 +2127,22 @@ public:
 
   EventRegionsOverride GetEventRegionsOverride() const {
     return mEventRegionsOverride;
   }
 
   /**
    * VR
    */
-  void SetVRDeviceID(uint32_t aVRDeviceID) {
-    mVRDeviceID = aVRDeviceID;
+  void SetVRDisplayID(uint32_t aVRDisplayID) {
+    mVRDisplayID = aVRDisplayID;
     Mutated();
   }
-  uint32_t GetVRDeviceID() {
-    return mVRDeviceID;
+  uint32_t GetVRDisplayID() {
+    return mVRDisplayID;
   }
   void SetInputFrameID(int32_t aInputFrameID) {
     mInputFrameID = aInputFrameID;
     Mutated();
   }
   int32_t GetInputFrameID() {
     return mInputFrameID;
   }
@@ -2216,17 +2216,17 @@ protected:
   bool mScaleToResolution;
   bool mUseIntermediateSurface;
   bool mSupportsComponentAlphaChildren;
   bool mMayHaveReadbackChild;
   // This is updated by ComputeDifferences. This will be true if we need to invalidate
   // the intermediate surface.
   bool mChildrenChanged;
   EventRegionsOverride mEventRegionsOverride;
-  uint32_t mVRDeviceID;
+  uint32_t mVRDisplayID;
   int32_t mInputFrameID;
 };
 
 /**
  * A Layer which just renders a solid color in its visible region. It actually
  * can fill any area that contains the visible region, so if you need to
  * restrict the area filled, set a clip region on this layer.
  */
--- a/gfx/layers/composite/ContainerLayerComposite.cpp
+++ b/gfx/layers/composite/ContainerLayerComposite.cpp
@@ -375,17 +375,17 @@ struct PreparedData
 template<class ContainerT> void
 ContainerPrepare(ContainerT* aContainer,
                  LayerManagerComposite* aManager,
                  const RenderTargetIntRect& aClipRect)
 {
   aContainer->mPrepared = MakeUnique<PreparedData>();
   aContainer->mPrepared->mNeedsSurfaceCopy = false;
 
-  RefPtr<gfx::VRHMDInfo> hmdInfo = gfx::VRManager::Get()->GetDevice(aContainer->GetVRDeviceID());
+  RefPtr<gfx::VRHMDInfo> hmdInfo = gfx::VRManager::Get()->GetDevice(aContainer->GetVRDisplayID());
   if (hmdInfo && hmdInfo->GetConfiguration().IsValid()) {
     // we're not going to do anything here; instead, we'll do it all in ContainerRender.
     // XXX fix this; we can win with the same optimizations.  Specifically, we
     // want to render thebes layers only once and then composite the intermeidate surfaces
     // with different transforms twice.
     return;
   }
 
@@ -724,17 +724,17 @@ RenderIntermediate(ContainerT* aContaine
 
 template<class ContainerT> void
 ContainerRender(ContainerT* aContainer,
                  LayerManagerComposite* aManager,
                  const gfx::IntRect& aClipRect)
 {
   MOZ_ASSERT(aContainer->mPrepared);
 
-  RefPtr<gfx::VRHMDInfo> hmdInfo = gfx::VRManager::Get()->GetDevice(aContainer->GetVRDeviceID());
+  RefPtr<gfx::VRHMDInfo> hmdInfo = gfx::VRManager::Get()->GetDevice(aContainer->GetVRDisplayID());
   if (hmdInfo && hmdInfo->GetConfiguration().IsValid()) {
     ContainerRenderVR(aContainer, aManager, aClipRect, hmdInfo);
     aContainer->mPrepared = nullptr;
     return;
   }
 
   if (aContainer->UseIntermediateSurface()) {
     RefPtr<CompositingRenderTarget> surface;
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -412,17 +412,17 @@ LayerTransactionParent::RecvUpdate(Infal
         containerLayer->SetPreScale(attrs.preXScale(), attrs.preYScale());
         containerLayer->SetInheritedScale(attrs.inheritedXScale(), attrs.inheritedYScale());
         containerLayer->SetScaleToResolution(attrs.scaleToResolution(),
                                              attrs.presShellResolution());
         containerLayer->SetEventRegionsOverride(attrs.eventRegionsOverride());
         containerLayer->SetInputFrameID(attrs.inputFrameID());
 
         if (attrs.hmdDeviceID()) {
-          containerLayer->SetVRDeviceID(attrs.hmdDeviceID());
+          containerLayer->SetVRDisplayID(attrs.hmdDeviceID());
         }
 
         break;
       }
       case Specific::TColorLayerAttributes: {
         MOZ_LAYERS_LOG(("[ParentSide]   color layer"));
 
         ColorLayerComposite* colorLayer = layerParent->AsColorLayerComposite();
deleted file mode 100644
--- a/gfx/vr/VRDeviceProxy.cpp
+++ /dev/null
@@ -1,165 +0,0 @@
-/* -*- Mode: C++; tab-width: 20; 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 <math.h>
-
-#include "prlink.h"
-#include "prmem.h"
-#include "prenv.h"
-#include "gfxPrefs.h"
-#include "nsString.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/unused.h"
-#include "nsServiceManagerUtils.h"
-#include "nsIScreenManager.h"
-
-
-#ifdef XP_WIN
-#include "../layers/d3d11/CompositorD3D11.h"
-#endif
-
-#include "VRDeviceProxy.h"
-#include "VRManagerChild.h"
-
-using namespace mozilla;
-using namespace mozilla::gfx;
-
-VRDeviceProxy::VRDeviceProxy(const VRDeviceUpdate& aDeviceUpdate)
-  : mDeviceInfo(aDeviceUpdate.mDeviceInfo)
-  , mSensorState(aDeviceUpdate.mSensorState)
-{
-  MOZ_COUNT_CTOR(VRDeviceProxy);
-
-  if (mDeviceInfo.mScreenRect.width && mDeviceInfo.mScreenRect.height) {
-    if (mDeviceInfo.mIsFakeScreen) {
-      mScreen = MakeFakeScreen(mDeviceInfo.mScreenRect);
-    } else {
-      nsCOMPtr<nsIScreenManager> screenmgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
-      if (screenmgr) {
-        screenmgr->ScreenForRect(mDeviceInfo.mScreenRect.x, mDeviceInfo.mScreenRect.y,
-                                 mDeviceInfo.mScreenRect.width, mDeviceInfo.mScreenRect.height,
-                                 getter_AddRefs(mScreen));
-      }
-    }
-#ifdef DEBUG
-    printf_stderr("VR DEVICE SCREEN: %d %d %d %d\n",
-                  mDeviceInfo.mScreenRect.x, mDeviceInfo.mScreenRect.y,
-                  mDeviceInfo.mScreenRect.width, mDeviceInfo.mScreenRect.height);
-#endif
-  }
-}
-
-VRDeviceProxy::~VRDeviceProxy() {
-  MOZ_COUNT_DTOR(VRDeviceProxy);
-}
-
-void
-VRDeviceProxy::UpdateDeviceInfo(const VRDeviceUpdate& aDeviceUpdate)
-{
-  mDeviceInfo = aDeviceUpdate.mDeviceInfo;
-  mSensorState = aDeviceUpdate.mSensorState;
-}
-
-bool
-VRDeviceProxy::SetFOV(const VRFieldOfView& aFOVLeft, const VRFieldOfView& aFOVRight,
-                       double zNear, double zFar)
-{
-  VRManagerChild *vm = VRManagerChild::Get();
-  vm->SendSetFOV(mDeviceInfo.mDeviceID, aFOVLeft, aFOVRight, zNear, zFar);
-  return true;
-}
-
-void
-VRDeviceProxy::ZeroSensor()
-{
-  VRManagerChild *vm = VRManagerChild::Get();
-  vm->SendResetSensor(mDeviceInfo.mDeviceID);
-}
-
-VRHMDSensorState
-VRDeviceProxy::GetSensorState()
-{
-  VRManagerChild *vm = VRManagerChild::Get();
-  Unused << vm->SendKeepSensorTracking(mDeviceInfo.mDeviceID);
-  return mSensorState;
-}
-
-VRHMDSensorState
-VRDeviceProxy::GetImmediateSensorState()
-{
-  // XXX TODO - Need to perform IPC call to get the current sensor
-  // state rather than the predictive state used for the frame rendering.
-  return GetSensorState();
-}
-
-void
-VRDeviceProxy::UpdateSensorState(const VRHMDSensorState& aSensorState)
-{
-  mSensorState = aSensorState;
-}
-
-// Dummy nsIScreen implementation, for when we just need to specify a size
-class FakeScreen : public nsIScreen
-{
-public:
-  explicit FakeScreen(const IntRect& aScreenRect)
-    : mScreenRect(aScreenRect)
-  { }
-
-  NS_DECL_ISUPPORTS
-
-  NS_IMETHOD GetRect(int32_t *l, int32_t *t, int32_t *w, int32_t *h) override {
-    *l = mScreenRect.x;
-    *t = mScreenRect.y;
-    *w = mScreenRect.width;
-    *h = mScreenRect.height;
-    return NS_OK;
-  }
-  NS_IMETHOD GetAvailRect(int32_t *l, int32_t *t, int32_t *w, int32_t *h) override {
-    return GetRect(l, t, w, h);
-  }
-  NS_IMETHOD GetRectDisplayPix(int32_t *l, int32_t *t, int32_t *w, int32_t *h) override {
-    return GetRect(l, t, w, h);
-  }
-  NS_IMETHOD GetAvailRectDisplayPix(int32_t *l, int32_t *t, int32_t *w, int32_t *h) override {
-    return GetAvailRect(l, t, w, h);
-  }
-
-  NS_IMETHOD GetId(uint32_t* aId) override { *aId = (uint32_t)-1; return NS_OK; }
-  NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth) override { *aPixelDepth = 24; return NS_OK; }
-  NS_IMETHOD GetColorDepth(int32_t* aColorDepth) override { *aColorDepth = 24; return NS_OK; }
-
-  NS_IMETHOD LockMinimumBrightness(uint32_t aBrightness) override { return NS_ERROR_NOT_AVAILABLE; }
-  NS_IMETHOD UnlockMinimumBrightness(uint32_t aBrightness) override { return NS_ERROR_NOT_AVAILABLE; }
-  NS_IMETHOD GetRotation(uint32_t* aRotation) override {
-    *aRotation = nsIScreen::ROTATION_0_DEG;
-    return NS_OK;
-  }
-  NS_IMETHOD SetRotation(uint32_t aRotation) override { return NS_ERROR_NOT_AVAILABLE; }
-  NS_IMETHOD GetContentsScaleFactor(double* aContentsScaleFactor) override {
-    *aContentsScaleFactor = 1.0;
-    return NS_OK;
-  }
-  NS_IMETHOD GetDefaultCSSScaleFactor(double* aScaleFactor) override {
-    *aScaleFactor = 1.0;
-    return NS_OK;
-  }
-
-protected:
-  virtual ~FakeScreen() {}
-
-  IntRect mScreenRect;
-};
-
-NS_IMPL_ISUPPORTS(FakeScreen, nsIScreen)
-
-
-/* static */ already_AddRefed<nsIScreen>
-VRDeviceProxy::MakeFakeScreen(const IntRect& aScreenRect)
-{
-  nsCOMPtr<nsIScreen> screen = new FakeScreen(aScreenRect);
-  return screen.forget();
-}
-
deleted file mode 100644
--- a/gfx/vr/VRDeviceProxy.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* -*- Mode: C++; tab-width: 20; 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/. */
-
-#ifndef GFX_VR_PROXY_H
-#define GFX_VR_PROXY_H
-
-#include "nsIScreen.h"
-#include "nsCOMPtr.h"
-#include "mozilla/RefPtr.h"
-
-#include "gfxVR.h"
-
-namespace mozilla {
-namespace gfx {
-
-class VRManagerChild;
-
-class VRDeviceProxy
-{
-public:
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRDeviceProxy)
-
-  explicit VRDeviceProxy(const VRDeviceUpdate& aDeviceUpdate);
-
-  void UpdateDeviceInfo(const VRDeviceUpdate& aDeviceUpdate);
-  void UpdateSensorState(const VRHMDSensorState& aSensorState);
-
-  const VRDeviceInfo& GetDeviceInfo() const { return mDeviceInfo; }
-  virtual VRHMDSensorState GetSensorState();
-  virtual VRHMDSensorState GetImmediateSensorState();
-
-  bool SetFOV(const VRFieldOfView& aFOVLeft, const VRFieldOfView& aFOVRight,
-              double zNear, double zFar);
-
-  virtual void ZeroSensor();
-
-
-  // The nsIScreen that represents this device
-  nsIScreen* GetScreen() { return mScreen; }
-
-protected:
-  virtual ~VRDeviceProxy();
-
-  VRDeviceInfo mDeviceInfo;
-  VRHMDSensorState mSensorState;
-
-  nsCOMPtr<nsIScreen> mScreen;
-
-  static already_AddRefed<nsIScreen> MakeFakeScreen(const IntRect& aScreenRect);
-
-};
-
-} // namespace gfx
-} // namespace mozilla
-
-#endif /* GFX_VR_PROXY_H */
deleted file mode 100644
--- a/gfx/vr/VRDeviceProxyOrientationFallBack.cpp
+++ /dev/null
@@ -1,206 +0,0 @@
-/* -*- Mode: C++; tab-width: 20; 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 <math.h>
-#include "VRDeviceProxyOrientationFallBack.h"
-#include "mozilla/dom/ScreenOrientation.h" // for ScreenOrientationInternal
-#include "mozilla/Hal.h"
-
-using namespace mozilla;
-using namespace mozilla::gfx;
-
-// 1/sqrt(2) (aka sqrt(2)/2)
-#ifndef M_SQRT1_2
-# define M_SQRT1_2	0.70710678118654752440
-#endif
-
-#ifdef ANDROID
-#include <android/log.h>
-#define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "GeckoVR" , ## args)
-#else
-#define LOG(...) do { } while(0)
-#endif
-
-namespace {
-// some utility functions
-
-// This remaps axes in the given matrix to a new configuration based on the
-// screen orientation.  Similar to what Android SensorManager.remapCoordinateSystem
-// does, except only for a fixed number of transforms that we need.
-Matrix4x4
-RemapMatrixForOrientation(dom::ScreenOrientationInternal screenConfig, const Matrix4x4& aMatrix)
-{
-  Matrix4x4 out;
-  const float *in = &aMatrix._11;
-  float *o = &out._11;
-
-  if (screenConfig == dom::eScreenOrientation_LandscapePrimary) {
-    // remap X,Y -> Y,-X
-    o[0] = -in[1]; o[1] = in[0]; o[2] = in[2];
-    o[4] = -in[5]; o[5] = in[4]; o[6] = in[6];
-    o[8] = -in[9]; o[9] = in[8]; o[10] = in[10];
-  } else if (screenConfig == dom::eScreenOrientation_LandscapeSecondary) {
-    // remap X,Y -> -Y,X
-    o[0] = in[1]; o[1] = -in[0]; o[2] = in[2];
-    o[4] = in[5]; o[5] = -in[4]; o[6] = in[6];
-    o[8] = in[9]; o[9] = -in[8]; o[10] = in[10];
-  } else if (screenConfig == dom::eScreenOrientation_PortraitPrimary) {
-    out = aMatrix;
-  } else if (screenConfig == dom::eScreenOrientation_PortraitSecondary) {
-    // remap X,Y -> X,-Z
-    o[0] = in[0]; o[1] = in[2]; o[2] = -in[1];
-    o[4] = in[4]; o[5] = in[6]; o[6] = -in[5];
-    o[8] = in[8]; o[9] = in[10]; o[10] = -in[9];
-  } else {
-    MOZ_ASSERT(0, "gfxVRCardboard::RemapMatrixForOrientation invalid screenConfig");
-  }
-
-  return out;
-}
-
-} // namespace
-
-namespace mozilla {
-namespace gfx {
-
-VRDeviceProxyOrientationFallBack::VRDeviceProxyOrientationFallBack(const VRDeviceUpdate& aDeviceUpdate)
-  : VRDeviceProxy(aDeviceUpdate)
-  , mOrient(dom::eScreenOrientation_PortraitPrimary)
-  , mTracking(false)
-{
-  MOZ_COUNT_CTOR_INHERITED(VRDeviceProxyOrientationFallBack, VRDeviceProxy);
-}
-
-VRDeviceProxyOrientationFallBack::~VRDeviceProxyOrientationFallBack()
-{
-  StopSensorTracking();
-  MOZ_COUNT_DTOR_INHERITED(VRDeviceProxyOrientationFallBack, VRDeviceProxy);
-}
-
-void
-VRDeviceProxyOrientationFallBack::StartSensorTracking()
-{
-  if (!mTracking) {
-    // it's never been started before; initialize observers and
-    // initial state.
-
-    hal::ScreenConfiguration sconfig;
-    hal::GetCurrentScreenConfiguration(&sconfig);
-    this->Notify(sconfig);
-
-    hal::RegisterSensorObserver(hal::SENSOR_GAME_ROTATION_VECTOR, this);
-    hal::RegisterScreenConfigurationObserver(this);
-
-    mSensorState.Clear();
-
-    mTracking = true;
-  }
-}
-
-void
-VRDeviceProxyOrientationFallBack::StopSensorTracking()
-{
-  if (mTracking) {
-    hal::UnregisterScreenConfigurationObserver(this);
-    hal::UnregisterSensorObserver(hal::SENSOR_GAME_ROTATION_VECTOR, this);
-    mTracking = false;
-  }
-}
-
-// Android sends us events that have a 90-degree rotation about 
-// the x axis compared to what we want (phone flat vs. phone held in front of the eyes).
-// Correct for this by applying a transform to undo this rotation.
-void
-VRDeviceProxyOrientationFallBack::Notify(const hal::ScreenConfiguration& config)
-{
-  mOrient = config.orientation();
-
-  if (mOrient == dom::eScreenOrientation_LandscapePrimary) {
-    mScreenTransform = Quaternion(-0.5f, 0.5f, 0.5f, 0.5f);
-  } else if (mOrient == dom::eScreenOrientation_LandscapeSecondary) {
-    mScreenTransform = Quaternion(-0.5f, -0.5f, -0.5f, 0.5f);
-  } else if (mOrient == dom::eScreenOrientation_PortraitPrimary) {
-    mScreenTransform = Quaternion((float) -M_SQRT1_2, 0.f, 0.f, (float) M_SQRT1_2);
-  } else if (mOrient == dom::eScreenOrientation_PortraitSecondary) {
-    // Currently, PortraitSecondary event doesn't be triggered.
-    mScreenTransform = Quaternion((float) M_SQRT1_2, 0.f, 0.f, (float) M_SQRT1_2);
-  }
-}
-
-void
-VRDeviceProxyOrientationFallBack::Notify(const hal::SensorData& data)
-{
-  if (data.sensor() != hal::SENSOR_GAME_ROTATION_VECTOR)
-    return;
-
-  const nsTArray<float>& sensorValues = data.values();
-
-  // This is super chatty
-  //LOG("HMDInfoCardboard::Notify %f %f %f %f\n", sensorValues[0], sensorValues[1], sensorValues[2], sensorValues[3]);
-
-  mSavedLastSensor.Set(sensorValues[0], sensorValues[1], sensorValues[2], sensorValues[3]);
-  mSavedLastSensorTime = data.timestamp();
-  mNeedsSensorCompute = true;
-}
-
-void
-VRDeviceProxyOrientationFallBack::ZeroSensor()
-{
-  mSensorZeroInverse = mSavedLastSensor;
-  mSensorZeroInverse.Invert();
-}
-
-void
-VRDeviceProxyOrientationFallBack::ComputeStateFromLastSensor()
-{
-  if (!mNeedsSensorCompute)
-    return;
-
-  // apply the zero orientation
-  Quaternion q = mSensorZeroInverse * mSavedLastSensor;
-
-  // make a matrix from the quat
-  Matrix4x4 qm;
-  qm.SetRotationFromQuaternion(q);
-
-  // remap the coordinate space, based on the orientation
-  Matrix4x4 qmRemapped = RemapMatrixForOrientation(mOrient, qm);
-
-  // turn it back into a quat
-  q.SetFromRotationMatrix(qmRemapped);
-
-  // apply adjustment based on what's been done to the screen and the original zero
-  // position of the base coordinate space
-  q = mScreenTransform * q;
-
-  mSensorState.flags |= VRStateValidFlags::State_Orientation;
-  mSensorState.orientation[0] = q.x;
-  mSensorState.orientation[1] = q.y;
-  mSensorState.orientation[2] = q.z;
-  mSensorState.orientation[3] = q.w;
-
-  mSensorState.timestamp = mSavedLastSensorTime / 1000000.0;
-
-  mNeedsSensorCompute = false;
-}
-
-VRHMDSensorState
-VRDeviceProxyOrientationFallBack::GetSensorState()
-{
-  StartSensorTracking();
-  ComputeStateFromLastSensor();
-  return mSensorState;
-}
-
-VRHMDSensorState
-VRDeviceProxyOrientationFallBack::GetImmediateSensorState()
-{
-  // XXX TODO - Should return actual immediate sensor state
-  return GetSensorState();
-}
-
-} // namespace gfx
-} // namespace mozilla
-
deleted file mode 100644
--- a/gfx/vr/VRDeviceProxyOrientationFallBack.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* -*- Mode: C++; tab-width: 20; 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/. */
-
-#ifndef GFX_VR_PROXY_ORIENTATION_FALLBACK_H
-#define GFX_VR_PROXY_ORIENTATION_FALLBACK_H
-
-#include "VRDeviceProxy.h"
-
-#include "mozilla/HalSensor.h"
-#include "mozilla/HalScreenConfiguration.h"
-
-namespace mozilla {
-namespace gfx {
-
-class VRDeviceProxyOrientationFallBack : public VRDeviceProxy
-                                       , public hal::ISensorObserver
-                                       , public hal::ScreenConfigurationObserver
-{
-public:
-
-  explicit VRDeviceProxyOrientationFallBack(const VRDeviceUpdate& aDeviceUpdate);
-
-  virtual void ZeroSensor() override;
-  virtual VRHMDSensorState GetSensorState() override;
-  virtual VRHMDSensorState GetImmediateSensorState() override;
-
-  // ISensorObserver interface
-  void Notify(const hal::SensorData& SensorData) override;
-  // ScreenConfigurationObserver interface
-  void Notify(const hal::ScreenConfiguration& ScreenConfiguration) override;
-
-
-protected:
-  virtual ~VRDeviceProxyOrientationFallBack();
-
-  void StartSensorTracking();
-  void StopSensorTracking();
-  void ComputeStateFromLastSensor();
-
-  uint32_t mOrient;
-  Quaternion mScreenTransform;
-  Quaternion mSensorZeroInverse;
-  Quaternion mSavedLastSensor;
-  double mSavedLastSensorTime;
-  bool mNeedsSensorCompute;    // if we need to compute the state from mSavedLastSensor
-
-  bool mTracking;
-};
-
-} // namespace gfx
-} // namespace mozilla
-
-#endif /* GFX_VR_PROXY_ORIENTATION_FALLBACK_H */
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/vr/VRDisplayProxy.cpp
@@ -0,0 +1,192 @@
+/* -*- Mode: C++; tab-width: 20; 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 <math.h>
+
+#include "prlink.h"
+#include "prmem.h"
+#include "prenv.h"
+#include "gfxPrefs.h"
+#include "nsString.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/unused.h"
+#include "nsServiceManagerUtils.h"
+#include "nsIScreenManager.h"
+
+
+#ifdef XP_WIN
+#include "../layers/d3d11/CompositorD3D11.h"
+#endif
+
+#include "VRDisplayProxy.h"
+#include "VRManagerChild.h"
+
+using namespace mozilla;
+using namespace mozilla::gfx;
+
+VRDisplayProxy::VRDisplayProxy(const VRDisplayUpdate& aDeviceUpdate)
+  : mDeviceInfo(aDeviceUpdate.mDeviceInfo)
+  , mSensorState(aDeviceUpdate.mSensorState)
+{
+  MOZ_COUNT_CTOR(VRDisplayProxy);
+
+  if (mDeviceInfo.mScreenRect.width && mDeviceInfo.mScreenRect.height) {
+    if (mDeviceInfo.mIsFakeScreen) {
+      mScreen = MakeFakeScreen(mDeviceInfo.mScreenRect);
+    } else {
+      nsCOMPtr<nsIScreenManager> screenmgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
+      if (screenmgr) {
+        screenmgr->ScreenForRect(mDeviceInfo.mScreenRect.x, mDeviceInfo.mScreenRect.y,
+                                 mDeviceInfo.mScreenRect.width, mDeviceInfo.mScreenRect.height,
+                                 getter_AddRefs(mScreen));
+      }
+    }
+#ifdef DEBUG
+    printf_stderr("VR DEVICE SCREEN: %d %d %d %d\n",
+                  mDeviceInfo.mScreenRect.x, mDeviceInfo.mScreenRect.y,
+                  mDeviceInfo.mScreenRect.width, mDeviceInfo.mScreenRect.height);
+#endif
+  }
+}
+
+VRDisplayProxy::~VRDisplayProxy() {
+  MOZ_COUNT_DTOR(VRDisplayProxy);
+}
+
+void
+VRDisplayProxy::UpdateDeviceInfo(const VRDisplayUpdate& aDeviceUpdate)
+{
+  mDeviceInfo = aDeviceUpdate.mDeviceInfo;
+  mSensorState = aDeviceUpdate.mSensorState;
+}
+
+bool
+VRDisplayProxy::SetFOV(const VRFieldOfView& aFOVLeft, const VRFieldOfView& aFOVRight,
+                       double zNear, double zFar)
+{
+  VRManagerChild *vm = VRManagerChild::Get();
+  vm->SendSetFOV(mDeviceInfo.mDeviceID, aFOVLeft, aFOVRight, zNear, zFar);
+  return true;
+}
+
+/* FINDME!! KIP!! Will need this...
+
+bool
+VRDisplayProxy::SetDepthNear(double aDepthNear)
+{
+  VRManagerChild *vm = VRManagerChild::Get();
+
+  vm->SendSetFOV(mDeviceInfo.mDeviceID,
+                 mDeviceInfo.mEyeFOV[VRDisplayInfo::Eye_Left],
+                 mDeviceInfo.mEyeFOV[VRDisplayInfo::Eye_Right],
+                 mDepthNear, mDeviceInfo.mDepthFar);
+  return true;
+}
+
+bool
+VRDisplayProxy::SetDepthFar(double aDepthFar)
+{
+  VRManagerChild *vm = VRManagerChild::Get();
+
+  vm->SendSetFOV(mDeviceInfo.mDeviceID,
+                 mDeviceInfo.mEyeFOV[VRDisplayInfo::Eye_Left],
+                 mDeviceInfo.mEyeFOV[VRDisplayInfo::Eye_Right],
+                 mDeviceInfo.mDepthNear, mDepthFar);
+  return true;
+}
+*/
+
+void
+VRDisplayProxy::ZeroSensor()
+{
+  VRManagerChild *vm = VRManagerChild::Get();
+  vm->SendResetSensor(mDeviceInfo.mDeviceID);
+}
+
+VRHMDSensorState
+VRDisplayProxy::GetSensorState()
+{
+  VRManagerChild *vm = VRManagerChild::Get();
+  Unused << vm->SendKeepSensorTracking(mDeviceInfo.mDeviceID);
+  return mSensorState;
+}
+
+VRHMDSensorState
+VRDisplayProxy::GetImmediateSensorState()
+{
+  // XXX TODO - Need to perform IPC call to get the current sensor
+  // state rather than the predictive state used for the frame rendering.
+  return GetSensorState();
+}
+
+void
+VRDisplayProxy::UpdateSensorState(const VRHMDSensorState& aSensorState)
+{
+  mSensorState = aSensorState;
+}
+
+// Dummy nsIScreen implementation, for when we just need to specify a size
+class FakeScreen : public nsIScreen
+{
+public:
+  explicit FakeScreen(const IntRect& aScreenRect)
+    : mScreenRect(aScreenRect)
+  { }
+
+  NS_DECL_ISUPPORTS
+
+  NS_IMETHOD GetRect(int32_t *l, int32_t *t, int32_t *w, int32_t *h) override {
+    *l = mScreenRect.x;
+    *t = mScreenRect.y;
+    *w = mScreenRect.width;
+    *h = mScreenRect.height;
+    return NS_OK;
+  }
+  NS_IMETHOD GetAvailRect(int32_t *l, int32_t *t, int32_t *w, int32_t *h) override {
+    return GetRect(l, t, w, h);
+  }
+  NS_IMETHOD GetRectDisplayPix(int32_t *l, int32_t *t, int32_t *w, int32_t *h) override {
+    return GetRect(l, t, w, h);
+  }
+  NS_IMETHOD GetAvailRectDisplayPix(int32_t *l, int32_t *t, int32_t *w, int32_t *h) override {
+    return GetAvailRect(l, t, w, h);
+  }
+
+  NS_IMETHOD GetId(uint32_t* aId) override { *aId = (uint32_t)-1; return NS_OK; }
+  NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth) override { *aPixelDepth = 24; return NS_OK; }
+  NS_IMETHOD GetColorDepth(int32_t* aColorDepth) override { *aColorDepth = 24; return NS_OK; }
+
+  NS_IMETHOD LockMinimumBrightness(uint32_t aBrightness) override { return NS_ERROR_NOT_AVAILABLE; }
+  NS_IMETHOD UnlockMinimumBrightness(uint32_t aBrightness) override { return NS_ERROR_NOT_AVAILABLE; }
+  NS_IMETHOD GetRotation(uint32_t* aRotation) override {
+    *aRotation = nsIScreen::ROTATION_0_DEG;
+    return NS_OK;
+  }
+  NS_IMETHOD SetRotation(uint32_t aRotation) override { return NS_ERROR_NOT_AVAILABLE; }
+  NS_IMETHOD GetContentsScaleFactor(double* aContentsScaleFactor) override {
+    *aContentsScaleFactor = 1.0;
+    return NS_OK;
+  }
+  NS_IMETHOD GetDefaultCSSScaleFactor(double* aScaleFactor) override {
+    *aScaleFactor = 1.0;
+    return NS_OK;
+  }
+
+protected:
+  virtual ~FakeScreen() {}
+
+  IntRect mScreenRect;
+};
+
+NS_IMPL_ISUPPORTS(FakeScreen, nsIScreen)
+
+
+/* static */ already_AddRefed<nsIScreen>
+VRDisplayProxy::MakeFakeScreen(const IntRect& aScreenRect)
+{
+  nsCOMPtr<nsIScreen> screen = new FakeScreen(aScreenRect);
+  return screen.forget();
+}
+
new file mode 100644
--- /dev/null
+++ b/gfx/vr/VRDisplayProxy.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 20; 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/. */
+
+#ifndef GFX_VR_PROXY_H
+#define GFX_VR_PROXY_H
+
+#include "nsIScreen.h"
+#include "nsCOMPtr.h"
+#include "mozilla/RefPtr.h"
+
+#include "gfxVR.h"
+
+namespace mozilla {
+namespace gfx {
+
+class VRManagerChild;
+
+class VRDisplayProxy
+{
+public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRDisplayProxy)
+
+  explicit VRDisplayProxy(const VRDisplayUpdate& aDeviceUpdate);
+
+  void UpdateDeviceInfo(const VRDisplayUpdate& aDeviceUpdate);
+  void UpdateSensorState(const VRHMDSensorState& aSensorState);
+
+  const VRDisplayInfo& GetDeviceInfo() const { return mDeviceInfo; }
+  virtual VRHMDSensorState GetSensorState();
+  virtual VRHMDSensorState GetImmediateSensorState();
+
+  bool SetFOV(const VRFieldOfView& aFOVLeft, const VRFieldOfView& aFOVRight,
+              double zNear, double zFar);
+
+  virtual void ZeroSensor();
+
+
+  // The nsIScreen that represents this device
+  nsIScreen* GetScreen() { return mScreen; }
+
+protected:
+  virtual ~VRDisplayProxy();
+
+  VRDisplayInfo mDeviceInfo;
+  VRHMDSensorState mSensorState;
+
+  nsCOMPtr<nsIScreen> mScreen;
+
+  static already_AddRefed<nsIScreen> MakeFakeScreen(const IntRect& aScreenRect);
+
+};
+
+} // namespace gfx
+} // namespace mozilla
+
+#endif /* GFX_VR_PROXY_H */
new file mode 100644
--- /dev/null
+++ b/gfx/vr/VRDisplayProxyOrientationFallBack.cpp
@@ -0,0 +1,207 @@
+/* -*- Mode: C++; tab-width: 20; 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 <math.h>
+#include "VRDisplayProxyOrientationFallBack.h"
+#include "mozilla/dom/ScreenOrientation.h" // for ScreenOrientationInternal
+#include "mozilla/Hal.h"
+
+using namespace mozilla;
+using namespace mozilla::gfx;
+
+// 1/sqrt(2) (aka sqrt(2)/2)
+#ifndef M_SQRT1_2
+# define M_SQRT1_2	0.70710678118654752440
+#endif
+
+#ifdef ANDROID
+#include <android/log.h>
+#define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "GeckoVR" , ## args)
+#else
+#define LOG(...) do { } while(0)
+#endif
+
+namespace {
+// some utility functions
+
+// This remaps axes in the given matrix to a new configuration based on the
+// screen orientation.  Similar to what Android SensorManager.remapCoordinateSystem
+// does, except only for a fixed number of transforms that we need.
+Matrix4x4
+RemapMatrixForOrientation(dom::ScreenOrientationInternal screenConfig, const Matrix4x4& aMatrix)
+{
+  Matrix4x4 out;
+  const float *in = &aMatrix._11;
+  float *o = &out._11;
+
+  if (screenConfig == dom::eScreenOrientation_LandscapePrimary) {
+    // remap X,Y -> Y,-X
+    o[0] = -in[1]; o[1] = in[0]; o[2] = in[2];
+    o[4] = -in[5]; o[5] = in[4]; o[6] = in[6];
+    o[8] = -in[9]; o[9] = in[8]; o[10] = in[10];
+  } else if (screenConfig == dom::eScreenOrientation_LandscapeSecondary) {
+    // remap X,Y -> -Y,X
+    o[0] = in[1]; o[1] = -in[0]; o[2] = in[2];
+    o[4] = in[5]; o[5] = -in[4]; o[6] = in[6];
+    o[8] = in[9]; o[9] = -in[8]; o[10] = in[10];
+  } else if (screenConfig == dom::eScreenOrientation_PortraitPrimary) {
+    out = aMatrix;
+  } else if (screenConfig == dom::eScreenOrientation_PortraitSecondary) {
+    // remap X,Y -> X,-Z
+    o[0] = in[0]; o[1] = in[2]; o[2] = -in[1];
+    o[4] = in[4]; o[5] = in[6]; o[6] = -in[5];
+    o[8] = in[8]; o[9] = in[10]; o[10] = -in[9];
+  } else {
+    MOZ_ASSERT(0, "gfxVRCardboard::RemapMatrixForOrientation invalid screenConfig");
+  }
+
+  return out;
+}
+
+} // namespace
+
+namespace mozilla {
+namespace gfx {
+
+VRDisplayProxyOrientationFallBack::VRDisplayProxyOrientationFallBack(const VRDisplayUpdate& aDeviceUpdate)
+  : VRDisplayProxy(aDeviceUpdate)
+  , mOrient(dom::eScreenOrientation_PortraitPrimary)
+  , mTracking(false)
+{
+  MOZ_COUNT_CTOR_INHERITED(VRDisplayProxyOrientationFallBack, VRDisplayProxy);
+}
+
+VRDisplayProxyOrientationFallBack::~VRDisplayProxyOrientationFallBack()
+{
+  StopSensorTracking();
+  MOZ_COUNT_DTOR_INHERITED(VRDisplayProxyOrientationFallBack, VRDisplayProxy);
+}
+
+void
+VRDisplayProxyOrientationFallBack::StartSensorTracking()
+{
+  if (!mTracking) {
+    // it's never been started before; initialize observers and
+    // initial state.
+
+    hal::ScreenConfiguration sconfig;
+    hal::GetCurrentScreenConfiguration(&sconfig);
+    this->Notify(sconfig);
+
+    hal::RegisterSensorObserver(hal::SENSOR_GAME_ROTATION_VECTOR, this);
+    hal::RegisterScreenConfigurationObserver(this);
+
+    mSensorState.Clear();
+
+    mTracking = true;
+  }
+}
+
+void
+VRDisplayProxyOrientationFallBack::StopSensorTracking()
+{
+  if (mTracking) {
+    hal::UnregisterScreenConfigurationObserver(this);
+    hal::UnregisterSensorObserver(hal::SENSOR_GAME_ROTATION_VECTOR, this);
+    mTracking = false;
+  }
+}
+
+// Android sends us events that have a 90-degree rotation about 
+// the x axis compared to what we want (phone flat vs. phone held in front of the eyes).
+// Correct for this by applying a transform to undo this rotation.
+void
+VRDisplayProxyOrientationFallBack::Notify(const hal::ScreenConfiguration& config)
+{
+  mOrient = config.orientation();
+
+  if (mOrient == dom::eScreenOrientation_LandscapePrimary) {
+    mScreenTransform = Quaternion(-0.5f, 0.5f, 0.5f, 0.5f);
+  } else if (mOrient == dom::eScreenOrientation_LandscapeSecondary) {
+    mScreenTransform = Quaternion(-0.5f, -0.5f, -0.5f, 0.5f);
+  } else if (mOrient == dom::eScreenOrientation_PortraitPrimary) {
+    mScreenTransform = Quaternion((float) -M_SQRT1_2, 0.f, 0.f, (float) M_SQRT1_2);
+  } else if (mOrient == dom::eScreenOrientation_PortraitSecondary) {
+    // Currently, PortraitSecondary event doesn't be triggered.
+    mScreenTransform = Quaternion((float) M_SQRT1_2, 0.f, 0.f, (float) M_SQRT1_2);
+  }
+}
+
+void
+VRDisplayProxyOrientationFallBack::Notify(const hal::SensorData& data)
+{
+  if (data.sensor() != hal::SENSOR_GAME_ROTATION_VECTOR)
+    return;
+
+  const nsTArray<float>& sensorValues = data.values();
+
+  // This is super chatty
+  //LOG("HMDInfoCardboard::Notify %f %f %f %f\n", sensorValues[0], sensorValues[1], sensorValues[2], sensorValues[3]);
+
+  mSavedLastSensor.Set(sensorValues[0], sensorValues[1], sensorValues[2], sensorValues[3]);
+  mSavedLastSensorTime = data.timestamp();
+  mNeedsSensorCompute = true;
+}
+
+void
+VRDisplayProxyOrientationFallBack::ZeroSensor()
+{
+  mSensorZeroInverse = mSavedLastSensor;
+  mSensorZeroInverse.Invert();
+}
+
+void
+VRDisplayProxyOrientationFallBack::ComputeStateFromLastSensor()
+{
+  if (!mNeedsSensorCompute)
+    return;
+
+  // apply the zero orientation
+  Quaternion q = mSensorZeroInverse * mSavedLastSensor;
+
+  // make a matrix from the quat
+  Matrix4x4 qm;
+  qm.SetRotationFromQuaternion(q);
+
+  // remap the coordinate space, based on the orientation
+  Matrix4x4 qmRemapped = RemapMatrixForOrientation(mOrient, qm);
+
+  // turn it back into a quat
+  q.SetFromRotationMatrix(qmRemapped);
+
+  // apply adjustment based on what's been done to the screen and the original zero
+  // position of the base coordinate space
+  q = mScreenTransform * q;
+
+  mSensorState.flags |= VRDisplayCapabilityFlags::Cap_Orientation;
+  mSensorState.flags |= VRDisplayCapabilityFlags::Cap_Present;
+  mSensorState.orientation[0] = q.x;
+  mSensorState.orientation[1] = q.y;
+  mSensorState.orientation[2] = q.z;
+  mSensorState.orientation[3] = q.w;
+
+  mSensorState.timestamp = mSavedLastSensorTime / 1000000.0;
+
+  mNeedsSensorCompute = false;
+}
+
+VRHMDSensorState
+VRDisplayProxyOrientationFallBack::GetSensorState()
+{
+  StartSensorTracking();
+  ComputeStateFromLastSensor();
+  return mSensorState;
+}
+
+VRHMDSensorState
+VRDisplayProxyOrientationFallBack::GetImmediateSensorState()
+{
+  // XXX TODO - Should return actual immediate sensor state
+  return GetSensorState();
+}
+
+} // namespace gfx
+} // namespace mozilla
+
new file mode 100644
--- /dev/null
+++ b/gfx/vr/VRDisplayProxyOrientationFallBack.h
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 20; 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/. */
+
+#ifndef GFX_VR_PROXY_ORIENTATION_FALLBACK_H
+#define GFX_VR_PROXY_ORIENTATION_FALLBACK_H
+
+#include "VRDisplayProxy.h"
+
+#include "mozilla/HalSensor.h"
+#include "mozilla/HalScreenConfiguration.h"
+
+namespace mozilla {
+namespace gfx {
+
+class VRDisplayProxyOrientationFallBack : public VRDisplayProxy
+                                       , public hal::ISensorObserver
+                                       , public hal::ScreenConfigurationObserver
+{
+public:
+
+  explicit VRDisplayProxyOrientationFallBack(const VRDisplayUpdate& aDeviceUpdate);
+
+  virtual void ZeroSensor() override;
+  virtual VRHMDSensorState GetSensorState() override;
+  virtual VRHMDSensorState GetImmediateSensorState() override;
+
+  // ISensorObserver interface
+  void Notify(const hal::SensorData& SensorData) override;
+  // ScreenConfigurationObserver interface
+  void Notify(const hal::ScreenConfiguration& ScreenConfiguration) override;
+
+
+protected:
+  virtual ~VRDisplayProxyOrientationFallBack();
+
+  void StartSensorTracking();
+  void StopSensorTracking();
+  void ComputeStateFromLastSensor();
+
+  uint32_t mOrient;
+  Quaternion mScreenTransform;
+  Quaternion mSensorZeroInverse;
+  Quaternion mSavedLastSensor;
+  double mSavedLastSensorTime;
+  bool mNeedsSensorCompute;    // if we need to compute the state from mSavedLastSensor
+
+  bool mTracking;
+};
+
+} // namespace gfx
+} // namespace mozilla
+
+#endif /* GFX_VR_PROXY_ORIENTATION_FALLBACK_H */
\ No newline at end of file
--- a/gfx/vr/VRManager.cpp
+++ b/gfx/vr/VRManager.cpp
@@ -3,17 +3,17 @@
  * 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 "VRManager.h"
 #include "VRManagerParent.h"
 #include "gfxVR.h"
 #include "mozilla/ClearOnShutdown.h"
-#include "mozilla/dom/VRDevice.h"
+#include "mozilla/dom/VRDisplay.h"
 #include "mozilla/unused.h"
 
 #include "gfxPrefs.h"
 #include "gfxVR.h"
 #if defined(XP_WIN)
 #include "gfxVROculus.h"
 #endif
 #if defined(XP_WIN) || defined(XP_MACOSX) || defined(XP_LINUX)
@@ -80,17 +80,17 @@ VRManager::~VRManager()
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mInitialized);
   MOZ_COUNT_DTOR(VRManager);
 }
 
 void
 VRManager::Destroy()
 {
-  mVRDevices.Clear();
+  mVRDisplays.Clear();
   for (uint32_t i = 0; i < mManagers.Length(); ++i) {
     mManagers[i]->Destroy();
   }
   mInitialized = false;
 }
 
 void
 VRManager::Init()
@@ -125,81 +125,81 @@ VRManager::RemoveVRManagerParent(VRManag
   if (mVRManagerParents.IsEmpty()) {
     Destroy();
   }
 }
 
 void
 VRManager::NotifyVsync(const TimeStamp& aVsyncTimestamp)
 {
-  for (auto iter = mVRDevices.Iter(); !iter.Done(); iter.Next()) {
+  for (auto iter = mVRDisplays.Iter(); !iter.Done(); iter.Next()) {
     gfx::VRHMDInfo* device = iter.UserData();
     device->NotifyVsync(aVsyncTimestamp);
   }
-  DispatchVRDeviceSensorUpdate();
+  DispatchVRDisplaySensorUpdate();
 }
 
 void
-VRManager::RefreshVRDevices()
+VRManager::RefreshVRDisplays()
 {
   nsTArray<RefPtr<gfx::VRHMDInfo> > devices;
 
   for (uint32_t i = 0; i < mManagers.Length(); ++i) {
     mManagers[i]->GetHMDs(devices);
   }
 
   bool deviceInfoChanged = false;
 
-  if (devices.Length() != mVRDevices.Count()) {
+  if (devices.Length() != mVRDisplays.Count()) {
     deviceInfoChanged = true;
   }
 
   for (const auto& device: devices) {
     RefPtr<VRHMDInfo> oldDevice = GetDevice(device->GetDeviceInfo().GetDeviceID());
     if (oldDevice == nullptr) {
       deviceInfoChanged = true;
       break;
     }
     if (oldDevice->GetDeviceInfo() != device->GetDeviceInfo()) {
       deviceInfoChanged = true;
       break;
     }
   }
 
   if (deviceInfoChanged) {
-    mVRDevices.Clear();
+    mVRDisplays.Clear();
     for (const auto& device: devices) {
-      mVRDevices.Put(device->GetDeviceInfo().GetDeviceID(), device);
+      mVRDisplays.Put(device->GetDeviceInfo().GetDeviceID(), device);
     }
   }
 
-  DispatchVRDeviceInfoUpdate();
+  DispatchVRDisplayInfoUpdate();
 }
 
 void
-VRManager::DispatchVRDeviceInfoUpdate()
+VRManager::DispatchVRDisplayInfoUpdate()
 {
-  nsTArray<VRDeviceUpdate> update;
-  for (auto iter = mVRDevices.Iter(); !iter.Done(); iter.Next()) {
+  nsTArray<VRDisplayUpdate> update;
+  for (auto iter = mVRDisplays.Iter(); !iter.Done(); iter.Next()) {
     gfx::VRHMDInfo* device = iter.UserData();
-    update.AppendElement(VRDeviceUpdate(device->GetDeviceInfo(),
+    update.AppendElement(VRDisplayUpdate(device->GetDeviceInfo(),
                                         device->GetSensorState()));
   }
 
   for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) {
     Unused << iter.Get()->GetKey()->SendUpdateDeviceInfo(update);
   }
 }
 
 void
-VRManager::DispatchVRDeviceSensorUpdate()
+VRManager::DispatchVRDisplaySensorUpdate()
 {
   nsTArray<VRSensorUpdate> update;
 
-  for (auto iter = mVRDevices.Iter(); !iter.Done(); iter.Next()) {
+  for (auto iter = mVRDisplays.Iter(); !iter.Done(); iter.Next()) {
     gfx::VRHMDInfo* device = iter.UserData();
     if (!device->GetDeviceInfo().GetUseMainThreadOrientation()) {
       update.AppendElement(VRSensorUpdate(device->GetDeviceInfo().GetDeviceID(),
                                           device->GetSensorState()));
     }
   }
   if (update.Length() > 0) {
     for (auto iter = mVRManagerParents.Iter(); !iter.Done(); iter.Next()) {
@@ -207,16 +207,16 @@ VRManager::DispatchVRDeviceSensorUpdate(
     }
   }
 }
 
 RefPtr<gfx::VRHMDInfo>
 VRManager::GetDevice(const uint32_t& aDeviceID)
 {
   RefPtr<gfx::VRHMDInfo> device;
-  if (mVRDevices.Get(aDeviceID, getter_AddRefs(device))) {
+  if (mVRDisplays.Get(aDeviceID, getter_AddRefs(device))) {
     return device;
   }
   return nullptr;
 }
 
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/vr/VRManager.h
+++ b/gfx/vr/VRManager.h
@@ -26,39 +26,39 @@ class VRManager
 public:
   static void ManagerInit();
   static VRManager* Get();
 
   void AddVRManagerParent(VRManagerParent* aVRManagerParent);
   void RemoveVRManagerParent(VRManagerParent* aVRManagerParent);
 
   void NotifyVsync(const TimeStamp& aVsyncTimestamp);
-  void RefreshVRDevices();
+  void RefreshVRDisplays();
   RefPtr<gfx::VRHMDInfo> GetDevice(const uint32_t& aDeviceID);
 
 protected:
   VRManager();
   ~VRManager();
 
 private:
 
   void Init();
   void Destroy();
 
-  void DispatchVRDeviceInfoUpdate();
-  void DispatchVRDeviceSensorUpdate();
+  void DispatchVRDisplayInfoUpdate();
+  void DispatchVRDisplaySensorUpdate();
 
   typedef nsTHashtable<nsRefPtrHashKey<VRManagerParent>> VRManagerParentSet;
   VRManagerParentSet mVRManagerParents;
 
   typedef nsTArray<RefPtr<VRHMDManager>> VRHMDManagerArray;
   VRHMDManagerArray mManagers;
 
   typedef nsRefPtrHashtable<nsUint32HashKey, gfx::VRHMDInfo> VRHMDInfoHashMap;
-  VRHMDInfoHashMap mVRDevices;
+  VRHMDInfoHashMap mVRDisplays;
 
   Atomic<bool> mInitialized;
 
 };
 
 } // namespace gfx
 } // namespace mozilla
 
--- a/gfx/vr/gfxVR.h
+++ b/gfx/vr/gfxVR.h
@@ -27,24 +27,48 @@ namespace gfx {
 
 enum class VRHMDType : uint16_t {
   Oculus,
   Cardboard,
   Oculus050,
   NumHMDTypes
 };
 
-enum class VRStateValidFlags : uint16_t {
-  State_None = 0,
-  State_Position = 1 << 1,
-  State_Orientation = 1 << 2,
-  // State_All used for validity checking during IPC serialization
-  State_All = (1 << 3) - 1
+enum class VRDisplayCapabilityFlags : uint16_t {
+  Cap_None = 0,
+  /**
+   * Cap_Position is set if the VRDisplay is capable of tracking its position.
+   */
+  Cap_Position = 1 << 1,
+  /**
+    * Cap_Orientation is set if the VRDisplay is capable of tracking its orientation.
+    */
+  Cap_Orientation = 1 << 2,
+  /**
+   * Cap_Present is set if the VRDisplay is capable of presenting content to an
+   * HMD or similar device.  Can be used to indicate “magic window” devices that
+   * are capable of 6DoF tracking but for which requestPresent is not meaningful.
+   * If false then calls to requestPresent should always fail, and
+   * getEyeParameters should return null.
+   */
+  Cap_Present = 1 << 3,
+  /**
+   * Cap_External is set if the VRDisplay is separate from the device’s
+   * primary display. If presenting VR content will obscure
+   * other content on the device, this should be un-set. When
+   * un-set, the application should not attempt to mirror VR content
+   * or update non-VR UI because that content will not be visible.
+   */
+  Cap_External = 1 << 4,
+  /**
+   * Cap_All used for validity checking during IPC serialization
+   */
+  Cap_All = (1 << 5) - 1
 };
-MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(VRStateValidFlags)
+MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(VRDisplayCapabilityFlags)
 
 struct VRFieldOfView {
   VRFieldOfView() {}
   VRFieldOfView(double up, double right, double down, double left)
     : upDegrees(up), rightDegrees(right), downDegrees(down), leftDegrees(left)
   {}
 
   bool operator==(const VRFieldOfView& other) const {
@@ -84,22 +108,22 @@ struct VRDistortionMesh {
 
 // 12 floats per vertex. Position, tex coordinates
 // for each channel, and 4 generic attributes
 struct VRDistortionConstants {
   float eyeToSourceScaleAndOffset[4];
   float destinationScaleAndOffset[4];
 };
 
-struct VRDeviceInfo
+struct VRDisplayInfo
 {
   VRHMDType GetType() const { return mType; }
   uint32_t GetDeviceID() const { return mDeviceID; }
   const nsCString& GetDeviceName() const { return mDeviceName; }
-  VRStateValidFlags GetSupportedSensorStateBits() const { return mSupportedSensorBits; }
+  VRDisplayCapabilityFlags GetCapabilities() const { return mCapabilityFlags; }
   const VRFieldOfView& GetRecommendedEyeFOV(uint32_t whichEye) const { return mRecommendedEyeFOV[whichEye]; }
   const VRFieldOfView& GetMaximumEyeFOV(uint32_t whichEye) const { return mMaximumEyeFOV[whichEye]; }
 
   const IntSize& SuggestedEyeResolution() const { return mEyeResolution; }
   const Point3D& GetEyeTranslation(uint32_t whichEye) const { return mEyeTranslation[whichEye]; }
   const Matrix4x4& GetEyeProjectionMatrix(uint32_t whichEye) const { return mEyeProjectionMatrix[whichEye]; }
   const VRFieldOfView& GetEyeFOV(uint32_t whichEye) const { return mEyeFOV[whichEye]; }
   bool GetUseMainThreadOrientation() const { return mUseMainThreadOrientation; }
@@ -108,66 +132,66 @@ struct VRDeviceInfo
     Eye_Left,
     Eye_Right,
     NumEyes
   };
 
   uint32_t mDeviceID;
   VRHMDType mType;
   nsCString mDeviceName;
-  VRStateValidFlags mSupportedSensorBits;
-  VRFieldOfView mMaximumEyeFOV[VRDeviceInfo::NumEyes];
-  VRFieldOfView mRecommendedEyeFOV[VRDeviceInfo::NumEyes];
-  VRFieldOfView mEyeFOV[VRDeviceInfo::NumEyes];
-  Point3D mEyeTranslation[VRDeviceInfo::NumEyes];
-  Matrix4x4 mEyeProjectionMatrix[VRDeviceInfo::NumEyes];
+  VRDisplayCapabilityFlags mCapabilityFlags;
+  VRFieldOfView mMaximumEyeFOV[VRDisplayInfo::NumEyes];
+  VRFieldOfView mRecommendedEyeFOV[VRDisplayInfo::NumEyes];
+  VRFieldOfView mEyeFOV[VRDisplayInfo::NumEyes];
+  Point3D mEyeTranslation[VRDisplayInfo::NumEyes];
+  Matrix4x4 mEyeProjectionMatrix[VRDisplayInfo::NumEyes];
   /* Suggested resolution for rendering a single eye.
    * Assumption is that left/right rendering will be 2x of this size.
    * XXX fix this for vertical displays
    */
   IntSize mEyeResolution;
   IntRect mScreenRect;
 
   bool mIsFakeScreen;
   bool mUseMainThreadOrientation;
 
 
 
-  bool operator==(const VRDeviceInfo& other) const {
+  bool operator==(const VRDisplayInfo& other) const {
     return mType == other.mType &&
            mDeviceID == other.mDeviceID &&
            mDeviceName == other.mDeviceName &&
-           mSupportedSensorBits == other.mSupportedSensorBits &&
+           mCapabilityFlags == other.mCapabilityFlags &&
            mEyeResolution == other.mEyeResolution &&
            mScreenRect == other.mScreenRect &&
            mIsFakeScreen == other.mIsFakeScreen &&
            mUseMainThreadOrientation == other.mUseMainThreadOrientation &&
            mMaximumEyeFOV[0] == other.mMaximumEyeFOV[0] &&
            mMaximumEyeFOV[1] == other.mMaximumEyeFOV[1] &&
            mRecommendedEyeFOV[0] == other.mRecommendedEyeFOV[0] &&
            mRecommendedEyeFOV[1] == other.mRecommendedEyeFOV[1] &&
            mEyeFOV[0] == other.mEyeFOV[0] &&
            mEyeFOV[1] == other.mEyeFOV[1] &&
            mEyeTranslation[0] == other.mEyeTranslation[0] &&
            mEyeTranslation[1] == other.mEyeTranslation[1] &&
            mEyeProjectionMatrix[0] == other.mEyeProjectionMatrix[0] &&
            mEyeProjectionMatrix[1] == other.mEyeProjectionMatrix[1];
   }
 
-  bool operator!=(const VRDeviceInfo& other) const {
+  bool operator!=(const VRDisplayInfo& other) const {
     return !(*this == other);
   }
 };
 
 
 
 struct VRHMDSensorState {
   double timestamp;
   int32_t inputFrameID;
-  VRStateValidFlags flags;
+  VRDisplayCapabilityFlags flags;
   float orientation[4];
   float position[3];
   float angularVelocity[3];
   float angularAcceleration[3];
   float linearVelocity[3];
   float linearAcceleration[3];
 
   void Clear() {
@@ -180,24 +204,24 @@ struct VRSensorUpdate {
   VRSensorUpdate(uint32_t aDeviceID, const VRHMDSensorState& aSensorState)
    : mDeviceID(aDeviceID)
    , mSensorState(aSensorState) { };
 
   uint32_t mDeviceID;
   VRHMDSensorState mSensorState;
 };
 
-struct VRDeviceUpdate {
-  VRDeviceUpdate() { }; // Required for ipdl binding
-  VRDeviceUpdate(const VRDeviceInfo& aDeviceInfo,
+struct VRDisplayUpdate {
+  VRDisplayUpdate() { }; // Required for ipdl binding
+  VRDisplayUpdate(const VRDisplayInfo& aDeviceInfo,
                  const VRHMDSensorState& aSensorState)
    : mDeviceInfo(aDeviceInfo)
    , mSensorState(aSensorState) { };
 
-  VRDeviceInfo mDeviceInfo;
+  VRDisplayInfo mDeviceInfo;
   VRHMDSensorState mSensorState;
 };
 
 /* A pure data struct that can be used to see if
  * the configuration of one HMDInfo matches another; for rendering purposes,
  * really asking "can the rendering details of this one be used for the other"
  */
 struct VRHMDConfiguration {
@@ -251,17 +275,17 @@ protected:
 };
 
 class VRHMDInfo {
 
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRHMDInfo)
 
   const VRHMDConfiguration& GetConfiguration() const { return mConfiguration; }
-  const VRDeviceInfo& GetDeviceInfo() const { return mDeviceInfo; }
+  const VRDisplayInfo& GetDeviceInfo() const { return mDeviceInfo; }
 
   /* set the FOV for this HMD unit; this triggers a computation of all the remaining bits.  Returns false if it fails */
   virtual bool SetFOV(const VRFieldOfView& aFOVLeft, const VRFieldOfView& aFOVRight,
                       double zNear, double zFar) = 0;
 
   virtual bool KeepSensorTracking() = 0;
   virtual void NotifyVsync(const TimeStamp& aVsyncTimestamp) = 0;
   virtual VRHMDSensorState GetSensorState() = 0;
@@ -281,18 +305,18 @@ public:
                                        VRDistortionConstants& values) = 0;
 
   const VRDistortionMesh& GetDistortionMesh(uint32_t whichEye) const { return mDistortionMesh[whichEye]; }
 protected:
   explicit VRHMDInfo(VRHMDType aType, bool aUseMainThreadOrientation);
   virtual ~VRHMDInfo();
 
   VRHMDConfiguration mConfiguration;
-  VRDeviceInfo mDeviceInfo;
-  VRDistortionMesh mDistortionMesh[VRDeviceInfo::NumEyes];
+  VRDisplayInfo mDeviceInfo;
+  VRDistortionMesh mDistortionMesh[VRDisplayInfo::NumEyes];
 };
 
 class VRHMDManager {
 public:
   static uint32_t AllocateDeviceID();
 
 protected:
   static Atomic<uint32_t> sDeviceBase;
--- a/gfx/vr/gfxVRCardboard.cpp
+++ b/gfx/vr/gfxVRCardboard.cpp
@@ -27,56 +27,57 @@ HMDInfoCardboard::HMDInfoCardboard()
 {
   MOZ_ASSERT(sizeof(HMDInfoCardboard::DistortionVertex) == sizeof(VRDistortionVertex),
              "HMDInfoCardboard::DistortionVertex must match the size of VRDistortionVertex");
 
   MOZ_COUNT_CTOR_INHERITED(HMDInfoCardboard, VRHMDInfo);
 
   mDeviceInfo.mDeviceName.AssignLiteral("Phone Sensor (Cardboard) HMD");
 
-  mDeviceInfo.mSupportedSensorBits = VRStateValidFlags::State_Orientation;
-
-  mDeviceInfo.mRecommendedEyeFOV[VRDeviceInfo::Eye_Left] = gfx::VRFieldOfView(45.0, 45.0, 45.0, 45.0);
-  mDeviceInfo.mRecommendedEyeFOV[VRDeviceInfo::Eye_Right] = gfx::VRFieldOfView(45.0, 45.0, 45.0, 45.0);
+  mDeviceInfo.mCapabilityFlags = VRDisplayCapabilityFlags::Cap_Orientation;
+  mDeviceInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_Present;
 
-  mDeviceInfo.mMaximumEyeFOV[VRDeviceInfo::Eye_Left] = gfx::VRFieldOfView(45.0, 45.0, 45.0, 45.0);
-  mDeviceInfo.mMaximumEyeFOV[VRDeviceInfo::Eye_Right] = gfx::VRFieldOfView(45.0, 45.0, 45.0, 45.0);
+  mDeviceInfo.mRecommendedEyeFOV[VRDisplayInfo::Eye_Left] = gfx::VRFieldOfView(45.0, 45.0, 45.0, 45.0);
+  mDeviceInfo.mRecommendedEyeFOV[VRDisplayInfo::Eye_Right] = gfx::VRFieldOfView(45.0, 45.0, 45.0, 45.0);
 
-  SetFOV(mDeviceInfo.mRecommendedEyeFOV[VRDeviceInfo::Eye_Left], mDeviceInfo.mRecommendedEyeFOV[VRDeviceInfo::Eye_Right], 0.01, 10000.0);
+  mDeviceInfo.mMaximumEyeFOV[VRDisplayInfo::Eye_Left] = gfx::VRFieldOfView(45.0, 45.0, 45.0, 45.0);
+  mDeviceInfo.mMaximumEyeFOV[VRDisplayInfo::Eye_Right] = gfx::VRFieldOfView(45.0, 45.0, 45.0, 45.0);
+
+  SetFOV(mDeviceInfo.mRecommendedEyeFOV[VRDisplayInfo::Eye_Left], mDeviceInfo.mRecommendedEyeFOV[VRDisplayInfo::Eye_Right], 0.01, 10000.0);
 
   mDeviceInfo.mScreenRect.x = 0;
   mDeviceInfo.mScreenRect.y = 0;
   mDeviceInfo.mScreenRect.width = 1920;
   mDeviceInfo.mScreenRect.height = 1080;
   mDeviceInfo.mIsFakeScreen = true;
 }
 
 
 VRHMDSensorState
 HMDInfoCardboard::GetSensorState()
 {
   // Actual sensor state is calculated on the main thread,
-  // within VRDeviceProxyOrientationFallBack
+  // within VRDisplayProxyOrientationFallBack
   VRHMDSensorState result;
   result.Clear();
   return result;
 }
 
 VRHMDSensorState
 HMDInfoCardboard::GetImmediateSensorState()
 {
   return GetSensorState();
 }
 
 
 void
 HMDInfoCardboard::ZeroSensor()
 {
   MOZ_ASSERT(0, "HMDInfoCardboard::ZeroSensor not implemented.  "
-                "Should use VRDeviceProxyOrientationFallBack on main thread");
+                "Should use VRDisplayProxyOrientationFallBack on main thread");
 }
 
 
 void
 HMDInfoCardboard::NotifyVsync(const TimeStamp& aVsyncTimestamp)
 {
   // Nothing to do here for Cardboard VR
 }
@@ -90,27 +91,27 @@ HMDInfoCardboard::KeepSensorTracking()
 
 bool
 HMDInfoCardboard::SetFOV(const gfx::VRFieldOfView& aFOVLeft,
                          const gfx::VRFieldOfView& aFOVRight,
                          double zNear, double zFar)
 {
   const float standardIPD = 0.064f;
 
-  for (uint32_t eye = 0; eye < VRDeviceInfo::NumEyes; eye++) {
-    mDeviceInfo.mEyeFOV[eye] = eye == VRDeviceInfo::Eye_Left ? aFOVLeft : aFOVRight;
-    mDeviceInfo.mEyeTranslation[eye] = Point3D(standardIPD * (eye == VRDeviceInfo::Eye_Left ? -1.0 : 1.0), 0.0, 0.0);
+  for (uint32_t eye = 0; eye < VRDisplayInfo::NumEyes; eye++) {
+    mDeviceInfo.mEyeFOV[eye] = eye == VRDisplayInfo::Eye_Left ? aFOVLeft : aFOVRight;
+    mDeviceInfo.mEyeTranslation[eye] = Point3D(standardIPD * (eye == VRDisplayInfo::Eye_Left ? -1.0 : 1.0), 0.0, 0.0);
     mDeviceInfo.mEyeProjectionMatrix[eye] = mDeviceInfo.mEyeFOV[eye].ConstructProjectionMatrix(zNear, zFar, true);
 
     mDistortionMesh[eye].mVertices.SetLength(4);
     mDistortionMesh[eye].mIndices.SetLength(6);
 
     HMDInfoCardboard::DistortionVertex *destv = reinterpret_cast<HMDInfoCardboard::DistortionVertex*>(mDistortionMesh[eye].mVertices.Elements());
-    float xoffs = eye == VRDeviceInfo::Eye_Left ? 0.0f : 1.0f;
-    float txoffs = eye == VRDeviceInfo::Eye_Left ? 0.0f : 0.5f;
+    float xoffs = eye == VRDisplayInfo::Eye_Left ? 0.0f : 1.0f;
+    float txoffs = eye == VRDisplayInfo::Eye_Left ? 0.0f : 0.5f;
     destv[0].pos[0] = -1.0 + xoffs;
     destv[0].pos[1] = -1.0;
     destv[0].texR[0] = destv[0].texG[0] = destv[0].texB[0] = 0.0 + txoffs;
     destv[0].texR[1] = destv[0].texG[1] = destv[0].texB[1] = 1.0;
     destv[0].padding[0] = 1.0; // vignette factor
 
     destv[1].pos[0] = 0.0 + xoffs;
     destv[1].pos[1] = -1.0;
--- a/gfx/vr/gfxVROculus.cpp
+++ b/gfx/vr/gfxVROculus.cpp
@@ -234,39 +234,41 @@ HMDInfoOculus::HMDInfoOculus(ovrSession 
              "HMDInfoOculus::DistortionVertex must match the size of VRDistortionVertex");
 
   MOZ_COUNT_CTOR_INHERITED(HMDInfoOculus, VRHMDInfo);
 
   mDeviceInfo.mDeviceName.AssignLiteral("Oculus VR HMD");
 
   mDesc = ovr_GetHmdDesc(aSession);
 
-  mDeviceInfo.mSupportedSensorBits = VRStateValidFlags::State_None;
+  mDeviceInfo.mCapabilityFlags = VRDisplayCapabilityFlags::Cap_None;
   if (mDesc.AvailableTrackingCaps & ovrTrackingCap_Orientation) {
-    mDeviceInfo.mSupportedSensorBits |= VRStateValidFlags::State_Orientation;
+    mDeviceInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_Orientation;
   }
   if (mDesc.AvailableTrackingCaps & ovrTrackingCap_Position) {
-    mDeviceInfo.mSupportedSensorBits |= VRStateValidFlags::State_Position;
+    mDeviceInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_Position;
   }
+  mDeviceInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_External;
+  mDeviceInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_Present;
 
-  mDeviceInfo.mRecommendedEyeFOV[VRDeviceInfo::Eye_Left] = FromFovPort(mDesc.DefaultEyeFov[ovrEye_Left]);
-  mDeviceInfo.mRecommendedEyeFOV[VRDeviceInfo::Eye_Right] = FromFovPort(mDesc.DefaultEyeFov[ovrEye_Right]);
+  mDeviceInfo.mRecommendedEyeFOV[VRDisplayInfo::Eye_Left] = FromFovPort(mDesc.DefaultEyeFov[ovrEye_Left]);
+  mDeviceInfo.mRecommendedEyeFOV[VRDisplayInfo::Eye_Right] = FromFovPort(mDesc.DefaultEyeFov[ovrEye_Right]);
 
-  mDeviceInfo.mMaximumEyeFOV[VRDeviceInfo::Eye_Left] = FromFovPort(mDesc.MaxEyeFov[ovrEye_Left]);
-  mDeviceInfo.mMaximumEyeFOV[VRDeviceInfo::Eye_Right] = FromFovPort(mDesc.MaxEyeFov[ovrEye_Right]);
+  mDeviceInfo.mMaximumEyeFOV[VRDisplayInfo::Eye_Left] = FromFovPort(mDesc.MaxEyeFov[ovrEye_Left]);
+  mDeviceInfo.mMaximumEyeFOV[VRDisplayInfo::Eye_Right] = FromFovPort(mDesc.MaxEyeFov[ovrEye_Right]);
 
   uint32_t w = mDesc.Resolution.w;
   uint32_t h = mDesc.Resolution.h;
   mDeviceInfo.mScreenRect.x = 0;
   mDeviceInfo.mScreenRect.y = 0;
   mDeviceInfo.mScreenRect.width = std::max(w, h);
   mDeviceInfo.mScreenRect.height = std::min(w, h);
   mDeviceInfo.mIsFakeScreen = true;
 
-  SetFOV(mDeviceInfo.mRecommendedEyeFOV[VRDeviceInfo::Eye_Left], mDeviceInfo.mRecommendedEyeFOV[VRDeviceInfo::Eye_Right], 0.01, 10000.0);
+  SetFOV(mDeviceInfo.mRecommendedEyeFOV[VRDisplayInfo::Eye_Left], mDeviceInfo.mRecommendedEyeFOV[VRDisplayInfo::Eye_Right], 0.01, 10000.0);
 
   for (int i = 0; i < kMaxLatencyFrames; i++) {
     mLastSensorState[i].Clear();
   }
 }
 
 void
 HMDInfoOculus::Destroy()
@@ -280,34 +282,34 @@ HMDInfoOculus::Destroy()
 bool
 HMDInfoOculus::SetFOV(const gfx::VRFieldOfView& aFOVLeft, const gfx::VRFieldOfView& aFOVRight,
                       double zNear, double zFar)
 {
   float pixelsPerDisplayPixel = 1.0;
   ovrSizei texSize[2];
 
   // get eye parameters and create the mesh
-  for (uint32_t eye = 0; eye < VRDeviceInfo::NumEyes; eye++) {
+  for (uint32_t eye = 0; eye < VRDisplayInfo::NumEyes; eye++) {
     mDeviceInfo.mEyeFOV[eye] = eye == 0 ? aFOVLeft : aFOVRight;
     mFOVPort[eye] = ToFovPort(mDeviceInfo.mEyeFOV[eye]);
 
     ovrEyeRenderDesc renderDesc = ovr_GetRenderDesc(mSession, (ovrEyeType)eye, mFOVPort[eye]);
 
     // As of Oculus 0.6.0, the HmdToEyeViewOffset values are correct and don't need to be negated.
     mDeviceInfo.mEyeTranslation[eye] = Point3D(renderDesc.HmdToEyeViewOffset.x, renderDesc.HmdToEyeViewOffset.y, renderDesc.HmdToEyeViewOffset.z);
 
     // note that we are using a right-handed coordinate system here, to match CSS
     mDeviceInfo.mEyeProjectionMatrix[eye] = mDeviceInfo.mEyeFOV[eye].ConstructProjectionMatrix(zNear, zFar, true);
 
     texSize[eye] = ovr_GetFovTextureSize(mSession, (ovrEyeType)eye, mFOVPort[eye], pixelsPerDisplayPixel);
   }
 
   // take the max of both for eye resolution
-  mDeviceInfo.mEyeResolution.width = std::max(texSize[VRDeviceInfo::Eye_Left].w, texSize[VRDeviceInfo::Eye_Right].w);
-  mDeviceInfo.mEyeResolution.height = std::max(texSize[VRDeviceInfo::Eye_Left].h, texSize[VRDeviceInfo::Eye_Right].h);
+  mDeviceInfo.mEyeResolution.width = std::max(texSize[VRDisplayInfo::Eye_Left].w, texSize[VRDisplayInfo::Eye_Right].w);
+  mDeviceInfo.mEyeResolution.height = std::max(texSize[VRDisplayInfo::Eye_Left].h, texSize[VRDisplayInfo::Eye_Right].h);
 
   mConfiguration.hmdType = mDeviceInfo.mType;
   mConfiguration.value = 0;
   mConfiguration.fov[0] = aFOVLeft;
   mConfiguration.fov[1] = aFOVRight;
 
   return true;
 }
@@ -368,47 +370,49 @@ HMDInfoOculus::GetSensorState(double tim
   result.Clear();
 
   ovrTrackingState state = ovr_GetTrackingState(mSession, timeOffset, true);
   ovrPoseStatef& pose(state.HeadPose);
 
   result.timestamp = pose.TimeInSeconds;
 
   if (state.StatusFlags & ovrStatus_OrientationTracked) {
-    result.flags |= VRStateValidFlags::State_Orientation;
+    result.flags |= VRDisplayCapabilityFlags::Cap_Orientation;
 
     result.orientation[0] = pose.ThePose.Orientation.x;
     result.orientation[1] = pose.ThePose.Orientation.y;
     result.orientation[2] = pose.ThePose.Orientation.z;
     result.orientation[3] = pose.ThePose.Orientation.w;
     
     result.angularVelocity[0] = pose.AngularVelocity.x;
     result.angularVelocity[1] = pose.AngularVelocity.y;
     result.angularVelocity[2] = pose.AngularVelocity.z;
 
     result.angularAcceleration[0] = pose.AngularAcceleration.x;
     result.angularAcceleration[1] = pose.AngularAcceleration.y;
     result.angularAcceleration[2] = pose.AngularAcceleration.z;
   }
 
   if (state.StatusFlags & ovrStatus_PositionTracked) {
-    result.flags |= VRStateValidFlags::State_Position;
+    result.flags |= VRDisplayCapabilityFlags::Cap_Position;
 
     result.position[0] = pose.ThePose.Position.x;
     result.position[1] = pose.ThePose.Position.y;
     result.position[2] = pose.ThePose.Position.z;
     
     result.linearVelocity[0] = pose.LinearVelocity.x;
     result.linearVelocity[1] = pose.LinearVelocity.y;
     result.linearVelocity[2] = pose.LinearVelocity.z;
 
     result.linearAcceleration[0] = pose.LinearAcceleration.x;
     result.linearAcceleration[1] = pose.LinearAcceleration.y;
     result.linearAcceleration[2] = pose.LinearAcceleration.z;
   }
+  result.flags |= VRDisplayCapabilityFlags::Cap_External;
+  result.flags |= VRDisplayCapabilityFlags::Cap_Present;
   
   return result;
 }
 
 struct RenderTargetSetOculus : public VRHMDRenderingSupport::RenderTargetSet
 {
   RenderTargetSetOculus(const IntSize& aSize,
                         HMDInfoOculus *aHMD,
--- a/gfx/vr/gfxVROculus050.cpp
+++ b/gfx/vr/gfxVROculus050.cpp
@@ -251,37 +251,39 @@ HMDInfoOculus050::HMDInfoOculus050(ovrHm
   MOZ_COUNT_CTOR_INHERITED(HMDInfoOculus050, VRHMDInfo);
 
   if (aDebug) {
     mDeviceInfo.mDeviceName.AssignLiteral("Oculus VR HMD (0.5.0 Debug)");
   } else {
     mDeviceInfo.mDeviceName.AssignLiteral("Oculus VR HMD (0.5.0)");
   }
 
-  mDeviceInfo.mSupportedSensorBits = VRStateValidFlags::State_None;
+  mDeviceInfo.mCapabilityFlags = VRDisplayCapabilityFlags::Cap_None;
   if (mHMD->TrackingCaps & ovrTrackingCap_Orientation) {
-    mDeviceInfo.mSupportedSensorBits |= VRStateValidFlags::State_Orientation;
+    mDeviceInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_Orientation;
   }
   if (mHMD->TrackingCaps & ovrTrackingCap_Position) {
-    mDeviceInfo.mSupportedSensorBits |= VRStateValidFlags::State_Position;
+    mDeviceInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_Position;
   }
+  mDeviceInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_External;
+  mDeviceInfo.mCapabilityFlags |= VRDisplayCapabilityFlags::Cap_Present;
 
-  mDeviceInfo.mRecommendedEyeFOV[VRDeviceInfo::Eye_Left] = FromFovPort(mHMD->DefaultEyeFov[ovrEye_Left]);
-  mDeviceInfo.mRecommendedEyeFOV[VRDeviceInfo::Eye_Right] = FromFovPort(mHMD->DefaultEyeFov[ovrEye_Right]);
+  mDeviceInfo.mRecommendedEyeFOV[VRDisplayInfo::Eye_Left] = FromFovPort(mHMD->DefaultEyeFov[ovrEye_Left]);
+  mDeviceInfo.mRecommendedEyeFOV[VRDisplayInfo::Eye_Right] = FromFovPort(mHMD->DefaultEyeFov[ovrEye_Right]);
 
-  mDeviceInfo.mMaximumEyeFOV[VRDeviceInfo::Eye_Left] = FromFovPort(mHMD->MaxEyeFov[ovrEye_Left]);
-  mDeviceInfo.mMaximumEyeFOV[VRDeviceInfo::Eye_Right] = FromFovPort(mHMD->MaxEyeFov[ovrEye_Right]);
+  mDeviceInfo.mMaximumEyeFOV[VRDisplayInfo::Eye_Left] = FromFovPort(mHMD->MaxEyeFov[ovrEye_Left]);
+  mDeviceInfo.mMaximumEyeFOV[VRDisplayInfo::Eye_Right] = FromFovPort(mHMD->MaxEyeFov[ovrEye_Right]);
 
   mDeviceInfo.mScreenRect.x = mHMD->WindowsPos.x;
   mDeviceInfo.mScreenRect.y = mHMD->WindowsPos.y;
   mDeviceInfo.mScreenRect.width = mHMD->Resolution.w;
   mDeviceInfo.mScreenRect.height = mHMD->Resolution.h;
   mDeviceInfo.mIsFakeScreen = false;
 
-  SetFOV(mDeviceInfo.mRecommendedEyeFOV[VRDeviceInfo::Eye_Left], mDeviceInfo.mRecommendedEyeFOV[VRDeviceInfo::Eye_Right], 0.01, 10000.0);
+  SetFOV(mDeviceInfo.mRecommendedEyeFOV[VRDisplayInfo::Eye_Left], mDeviceInfo.mRecommendedEyeFOV[VRDisplayInfo::Eye_Right], 0.01, 10000.0);
 }
 
 bool
 HMDInfoOculus050::GetIsDebug() const
 {
   return mDebug;
 }
 
@@ -307,17 +309,17 @@ HMDInfoOculus050::SetFOV(const VRFieldOf
                       double zNear, double zFar)
 {
   float pixelsPerDisplayPixel = 1.0;
   ovrSizei texSize[2];
 
   uint32_t caps = ovrDistortionCap_Chromatic | ovrDistortionCap_Vignette; // XXX TODO add TimeWarp
 
   // get eye parameters and create the mesh
-  for (uint32_t eye = 0; eye < VRDeviceInfo::NumEyes; eye++) {
+  for (uint32_t eye = 0; eye < VRDisplayInfo::NumEyes; eye++) {
     mDeviceInfo.mEyeFOV[eye] = eye == 0 ? aFOVLeft : aFOVRight;
     mFOVPort[eye] = ToFovPort(mDeviceInfo.mEyeFOV[eye]);
 
     ovrEyeRenderDesc renderDesc = ovrHmd_GetRenderDesc(mHMD, (ovrEyeType) eye, mFOVPort[eye]);
 
     // these values are negated so that content can add the adjustment to its camera position,
     // instead of subtracting
     mDeviceInfo.mEyeTranslation[eye] = Point3D(-renderDesc.HmdToEyeViewOffset.x, -renderDesc.HmdToEyeViewOffset.y, -renderDesc.HmdToEyeViewOffset.z);
@@ -353,18 +355,18 @@ HMDInfoOculus050::SetFOV(const VRFieldOf
       destv[i].genericAttribs[1] = srcv[i].TimeWarpFactor;
     }
 
     memcpy(mDistortionMesh[eye].mIndices.Elements(), mesh.pIndexData, mesh.IndexCount * sizeof(uint16_t));
     ovrHmd_DestroyDistortionMesh(&mesh);
   }
 
   // take the max of both for eye resolution
-  mDeviceInfo.mEyeResolution.width = std::max(texSize[VRDeviceInfo::Eye_Left].w, texSize[VRDeviceInfo::Eye_Right].w);
-  mDeviceInfo.mEyeResolution.height = std::max(texSize[VRDeviceInfo::Eye_Left].h, texSize[VRDeviceInfo::Eye_Right].h);
+  mDeviceInfo.mEyeResolution.width = std::max(texSize[VRDisplayInfo::Eye_Left].w, texSize[VRDisplayInfo::Eye_Right].w);
+  mDeviceInfo.mEyeResolution.height = std::max(texSize[VRDisplayInfo::Eye_Left].h, texSize[VRDisplayInfo::Eye_Right].h);
 
   mConfiguration.hmdType = mDeviceInfo.mType;
   mConfiguration.value = 0;
   mConfiguration.fov[0] = aFOVLeft;
   mConfiguration.fov[1] = aFOVRight;
 
   return true;
 }
@@ -476,48 +478,51 @@ HMDInfoOculus050::GetSensorState()
   // XXX this is the wrong time base for timeOffset; we need to figure out how to synchronize
   // the Oculus time base and the browser one.
   ovrTrackingState state = ovrHmd_GetTrackingState(mHMD, ovr_GetTimeInSeconds());
   ovrPoseStatef& pose(state.HeadPose);
 
   result.timestamp = pose.TimeInSeconds;
 
   if (state.StatusFlags & ovrStatus_OrientationTracked) {
-    result.flags |= VRStateValidFlags::State_Orientation;
+    result.flags |= VRDisplayCapabilityFlags::Cap_Orientation;
 
     result.orientation[0] = pose.ThePose.Orientation.x;
     result.orientation[1] = pose.ThePose.Orientation.y;
     result.orientation[2] = pose.ThePose.Orientation.z;
     result.orientation[3] = pose.ThePose.Orientation.w;
     
     result.angularVelocity[0] = pose.AngularVelocity.x;
     result.angularVelocity[1] = pose.AngularVelocity.y;
     result.angularVelocity[2] = pose.AngularVelocity.z;
 
     result.angularAcceleration[0] = pose.AngularAcceleration.x;
     result.angularAcceleration[1] = pose.AngularAcceleration.y;
     result.angularAcceleration[2] = pose.AngularAcceleration.z;
   }
 
   if (state.StatusFlags & ovrStatus_PositionTracked) {
-    result.flags |= VRStateValidFlags::State_Position;
+    result.flags |= VRDisplayCapabilityFlags::Cap_Position;
 
     result.position[0] = pose.ThePose.Position.x;
     result.position[1] = pose.ThePose.Position.y;
     result.position[2] = pose.ThePose.Position.z;
     
     result.linearVelocity[0] = pose.LinearVelocity.x;
     result.linearVelocity[1] = pose.LinearVelocity.y;
     result.linearVelocity[2] = pose.LinearVelocity.z;
 
     result.linearAcceleration[0] = pose.LinearAcceleration.x;
     result.linearAcceleration[1] = pose.LinearAcceleration.y;
     result.linearAcceleration[2] = pose.LinearAcceleration.z;
   }
 
+  result.flags |= VRDisplayCapabilityFlags::Cap_External;
+  result.flags |= VRDisplayCapabilityFlags::Cap_Present;
+
   return result;
 }
 
 /*static*/ already_AddRefed<VRHMDManagerOculus050>
 VRHMDManagerOculus050::Create()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
--- a/gfx/vr/ipc/PVRManager.ipdl
+++ b/gfx/vr/ipc/PVRManager.ipdl
@@ -3,17 +3,17 @@
  */
 /* 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 "VRMessageUtils.h";
 
 using struct mozilla::gfx::VRFieldOfView from "gfxVR.h";
-using struct mozilla::gfx::VRDeviceUpdate from "gfxVR.h";
+using struct mozilla::gfx::VRDisplayUpdate from "gfxVR.h";
 using struct mozilla::gfx::VRSensorUpdate from "gfxVR.h";
 
 namespace mozilla {
 namespace gfx {
 
 /**
  * The PVRManager protocol is used to enable communication of VR device
  * enumeration and sensor state between the compositor thread and
@@ -43,17 +43,17 @@ parent:
                VRFieldOfView aFOVRight, double zNear, double zFar);
 
 child:
 
   // Notify children of updated VR device enumeration and details.  This will
   // be sent to all children when the parent receives RefreshDevices, even
   // if no changes have been detected.  This ensures that Promises exposed
   // through DOM calls are always resolved.
-  async UpdateDeviceInfo(VRDeviceUpdate[] aDeviceUpdates);
+  async UpdateDeviceInfo(VRDisplayUpdate[] aDeviceUpdates);
 
   // Notify children of updated VR device sensor states.  This will be
   // sent once per frame for at least one second after the parent receives
   // KeepSensorTracking.
   async UpdateDeviceSensors(VRSensorUpdate[] aDeviceSensorUpdates);
 
   async __delete__();
 
--- a/gfx/vr/ipc/VRManagerChild.cpp
+++ b/gfx/vr/ipc/VRManagerChild.cpp
@@ -2,18 +2,18 @@
  * vim: sw=2 ts=8 et :
  */
 /* 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 "VRManagerChild.h"
 #include "VRManagerParent.h"
-#include "VRDeviceProxy.h"
-#include "VRDeviceProxyOrientationFallBack.h"
+#include "VRDisplayProxy.h"
+#include "VRDisplayProxyOrientationFallBack.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/layers/CompositorParent.h" // for CompositorParent
 #include "mozilla/dom/Navigator.h"
 
 namespace mozilla {
 namespace gfx {
 
 static StaticRefPtr<VRManagerChild> sVRManagerChildSingleton;
@@ -109,45 +109,45 @@ VRManagerChild::Destroy()
 
   // The DeferredDestroyVRManager task takes ownership of
   // the VRManagerChild and will release it when it runs.
   MessageLoop::current()->PostTask(FROM_HERE,
              NewRunnableFunction(DeferredDestroy, selfRef));
 }
 
 bool
-VRManagerChild::RecvUpdateDeviceInfo(nsTArray<VRDeviceUpdate>&& aDeviceUpdates)
+VRManagerChild::RecvUpdateDeviceInfo(nsTArray<VRDisplayUpdate>&& aDeviceUpdates)
 {
   // mDevices could be a hashed container for more scalability, but not worth
   // it now as we expect < 10 entries.
-  nsTArray<RefPtr<VRDeviceProxy> > devices;
+  nsTArray<RefPtr<VRDisplayProxy> > devices;
   for (auto& deviceUpdate: aDeviceUpdates) {
     bool isNewDevice = true;
     for (auto& device: mDevices) {
       if (device->GetDeviceInfo().GetDeviceID() == deviceUpdate.mDeviceInfo.GetDeviceID()) {
         device->UpdateDeviceInfo(deviceUpdate);
         devices.AppendElement(device);
         isNewDevice = false;
         break;
       }
     }
     if (isNewDevice) {
       if (deviceUpdate.mDeviceInfo.GetUseMainThreadOrientation()) {
-        devices.AppendElement(new VRDeviceProxyOrientationFallBack(deviceUpdate));
+        devices.AppendElement(new VRDisplayProxyOrientationFallBack(deviceUpdate));
       } else {
-        devices.AppendElement(new VRDeviceProxy(deviceUpdate));
+        devices.AppendElement(new VRDisplayProxy(deviceUpdate));
       }
     }
   }
 
   mDevices = devices;
 
 
   for (auto& nav: mNavigatorCallbacks) {
-    nav->NotifyVRDevicesUpdated();
+    nav->NotifyVRDisplaysUpdated();
   }
   mNavigatorCallbacks.Clear();
 
   return true;
 }
 
 bool
 VRManagerChild::RecvUpdateDeviceSensors(nsTArray<VRSensorUpdate>&& aDeviceSensorUpdates)
@@ -163,24 +163,24 @@ VRManagerChild::RecvUpdateDeviceSensors(
       }
     }
   }
 
   return true;
 }
 
 bool
-VRManagerChild::GetVRDevices(nsTArray<RefPtr<VRDeviceProxy> >& aDevices)
+VRManagerChild::GetVRDisplays(nsTArray<RefPtr<VRDisplayProxy> >& aDevices)
 {
   aDevices = mDevices;
   return true;
 }
 
 bool
-VRManagerChild::RefreshVRDevicesWithCallback(dom::Navigator* aNavigator)
+VRManagerChild::RefreshVRDisplaysWithCallback(dom::Navigator* aNavigator)
 {
   bool success = SendRefreshDevices();
   if (success) {
     mNavigatorCallbacks.AppendElement(aNavigator);
   }
   return success;
 }
 
--- a/gfx/vr/ipc/VRManagerChild.h
+++ b/gfx/vr/ipc/VRManagerChild.h
@@ -9,53 +9,53 @@
 #define MOZILLA_GFX_VR_VRMANAGERCHILD_H
 
 #include "mozilla/gfx/PVRManagerChild.h"
 #include "ThreadSafeRefcountingWithMainThreadDestruction.h"
 
 namespace mozilla {
 namespace dom {
 class Navigator;
-class VRDevice;
+class VRDisplay;
 } // namespace dom
 namespace gfx {
-class VRDeviceProxy;
+class VRDisplayProxy;
 
 
 class VRManagerChild : public PVRManagerChild
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(VRManagerChild)
 
   int GetInputFrameID();
-  bool GetVRDevices(nsTArray<RefPtr<VRDeviceProxy> >& aDevices);
-  bool RefreshVRDevicesWithCallback(dom::Navigator* aNavigator);
+  bool GetVRDisplays(nsTArray<RefPtr<VRDisplayProxy> >& aDevices);
+  bool RefreshVRDisplaysWithCallback(dom::Navigator* aNavigator);
   static VRManagerChild* StartUpInChildProcess(Transport* aTransport,
                                                ProcessId aOtherProcess);
 
   static void StartUpSameProcess();
   static void ShutDown();
 
 
   static VRManagerChild* Get();
 
 protected:
   explicit VRManagerChild();
   ~VRManagerChild();
   void Destroy();
   static void DeferredDestroy(RefPtr<VRManagerChild> aVRManagerChild);
 
-  virtual bool RecvUpdateDeviceInfo(nsTArray<VRDeviceUpdate>&& aDeviceUpdates) override;
+  virtual bool RecvUpdateDeviceInfo(nsTArray<VRDisplayUpdate>&& aDeviceUpdates) override;
   virtual bool RecvUpdateDeviceSensors(nsTArray<VRSensorUpdate>&& aDeviceSensorUpdates) override;
 
   friend class layers::CompositorChild;
 
 private:
 
-  nsTArray<RefPtr<VRDeviceProxy> > mDevices;
+  nsTArray<RefPtr<VRDisplayProxy> > mDevices;
   nsTArray<dom::Navigator*> mNavigatorCallbacks;
 
   int32_t mInputFrameID;
 };
 
 } // namespace mozilla
 } // namespace gfx
 
--- a/gfx/vr/ipc/VRManagerParent.cpp
+++ b/gfx/vr/ipc/VRManagerParent.cpp
@@ -145,17 +145,17 @@ VRManagerParent::OnChannelConnected(int3
 {
   mCompositorThreadHolder = layers::GetCompositorThreadHolder();
 }
 
 bool
 VRManagerParent::RecvRefreshDevices()
 {
   VRManager* vm = VRManager::Get();
-  vm->RefreshVRDevices();
+  vm->RefreshVRDisplays();
 
   return true;
 }
 
 bool
 VRManagerParent::RecvResetSensor(const uint32_t& aDeviceID)
 {
   VRManager* vm = VRManager::Get();
--- a/gfx/vr/ipc/VRMessageUtils.h
+++ b/gfx/vr/ipc/VRMessageUtils.h
@@ -17,24 +17,24 @@ namespace IPC {
 
 template<>
 struct ParamTraits<mozilla::gfx::VRHMDType> :
   public ContiguousEnumSerializer<mozilla::gfx::VRHMDType,
                                   mozilla::gfx::VRHMDType(0),
                                   mozilla::gfx::VRHMDType(mozilla::gfx::VRHMDType::NumHMDTypes)> {};
 
 template<>
-struct ParamTraits<mozilla::gfx::VRStateValidFlags> :
-  public BitFlagsEnumSerializer<mozilla::gfx::VRStateValidFlags,
-                                mozilla::gfx::VRStateValidFlags::State_All> {};
+struct ParamTraits<mozilla::gfx::VRDisplayCapabilityFlags> :
+  public BitFlagsEnumSerializer<mozilla::gfx::VRDisplayCapabilityFlags,
+                                mozilla::gfx::VRDisplayCapabilityFlags::Cap_All> {};
 
 template <>
-struct ParamTraits<mozilla::gfx::VRDeviceUpdate>
+struct ParamTraits<mozilla::gfx::VRDisplayUpdate>
 {
-  typedef mozilla::gfx::VRDeviceUpdate paramType;
+  typedef mozilla::gfx::VRDisplayUpdate paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mDeviceInfo);
     WriteParam(aMsg, aParam.mSensorState);
   }
 
   static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
@@ -64,53 +64,53 @@ struct ParamTraits<mozilla::gfx::VRSenso
         !ReadParam(aMsg, aIter, &(aResult->mSensorState))) {
       return false;
     }
     return true;
   }
 };
 
 template <>
-struct ParamTraits<mozilla::gfx::VRDeviceInfo>
+struct ParamTraits<mozilla::gfx::VRDisplayInfo>
 {
-  typedef mozilla::gfx::VRDeviceInfo paramType;
+  typedef mozilla::gfx::VRDisplayInfo paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mType);
     WriteParam(aMsg, aParam.mDeviceID);
     WriteParam(aMsg, aParam.mDeviceName);
-    WriteParam(aMsg, aParam.mSupportedSensorBits);
+    WriteParam(aMsg, aParam.mCapabilityFlags);
     WriteParam(aMsg, aParam.mEyeResolution);
     WriteParam(aMsg, aParam.mScreenRect);
     WriteParam(aMsg, aParam.mIsFakeScreen);
     WriteParam(aMsg, aParam.mUseMainThreadOrientation);
-    for (int i = 0; i < mozilla::gfx::VRDeviceInfo::NumEyes; i++) {
+    for (int i = 0; i < mozilla::gfx::VRDisplayInfo::NumEyes; i++) {
       WriteParam(aMsg, aParam.mMaximumEyeFOV[i]);
       WriteParam(aMsg, aParam.mRecommendedEyeFOV[i]);
       WriteParam(aMsg, aParam.mEyeFOV[i]);
       WriteParam(aMsg, aParam.mEyeTranslation[i]);
       WriteParam(aMsg, aParam.mEyeProjectionMatrix[i]);
     }
   }
 
   static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->mType)) ||
         !ReadParam(aMsg, aIter, &(aResult->mDeviceID)) ||
         !ReadParam(aMsg, aIter, &(aResult->mDeviceName)) ||
-        !ReadParam(aMsg, aIter, &(aResult->mSupportedSensorBits)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mCapabilityFlags)) ||
         !ReadParam(aMsg, aIter, &(aResult->mEyeResolution)) ||
         !ReadParam(aMsg, aIter, &(aResult->mScreenRect)) ||
         !ReadParam(aMsg, aIter, &(aResult->mIsFakeScreen)) ||
         !ReadParam(aMsg, aIter, &(aResult->mUseMainThreadOrientation))
         ) {
       return false;
     }
-    for (int i = 0; i < mozilla::gfx::VRDeviceInfo::NumEyes; i++) {
+    for (int i = 0; i < mozilla::gfx::VRDisplayInfo::NumEyes; i++) {
       if (!ReadParam(aMsg, aIter, &(aResult->mMaximumEyeFOV[i])) ||
           !ReadParam(aMsg, aIter, &(aResult->mRecommendedEyeFOV[i])) ||
           !ReadParam(aMsg, aIter, &(aResult->mEyeFOV[i])) ||
           !ReadParam(aMsg, aIter, &(aResult->mEyeTranslation[i])) ||
           !ReadParam(aMsg, aIter, &(aResult->mEyeProjectionMatrix[i]))) {
         return false;
       }
     }
--- a/gfx/vr/moz.build
+++ b/gfx/vr/moz.build
@@ -4,32 +4,32 @@
 # 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/.
 
 EXPORTS += [
     'gfxVR.h',
     'ipc/VRManagerChild.h',
     'ipc/VRManagerParent.h',
     'ipc/VRMessageUtils.h',
-    'VRDeviceProxy.h',
+    'VRDisplayProxy.h',
     'VRManager.h',
 ]
 
 LOCAL_INCLUDES += [
     '/gfx/thebes',
 ]
 
 UNIFIED_SOURCES += [
     'gfxVR.cpp',
     'gfxVRCardboard.cpp',
     'gfxVROculus.cpp',
     'ipc/VRManagerChild.cpp',
     'ipc/VRManagerParent.cpp',
-    'VRDeviceProxy.cpp',
-    'VRDeviceProxyOrientationFallBack.cpp',
+    'VRDisplayProxy.cpp',
+    'VRDisplayProxyOrientationFallBack.cpp',
     'VRManager.cpp',
 ]
 
 SOURCES += [
     'gfxVROculus050.cpp',
 ]
 
 IPDL_SOURCES = [
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -71,16 +71,17 @@
 #include "mozilla/RestyleManager.h"
 #include "nsCaret.h"
 #include "nsISelection.h"
 #include "nsDOMTokenList.h"
 #include "mozilla/RuleNodeCacheConditions.h"
 #include "nsCSSProps.h"
 #include "nsPluginFrame.h"
 #include "DisplayItemScrollClip.h"
+#include "VRDisplayProxy.h"
 
 // GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
 // GetTickCount().
 #ifdef GetCurrentTime
 #undef GetCurrentTime
 #endif
 
 using namespace mozilla;
@@ -6448,17 +6449,17 @@ nsDisplaySVGEffects::nsDisplaySVGEffects
 #ifdef NS_BUILD_REFCNT_LOGGING
 nsDisplaySVGEffects::~nsDisplaySVGEffects()
 {
   MOZ_COUNT_DTOR(nsDisplaySVGEffects);
 }
 #endif
 
 nsDisplayVR::nsDisplayVR(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
-                         nsDisplayList* aList, mozilla::gfx::VRDeviceProxy* aHMD)
+                         nsDisplayList* aList, mozilla::gfx::VRDisplayProxy* aHMD)
   : nsDisplayOwnLayer(aBuilder, aFrame, aList)
   , mHMD(aHMD)
 {
 }
 
 already_AddRefed<Layer>
 nsDisplayVR::BuildLayer(nsDisplayListBuilder* aBuilder,
                         LayerManager* aManager,
@@ -6466,17 +6467,17 @@ nsDisplayVR::BuildLayer(nsDisplayListBui
 {
   ContainerLayerParameters newContainerParameters = aContainerParameters;
   uint32_t flags = FrameLayerBuilder::CONTAINER_NOT_CLIPPED_BY_ANCESTORS |
                    FrameLayerBuilder::CONTAINER_ALLOW_PULL_BACKGROUND_COLOR;
   RefPtr<ContainerLayer> container = aManager->GetLayerBuilder()->
     BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
                            newContainerParameters, nullptr, flags);
 
-  container->SetVRDeviceID(mHMD->GetDeviceInfo().GetDeviceID());
+  container->SetVRDisplayID(mHMD->GetDeviceInfo().GetDeviceID());
   container->SetInputFrameID(mHMD->GetSensorState().inputFrameID);
   container->SetUserData(nsIFrame::LayerIsPrerenderedDataKey(),
                          /*the value is irrelevant*/nullptr);
 
   return container.forget();
 }
 nsRegion nsDisplaySVGEffects::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
                                               bool* aSnap)
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -51,17 +51,17 @@ namespace mozilla {
 class FrameLayerBuilder;
 class DisplayItemScrollClip;
 namespace layers {
 class Layer;
 class ImageLayer;
 class ImageContainer;
 } // namespace layers
 namespace gfx {
-class VRDeviceProxy;
+class VRDisplayProxy;
 } // namespace gfx
 } // namespace mozilla
 
 // A set of blend modes, that never includes OP_OVER (since it's
 // considered the default, rather than a specific blend mode).
 typedef mozilla::EnumSet<mozilla::gfx::CompositionOp> BlendModeSet;
 
 /*
@@ -4354,26 +4354,26 @@ public:
 /**
  * A wrapper layer that wraps its children in a container, then renders
  * everything with an appropriate VR effect based on the HMDInfo.
  */
 
 class nsDisplayVR : public nsDisplayOwnLayer {
 public:
   nsDisplayVR(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
-              nsDisplayList* aList, mozilla::gfx::VRDeviceProxy* aHMD);
+              nsDisplayList* aList, mozilla::gfx::VRDisplayProxy* aHMD);
 
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override
   {
     return mozilla::LAYER_ACTIVE;
   }
 
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
 
 protected:
-  RefPtr<mozilla::gfx::VRDeviceProxy> mHMD;
+  RefPtr<mozilla::gfx::VRDisplayProxy> mHMD;
 };
 
 #endif /*NSDISPLAYLIST_H_*/
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -111,17 +111,17 @@ using namespace mozilla::css;
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
 using namespace mozilla::layers;
 using namespace mozilla::layout;
 typedef nsAbsoluteContainingBlock::AbsPosReflowFlags AbsPosReflowFlags;
 
 namespace mozilla {
 namespace gfx {
-class VRDeviceProxy;
+class VRDisplayProxy;
 } // namespace gfx
 } // namespace mozilla
 
 // Struct containing cached metrics for box-wrapped frames.
 struct nsBoxLayoutMetrics
 {
   nsSize mPrefSize;
   nsSize mMinSize;
@@ -2028,19 +2028,19 @@ nsIFrame::BuildDisplayListForStackingCon
                         nsLayoutUtils::GetNearestScrollableFrame(GetParent(),
                         nsLayoutUtils::SCROLLABLE_SAME_DOC |
                         nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN));
   bool useFixedPosition = nsLayoutUtils::IsFixedPosFrameInDisplayPort(this);
 
   nsDisplayListBuilder::AutoBuildingDisplayList
     buildingDisplayList(aBuilder, this, dirtyRect, true);
 
-  mozilla::gfx::VRDeviceProxy* vrHMDInfo = nullptr;
+  mozilla::gfx::VRDisplayProxy* vrHMDInfo = nullptr;
   if ((GetStateBits() & NS_FRAME_HAS_VR_CONTENT)) {
-    vrHMDInfo = static_cast<mozilla::gfx::VRDeviceProxy*>(mContent->GetProperty(nsGkAtoms::vr_state));
+    vrHMDInfo = static_cast<mozilla::gfx::VRDisplayProxy*>(mContent->GetProperty(nsGkAtoms::vr_state));
   }
 
   DisplayListClipState::AutoSaveRestore clipState(aBuilder);
 
   bool clearClip = false;
   if (isTransformed || usingSVGEffects || useFixedPosition || useStickyPosition) {
     // We don't need to pass ancestor clipping down to our children;
     // everything goes inside a display item's child list, and the display