Bug 1148009; [webvr] Move gfx vr code to gfx/vr; r=jrmuizel
authorVladimir Vukicevic <vladimir@pobox.com>
Wed, 01 Apr 2015 16:02:20 -0400
changeset 237074 d9063bc41c68403f1775068f535fe568e1b8c0cc
parent 237073 345dda450c52f8ad41ba84461b2e257b99aa830f
child 237075 250695bd9883399ded1180bfdb4ec88b571d7435
push id57863
push uservladimir@pobox.com
push dateWed, 01 Apr 2015 20:04:16 +0000
treeherdermozilla-inbound@43cbc390f436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1148009
milestone40.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1148009; [webvr] Move gfx vr code to gfx/vr; r=jrmuizel
gfx/moz.build
gfx/thebes/gfxVR.cpp
gfx/thebes/gfxVR.h
gfx/thebes/moz.build
gfx/thebes/ovr_capi_dynamic.h
gfx/vr/gfxVR.cpp
gfx/vr/gfxVR.h
gfx/vr/moz.build
gfx/vr/ovr_capi_dynamic.h
--- a/gfx/moz.build
+++ b/gfx/moz.build
@@ -18,16 +18,17 @@ DIRS += [
     'qcms',
     'gl',
     'layers',
     'graphite2/src',
     'harfbuzz/src',
     'ots/src',
     'thebes',
     'ipc',
+    'vr',
 ]
 
 if CONFIG['MOZ_ENABLE_SKIA']:
     DIRS += ['skia']
 
 if CONFIG['ENABLE_TESTS']:
     DIRS += ['tests/gtest']
 
deleted file mode 100644
--- a/gfx/thebes/gfxVR.cpp
+++ /dev/null
@@ -1,658 +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 "gfxVR.h"
-#include "nsString.h"
-#include "mozilla/Preferences.h"
-
-#include "ovr_capi_dynamic.h"
-
-#include "nsServiceManagerUtils.h"
-#include "nsIScreenManager.h"
-
-#ifdef XP_WIN
-#include "gfxWindowsPlatform.h" // for gfxWindowsPlatform::GetDPIScale
-#endif
-
-#ifndef M_PI
-# define M_PI 3.14159265358979323846
-#endif
-
-namespace {
-
-#ifdef OVR_CAPI_LIMITED_MOZILLA
-static pfn_ovr_Initialize ovr_Initialize = nullptr;
-static pfn_ovr_Shutdown ovr_Shutdown = nullptr;
-static pfn_ovrHmd_Detect ovrHmd_Detect = nullptr;
-static pfn_ovrHmd_Create ovrHmd_Create = nullptr;
-static pfn_ovrHmd_Destroy ovrHmd_Destroy = nullptr;
-static pfn_ovrHmd_CreateDebug ovrHmd_CreateDebug = nullptr;
-static pfn_ovrHmd_GetLastError ovrHmd_GetLastError = nullptr;
-static pfn_ovrHmd_AttachToWindow ovrHmd_AttachToWindow = nullptr;
-static pfn_ovrHmd_GetEnabledCaps ovrHmd_GetEnabledCaps = nullptr;
-static pfn_ovrHmd_SetEnabledCaps ovrHmd_SetEnabledCaps = nullptr;
-static pfn_ovrHmd_ConfigureTracking ovrHmd_ConfigureTracking = nullptr;
-static pfn_ovrHmd_RecenterPose ovrHmd_RecenterPose = nullptr;
-static pfn_ovrHmd_GetTrackingState ovrHmd_GetTrackingState = nullptr;
-static pfn_ovrHmd_GetFovTextureSize ovrHmd_GetFovTextureSize = nullptr;
-static pfn_ovrHmd_GetRenderDesc ovrHmd_GetRenderDesc = nullptr;
-static pfn_ovrHmd_CreateDistortionMesh ovrHmd_CreateDistortionMesh = nullptr;
-static pfn_ovrHmd_DestroyDistortionMesh ovrHmd_DestroyDistortionMesh = nullptr;
-static pfn_ovrHmd_GetRenderScaleAndOffset ovrHmd_GetRenderScaleAndOffset = nullptr;
-static pfn_ovrHmd_GetFrameTiming ovrHmd_GetFrameTiming = nullptr;
-static pfn_ovrHmd_BeginFrameTiming ovrHmd_BeginFrameTiming = nullptr;
-static pfn_ovrHmd_EndFrameTiming ovrHmd_EndFrameTiming = nullptr;
-static pfn_ovrHmd_ResetFrameTiming ovrHmd_ResetFrameTiming = nullptr;
-static pfn_ovrHmd_GetEyePoses ovrHmd_GetEyePoses = nullptr;
-static pfn_ovrHmd_GetHmdPosePerEye ovrHmd_GetHmdPosePerEye = nullptr;
-static pfn_ovrHmd_GetEyeTimewarpMatrices ovrHmd_GetEyeTimewarpMatrices = nullptr;
-static pfn_ovrMatrix4f_Projection ovrMatrix4f_Projection = nullptr;
-static pfn_ovrMatrix4f_OrthoSubProjection ovrMatrix4f_OrthoSubProjection = nullptr;
-static pfn_ovr_GetTimeInSeconds ovr_GetTimeInSeconds = nullptr;
-
-#if defined(XP_WIN)
-# ifdef HAVE_64BIT_BUILD
-#  define OVR_LIB_NAME "libovr64.dll"
-# else
-#  define OVR_LIB_NAME "libovr.dll"
-# endif
-#elif defined(XP_MACOSX)
-# define OVR_LIB_NAME "libovr.dylib"
-#else
-# define OVR_LIB_NAME 0
-#endif
-
-static bool
-InitializeOculusCAPI()
-{
-  static PRLibrary *ovrlib = nullptr;
-
-  if (!ovrlib) {
-    const char *libName = OVR_LIB_NAME;
-
-    // If the pref is present, we override libName
-    nsAdoptingCString prefLibName = mozilla::Preferences::GetCString("dom.vr.ovr_lib_path");
-    if (prefLibName && prefLibName.get()) {
-      libName = prefLibName.get();
-    }
-
-    // If the env var is present, we override libName
-    if (PR_GetEnv("OVR_LIB_NAME")) {
-      libName = PR_GetEnv("OVR_LIB_NAME");
-    }
-
-    if (!libName) {
-      printf_stderr("Don't know how to find Oculus VR library; missing dom.vr.ovr_lib_path or OVR_LIB_NAME\n");
-      return false;
-    }
-
-    ovrlib = PR_LoadLibrary(libName);
-
-    if (!ovrlib) {
-      // Not found? Try harder. Needed mainly on OSX/etc. where
-      // the binary location is not in the search path.
-      const char *xulName = "libxul.so";
-#if defined(XP_MACOSX)
-      xulName = "XUL";
-#endif
-
-      char *xulpath = PR_GetLibraryFilePathname(xulName, (PRFuncPtr) &InitializeOculusCAPI);
-      if (xulpath) {
-        char *xuldir = strrchr(xulpath, '/');
-        if (xuldir) {
-          *xuldir = 0;
-          xuldir = xulpath;
-
-          char *ovrpath = PR_GetLibraryName(xuldir, libName);
-          ovrlib = PR_LoadLibrary(ovrpath);
-          PR_Free(ovrpath);
-        }
-        PR_Free(xulpath);
-      }
-    }
-
-    if (!ovrlib) {
-      printf_stderr("Failed to load Oculus VR library, tried '%s'\n", libName);
-      return false;
-    }
-  }
-
-  // was it already initialized?
-  if (ovr_Initialize)
-    return true;
-
-#define REQUIRE_FUNCTION(_x) do { \
-    *(void **)&_x = (void *) PR_FindSymbol(ovrlib, #_x);                \
-    if (!_x) { printf_stderr(#_x " symbol missing\n"); goto fail; }       \
-  } while (0)
-
-  REQUIRE_FUNCTION(ovr_Initialize);
-  REQUIRE_FUNCTION(ovr_Shutdown);
-  REQUIRE_FUNCTION(ovrHmd_Detect);
-  REQUIRE_FUNCTION(ovrHmd_Create);
-  REQUIRE_FUNCTION(ovrHmd_Destroy);
-  REQUIRE_FUNCTION(ovrHmd_CreateDebug);
-  REQUIRE_FUNCTION(ovrHmd_GetLastError);
-  REQUIRE_FUNCTION(ovrHmd_AttachToWindow);
-  REQUIRE_FUNCTION(ovrHmd_GetEnabledCaps);
-  REQUIRE_FUNCTION(ovrHmd_SetEnabledCaps);
-  REQUIRE_FUNCTION(ovrHmd_ConfigureTracking);
-  REQUIRE_FUNCTION(ovrHmd_RecenterPose);
-  REQUIRE_FUNCTION(ovrHmd_GetTrackingState);
-
-  REQUIRE_FUNCTION(ovrHmd_GetFovTextureSize);
-  REQUIRE_FUNCTION(ovrHmd_GetRenderDesc);
-  REQUIRE_FUNCTION(ovrHmd_CreateDistortionMesh);
-  REQUIRE_FUNCTION(ovrHmd_DestroyDistortionMesh);
-  REQUIRE_FUNCTION(ovrHmd_GetRenderScaleAndOffset);
-  REQUIRE_FUNCTION(ovrHmd_GetFrameTiming);
-  REQUIRE_FUNCTION(ovrHmd_BeginFrameTiming);
-  REQUIRE_FUNCTION(ovrHmd_EndFrameTiming);
-  REQUIRE_FUNCTION(ovrHmd_ResetFrameTiming);
-  REQUIRE_FUNCTION(ovrHmd_GetEyePoses);
-  REQUIRE_FUNCTION(ovrHmd_GetHmdPosePerEye);
-  REQUIRE_FUNCTION(ovrHmd_GetEyeTimewarpMatrices);
-  REQUIRE_FUNCTION(ovrMatrix4f_Projection);
-  REQUIRE_FUNCTION(ovrMatrix4f_OrthoSubProjection);
-  REQUIRE_FUNCTION(ovr_GetTimeInSeconds);
-
-#undef REQUIRE_FUNCTION
-
-  return true;
-
- fail:
-  ovr_Initialize = nullptr;
-  return false;
-}
-
-#else
-// we're statically linked; it's available
-static bool InitializeOculusCAPI()
-{
-  return true;
-}
-#endif
-
-} // anonymous namespace
-
-using namespace mozilla::gfx;
-
-// 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;
-  }
-
-protected:
-  virtual ~FakeScreen() {}
-
-  IntRect mScreenRect;
-};
-
-NS_IMPL_ISUPPORTS(FakeScreen, nsIScreen)
-
-class HMDInfoOculus : public VRHMDInfo {
-  friend class VRHMDManagerOculusImpl;
-public:
-  explicit HMDInfoOculus(ovrHmd aHMD);
-
-  bool SetFOV(const VRFieldOfView& aFOVLeft, const VRFieldOfView& aFOVRight,
-              double zNear, double zFar) override;
-
-  bool StartSensorTracking() override;
-  VRHMDSensorState GetSensorState(double timeOffset) override;
-  void StopSensorTracking() override;
-  void ZeroSensor() override;
-
-  void FillDistortionConstants(uint32_t whichEye,
-                               const IntSize& textureSize, const IntRect& eyeViewport,
-                               const Size& destViewport, const Rect& destRect,
-                               VRDistortionConstants& values) override;
-
-  void Destroy();
-
-protected:
-  virtual ~HMDInfoOculus() {
-      Destroy();
-      MOZ_COUNT_DTOR_INHERITED(HMDInfoOculus, VRHMDInfo);
-  }
-
-  ovrHmd mHMD;
-  ovrFovPort mFOVPort[2];
-  uint32_t mStartCount;
-};
-
-static ovrFovPort
-ToFovPort(const VRFieldOfView& aFOV)
-{
-  ovrFovPort fovPort;
-  fovPort.LeftTan = tan(aFOV.leftDegrees * M_PI / 180.0);
-  fovPort.RightTan = tan(aFOV.rightDegrees * M_PI / 180.0);
-  fovPort.UpTan = tan(aFOV.upDegrees * M_PI / 180.0);
-  fovPort.DownTan = tan(aFOV.downDegrees * M_PI / 180.0);
-  return fovPort;
-}
-
-static VRFieldOfView
-FromFovPort(const ovrFovPort& aFOV)
-{
-  VRFieldOfView fovInfo;
-  fovInfo.leftDegrees = atan(aFOV.LeftTan) * 180.0 / M_PI;
-  fovInfo.rightDegrees = atan(aFOV.RightTan) * 180.0 / M_PI;
-  fovInfo.upDegrees = atan(aFOV.UpTan) * 180.0 / M_PI;
-  fovInfo.downDegrees = atan(aFOV.DownTan) * 180.0 / M_PI;
-  return fovInfo;
-}
-
-HMDInfoOculus::HMDInfoOculus(ovrHmd aHMD)
-  : VRHMDInfo(VRHMDType::Oculus)
-  , mHMD(aHMD)
-  , mStartCount(0)
-{
-  MOZ_COUNT_CTOR_INHERITED(HMDInfoOculus, VRHMDInfo);
-
-  mSupportedSensorBits = 0;
-  if (mHMD->TrackingCaps & ovrTrackingCap_Orientation)
-    mSupportedSensorBits |= State_Orientation;
-  if (mHMD->TrackingCaps & ovrTrackingCap_Position)
-    mSupportedSensorBits |= State_Position;
-
-  mRecommendedEyeFOV[Eye_Left] = FromFovPort(mHMD->DefaultEyeFov[ovrEye_Left]);
-  mRecommendedEyeFOV[Eye_Right] = FromFovPort(mHMD->DefaultEyeFov[ovrEye_Right]);
-
-  mMaximumEyeFOV[Eye_Left] = FromFovPort(mHMD->MaxEyeFov[ovrEye_Left]);
-  mMaximumEyeFOV[Eye_Right] = FromFovPort(mHMD->MaxEyeFov[ovrEye_Right]);
-
-  SetFOV(mRecommendedEyeFOV[Eye_Left], mRecommendedEyeFOV[Eye_Right], 0.01, 10000.0);
-
-  nsCOMPtr<nsIScreenManager> screenmgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
-  if (screenmgr) {
-    screenmgr->ScreenForRect(mHMD->WindowsPos.x, mHMD->WindowsPos.y,
-                             mHMD->Resolution.w, mHMD->Resolution.h,
-                             getter_AddRefs(mScreen));
-  }
-}
-
-void
-HMDInfoOculus::Destroy()
-{
-  if (mHMD) {
-    ovrHmd_Destroy(mHMD);
-    mHMD = nullptr;
-  }
-}
-
-bool
-HMDInfoOculus::SetFOV(const VRFieldOfView& aFOVLeft, const VRFieldOfView& aFOVRight,
-                      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 < NumEyes; eye++) {
-    mEyeFOV[eye] = eye == 0 ? aFOVLeft : aFOVRight;
-    mFOVPort[eye] = ToFovPort(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
-    mEyeTranslation[eye] = Point3D(-renderDesc.ViewAdjust.x, -renderDesc.ViewAdjust.y, -renderDesc.ViewAdjust.z);
-
-    // note that we are using a right-handed coordinate system here, to match CSS
-    ovrMatrix4f projMatrix = ovrMatrix4f_Projection(mFOVPort[eye], zNear, zFar, true);
-
-    // XXX this is gross, we really need better methods on Matrix4x4
-    memcpy(&mEyeProjectionMatrix[eye], projMatrix.M, sizeof(ovrMatrix4f));
-    mEyeProjectionMatrix[eye].Transpose();
-
-    texSize[eye] = ovrHmd_GetFovTextureSize(mHMD, (ovrEyeType) eye, mFOVPort[eye], pixelsPerDisplayPixel);
-
-    ovrDistortionMesh mesh;
-    bool ok = ovrHmd_CreateDistortionMesh(mHMD, (ovrEyeType) eye, mFOVPort[eye], caps, &mesh);
-    if (!ok)
-      return false;
-
-    mDistortionMesh[eye].mVertices.SetLength(mesh.VertexCount);
-    mDistortionMesh[eye].mIndices.SetLength(mesh.IndexCount);
-
-    ovrDistortionVertex *srcv = mesh.pVertexData;
-    VRDistortionVertex *destv = mDistortionMesh[eye].mVertices.Elements();
-    memset(destv, 0, mesh.VertexCount * sizeof(VRDistortionVertex));
-    for (uint32_t i = 0; i < mesh.VertexCount; ++i) {
-      destv[i].pos[0] = srcv[i].ScreenPosNDC.x;
-      destv[i].pos[1] = srcv[i].ScreenPosNDC.y;
-
-      destv[i].texR[0] = srcv[i].TanEyeAnglesR.x;
-      destv[i].texR[1] = srcv[i].TanEyeAnglesR.y;
-      destv[i].texG[0] = srcv[i].TanEyeAnglesG.x;
-      destv[i].texG[1] = srcv[i].TanEyeAnglesG.y;
-      destv[i].texB[0] = srcv[i].TanEyeAnglesB.x;
-      destv[i].texB[1] = srcv[i].TanEyeAnglesB.y;
-
-      destv[i].genericAttribs[0] = srcv[i].VignetteFactor;
-      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
-  mEyeResolution.width = std::max(texSize[Eye_Left].w, texSize[Eye_Right].w);
-  mEyeResolution.height = std::max(texSize[Eye_Left].h, texSize[Eye_Right].h);
-
-  mConfiguration.hmdType = mType;
-  mConfiguration.value = 0;
-  mConfiguration.fov[0] = aFOVLeft;
-  mConfiguration.fov[1] = aFOVRight;
-
-  return true;
-  //* need to call this during rendering each frame I think? */
-  //ovrHmd_GetRenderScaleAndOffset(fovPort, texSize, renderViewport, uvScaleOffsetOut);
-}
-
-void
-HMDInfoOculus::FillDistortionConstants(uint32_t whichEye,
-                                       const IntSize& textureSize,
-                                       const IntRect& eyeViewport,
-                                       const Size& destViewport,
-                                       const Rect& destRect,
-                                       VRDistortionConstants& values)
-{
-  ovrSizei texSize = { textureSize.width, textureSize.height };
-  ovrRecti eyePort = { { eyeViewport.x, eyeViewport.y }, { eyeViewport.width, eyeViewport.height } };
-  ovrVector2f scaleOut[2];
-
-  ovrHmd_GetRenderScaleAndOffset(mFOVPort[whichEye], texSize, eyePort, scaleOut);
-
-  values.eyeToSourceScaleAndOffset[0] = scaleOut[0].x;
-  values.eyeToSourceScaleAndOffset[1] = scaleOut[0].y;
-  values.eyeToSourceScaleAndOffset[2] = scaleOut[1].x;
-  values.eyeToSourceScaleAndOffset[3] = scaleOut[1].y;
-
-  // These values are in clip space [-1..1] range, but we're providing
-  // scaling in the 0..2 space for sanity.
-
-  // this is the destRect in clip space
-  float x0 = destRect.x / destViewport.width * 2.0 - 1.0;
-  float x1 = (destRect.x + destRect.width) / destViewport.width * 2.0 - 1.0;
-
-  float y0 = destRect.y / destViewport.height * 2.0 - 1.0;
-  float y1 = (destRect.y + destRect.height) / destViewport.height * 2.0 - 1.0;
-
-  // offset
-  values.destinationScaleAndOffset[0] = (x0+x1) / 2.0;
-  values.destinationScaleAndOffset[1] = (y0+y1) / 2.0;
-  // scale
-  values.destinationScaleAndOffset[2] = destRect.width / destViewport.width;
-  values.destinationScaleAndOffset[3] = destRect.height / destViewport.height;
-}
-
-bool
-HMDInfoOculus::StartSensorTracking()
-{
-  if (mStartCount == 0) {
-    bool ok = ovrHmd_ConfigureTracking(mHMD, ovrTrackingCap_Orientation | ovrTrackingCap_Position, 0);
-    if (!ok)
-      return false;
-  }
-
-  mStartCount++;
-  return true;
-}
-
-void
-HMDInfoOculus::StopSensorTracking()
-{
-  if (--mStartCount == 0) {
-    ovrHmd_ConfigureTracking(mHMD, 0, 0);
-  }
-}
-
-void
-HMDInfoOculus::ZeroSensor()
-{
-  ovrHmd_RecenterPose(mHMD);
-}
-
-VRHMDSensorState
-HMDInfoOculus::GetSensorState(double timeOffset)
-{
-  VRHMDSensorState result;
-  result.Clear();
-
-  // 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() + timeOffset);
-  ovrPoseStatef& pose(state.HeadPose);
-
-  result.timestamp = pose.TimeInSeconds;
-
-  if (state.StatusFlags & ovrStatus_OrientationTracked) {
-    result.flags |= State_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 |= State_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;
-  }
-
-  return result;
-}
-
-namespace mozilla {
-namespace gfx {
-
-class VRHMDManagerOculusImpl {
-public:
-  VRHMDManagerOculusImpl() : mOculusInitialized(false), mOculusPlatformInitialized(false)
-  { }
-
-  bool PlatformInit();
-  bool Init();
-  void Destroy();
-  void GetOculusHMDs(nsTArray<nsRefPtr<VRHMDInfo> >& aHMDResult);
-protected:
-  nsTArray<nsRefPtr<HMDInfoOculus>> mOculusHMDs;
-  bool mOculusInitialized;
-  bool mOculusPlatformInitialized;
-};
-
-} // namespace gfx
-} // namespace mozilla
-
-VRHMDManagerOculusImpl *VRHMDManagerOculus::mImpl = nullptr;
-
-// These just forward to the Impl class, to have a non-static container for various
-// objects.
-
-bool
-VRHMDManagerOculus::PlatformInit()
-{
-  if (!mImpl) {
-    mImpl = new VRHMDManagerOculusImpl;
-  }
-  return mImpl->PlatformInit();
-}
-
-bool
-VRHMDManagerOculus::Init()
-{
-  if (!mImpl) {
-    mImpl = new VRHMDManagerOculusImpl;
-  }
-  return mImpl->Init();
-}
-
-void
-VRHMDManagerOculus::GetOculusHMDs(nsTArray<nsRefPtr<VRHMDInfo>>& aHMDResult)
-{
-  if (!mImpl) {
-    mImpl = new VRHMDManagerOculusImpl;
-  }
-  mImpl->GetOculusHMDs(aHMDResult);
-}
-
-void
-VRHMDManagerOculus::Destroy()
-{
-  if (!mImpl)
-    return;
-  mImpl->Destroy();
-  delete mImpl;
-  mImpl = nullptr;
-}
-
-bool
-VRHMDManagerOculusImpl::PlatformInit()
-{
-  if (mOculusPlatformInitialized)
-    return true;
-
-  if (!gfxPrefs::VREnabled())
-    return false;
-
-  if (!InitializeOculusCAPI())
-    return false;
-
-  bool ok = ovr_Initialize();
-
-  if (!ok)
-    return false;
-
-  mOculusPlatformInitialized = true;
-  return true;
-}
-
-bool
-VRHMDManagerOculusImpl::Init()
-{
-  if (mOculusInitialized)
-    return true;
-
-  if (!PlatformInit())
-    return false;
-
-  int count = ovrHmd_Detect();
-
-  for (int i = 0; i < count; ++i) {
-    ovrHmd hmd = ovrHmd_Create(i);
-    if (!hmd)
-      continue;
-    nsRefPtr<HMDInfoOculus> oc = new HMDInfoOculus(hmd);
-    mOculusHMDs.AppendElement(oc);
-  }
-
-  // VRAddTestDevices == 1: add test device only if no real devices present
-  // VRAddTestDevices == 2: add test device always
-  if ((count == 0 && gfxPrefs::VRAddTestDevices() == 1) ||
-      (gfxPrefs::VRAddTestDevices() == 2))
-  {
-    ovrHmd hmd = ovrHmd_CreateDebug(ovrHmd_DK2);
-    if (hmd) {
-      nsRefPtr<HMDInfoOculus> oc = new HMDInfoOculus(hmd);
-      mOculusHMDs.AppendElement(oc);
-    }
-  }
-
-  mOculusInitialized = true;
-  return true;
-}
-
-void
-VRHMDManagerOculusImpl::Destroy()
-{
-  if (!mOculusInitialized)
-    return;
-
-  for (size_t i = 0; i < mOculusHMDs.Length(); ++i) {
-    mOculusHMDs[i]->Destroy();
-  }
-
-  mOculusHMDs.Clear();
-
-  ovr_Shutdown();
-  mOculusInitialized = false;
-}
-
-void
-VRHMDManagerOculusImpl::GetOculusHMDs(nsTArray<nsRefPtr<VRHMDInfo>>& aHMDResult)
-{
-  Init();
-  for (size_t i = 0; i < mOculusHMDs.Length(); ++i) {
-    aHMDResult.AppendElement(mOculusHMDs[i]);
-  }
-}
deleted file mode 100644
--- a/gfx/thebes/gfxVR.h
+++ /dev/null
@@ -1,217 +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_H
-#define GFX_VR_H
-
-#include "nsTArray.h"
-#include "nsIScreen.h"
-#include "nsCOMPtr.h"
-#include "nsRefPtr.h"
-
-#include "mozilla/gfx/2D.h"
-#include "mozilla/EnumeratedArray.h"
-
-namespace mozilla {
-namespace gfx {
-
-enum class VRHMDType : uint16_t {
-  Oculus,
-  NumHMDTypes
-};
-
-struct VRFieldOfView {
-  static VRFieldOfView FromCSSPerspectiveInfo(double aPerspectiveDistance,
-                                              const Point& aPerspectiveOrigin,
-                                              const Point& aTransformOrigin,
-                                              const Rect& aContentRectangle)
-  {
-    /**/
-    return 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 {
-    return other.upDegrees == upDegrees &&
-           other.downDegrees == downDegrees &&
-           other.rightDegrees == rightDegrees &&
-           other.leftDegrees == leftDegrees;
-  }
-
-  bool operator!=(const VRFieldOfView& other) const {
-    return !(*this == other);
-  }
-
-  bool IsZero() const {
-    return upDegrees == 0.0 ||
-      rightDegrees == 0.0 ||
-      downDegrees == 0.0 ||
-      leftDegrees == 0.0;
-  }
-
-  double upDegrees;
-  double rightDegrees;
-  double downDegrees;
-  double leftDegrees;
-};
-
-// 12 floats per vertex. Position, tex coordinates
-// for each channel, and 4 generic attributes
-struct VRDistortionConstants {
-  float eyeToSourceScaleAndOffset[4];
-  float destinationScaleAndOffset[4];
-};
-
-struct VRDistortionVertex {
-  float pos[2];
-  float texR[2];
-  float texG[2];
-  float texB[2];
-  float genericAttribs[4];
-};
-
-struct VRDistortionMesh {
-  nsTArray<VRDistortionVertex> mVertices;
-  nsTArray<uint16_t> mIndices;
-};
-
-struct VRHMDSensorState {
-  double timestamp;
-  uint32_t flags;
-  float orientation[4];
-  float position[3];
-  float angularVelocity[3];
-  float angularAcceleration[3];
-  float linearVelocity[3];
-  float linearAcceleration[3];
-
-  void Clear() {
-    memset(this, 0, sizeof(VRHMDSensorState));
-  }
-};
-
-/* 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 {
-  VRHMDConfiguration() : hmdType(VRHMDType::NumHMDTypes) {}
-
-  bool operator==(const VRHMDConfiguration& other) const {
-    return hmdType == other.hmdType &&
-      value == other.value &&
-      fov[0] == other.fov[0] &&
-      fov[1] == other.fov[1];
-  }
-
-  bool operator!=(const VRHMDConfiguration& other) const {
-    return hmdType != other.hmdType ||
-      value != other.value ||
-      fov[0] != other.fov[0] ||
-      fov[1] != other.fov[1];
-  }
-
-  bool IsValid() const {
-    return hmdType != VRHMDType::NumHMDTypes;
-  }
-
-  VRHMDType hmdType;
-  uint32_t value;
-  VRFieldOfView fov[2];
-};
-
-class VRHMDInfo {
-public:
-  enum Eye {
-    Eye_Left,
-    Eye_Right,
-    NumEyes
-  };
-
-  enum StateValidFlags {
-    State_Position = 1 << 1,
-    State_Orientation = 1 << 2
-  };
-
-public:
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRHMDInfo)
-
-  VRHMDType GetType() const { return mType; }
-
-  virtual const VRFieldOfView& GetRecommendedEyeFOV(uint32_t whichEye) { return mRecommendedEyeFOV[whichEye]; }
-  virtual const VRFieldOfView& GetMaximumEyeFOV(uint32_t whichEye) { return mMaximumEyeFOV[whichEye]; }
-
-  const VRHMDConfiguration& GetConfiguration() const { return mConfiguration; }
-
-  /* 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;
-  const VRFieldOfView& GetEyeFOV(uint32_t whichEye)  { return mEyeFOV[whichEye]; }
-
-  /* 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
-   */
-  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]; }
-
-  virtual uint32_t GetSupportedSensorStateBits() { return mSupportedSensorBits; }
-  virtual bool StartSensorTracking() = 0;
-  virtual VRHMDSensorState GetSensorState(double timeOffset = 0.0) = 0;
-  virtual void StopSensorTracking() = 0;
-
-  virtual void ZeroSensor() = 0;
-
-  virtual void FillDistortionConstants(uint32_t whichEye,
-                                       const IntSize& textureSize, // the full size of the texture
-                                       const IntRect& eyeViewport, // the viewport within the texture for the current eye
-                                       const Size& destViewport,   // the size of the destination viewport
-                                       const Rect& destRect,       // the rectangle within the dest viewport that this should be rendered
-                                       VRDistortionConstants& values) = 0;
-
-  virtual const VRDistortionMesh& GetDistortionMesh(uint32_t whichEye) const { return mDistortionMesh[whichEye]; }
-
-  // The nsIScreen that represents this device
-  virtual nsIScreen* GetScreen() { return mScreen; }
-
-protected:
-  explicit VRHMDInfo(VRHMDType aType) : mType(aType) { MOZ_COUNT_CTOR(VRHMDInfo); }
-  virtual ~VRHMDInfo() { MOZ_COUNT_DTOR(VRHMDInfo); }
-
-  VRHMDType mType;
-  VRHMDConfiguration mConfiguration;
-
-  VRFieldOfView mEyeFOV[NumEyes];
-  IntSize mEyeResolution;
-  Point3D mEyeTranslation[NumEyes];
-  Matrix4x4 mEyeProjectionMatrix[NumEyes];
-  VRDistortionMesh mDistortionMesh[NumEyes];
-  uint32_t mSupportedSensorBits;
-
-  VRFieldOfView mRecommendedEyeFOV[NumEyes];
-  VRFieldOfView mMaximumEyeFOV[NumEyes];
-
-  nsCOMPtr<nsIScreen> mScreen;
-};
-
-class VRHMDManagerOculusImpl;
-class VRHMDManagerOculus {
-  static VRHMDManagerOculusImpl *mImpl;
-public:
-  static bool PlatformInit();
-  static bool Init();
-  static void Destroy();
-  static void GetOculusHMDs(nsTArray<nsRefPtr<VRHMDInfo> >& aHMDResult);
-};
-
-} // namespace gfx
-} // namespace mozilla
-
-#endif /* GFX_VR_H */
--- a/gfx/thebes/moz.build
+++ b/gfx/thebes/moz.build
@@ -44,17 +44,16 @@ EXPORTS += [
     'gfxSharedQuartzSurface.h',
     'gfxSkipChars.h',
     'gfxSVGGlyphs.h',
     'gfxTeeSurface.h',
     'gfxTextRun.h',
     'gfxTypes.h',
     'gfxUserFontSet.h',
     'gfxUtils.h',
-    'gfxVR.h',
     'GraphicsFilter.h',
     'RoundedRect.h',
     'SoftwareVsyncSource.h',
     'VsyncSource.h',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
     EXPORTS += [
@@ -239,17 +238,16 @@ UNIFIED_SOURCES += [
     'gfxReusableSharedImageSurfaceWrapper.cpp',
     'gfxScriptItemizer.cpp',
     'gfxSkipChars.cpp',
     'gfxSVGGlyphs.cpp',
     'gfxTeeSurface.cpp',
     'gfxTextRun.cpp',
     'gfxUserFontSet.cpp',
     'gfxUtils.cpp',
-    'gfxVR.cpp',
     'nsUnicodeRange.cpp',
     'SoftwareVsyncSource.cpp',
     'VsyncSource.cpp',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     UNIFIED_SOURCES += [
         'gfxMacPlatformFontList.mm',
deleted file mode 100644
--- a/gfx/thebes/ovr_capi_dynamic.h
+++ /dev/null
@@ -1,228 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* 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/. */
-
-/* This file contains just the needed struct definitions for
- * interacting with the Oculus VR C API, without needing to #include
- * OVR_CAPI.h directly.  Note that it uses the same type names as the
- * CAPI, and cannot be #included at the same time as OVR_CAPI.h.  It
- * does not include the entire C API, just want's needed.
- */
-
-#ifdef OVR_CAPI_h
-#warning OVR_CAPI.h included before ovr_capi_dynamic.h, skpping this
-#define mozilla_ovr_capi_dynamic_h_
-#endif
-
-#ifndef mozilla_ovr_capi_dynamic_h_
-#define mozilla_ovr_capi_dynamic_h_
-
-#define OVR_CAPI_LIMITED_MOZILLA 1
-
-#ifdef __cplusplus 
-extern "C" {
-#endif
-
-typedef char ovrBool;
-typedef struct { int x, y; } ovrVector2i;
-typedef struct { int w, h; } ovrSizei;
-typedef struct { ovrVector2i Pos; ovrSizei Size; } ovrRecti;
-typedef struct { float x, y, z, w; } ovrQuatf;
-typedef struct { float x, y; } ovrVector2f;
-typedef struct { float x, y, z; } ovrVector3f;
-typedef struct { float M[4][4]; } ovrMatrix4f;
-
-typedef struct {
-  ovrQuatf Orientation;
-  ovrVector3f Position;
-} ovrPosef;
-
-typedef struct {
-  ovrPosef ThePose;
-  ovrVector3f AngularVelocity;
-  ovrVector3f LinearVelocity;
-  ovrVector3f AngularAcceleration;
-  ovrVector3f LinearAcceleration;
-  double TimeInSeconds;
-} ovrPoseStatef;
-
-typedef struct {
-  float UpTan;
-  float DownTan;
-  float LeftTan;
-  float RightTan;
-} ovrFovPort;
-
-typedef enum {
-  ovrHmd_None             = 0,    
-  ovrHmd_DK1              = 3,
-  ovrHmd_DKHD             = 4,
-  ovrHmd_DK2              = 6,
-  ovrHmd_Other
-} ovrHmdType;
-
-typedef enum {
-  ovrHmdCap_Present           = 0x0001,
-  ovrHmdCap_Available         = 0x0002,
-  ovrHmdCap_Captured          = 0x0004,
-  ovrHmdCap_ExtendDesktop     = 0x0008,
-  ovrHmdCap_DisplayOff        = 0x0040,
-  ovrHmdCap_LowPersistence    = 0x0080,
-  ovrHmdCap_DynamicPrediction = 0x0200,
-  ovrHmdCap_NoVSync           = 0x1000,
-  ovrHmdCap_NoMirrorToWindow  = 0x2000
-} ovrHmdCapBits;
-
-typedef enum
-{
-  ovrTrackingCap_Orientation      = 0x0010,
-  ovrTrackingCap_MagYawCorrection = 0x0020,
-  ovrTrackingCap_Position         = 0x0040,
-  ovrTrackingCap_Idle             = 0x0100
-} ovrTrackingCaps;
-
-typedef enum {
-  ovrDistortionCap_Chromatic = 0x01,
-  ovrDistortionCap_TimeWarp  = 0x02,
-  ovrDistortionCap_Vignette  = 0x08,
-  ovrDistortionCap_NoRestore = 0x10,
-  ovrDistortionCap_FlipInput = 0x20,
-  ovrDistortionCap_SRGB      = 0x40,
-  ovrDistortionCap_Overdrive = 0x80,
-  ovrDistortionCap_ProfileNoTimewarpSpinWaits = 0x10000
-} ovrDistortionCaps;
-
-typedef enum {
-  ovrEye_Left  = 0,
-  ovrEye_Right = 1,
-  ovrEye_Count = 2
-} ovrEyeType;
-
-typedef struct ovrHmdDesc_ {
-  void* Handle;
-  ovrHmdType  Type;
-  const char* ProductName;    
-  const char* Manufacturer;
-  short VendorId;
-  short ProductId;
-  char SerialNumber[24];
-  short FirmwareMajor;
-  short FirmwareMinor;
-  float CameraFrustumHFovInRadians;
-  float CameraFrustumVFovInRadians;
-  float CameraFrustumNearZInMeters;
-  float CameraFrustumFarZInMeters;
-
-  unsigned int HmdCaps;
-  unsigned int TrackingCaps;
-  unsigned int DistortionCaps;
-
-  ovrFovPort  DefaultEyeFov[ovrEye_Count];
-  ovrFovPort  MaxEyeFov[ovrEye_Count];
-  ovrEyeType  EyeRenderOrder[ovrEye_Count];
-
-  ovrSizei    Resolution;
-  ovrVector2i WindowsPos;
-
-  const char* DisplayDeviceName;
-  int         DisplayId;
-} ovrHmdDesc;
-
-typedef const ovrHmdDesc* ovrHmd;
-
-typedef enum {
-  ovrStatus_OrientationTracked    = 0x0001,
-  ovrStatus_PositionTracked       = 0x0002,
-  ovrStatus_CameraPoseTracked     = 0x0004,
-  ovrStatus_PositionConnected     = 0x0020,
-  ovrStatus_HmdConnected          = 0x0080
-} ovrStatusBits;
-
-typedef struct ovrSensorData_ {
-  ovrVector3f    Accelerometer;
-  ovrVector3f    Gyro;
-  ovrVector3f    Magnetometer;
-  float          Temperature;
-  float          TimeInSeconds;
-} ovrSensorData;
-
-
-typedef struct ovrTrackingState_ {
-  ovrPoseStatef HeadPose;
-  ovrPosef CameraPose;
-  ovrPosef LeveledCameraPose;
-  ovrSensorData RawSensorData;
-  unsigned int StatusFlags;
-  double LastVisionProcessingTime;
-  double LastVisionFrameLatency;
-  uint32_t LastCameraFrameCounter;
-} ovrTrackingState;
-
-typedef struct ovrFrameTiming_ {
-  float DeltaSeconds;
-  double ThisFrameSeconds;
-  double TimewarpPointSeconds;
-  double NextFrameSeconds;
-  double ScanoutMidpointSeconds;
-  double EyeScanoutSeconds[2];    
-} ovrFrameTiming;
-
-typedef struct ovrEyeRenderDesc_ {
-  ovrEyeType  Eye;        
-  ovrFovPort  Fov;
-  ovrRecti DistortedViewport;
-  ovrVector2f PixelsPerTanAngleAtCenter;
-  ovrVector3f ViewAdjust;
-} ovrEyeRenderDesc;
-
-typedef struct ovrDistortionVertex_ {
-  ovrVector2f ScreenPosNDC;
-  float       TimeWarpFactor;
-  float       VignetteFactor;
-  ovrVector2f TanEyeAnglesR;
-  ovrVector2f TanEyeAnglesG;
-  ovrVector2f TanEyeAnglesB;    
-} ovrDistortionVertex;
-
-typedef struct ovrDistortionMesh_ {
-  ovrDistortionVertex* pVertexData;
-  unsigned short*      pIndexData;
-  unsigned int         VertexCount;
-  unsigned int         IndexCount;
-} ovrDistortionMesh;
-
-typedef ovrBool (*pfn_ovr_Initialize)();
-typedef void (*pfn_ovr_Shutdown)();
-typedef int (*pfn_ovrHmd_Detect)();
-typedef ovrHmd (*pfn_ovrHmd_Create)(int index);
-typedef void (*pfn_ovrHmd_Destroy)(ovrHmd hmd);
-typedef ovrHmd (*pfn_ovrHmd_CreateDebug)(ovrHmdType type);
-typedef const char* (*pfn_ovrHmd_GetLastError)(ovrHmd hmd);
-typedef ovrBool (*pfn_ovrHmd_AttachToWindow)(ovrHmd hmd, void* window, const ovrRecti* destMirrorRect, const ovrRecti* sourceRenderTargetRect);
-typedef unsigned int (*pfn_ovrHmd_GetEnabledCaps)(ovrHmd hmd);
-typedef void (*pfn_ovrHmd_SetEnabledCaps)(ovrHmd hmd, unsigned int hmdCaps);
-typedef ovrBool (*pfn_ovrHmd_ConfigureTracking)(ovrHmd hmd, unsigned int supportedTrackingCaps, unsigned int requiredTrackingCaps); 
-typedef void (*pfn_ovrHmd_RecenterPose)(ovrHmd hmd);
-typedef ovrTrackingState (*pfn_ovrHmd_GetTrackingState)(ovrHmd hmd, double absTime);
-typedef ovrSizei (*pfn_ovrHmd_GetFovTextureSize)(ovrHmd hmd, ovrEyeType eye, ovrFovPort fov, float pixelsPerDisplayPixel);
-typedef ovrEyeRenderDesc (*pfn_ovrHmd_GetRenderDesc)(ovrHmd hmd, ovrEyeType eyeType, ovrFovPort fov);
-typedef ovrBool (*pfn_ovrHmd_CreateDistortionMesh)(ovrHmd hmd, ovrEyeType eyeType, ovrFovPort fov, unsigned int distortionCaps, ovrDistortionMesh *meshData);
-typedef void (*pfn_ovrHmd_DestroyDistortionMesh)(ovrDistortionMesh* meshData);
-typedef void (*pfn_ovrHmd_GetRenderScaleAndOffset)(ovrFovPort fov, ovrSizei textureSize, ovrRecti renderViewport, ovrVector2f uvScaleOffsetOut[2]);
-typedef ovrFrameTiming (*pfn_ovrHmd_GetFrameTiming)(ovrHmd hmd, unsigned int frameIndex);
-typedef ovrFrameTiming (*pfn_ovrHmd_BeginFrameTiming)(ovrHmd hmd, unsigned int frameIndex);
-typedef void (*pfn_ovrHmd_EndFrameTiming)(ovrHmd hmd);
-typedef void (*pfn_ovrHmd_ResetFrameTiming)(ovrHmd hmd, unsigned int frameIndex, bool vsync);
-typedef void (*pfn_ovrHmd_GetEyePoses)(ovrHmd hmd, unsigned int frameIndex, ovrVector3f hmdToEyeViewOffset[2], ovrPosef outEyePoses[2], ovrTrackingState* outHmdTrackingState);
-typedef ovrPosef (*pfn_ovrHmd_GetHmdPosePerEye)(ovrHmd hmd, ovrEyeType eye);
-typedef void (*pfn_ovrHmd_GetEyeTimewarpMatrices)(ovrHmd hmd, ovrEyeType eye, ovrPosef renderPose, ovrMatrix4f twmOut[2]);
-typedef ovrMatrix4f (*pfn_ovrMatrix4f_Projection) (ovrFovPort fov, float znear, float zfar, ovrBool rightHanded );
-typedef ovrMatrix4f (*pfn_ovrMatrix4f_OrthoSubProjection) (ovrFovPort fov, ovrVector2f orthoScale, float orthoDistance, float eyeViewAdjustX);
-typedef double (*pfn_ovr_GetTimeInSeconds)();
-
-#ifdef __cplusplus 
-}
-#endif
-
-#endif /* mozilla_ovr_capi_dynamic_h_ */
new file mode 100644
--- /dev/null
+++ b/gfx/vr/gfxVR.cpp
@@ -0,0 +1,658 @@
+/* -*- 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 "gfxVR.h"
+#include "nsString.h"
+#include "mozilla/Preferences.h"
+
+#include "ovr_capi_dynamic.h"
+
+#include "nsServiceManagerUtils.h"
+#include "nsIScreenManager.h"
+
+#ifdef XP_WIN
+#include "gfxWindowsPlatform.h" // for gfxWindowsPlatform::GetDPIScale
+#endif
+
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif
+
+namespace {
+
+#ifdef OVR_CAPI_LIMITED_MOZILLA
+static pfn_ovr_Initialize ovr_Initialize = nullptr;
+static pfn_ovr_Shutdown ovr_Shutdown = nullptr;
+static pfn_ovrHmd_Detect ovrHmd_Detect = nullptr;
+static pfn_ovrHmd_Create ovrHmd_Create = nullptr;
+static pfn_ovrHmd_Destroy ovrHmd_Destroy = nullptr;
+static pfn_ovrHmd_CreateDebug ovrHmd_CreateDebug = nullptr;
+static pfn_ovrHmd_GetLastError ovrHmd_GetLastError = nullptr;
+static pfn_ovrHmd_AttachToWindow ovrHmd_AttachToWindow = nullptr;
+static pfn_ovrHmd_GetEnabledCaps ovrHmd_GetEnabledCaps = nullptr;
+static pfn_ovrHmd_SetEnabledCaps ovrHmd_SetEnabledCaps = nullptr;
+static pfn_ovrHmd_ConfigureTracking ovrHmd_ConfigureTracking = nullptr;
+static pfn_ovrHmd_RecenterPose ovrHmd_RecenterPose = nullptr;
+static pfn_ovrHmd_GetTrackingState ovrHmd_GetTrackingState = nullptr;
+static pfn_ovrHmd_GetFovTextureSize ovrHmd_GetFovTextureSize = nullptr;
+static pfn_ovrHmd_GetRenderDesc ovrHmd_GetRenderDesc = nullptr;
+static pfn_ovrHmd_CreateDistortionMesh ovrHmd_CreateDistortionMesh = nullptr;
+static pfn_ovrHmd_DestroyDistortionMesh ovrHmd_DestroyDistortionMesh = nullptr;
+static pfn_ovrHmd_GetRenderScaleAndOffset ovrHmd_GetRenderScaleAndOffset = nullptr;
+static pfn_ovrHmd_GetFrameTiming ovrHmd_GetFrameTiming = nullptr;
+static pfn_ovrHmd_BeginFrameTiming ovrHmd_BeginFrameTiming = nullptr;
+static pfn_ovrHmd_EndFrameTiming ovrHmd_EndFrameTiming = nullptr;
+static pfn_ovrHmd_ResetFrameTiming ovrHmd_ResetFrameTiming = nullptr;
+static pfn_ovrHmd_GetEyePoses ovrHmd_GetEyePoses = nullptr;
+static pfn_ovrHmd_GetHmdPosePerEye ovrHmd_GetHmdPosePerEye = nullptr;
+static pfn_ovrHmd_GetEyeTimewarpMatrices ovrHmd_GetEyeTimewarpMatrices = nullptr;
+static pfn_ovrMatrix4f_Projection ovrMatrix4f_Projection = nullptr;
+static pfn_ovrMatrix4f_OrthoSubProjection ovrMatrix4f_OrthoSubProjection = nullptr;
+static pfn_ovr_GetTimeInSeconds ovr_GetTimeInSeconds = nullptr;
+
+#if defined(XP_WIN)
+# ifdef HAVE_64BIT_BUILD
+#  define OVR_LIB_NAME "libovr64.dll"
+# else
+#  define OVR_LIB_NAME "libovr.dll"
+# endif
+#elif defined(XP_MACOSX)
+# define OVR_LIB_NAME "libovr.dylib"
+#else
+# define OVR_LIB_NAME 0
+#endif
+
+static bool
+InitializeOculusCAPI()
+{
+  static PRLibrary *ovrlib = nullptr;
+
+  if (!ovrlib) {
+    const char *libName = OVR_LIB_NAME;
+
+    // If the pref is present, we override libName
+    nsAdoptingCString prefLibName = mozilla::Preferences::GetCString("dom.vr.ovr_lib_path");
+    if (prefLibName && prefLibName.get()) {
+      libName = prefLibName.get();
+    }
+
+    // If the env var is present, we override libName
+    if (PR_GetEnv("OVR_LIB_NAME")) {
+      libName = PR_GetEnv("OVR_LIB_NAME");
+    }
+
+    if (!libName) {
+      printf_stderr("Don't know how to find Oculus VR library; missing dom.vr.ovr_lib_path or OVR_LIB_NAME\n");
+      return false;
+    }
+
+    ovrlib = PR_LoadLibrary(libName);
+
+    if (!ovrlib) {
+      // Not found? Try harder. Needed mainly on OSX/etc. where
+      // the binary location is not in the search path.
+      const char *xulName = "libxul.so";
+#if defined(XP_MACOSX)
+      xulName = "XUL";
+#endif
+
+      char *xulpath = PR_GetLibraryFilePathname(xulName, (PRFuncPtr) &InitializeOculusCAPI);
+      if (xulpath) {
+        char *xuldir = strrchr(xulpath, '/');
+        if (xuldir) {
+          *xuldir = 0;
+          xuldir = xulpath;
+
+          char *ovrpath = PR_GetLibraryName(xuldir, libName);
+          ovrlib = PR_LoadLibrary(ovrpath);
+          PR_Free(ovrpath);
+        }
+        PR_Free(xulpath);
+      }
+    }
+
+    if (!ovrlib) {
+      printf_stderr("Failed to load Oculus VR library, tried '%s'\n", libName);
+      return false;
+    }
+  }
+
+  // was it already initialized?
+  if (ovr_Initialize)
+    return true;
+
+#define REQUIRE_FUNCTION(_x) do { \
+    *(void **)&_x = (void *) PR_FindSymbol(ovrlib, #_x);                \
+    if (!_x) { printf_stderr(#_x " symbol missing\n"); goto fail; }       \
+  } while (0)
+
+  REQUIRE_FUNCTION(ovr_Initialize);
+  REQUIRE_FUNCTION(ovr_Shutdown);
+  REQUIRE_FUNCTION(ovrHmd_Detect);
+  REQUIRE_FUNCTION(ovrHmd_Create);
+  REQUIRE_FUNCTION(ovrHmd_Destroy);
+  REQUIRE_FUNCTION(ovrHmd_CreateDebug);
+  REQUIRE_FUNCTION(ovrHmd_GetLastError);
+  REQUIRE_FUNCTION(ovrHmd_AttachToWindow);
+  REQUIRE_FUNCTION(ovrHmd_GetEnabledCaps);
+  REQUIRE_FUNCTION(ovrHmd_SetEnabledCaps);
+  REQUIRE_FUNCTION(ovrHmd_ConfigureTracking);
+  REQUIRE_FUNCTION(ovrHmd_RecenterPose);
+  REQUIRE_FUNCTION(ovrHmd_GetTrackingState);
+
+  REQUIRE_FUNCTION(ovrHmd_GetFovTextureSize);
+  REQUIRE_FUNCTION(ovrHmd_GetRenderDesc);
+  REQUIRE_FUNCTION(ovrHmd_CreateDistortionMesh);
+  REQUIRE_FUNCTION(ovrHmd_DestroyDistortionMesh);
+  REQUIRE_FUNCTION(ovrHmd_GetRenderScaleAndOffset);
+  REQUIRE_FUNCTION(ovrHmd_GetFrameTiming);
+  REQUIRE_FUNCTION(ovrHmd_BeginFrameTiming);
+  REQUIRE_FUNCTION(ovrHmd_EndFrameTiming);
+  REQUIRE_FUNCTION(ovrHmd_ResetFrameTiming);
+  REQUIRE_FUNCTION(ovrHmd_GetEyePoses);
+  REQUIRE_FUNCTION(ovrHmd_GetHmdPosePerEye);
+  REQUIRE_FUNCTION(ovrHmd_GetEyeTimewarpMatrices);
+  REQUIRE_FUNCTION(ovrMatrix4f_Projection);
+  REQUIRE_FUNCTION(ovrMatrix4f_OrthoSubProjection);
+  REQUIRE_FUNCTION(ovr_GetTimeInSeconds);
+
+#undef REQUIRE_FUNCTION
+
+  return true;
+
+ fail:
+  ovr_Initialize = nullptr;
+  return false;
+}
+
+#else
+// we're statically linked; it's available
+static bool InitializeOculusCAPI()
+{
+  return true;
+}
+#endif
+
+} // anonymous namespace
+
+using namespace mozilla::gfx;
+
+// 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;
+  }
+
+protected:
+  virtual ~FakeScreen() {}
+
+  IntRect mScreenRect;
+};
+
+NS_IMPL_ISUPPORTS(FakeScreen, nsIScreen)
+
+class HMDInfoOculus : public VRHMDInfo {
+  friend class VRHMDManagerOculusImpl;
+public:
+  explicit HMDInfoOculus(ovrHmd aHMD);
+
+  bool SetFOV(const VRFieldOfView& aFOVLeft, const VRFieldOfView& aFOVRight,
+              double zNear, double zFar) override;
+
+  bool StartSensorTracking() override;
+  VRHMDSensorState GetSensorState(double timeOffset) override;
+  void StopSensorTracking() override;
+  void ZeroSensor() override;
+
+  void FillDistortionConstants(uint32_t whichEye,
+                               const IntSize& textureSize, const IntRect& eyeViewport,
+                               const Size& destViewport, const Rect& destRect,
+                               VRDistortionConstants& values) override;
+
+  void Destroy();
+
+protected:
+  virtual ~HMDInfoOculus() {
+      Destroy();
+      MOZ_COUNT_DTOR_INHERITED(HMDInfoOculus, VRHMDInfo);
+  }
+
+  ovrHmd mHMD;
+  ovrFovPort mFOVPort[2];
+  uint32_t mStartCount;
+};
+
+static ovrFovPort
+ToFovPort(const VRFieldOfView& aFOV)
+{
+  ovrFovPort fovPort;
+  fovPort.LeftTan = tan(aFOV.leftDegrees * M_PI / 180.0);
+  fovPort.RightTan = tan(aFOV.rightDegrees * M_PI / 180.0);
+  fovPort.UpTan = tan(aFOV.upDegrees * M_PI / 180.0);
+  fovPort.DownTan = tan(aFOV.downDegrees * M_PI / 180.0);
+  return fovPort;
+}
+
+static VRFieldOfView
+FromFovPort(const ovrFovPort& aFOV)
+{
+  VRFieldOfView fovInfo;
+  fovInfo.leftDegrees = atan(aFOV.LeftTan) * 180.0 / M_PI;
+  fovInfo.rightDegrees = atan(aFOV.RightTan) * 180.0 / M_PI;
+  fovInfo.upDegrees = atan(aFOV.UpTan) * 180.0 / M_PI;
+  fovInfo.downDegrees = atan(aFOV.DownTan) * 180.0 / M_PI;
+  return fovInfo;
+}
+
+HMDInfoOculus::HMDInfoOculus(ovrHmd aHMD)
+  : VRHMDInfo(VRHMDType::Oculus)
+  , mHMD(aHMD)
+  , mStartCount(0)
+{
+  MOZ_COUNT_CTOR_INHERITED(HMDInfoOculus, VRHMDInfo);
+
+  mSupportedSensorBits = 0;
+  if (mHMD->TrackingCaps & ovrTrackingCap_Orientation)
+    mSupportedSensorBits |= State_Orientation;
+  if (mHMD->TrackingCaps & ovrTrackingCap_Position)
+    mSupportedSensorBits |= State_Position;
+
+  mRecommendedEyeFOV[Eye_Left] = FromFovPort(mHMD->DefaultEyeFov[ovrEye_Left]);
+  mRecommendedEyeFOV[Eye_Right] = FromFovPort(mHMD->DefaultEyeFov[ovrEye_Right]);
+
+  mMaximumEyeFOV[Eye_Left] = FromFovPort(mHMD->MaxEyeFov[ovrEye_Left]);
+  mMaximumEyeFOV[Eye_Right] = FromFovPort(mHMD->MaxEyeFov[ovrEye_Right]);
+
+  SetFOV(mRecommendedEyeFOV[Eye_Left], mRecommendedEyeFOV[Eye_Right], 0.01, 10000.0);
+
+  nsCOMPtr<nsIScreenManager> screenmgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
+  if (screenmgr) {
+    screenmgr->ScreenForRect(mHMD->WindowsPos.x, mHMD->WindowsPos.y,
+                             mHMD->Resolution.w, mHMD->Resolution.h,
+                             getter_AddRefs(mScreen));
+  }
+}
+
+void
+HMDInfoOculus::Destroy()
+{
+  if (mHMD) {
+    ovrHmd_Destroy(mHMD);
+    mHMD = nullptr;
+  }
+}
+
+bool
+HMDInfoOculus::SetFOV(const VRFieldOfView& aFOVLeft, const VRFieldOfView& aFOVRight,
+                      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 < NumEyes; eye++) {
+    mEyeFOV[eye] = eye == 0 ? aFOVLeft : aFOVRight;
+    mFOVPort[eye] = ToFovPort(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
+    mEyeTranslation[eye] = Point3D(-renderDesc.ViewAdjust.x, -renderDesc.ViewAdjust.y, -renderDesc.ViewAdjust.z);
+
+    // note that we are using a right-handed coordinate system here, to match CSS
+    ovrMatrix4f projMatrix = ovrMatrix4f_Projection(mFOVPort[eye], zNear, zFar, true);
+
+    // XXX this is gross, we really need better methods on Matrix4x4
+    memcpy(&mEyeProjectionMatrix[eye], projMatrix.M, sizeof(ovrMatrix4f));
+    mEyeProjectionMatrix[eye].Transpose();
+
+    texSize[eye] = ovrHmd_GetFovTextureSize(mHMD, (ovrEyeType) eye, mFOVPort[eye], pixelsPerDisplayPixel);
+
+    ovrDistortionMesh mesh;
+    bool ok = ovrHmd_CreateDistortionMesh(mHMD, (ovrEyeType) eye, mFOVPort[eye], caps, &mesh);
+    if (!ok)
+      return false;
+
+    mDistortionMesh[eye].mVertices.SetLength(mesh.VertexCount);
+    mDistortionMesh[eye].mIndices.SetLength(mesh.IndexCount);
+
+    ovrDistortionVertex *srcv = mesh.pVertexData;
+    VRDistortionVertex *destv = mDistortionMesh[eye].mVertices.Elements();
+    memset(destv, 0, mesh.VertexCount * sizeof(VRDistortionVertex));
+    for (uint32_t i = 0; i < mesh.VertexCount; ++i) {
+      destv[i].pos[0] = srcv[i].ScreenPosNDC.x;
+      destv[i].pos[1] = srcv[i].ScreenPosNDC.y;
+
+      destv[i].texR[0] = srcv[i].TanEyeAnglesR.x;
+      destv[i].texR[1] = srcv[i].TanEyeAnglesR.y;
+      destv[i].texG[0] = srcv[i].TanEyeAnglesG.x;
+      destv[i].texG[1] = srcv[i].TanEyeAnglesG.y;
+      destv[i].texB[0] = srcv[i].TanEyeAnglesB.x;
+      destv[i].texB[1] = srcv[i].TanEyeAnglesB.y;
+
+      destv[i].genericAttribs[0] = srcv[i].VignetteFactor;
+      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
+  mEyeResolution.width = std::max(texSize[Eye_Left].w, texSize[Eye_Right].w);
+  mEyeResolution.height = std::max(texSize[Eye_Left].h, texSize[Eye_Right].h);
+
+  mConfiguration.hmdType = mType;
+  mConfiguration.value = 0;
+  mConfiguration.fov[0] = aFOVLeft;
+  mConfiguration.fov[1] = aFOVRight;
+
+  return true;
+  //* need to call this during rendering each frame I think? */
+  //ovrHmd_GetRenderScaleAndOffset(fovPort, texSize, renderViewport, uvScaleOffsetOut);
+}
+
+void
+HMDInfoOculus::FillDistortionConstants(uint32_t whichEye,
+                                       const IntSize& textureSize,
+                                       const IntRect& eyeViewport,
+                                       const Size& destViewport,
+                                       const Rect& destRect,
+                                       VRDistortionConstants& values)
+{
+  ovrSizei texSize = { textureSize.width, textureSize.height };
+  ovrRecti eyePort = { { eyeViewport.x, eyeViewport.y }, { eyeViewport.width, eyeViewport.height } };
+  ovrVector2f scaleOut[2];
+
+  ovrHmd_GetRenderScaleAndOffset(mFOVPort[whichEye], texSize, eyePort, scaleOut);
+
+  values.eyeToSourceScaleAndOffset[0] = scaleOut[0].x;
+  values.eyeToSourceScaleAndOffset[1] = scaleOut[0].y;
+  values.eyeToSourceScaleAndOffset[2] = scaleOut[1].x;
+  values.eyeToSourceScaleAndOffset[3] = scaleOut[1].y;
+
+  // These values are in clip space [-1..1] range, but we're providing
+  // scaling in the 0..2 space for sanity.
+
+  // this is the destRect in clip space
+  float x0 = destRect.x / destViewport.width * 2.0 - 1.0;
+  float x1 = (destRect.x + destRect.width) / destViewport.width * 2.0 - 1.0;
+
+  float y0 = destRect.y / destViewport.height * 2.0 - 1.0;
+  float y1 = (destRect.y + destRect.height) / destViewport.height * 2.0 - 1.0;
+
+  // offset
+  values.destinationScaleAndOffset[0] = (x0+x1) / 2.0;
+  values.destinationScaleAndOffset[1] = (y0+y1) / 2.0;
+  // scale
+  values.destinationScaleAndOffset[2] = destRect.width / destViewport.width;
+  values.destinationScaleAndOffset[3] = destRect.height / destViewport.height;
+}
+
+bool
+HMDInfoOculus::StartSensorTracking()
+{
+  if (mStartCount == 0) {
+    bool ok = ovrHmd_ConfigureTracking(mHMD, ovrTrackingCap_Orientation | ovrTrackingCap_Position, 0);
+    if (!ok)
+      return false;
+  }
+
+  mStartCount++;
+  return true;
+}
+
+void
+HMDInfoOculus::StopSensorTracking()
+{
+  if (--mStartCount == 0) {
+    ovrHmd_ConfigureTracking(mHMD, 0, 0);
+  }
+}
+
+void
+HMDInfoOculus::ZeroSensor()
+{
+  ovrHmd_RecenterPose(mHMD);
+}
+
+VRHMDSensorState
+HMDInfoOculus::GetSensorState(double timeOffset)
+{
+  VRHMDSensorState result;
+  result.Clear();
+
+  // 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() + timeOffset);
+  ovrPoseStatef& pose(state.HeadPose);
+
+  result.timestamp = pose.TimeInSeconds;
+
+  if (state.StatusFlags & ovrStatus_OrientationTracked) {
+    result.flags |= State_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 |= State_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;
+  }
+
+  return result;
+}
+
+namespace mozilla {
+namespace gfx {
+
+class VRHMDManagerOculusImpl {
+public:
+  VRHMDManagerOculusImpl() : mOculusInitialized(false), mOculusPlatformInitialized(false)
+  { }
+
+  bool PlatformInit();
+  bool Init();
+  void Destroy();
+  void GetOculusHMDs(nsTArray<nsRefPtr<VRHMDInfo> >& aHMDResult);
+protected:
+  nsTArray<nsRefPtr<HMDInfoOculus>> mOculusHMDs;
+  bool mOculusInitialized;
+  bool mOculusPlatformInitialized;
+};
+
+} // namespace gfx
+} // namespace mozilla
+
+VRHMDManagerOculusImpl *VRHMDManagerOculus::mImpl = nullptr;
+
+// These just forward to the Impl class, to have a non-static container for various
+// objects.
+
+bool
+VRHMDManagerOculus::PlatformInit()
+{
+  if (!mImpl) {
+    mImpl = new VRHMDManagerOculusImpl;
+  }
+  return mImpl->PlatformInit();
+}
+
+bool
+VRHMDManagerOculus::Init()
+{
+  if (!mImpl) {
+    mImpl = new VRHMDManagerOculusImpl;
+  }
+  return mImpl->Init();
+}
+
+void
+VRHMDManagerOculus::GetOculusHMDs(nsTArray<nsRefPtr<VRHMDInfo>>& aHMDResult)
+{
+  if (!mImpl) {
+    mImpl = new VRHMDManagerOculusImpl;
+  }
+  mImpl->GetOculusHMDs(aHMDResult);
+}
+
+void
+VRHMDManagerOculus::Destroy()
+{
+  if (!mImpl)
+    return;
+  mImpl->Destroy();
+  delete mImpl;
+  mImpl = nullptr;
+}
+
+bool
+VRHMDManagerOculusImpl::PlatformInit()
+{
+  if (mOculusPlatformInitialized)
+    return true;
+
+  if (!gfxPrefs::VREnabled())
+    return false;
+
+  if (!InitializeOculusCAPI())
+    return false;
+
+  bool ok = ovr_Initialize();
+
+  if (!ok)
+    return false;
+
+  mOculusPlatformInitialized = true;
+  return true;
+}
+
+bool
+VRHMDManagerOculusImpl::Init()
+{
+  if (mOculusInitialized)
+    return true;
+
+  if (!PlatformInit())
+    return false;
+
+  int count = ovrHmd_Detect();
+
+  for (int i = 0; i < count; ++i) {
+    ovrHmd hmd = ovrHmd_Create(i);
+    if (!hmd)
+      continue;
+    nsRefPtr<HMDInfoOculus> oc = new HMDInfoOculus(hmd);
+    mOculusHMDs.AppendElement(oc);
+  }
+
+  // VRAddTestDevices == 1: add test device only if no real devices present
+  // VRAddTestDevices == 2: add test device always
+  if ((count == 0 && gfxPrefs::VRAddTestDevices() == 1) ||
+      (gfxPrefs::VRAddTestDevices() == 2))
+  {
+    ovrHmd hmd = ovrHmd_CreateDebug(ovrHmd_DK2);
+    if (hmd) {
+      nsRefPtr<HMDInfoOculus> oc = new HMDInfoOculus(hmd);
+      mOculusHMDs.AppendElement(oc);
+    }
+  }
+
+  mOculusInitialized = true;
+  return true;
+}
+
+void
+VRHMDManagerOculusImpl::Destroy()
+{
+  if (!mOculusInitialized)
+    return;
+
+  for (size_t i = 0; i < mOculusHMDs.Length(); ++i) {
+    mOculusHMDs[i]->Destroy();
+  }
+
+  mOculusHMDs.Clear();
+
+  ovr_Shutdown();
+  mOculusInitialized = false;
+}
+
+void
+VRHMDManagerOculusImpl::GetOculusHMDs(nsTArray<nsRefPtr<VRHMDInfo>>& aHMDResult)
+{
+  Init();
+  for (size_t i = 0; i < mOculusHMDs.Length(); ++i) {
+    aHMDResult.AppendElement(mOculusHMDs[i]);
+  }
+}
new file mode 100644
--- /dev/null
+++ b/gfx/vr/gfxVR.h
@@ -0,0 +1,217 @@
+/* -*- 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_H
+#define GFX_VR_H
+
+#include "nsTArray.h"
+#include "nsIScreen.h"
+#include "nsCOMPtr.h"
+#include "nsRefPtr.h"
+
+#include "mozilla/gfx/2D.h"
+#include "mozilla/EnumeratedArray.h"
+
+namespace mozilla {
+namespace gfx {
+
+enum class VRHMDType : uint16_t {
+  Oculus,
+  NumHMDTypes
+};
+
+struct VRFieldOfView {
+  static VRFieldOfView FromCSSPerspectiveInfo(double aPerspectiveDistance,
+                                              const Point& aPerspectiveOrigin,
+                                              const Point& aTransformOrigin,
+                                              const Rect& aContentRectangle)
+  {
+    /**/
+    return 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 {
+    return other.upDegrees == upDegrees &&
+           other.downDegrees == downDegrees &&
+           other.rightDegrees == rightDegrees &&
+           other.leftDegrees == leftDegrees;
+  }
+
+  bool operator!=(const VRFieldOfView& other) const {
+    return !(*this == other);
+  }
+
+  bool IsZero() const {
+    return upDegrees == 0.0 ||
+      rightDegrees == 0.0 ||
+      downDegrees == 0.0 ||
+      leftDegrees == 0.0;
+  }
+
+  double upDegrees;
+  double rightDegrees;
+  double downDegrees;
+  double leftDegrees;
+};
+
+// 12 floats per vertex. Position, tex coordinates
+// for each channel, and 4 generic attributes
+struct VRDistortionConstants {
+  float eyeToSourceScaleAndOffset[4];
+  float destinationScaleAndOffset[4];
+};
+
+struct VRDistortionVertex {
+  float pos[2];
+  float texR[2];
+  float texG[2];
+  float texB[2];
+  float genericAttribs[4];
+};
+
+struct VRDistortionMesh {
+  nsTArray<VRDistortionVertex> mVertices;
+  nsTArray<uint16_t> mIndices;
+};
+
+struct VRHMDSensorState {
+  double timestamp;
+  uint32_t flags;
+  float orientation[4];
+  float position[3];
+  float angularVelocity[3];
+  float angularAcceleration[3];
+  float linearVelocity[3];
+  float linearAcceleration[3];
+
+  void Clear() {
+    memset(this, 0, sizeof(VRHMDSensorState));
+  }
+};
+
+/* 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 {
+  VRHMDConfiguration() : hmdType(VRHMDType::NumHMDTypes) {}
+
+  bool operator==(const VRHMDConfiguration& other) const {
+    return hmdType == other.hmdType &&
+      value == other.value &&
+      fov[0] == other.fov[0] &&
+      fov[1] == other.fov[1];
+  }
+
+  bool operator!=(const VRHMDConfiguration& other) const {
+    return hmdType != other.hmdType ||
+      value != other.value ||
+      fov[0] != other.fov[0] ||
+      fov[1] != other.fov[1];
+  }
+
+  bool IsValid() const {
+    return hmdType != VRHMDType::NumHMDTypes;
+  }
+
+  VRHMDType hmdType;
+  uint32_t value;
+  VRFieldOfView fov[2];
+};
+
+class VRHMDInfo {
+public:
+  enum Eye {
+    Eye_Left,
+    Eye_Right,
+    NumEyes
+  };
+
+  enum StateValidFlags {
+    State_Position = 1 << 1,
+    State_Orientation = 1 << 2
+  };
+
+public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRHMDInfo)
+
+  VRHMDType GetType() const { return mType; }
+
+  virtual const VRFieldOfView& GetRecommendedEyeFOV(uint32_t whichEye) { return mRecommendedEyeFOV[whichEye]; }
+  virtual const VRFieldOfView& GetMaximumEyeFOV(uint32_t whichEye) { return mMaximumEyeFOV[whichEye]; }
+
+  const VRHMDConfiguration& GetConfiguration() const { return mConfiguration; }
+
+  /* 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;
+  const VRFieldOfView& GetEyeFOV(uint32_t whichEye)  { return mEyeFOV[whichEye]; }
+
+  /* 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
+   */
+  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]; }
+
+  virtual uint32_t GetSupportedSensorStateBits() { return mSupportedSensorBits; }
+  virtual bool StartSensorTracking() = 0;
+  virtual VRHMDSensorState GetSensorState(double timeOffset = 0.0) = 0;
+  virtual void StopSensorTracking() = 0;
+
+  virtual void ZeroSensor() = 0;
+
+  virtual void FillDistortionConstants(uint32_t whichEye,
+                                       const IntSize& textureSize, // the full size of the texture
+                                       const IntRect& eyeViewport, // the viewport within the texture for the current eye
+                                       const Size& destViewport,   // the size of the destination viewport
+                                       const Rect& destRect,       // the rectangle within the dest viewport that this should be rendered
+                                       VRDistortionConstants& values) = 0;
+
+  virtual const VRDistortionMesh& GetDistortionMesh(uint32_t whichEye) const { return mDistortionMesh[whichEye]; }
+
+  // The nsIScreen that represents this device
+  virtual nsIScreen* GetScreen() { return mScreen; }
+
+protected:
+  explicit VRHMDInfo(VRHMDType aType) : mType(aType) { MOZ_COUNT_CTOR(VRHMDInfo); }
+  virtual ~VRHMDInfo() { MOZ_COUNT_DTOR(VRHMDInfo); }
+
+  VRHMDType mType;
+  VRHMDConfiguration mConfiguration;
+
+  VRFieldOfView mEyeFOV[NumEyes];
+  IntSize mEyeResolution;
+  Point3D mEyeTranslation[NumEyes];
+  Matrix4x4 mEyeProjectionMatrix[NumEyes];
+  VRDistortionMesh mDistortionMesh[NumEyes];
+  uint32_t mSupportedSensorBits;
+
+  VRFieldOfView mRecommendedEyeFOV[NumEyes];
+  VRFieldOfView mMaximumEyeFOV[NumEyes];
+
+  nsCOMPtr<nsIScreen> mScreen;
+};
+
+class VRHMDManagerOculusImpl;
+class VRHMDManagerOculus {
+  static VRHMDManagerOculusImpl *mImpl;
+public:
+  static bool PlatformInit();
+  static bool Init();
+  static void Destroy();
+  static void GetOculusHMDs(nsTArray<nsRefPtr<VRHMDInfo> >& aHMDResult);
+};
+
+} // namespace gfx
+} // namespace mozilla
+
+#endif /* GFX_VR_H */
new file mode 100644
--- /dev/null
+++ b/gfx/vr/moz.build
@@ -0,0 +1,31 @@
+# -*- 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 += [
+    'gfxVR.h',
+]
+
+LOCAL_INCLUDES += [
+    '/gfx/thebes',
+]
+
+UNIFIED_SOURCES += [
+    'gfxVR.cpp',
+]
+
+CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
+CXXFLAGS += CONFIG['TK_CFLAGS']
+CFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
+CFLAGS += CONFIG['TK_CFLAGS']
+
+FAIL_ON_WARNINGS = not CONFIG['_MSC_VER']
+
+MSVC_ENABLE_PGO = True
+
+include('/ipc/chromium/chromium-config.mozbuild')
+
+FINAL_LIBRARY = 'xul'
+
new file mode 100644
--- /dev/null
+++ b/gfx/vr/ovr_capi_dynamic.h
@@ -0,0 +1,228 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* 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/. */
+
+/* This file contains just the needed struct definitions for
+ * interacting with the Oculus VR C API, without needing to #include
+ * OVR_CAPI.h directly.  Note that it uses the same type names as the
+ * CAPI, and cannot be #included at the same time as OVR_CAPI.h.  It
+ * does not include the entire C API, just want's needed.
+ */
+
+#ifdef OVR_CAPI_h
+#warning OVR_CAPI.h included before ovr_capi_dynamic.h, skpping this
+#define mozilla_ovr_capi_dynamic_h_
+#endif
+
+#ifndef mozilla_ovr_capi_dynamic_h_
+#define mozilla_ovr_capi_dynamic_h_
+
+#define OVR_CAPI_LIMITED_MOZILLA 1
+
+#ifdef __cplusplus 
+extern "C" {
+#endif
+
+typedef char ovrBool;
+typedef struct { int x, y; } ovrVector2i;
+typedef struct { int w, h; } ovrSizei;
+typedef struct { ovrVector2i Pos; ovrSizei Size; } ovrRecti;
+typedef struct { float x, y, z, w; } ovrQuatf;
+typedef struct { float x, y; } ovrVector2f;
+typedef struct { float x, y, z; } ovrVector3f;
+typedef struct { float M[4][4]; } ovrMatrix4f;
+
+typedef struct {
+  ovrQuatf Orientation;
+  ovrVector3f Position;
+} ovrPosef;
+
+typedef struct {
+  ovrPosef ThePose;
+  ovrVector3f AngularVelocity;
+  ovrVector3f LinearVelocity;
+  ovrVector3f AngularAcceleration;
+  ovrVector3f LinearAcceleration;
+  double TimeInSeconds;
+} ovrPoseStatef;
+
+typedef struct {
+  float UpTan;
+  float DownTan;
+  float LeftTan;
+  float RightTan;
+} ovrFovPort;
+
+typedef enum {
+  ovrHmd_None             = 0,    
+  ovrHmd_DK1              = 3,
+  ovrHmd_DKHD             = 4,
+  ovrHmd_DK2              = 6,
+  ovrHmd_Other
+} ovrHmdType;
+
+typedef enum {
+  ovrHmdCap_Present           = 0x0001,
+  ovrHmdCap_Available         = 0x0002,
+  ovrHmdCap_Captured          = 0x0004,
+  ovrHmdCap_ExtendDesktop     = 0x0008,
+  ovrHmdCap_DisplayOff        = 0x0040,
+  ovrHmdCap_LowPersistence    = 0x0080,
+  ovrHmdCap_DynamicPrediction = 0x0200,
+  ovrHmdCap_NoVSync           = 0x1000,
+  ovrHmdCap_NoMirrorToWindow  = 0x2000
+} ovrHmdCapBits;
+
+typedef enum
+{
+  ovrTrackingCap_Orientation      = 0x0010,
+  ovrTrackingCap_MagYawCorrection = 0x0020,
+  ovrTrackingCap_Position         = 0x0040,
+  ovrTrackingCap_Idle             = 0x0100
+} ovrTrackingCaps;
+
+typedef enum {
+  ovrDistortionCap_Chromatic = 0x01,
+  ovrDistortionCap_TimeWarp  = 0x02,
+  ovrDistortionCap_Vignette  = 0x08,
+  ovrDistortionCap_NoRestore = 0x10,
+  ovrDistortionCap_FlipInput = 0x20,
+  ovrDistortionCap_SRGB      = 0x40,
+  ovrDistortionCap_Overdrive = 0x80,
+  ovrDistortionCap_ProfileNoTimewarpSpinWaits = 0x10000
+} ovrDistortionCaps;
+
+typedef enum {
+  ovrEye_Left  = 0,
+  ovrEye_Right = 1,
+  ovrEye_Count = 2
+} ovrEyeType;
+
+typedef struct ovrHmdDesc_ {
+  void* Handle;
+  ovrHmdType  Type;
+  const char* ProductName;    
+  const char* Manufacturer;
+  short VendorId;
+  short ProductId;
+  char SerialNumber[24];
+  short FirmwareMajor;
+  short FirmwareMinor;
+  float CameraFrustumHFovInRadians;
+  float CameraFrustumVFovInRadians;
+  float CameraFrustumNearZInMeters;
+  float CameraFrustumFarZInMeters;
+
+  unsigned int HmdCaps;
+  unsigned int TrackingCaps;
+  unsigned int DistortionCaps;
+
+  ovrFovPort  DefaultEyeFov[ovrEye_Count];
+  ovrFovPort  MaxEyeFov[ovrEye_Count];
+  ovrEyeType  EyeRenderOrder[ovrEye_Count];
+
+  ovrSizei    Resolution;
+  ovrVector2i WindowsPos;
+
+  const char* DisplayDeviceName;
+  int         DisplayId;
+} ovrHmdDesc;
+
+typedef const ovrHmdDesc* ovrHmd;
+
+typedef enum {
+  ovrStatus_OrientationTracked    = 0x0001,
+  ovrStatus_PositionTracked       = 0x0002,
+  ovrStatus_CameraPoseTracked     = 0x0004,
+  ovrStatus_PositionConnected     = 0x0020,
+  ovrStatus_HmdConnected          = 0x0080
+} ovrStatusBits;
+
+typedef struct ovrSensorData_ {
+  ovrVector3f    Accelerometer;
+  ovrVector3f    Gyro;
+  ovrVector3f    Magnetometer;
+  float          Temperature;
+  float          TimeInSeconds;
+} ovrSensorData;
+
+
+typedef struct ovrTrackingState_ {
+  ovrPoseStatef HeadPose;
+  ovrPosef CameraPose;
+  ovrPosef LeveledCameraPose;
+  ovrSensorData RawSensorData;
+  unsigned int StatusFlags;
+  double LastVisionProcessingTime;
+  double LastVisionFrameLatency;
+  uint32_t LastCameraFrameCounter;
+} ovrTrackingState;
+
+typedef struct ovrFrameTiming_ {
+  float DeltaSeconds;
+  double ThisFrameSeconds;
+  double TimewarpPointSeconds;
+  double NextFrameSeconds;
+  double ScanoutMidpointSeconds;
+  double EyeScanoutSeconds[2];    
+} ovrFrameTiming;
+
+typedef struct ovrEyeRenderDesc_ {
+  ovrEyeType  Eye;        
+  ovrFovPort  Fov;
+  ovrRecti DistortedViewport;
+  ovrVector2f PixelsPerTanAngleAtCenter;
+  ovrVector3f ViewAdjust;
+} ovrEyeRenderDesc;
+
+typedef struct ovrDistortionVertex_ {
+  ovrVector2f ScreenPosNDC;
+  float       TimeWarpFactor;
+  float       VignetteFactor;
+  ovrVector2f TanEyeAnglesR;
+  ovrVector2f TanEyeAnglesG;
+  ovrVector2f TanEyeAnglesB;    
+} ovrDistortionVertex;
+
+typedef struct ovrDistortionMesh_ {
+  ovrDistortionVertex* pVertexData;
+  unsigned short*      pIndexData;
+  unsigned int         VertexCount;
+  unsigned int         IndexCount;
+} ovrDistortionMesh;
+
+typedef ovrBool (*pfn_ovr_Initialize)();
+typedef void (*pfn_ovr_Shutdown)();
+typedef int (*pfn_ovrHmd_Detect)();
+typedef ovrHmd (*pfn_ovrHmd_Create)(int index);
+typedef void (*pfn_ovrHmd_Destroy)(ovrHmd hmd);
+typedef ovrHmd (*pfn_ovrHmd_CreateDebug)(ovrHmdType type);
+typedef const char* (*pfn_ovrHmd_GetLastError)(ovrHmd hmd);
+typedef ovrBool (*pfn_ovrHmd_AttachToWindow)(ovrHmd hmd, void* window, const ovrRecti* destMirrorRect, const ovrRecti* sourceRenderTargetRect);
+typedef unsigned int (*pfn_ovrHmd_GetEnabledCaps)(ovrHmd hmd);
+typedef void (*pfn_ovrHmd_SetEnabledCaps)(ovrHmd hmd, unsigned int hmdCaps);
+typedef ovrBool (*pfn_ovrHmd_ConfigureTracking)(ovrHmd hmd, unsigned int supportedTrackingCaps, unsigned int requiredTrackingCaps); 
+typedef void (*pfn_ovrHmd_RecenterPose)(ovrHmd hmd);
+typedef ovrTrackingState (*pfn_ovrHmd_GetTrackingState)(ovrHmd hmd, double absTime);
+typedef ovrSizei (*pfn_ovrHmd_GetFovTextureSize)(ovrHmd hmd, ovrEyeType eye, ovrFovPort fov, float pixelsPerDisplayPixel);
+typedef ovrEyeRenderDesc (*pfn_ovrHmd_GetRenderDesc)(ovrHmd hmd, ovrEyeType eyeType, ovrFovPort fov);
+typedef ovrBool (*pfn_ovrHmd_CreateDistortionMesh)(ovrHmd hmd, ovrEyeType eyeType, ovrFovPort fov, unsigned int distortionCaps, ovrDistortionMesh *meshData);
+typedef void (*pfn_ovrHmd_DestroyDistortionMesh)(ovrDistortionMesh* meshData);
+typedef void (*pfn_ovrHmd_GetRenderScaleAndOffset)(ovrFovPort fov, ovrSizei textureSize, ovrRecti renderViewport, ovrVector2f uvScaleOffsetOut[2]);
+typedef ovrFrameTiming (*pfn_ovrHmd_GetFrameTiming)(ovrHmd hmd, unsigned int frameIndex);
+typedef ovrFrameTiming (*pfn_ovrHmd_BeginFrameTiming)(ovrHmd hmd, unsigned int frameIndex);
+typedef void (*pfn_ovrHmd_EndFrameTiming)(ovrHmd hmd);
+typedef void (*pfn_ovrHmd_ResetFrameTiming)(ovrHmd hmd, unsigned int frameIndex, bool vsync);
+typedef void (*pfn_ovrHmd_GetEyePoses)(ovrHmd hmd, unsigned int frameIndex, ovrVector3f hmdToEyeViewOffset[2], ovrPosef outEyePoses[2], ovrTrackingState* outHmdTrackingState);
+typedef ovrPosef (*pfn_ovrHmd_GetHmdPosePerEye)(ovrHmd hmd, ovrEyeType eye);
+typedef void (*pfn_ovrHmd_GetEyeTimewarpMatrices)(ovrHmd hmd, ovrEyeType eye, ovrPosef renderPose, ovrMatrix4f twmOut[2]);
+typedef ovrMatrix4f (*pfn_ovrMatrix4f_Projection) (ovrFovPort fov, float znear, float zfar, ovrBool rightHanded );
+typedef ovrMatrix4f (*pfn_ovrMatrix4f_OrthoSubProjection) (ovrFovPort fov, ovrVector2f orthoScale, float orthoDistance, float eyeViewAdjustX);
+typedef double (*pfn_ovr_GetTimeInSeconds)();
+
+#ifdef __cplusplus 
+}
+#endif
+
+#endif /* mozilla_ovr_capi_dynamic_h_ */