diff --git a/cmake/externals/LibOVR/CMakeLists.txt b/cmake/externals/LibOVR/CMakeLists.txt
index 97508be0c5..ed76f181e7 100644
--- a/cmake/externals/LibOVR/CMakeLists.txt
+++ b/cmake/externals/LibOVR/CMakeLists.txt
@@ -17,8 +17,8 @@ if (WIN32)
 
   ExternalProject_Add(
     ${EXTERNAL_NAME}
-    URL https://static.oculus.com/sdk-downloads/1.11.0/Public/1486063832/ovr_sdk_win_1.11.0_public.zip
-    URL_MD5 ea484403757cbfdfa743b6577fb1f9d2
+    URL http://hifi-public.s3.amazonaws.com/dependencies/ovr_sdk_win_1.26.0_public.zip
+    URL_MD5 06804ff9727b910dcd04a37c800053b5
     CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
     PATCH_COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/LibOVRCMakeLists.txt" <SOURCE_DIR>/CMakeLists.txt
     LOG_DOWNLOAD 1
diff --git a/cmake/externals/LibOVR/LibOVRCMakeLists.txt b/cmake/externals/LibOVR/LibOVRCMakeLists.txt
index 556533f0c2..a52cff5463 100644
--- a/cmake/externals/LibOVR/LibOVRCMakeLists.txt
+++ b/cmake/externals/LibOVR/LibOVRCMakeLists.txt
@@ -4,7 +4,7 @@ project(LibOVR)
 include_directories(LibOVR/Include LibOVR/Src)
 file(GLOB HEADER_FILES LibOVR/Include/*.h)
 file(GLOB EXTRA_HEADER_FILES LibOVR/Include/Extras/*.h)  
-file(GLOB_RECURSE SOURCE_FILES LibOVR/Src/*.c LibOVR/Src/*.cpp)
+file(GLOB_RECURSE SOURCE_FILES LibOVR/Shim/*.c LibOVR/Shim/*.cpp)
 set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DOVR_BUILD_DEBUG")
 add_library(LibOVR STATIC ${SOURCE_FILES} ${HEADER_FILES} ${EXTRA_HEADER_FILES})
 set_target_properties(LibOVR PROPERTIES DEBUG_POSTFIX "d")
diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp
index 7e337070d3..5aa1e45943 100644
--- a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp
+++ b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp
@@ -15,19 +15,25 @@
 
 #include "OculusHelpers.h"
 
+using namespace hifi;
+
 void OculusBaseDisplayPlugin::resetSensors() {
     ovr_RecenterTrackingOrigin(_session);
-
     _currentRenderFrameInfo.renderPose = glm::mat4(); // identity
 }
 
 bool OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
-    handleOVREvents();
-    if (quitRequested()) {
+    ovrSessionStatus status{};
+    if (!OVR_SUCCESS(ovr_GetSessionStatus(_session, &status))) {
+        qCWarning(oculusLog) << "Unable to fetch Oculus session status" << ovr::getError();
+        return false;
+    }
+
+    if (ovr::quitRequested(status)) {
         QMetaObject::invokeMethod(qApp, "quit");
         return false;
     }
-    if (reorientRequested()) {
+    if (ovr::reorientRequested(status)) {
         emit resetSensorsRequested();
     }
 
@@ -35,18 +41,18 @@ bool OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
     _currentRenderFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds();
     _currentRenderFrameInfo.predictedDisplayTime = ovr_GetPredictedDisplayTime(_session, frameIndex);
     auto trackingState = ovr_GetTrackingState(_session, _currentRenderFrameInfo.predictedDisplayTime, ovrTrue);
-    _currentRenderFrameInfo.renderPose = toGlm(trackingState.HeadPose.ThePose);
+    _currentRenderFrameInfo.renderPose = ovr::toGlm(trackingState.HeadPose.ThePose);
     _currentRenderFrameInfo.presentPose = _currentRenderFrameInfo.renderPose;
 
     std::array<glm::mat4, 2> handPoses;
     // Make controller poses available to the presentation thread
-    ovr_for_each_hand([&](ovrHandType hand) {
+    ovr::for_each_hand([&](ovrHandType hand) {
         static const auto REQUIRED_HAND_STATUS = ovrStatus_OrientationTracked | ovrStatus_PositionTracked;
         if (REQUIRED_HAND_STATUS != (trackingState.HandStatusFlags[hand] & REQUIRED_HAND_STATUS)) {
             return;
         }
 
-        auto correctedPose = ovrControllerPoseToHandPose(hand, trackingState.HandPoses[hand]);
+        auto correctedPose = ovr::toControllerPose(hand, trackingState.HandPoses[hand]);
         static const glm::quat HAND_TO_LASER_ROTATION = glm::rotation(Vectors::UNIT_Z, Vectors::UNIT_NEG_Y);
         handPoses[hand] = glm::translate(glm::mat4(), correctedPose.translation) * glm::mat4_cast(correctedPose.rotation * HAND_TO_LASER_ROTATION);
     });
@@ -58,7 +64,7 @@ bool OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
 }
 
 bool OculusBaseDisplayPlugin::isSupported() const {
-    return oculusAvailable();
+    return ovr::available();
 }
 
 glm::mat4 OculusBaseDisplayPlugin::getEyeProjection(Eye eye, const glm::mat4& baseProjection) const {
@@ -71,7 +77,7 @@ glm::mat4 OculusBaseDisplayPlugin::getEyeProjection(Eye eye, const glm::mat4& ba
         ovrFovPort fovPort = _hmdDesc.DefaultEyeFov[eye];
         ovrEyeRenderDesc& erd = ovr_GetRenderDesc(_session, ovrEye, fovPort);
         ovrMatrix4f ovrPerspectiveProjection = ovrMatrix4f_Projection(erd.Fov, baseNearClip, baseFarClip, ovrProjection_ClipRangeOpenGL);
-        return toGlm(ovrPerspectiveProjection);
+        return ovr::toGlm(ovrPerspectiveProjection);
     } else {
         return baseProjection;
     }
@@ -85,7 +91,7 @@ glm::mat4 OculusBaseDisplayPlugin::getCullingProjection(const glm::mat4& basePro
         float baseFarClip = baseFrustum.getFarClip();
         auto combinedFov = _eyeFovs[0];
         combinedFov.LeftTan = combinedFov.RightTan = std::max(combinedFov.LeftTan, combinedFov.RightTan);
-        return toGlm(ovrMatrix4f_Projection(combinedFov, baseNearClip, baseFarClip, ovrProjection_ClipRangeOpenGL));
+        return ovr::toGlm(ovrMatrix4f_Projection(combinedFov, baseNearClip, baseFarClip, ovrProjection_ClipRangeOpenGL));
     } else {
         return baseProjection;
     }
@@ -102,7 +108,7 @@ void OculusBaseDisplayPlugin::uncustomizeContext() {
 }
 
 bool OculusBaseDisplayPlugin::internalActivate() {
-    _session = acquireOculusSession();
+    _session = ovr::acquireRenderSession();
     if (!_session) {
         return false;
     }
@@ -113,21 +119,21 @@ bool OculusBaseDisplayPlugin::internalActivate() {
     _viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f;
 
     _ipd = 0;
-    ovr_for_each_eye([&](ovrEyeType eye) {
+    ovr::for_each_eye([&](ovrEyeType eye) {
         _eyeFovs[eye] = _hmdDesc.DefaultEyeFov[eye];
         ovrEyeRenderDesc& erd = _eyeRenderDescs[eye] = ovr_GetRenderDesc(_session, eye, _eyeFovs[eye]);
         ovrMatrix4f ovrPerspectiveProjection =
             ovrMatrix4f_Projection(erd.Fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_ClipRangeOpenGL);
-        _eyeProjections[eye] = toGlm(ovrPerspectiveProjection);
-        _eyeOffsets[eye] = glm::translate(mat4(), toGlm(erd.HmdToEyeOffset));
-        eyeSizes[eye] = toGlm(ovr_GetFovTextureSize(_session, eye, erd.Fov, 1.0f));
-        _viewScaleDesc.HmdToEyeOffset[eye] = erd.HmdToEyeOffset;
-        _ipd += glm::abs(glm::length(toGlm(erd.HmdToEyeOffset)));
+        _eyeProjections[eye] = ovr::toGlm(ovrPerspectiveProjection);
+        _eyeOffsets[eye] = ovr::toGlm(erd.HmdToEyePose);
+        eyeSizes[eye] = ovr::toGlm(ovr_GetFovTextureSize(_session, eye, erd.Fov, 1.0f));
+        _viewScaleDesc.HmdToEyePose[eye] = erd.HmdToEyePose;
+        _ipd += glm::abs(glm::length(ovr::toGlm(erd.HmdToEyePose.Position)));
     });
 
     auto combinedFov = _eyeFovs[0];
     combinedFov.LeftTan = combinedFov.RightTan = std::max(combinedFov.LeftTan, combinedFov.RightTan);
-    _cullingProjection = toGlm(ovrMatrix4f_Projection(combinedFov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_ClipRangeOpenGL));
+    _cullingProjection = ovr::toGlm(ovrMatrix4f_Projection(combinedFov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_ClipRangeOpenGL));
 
     _renderTargetSize = uvec2(
         eyeSizes[0].x + eyeSizes[1].x,
@@ -136,7 +142,7 @@ bool OculusBaseDisplayPlugin::internalActivate() {
     memset(&_sceneLayer, 0, sizeof(ovrLayerEyeFov));
     _sceneLayer.Header.Type = ovrLayerType_EyeFov;
     _sceneLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft;
-    ovr_for_each_eye([&](ovrEyeType eye) {
+    ovr::for_each_eye([&](ovrEyeType eye) {
         ovrFovPort & fov = _sceneLayer.Fov[eye] = _eyeRenderDescs[eye].Fov;
         ovrSizei & size = _sceneLayer.Viewport[eye].Size = ovr_GetFovTextureSize(_session, eye, fov, 1.0f);
         _sceneLayer.Viewport[eye].Pos = { eye == ovrEye_Left ? 0 : size.w, 0 };
@@ -150,28 +156,14 @@ bool OculusBaseDisplayPlugin::internalActivate() {
 
 void OculusBaseDisplayPlugin::internalDeactivate() {
     Parent::internalDeactivate();
+    ovr::releaseRenderSession(_session);
 }
 
-bool OculusBaseDisplayPlugin::activateStandBySession() {
-    if (!_session) {
-        _session = acquireOculusSession();
-    }
-    return _session;
-}
-void OculusBaseDisplayPlugin::deactivateSession() {
-    // FIXME
-    // Switching to Qt 5.9 exposed a race condition or similar issue that caused a crash when putting on an Rift
-    // while already in VR mode.  Commenting these out is a workaround.
-    //releaseOculusSession();
-    //_session = nullptr;
-}
 void OculusBaseDisplayPlugin::updatePresentPose() {
+    ovrTrackingState trackingState;
     _currentPresentFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds();
     _currentPresentFrameInfo.predictedDisplayTime = ovr_GetPredictedDisplayTime(_session, 0);
-    auto trackingState = ovr_GetTrackingState(_session, _currentRenderFrameInfo.predictedDisplayTime, ovrFalse);
-    _currentPresentFrameInfo.presentPose = toGlm(trackingState.HeadPose.ThePose);
+    trackingState = ovr_GetTrackingState(_session, _currentRenderFrameInfo.predictedDisplayTime, ovrFalse);
+    _currentPresentFrameInfo.presentPose = ovr::toGlm(trackingState.HeadPose.ThePose);
     _currentPresentFrameInfo.renderPose = _currentPresentFrameInfo.presentPose;
 }
-
-OculusBaseDisplayPlugin::~OculusBaseDisplayPlugin() {
-}
diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.h b/plugins/oculus/src/OculusBaseDisplayPlugin.h
index b3b99c0ad1..d70d14dc28 100644
--- a/plugins/oculus/src/OculusBaseDisplayPlugin.h
+++ b/plugins/oculus/src/OculusBaseDisplayPlugin.h
@@ -16,37 +16,32 @@
 class OculusBaseDisplayPlugin : public HmdDisplayPlugin {
     using Parent = HmdDisplayPlugin;
 public:
-    ~OculusBaseDisplayPlugin();
     bool isSupported() const override;
+    bool hasAsyncReprojection() const override { return true; }
+    bool getSupportsAutoSwitch() override final { return true; }
 
     glm::mat4 getEyeProjection(Eye eye, const glm::mat4& baseProjection) const override;
     glm::mat4 getCullingProjection(const glm::mat4& baseProjection) const override;
 
-    bool hasAsyncReprojection() const override { return true; }
-
-
     // Stereo specific methods
     void resetSensors() override final;
     bool beginFrameRender(uint32_t frameIndex) override;
     float getTargetFrameRate() const override { return _hmdDesc.DisplayRefreshRate; }
-    bool getSupportsAutoSwitch() override final { return true; }
-    
-
+   
 protected:
     void customizeContext() override;
     void uncustomizeContext() override;
     bool internalActivate() override;
     void internalDeactivate() override;
-    bool activateStandBySession() override;
-    void deactivateSession() override;
     void updatePresentPose() override;
 
 protected:
-    ovrSession _session { nullptr };
+    ovrSession _session{ nullptr };
     ovrGraphicsLuid _luid;
-    ovrEyeRenderDesc _eyeRenderDescs[2];
-    ovrFovPort _eyeFovs[2];
+    std::array<ovrEyeRenderDesc, 2> _eyeRenderDescs;
+    std::array<ovrFovPort, 2> _eyeFovs;
     ovrHmdDesc _hmdDesc;
     ovrLayerEyeFov _sceneLayer;
     ovrViewScaleDesc _viewScaleDesc;
+    // ovrLayerEyeFovDepth _depthLayer;
 };
diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp
index 7a176d36fb..943af301a2 100644
--- a/plugins/oculus/src/OculusControllerManager.cpp
+++ b/plugins/oculus/src/OculusControllerManager.cpp
@@ -22,34 +22,23 @@
 #include <NumericalConstants.h>
 #include <StreamUtils.h>
 
-#include <OVR_CAPI.h>
+#include <ovr_capi.h>
 
 #include "OculusHelpers.h"
 
-Q_DECLARE_LOGGING_CATEGORY(oculus)
-
-
-static const char* MENU_PARENT = "Avatar";
-static const char* MENU_NAME = "Oculus Touch Controllers";
-static const char* MENU_PATH = "Avatar" ">" "Oculus Touch Controllers";
+using namespace hifi;
 
 const char* OculusControllerManager::NAME = "Oculus";
 
 const quint64 LOST_TRACKING_DELAY = 3000000;
 
 bool OculusControllerManager::isSupported() const {
-    return oculusAvailable();
+    return hifi::ovr::available();
 }
 
 bool OculusControllerManager::activate() {
     InputPlugin::activate();
-    if (!_session) {
-        _session = acquireOculusSession();
-    }
-    Q_ASSERT(_session);
-
     checkForConnectedDevices();
-
     return true;
 }
 
@@ -58,33 +47,30 @@ void OculusControllerManager::checkForConnectedDevices() {
         return;
     }
 
-    unsigned int controllerConnected = ovr_GetConnectedControllerTypes(_session);
+    ovr::withSession([&] (ovrSession session) {
+        unsigned int controllerConnected = ovr_GetConnectedControllerTypes(session);
 
-    if (!_remote && (controllerConnected & ovrControllerType_Remote) == ovrControllerType_Remote) {
-        if (OVR_SUCCESS(ovr_GetInputState(_session, ovrControllerType_Remote, &_inputState))) {
-            auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
-            _remote = std::make_shared<RemoteDevice>(*this);
-            userInputMapper->registerDevice(_remote);
+        if (!_remote && (controllerConnected & ovrControllerType_Remote) == ovrControllerType_Remote) {
+            if (OVR_SUCCESS(ovr_GetInputState(session, ovrControllerType_Remote, &_inputState))) {
+                auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
+                _remote = std::make_shared<RemoteDevice>(*this);
+                userInputMapper->registerDevice(_remote);
+            }
         }
-    }
 
-    if (!_touch && (controllerConnected & ovrControllerType_Touch) != 0) {
-        if (OVR_SUCCESS(ovr_GetInputState(_session, ovrControllerType_Touch, &_inputState))) {
-            auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
-            _touch = std::make_shared<TouchDevice>(*this);
-            userInputMapper->registerDevice(_touch);
+        if (!_touch && (controllerConnected & ovrControllerType_Touch) != 0) {
+            if (OVR_SUCCESS(ovr_GetInputState(session, ovrControllerType_Touch, &_inputState))) {
+                auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
+                _touch = std::make_shared<TouchDevice>(*this);
+                userInputMapper->registerDevice(_touch);
+            }
         }
-    }
+    });
 }
 
 void OculusControllerManager::deactivate() {
     InputPlugin::deactivate();
 
-    if (_session) {
-        releaseOculusSession();
-        _session = nullptr;
-    }
-
     // unregister with UserInputMapper
     auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
     if (_touch) {
@@ -100,20 +86,30 @@ void OculusControllerManager::pluginUpdate(float deltaTime, const controller::In
 
     checkForConnectedDevices();
 
-    if (_touch) {
-        if (OVR_SUCCESS(ovr_GetInputState(_session, ovrControllerType_Touch, &_inputState))) {
-            _touch->update(deltaTime, inputCalibrationData);
-        } else {
-            qCWarning(oculus) << "Unable to read Oculus touch input state";
+    bool updateRemote = false, updateTouch = false;
+
+    ovr::withSession([&](ovrSession session) {
+        if (_touch) {
+            updateTouch = OVR_SUCCESS(ovr_GetInputState(session, ovrControllerType_Touch, &_inputState));
+            if (!updateTouch) {
+                qCWarning(oculusLog) << "Unable to read Oculus touch input state" << ovr::getError();
+            }
         }
+        if (_remote) {
+            updateRemote = OVR_SUCCESS(ovr_GetInputState(session, ovrControllerType_Remote, &_inputState));
+            if (!updateRemote) {
+                qCWarning(oculusLog) << "Unable to read Oculus remote input state" << ovr::getError();
+            }
+        }
+    });
+
+
+    if (_touch && updateTouch) {
+        _touch->update(deltaTime, inputCalibrationData);
     }
 
-    if (_remote) {
-        if (OVR_SUCCESS(ovr_GetInputState(_session, ovrControllerType_Remote, &_inputState))) {
-            _remote->update(deltaTime, inputCalibrationData);
-        } else {
-            qCWarning(oculus) << "Unable to read Oculus remote input state";
-        }
+    if (_remote && updateRemote) {
+        _remote->update(deltaTime, inputCalibrationData);
     }
 }
 
@@ -210,15 +206,6 @@ void OculusControllerManager::RemoteDevice::focusOutEvent() {
     _buttonPressedMap.clear();
 }
 
-bool OculusControllerManager::isHeadControllerMounted() const {
-    ovrSessionStatus status;
-    bool success = OVR_SUCCESS(ovr_GetSessionStatus(_session, &status));
-    if (!success) {
-        return false;
-    }
-    return status.HmdMounted == ovrTrue;
-}
-
 void OculusControllerManager::TouchDevice::update(float deltaTime,
                                                   const controller::InputCalibrationData& inputCalibrationData) {
     _buttonPressedMap.clear();
@@ -226,10 +213,19 @@ void OculusControllerManager::TouchDevice::update(float deltaTime,
     int numTrackedControllers = 0;
     quint64 currentTime = usecTimestampNow();
     static const auto REQUIRED_HAND_STATUS = ovrStatus_OrientationTracked | ovrStatus_PositionTracked;
-    auto tracking = ovr_GetTrackingState(_parent._session, 0, false);
-    ovr_for_each_hand([&](ovrHandType hand) {
+    bool hasInputFocus = ovr::hasInputFocus();
+    auto tracking = ovr::getTrackingState(); // ovr_GetTrackingState(_parent._session, 0, false);
+    ovr::for_each_hand([&](ovrHandType hand) {
         ++numTrackedControllers;
         int controller = (hand == ovrHand_Left ? controller::LEFT_HAND : controller::RIGHT_HAND);
+
+        // Disable hand tracking while in Oculus Dash (Dash renders it's own hands)
+        if (!hasInputFocus) {
+            _poseStateMap.erase(controller);
+            _poseStateMap[controller].valid = false;
+            return;
+        }
+
         if (REQUIRED_HAND_STATUS == (tracking.HandStatusFlags[hand] & REQUIRED_HAND_STATUS)) {
             _poseStateMap.erase(controller);
             handlePose(deltaTime, inputCalibrationData, hand, tracking.HandPoses[hand]);
@@ -253,7 +249,7 @@ void OculusControllerManager::TouchDevice::update(float deltaTime,
         handleRotationForUntrackedHand(inputCalibrationData, hand, tracking.HandPoses[hand]);
     });
 
-    if (_parent.isHeadControllerMounted()) {
+    if (ovr::hmdMounted()) {
         handleHeadPose(deltaTime, inputCalibrationData, tracking.HeadPose);
     } else {
         _poseStateMap[controller::HEAD].valid = false;
@@ -311,7 +307,7 @@ void OculusControllerManager::TouchDevice::handlePose(float deltaTime,
                                                       ovrHandType hand, const ovrPoseStatef& handPose) {
     auto poseId = hand == ovrHand_Left ? controller::LEFT_HAND : controller::RIGHT_HAND;
     auto& pose = _poseStateMap[poseId];
-    pose = ovrControllerPoseToHandPose(hand, handPose);
+    pose = ovr::toControllerPose(hand, handPose);
     // transform into avatar frame
     glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat;
     pose = pose.transform(controllerToAvatar);
@@ -320,15 +316,15 @@ void OculusControllerManager::TouchDevice::handlePose(float deltaTime,
 void OculusControllerManager::TouchDevice::handleHeadPose(float deltaTime,
                                                           const controller::InputCalibrationData& inputCalibrationData,
                                                           const ovrPoseStatef& headPose) {
-    glm::mat4 mat = createMatFromQuatAndPos(toGlm(headPose.ThePose.Orientation),
-                                            toGlm(headPose.ThePose.Position));
+    glm::mat4 mat = createMatFromQuatAndPos(ovr::toGlm(headPose.ThePose.Orientation),
+                                            ovr::toGlm(headPose.ThePose.Position));
 
     //perform a 180 flip to make the HMD face the +z instead of -z, beacuse the head faces +z
     glm::mat4 matYFlip = mat * Matrices::Y_180;
     controller::Pose pose(extractTranslation(matYFlip),
                           glmExtractRotation(matYFlip),
-                          toGlm(headPose.LinearVelocity), // XXX * matYFlip ?
-                          toGlm(headPose.AngularVelocity));
+                          ovr::toGlm(headPose.LinearVelocity), // XXX * matYFlip ?
+                          ovr::toGlm(headPose.AngularVelocity));
 
     glm::mat4 sensorToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat;
     glm::mat4 defaultHeadOffset = glm::inverse(inputCalibrationData.defaultCenterEyeMat) *
@@ -343,7 +339,7 @@ void OculusControllerManager::TouchDevice::handleRotationForUntrackedHand(const
     auto poseId = (hand == ovrHand_Left ? controller::LEFT_HAND : controller::RIGHT_HAND);
     auto& pose = _poseStateMap[poseId];
     auto lastHandPose = _lastControllerPose[poseId];
-    pose = ovrControllerRotationToHandRotation(hand, handPose, lastHandPose);
+    pose = ovr::toControllerPose(hand, handPose, lastHandPose);
     glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat;
     pose = pose.transform(controllerToAvatar);
 }
@@ -351,36 +347,40 @@ void OculusControllerManager::TouchDevice::handleRotationForUntrackedHand(const
 bool OculusControllerManager::TouchDevice::triggerHapticPulse(float strength, float duration, controller::Hand hand) {
     Locker locker(_lock);
     bool toReturn = true;
-    if (hand == controller::BOTH || hand == controller::LEFT) {
-        if (strength == 0.0f) {
-            _leftHapticStrength = 0.0f;
-            _leftHapticDuration = 0.0f;
-        } else {
-            _leftHapticStrength = (duration > _leftHapticDuration) ? strength : _leftHapticStrength;
-            if (ovr_SetControllerVibration(_parent._session, ovrControllerType_LTouch, 1.0f, _leftHapticStrength) != ovrSuccess) {
-                toReturn = false;
+    ovr::withSession([&](ovrSession session) {
+        if (hand == controller::BOTH || hand == controller::LEFT) {
+            if (strength == 0.0f) {
+                _leftHapticStrength = 0.0f;
+                _leftHapticDuration = 0.0f;
+            } else {
+                _leftHapticStrength = (duration > _leftHapticDuration) ? strength : _leftHapticStrength;
+                if (ovr_SetControllerVibration(session, ovrControllerType_LTouch, 1.0f, _leftHapticStrength) != ovrSuccess) {
+                    toReturn = false;
+                }
+                _leftHapticDuration = std::max(duration, _leftHapticDuration);
             }
-            _leftHapticDuration = std::max(duration, _leftHapticDuration);
         }
-    }
-    if (hand == controller::BOTH || hand == controller::RIGHT) {
-        if (strength == 0.0f) {
-            _rightHapticStrength = 0.0f;
-            _rightHapticDuration = 0.0f;
-        } else {
-            _rightHapticStrength = (duration > _rightHapticDuration) ? strength : _rightHapticStrength;
-            if (ovr_SetControllerVibration(_parent._session, ovrControllerType_RTouch, 1.0f, _rightHapticStrength) != ovrSuccess) {
-                toReturn = false;
+        if (hand == controller::BOTH || hand == controller::RIGHT) {
+            if (strength == 0.0f) {
+                _rightHapticStrength = 0.0f;
+                _rightHapticDuration = 0.0f;
+            } else {
+                _rightHapticStrength = (duration > _rightHapticDuration) ? strength : _rightHapticStrength;
+                if (ovr_SetControllerVibration(session, ovrControllerType_RTouch, 1.0f, _rightHapticStrength) != ovrSuccess) {
+                    toReturn = false;
+                }
+                _rightHapticDuration = std::max(duration, _rightHapticDuration);
             }
-            _rightHapticDuration = std::max(duration, _rightHapticDuration);
         }
-    }
+    });
     return toReturn;
 }
 
 void OculusControllerManager::TouchDevice::stopHapticPulse(bool leftHand) {
     auto handType = (leftHand ? ovrControllerType_LTouch : ovrControllerType_RTouch);
-    ovr_SetControllerVibration(_parent._session, handType, 0.0f, 0.0f);
+    ovr::withSession([&](ovrSession session) {
+        ovr_SetControllerVibration(session, handType, 0.0f, 0.0f);
+    });
 }
 
 /**jsdoc
diff --git a/plugins/oculus/src/OculusControllerManager.h b/plugins/oculus/src/OculusControllerManager.h
index 69187f94a6..b08d54babe 100644
--- a/plugins/oculus/src/OculusControllerManager.h
+++ b/plugins/oculus/src/OculusControllerManager.h
@@ -26,10 +26,8 @@ public:
     // Plugin functions
     bool isSupported() const override;
     const QString getName() const override { return NAME; }
-
     bool isHandController() const override { return _touch != nullptr; }
     bool isHeadController() const override { return true; }
-    bool isHeadControllerMounted() const;
     QStringList getSubdeviceNames() override;
 
     bool activate() override;
@@ -105,7 +103,6 @@ private:
 
     void checkForConnectedDevices();
 
-    ovrSession _session { nullptr };
     ovrInputState _inputState {};
     RemoteDevice::Pointer _remote;
     TouchDevice::Pointer _touch;
diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp
index 0fd8467e38..308652cacd 100644
--- a/plugins/oculus/src/OculusDisplayPlugin.cpp
+++ b/plugins/oculus/src/OculusDisplayPlugin.cpp
@@ -19,6 +19,8 @@
 
 #include "OculusHelpers.h"
 
+using namespace hifi;
+
 const char* OculusDisplayPlugin::NAME { "Oculus Rift" };
 static ovrPerfHudMode currentDebugMode = ovrPerfHud_Off;
 
@@ -63,7 +65,7 @@ void OculusDisplayPlugin::cycleDebugOutput() {
 
 void OculusDisplayPlugin::customizeContext() {
     Parent::customizeContext();
-    _outputFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OculusOutput", gpu::Element::COLOR_SRGBA_32, _renderTargetSize.x, _renderTargetSize.y));
+    _outputFramebuffer.reset(gpu::Framebuffer::create("OculusOutput", gpu::Element::COLOR_SRGBA_32, _renderTargetSize.x, _renderTargetSize.y));
     ovrTextureSwapChainDesc desc = { };
     desc.Type = ovrTexture_2D;
     desc.ArraySize = 1;
@@ -76,14 +78,14 @@ void OculusDisplayPlugin::customizeContext() {
 
     ovrResult result = ovr_CreateTextureSwapChainGL(_session, &desc, &_textureSwapChain);
     if (!OVR_SUCCESS(result)) {
-        logCritical("Failed to create swap textures");
+        qCritical(oculusLog) << "Failed to create swap textures" << ovr::getError();
         return;
     }
 
     int length = 0;
     result = ovr_GetTextureSwapChainLength(_session, _textureSwapChain, &length);
     if (!OVR_SUCCESS(result) || !length) {
-        logCritical("Unable to count swap chain textures");
+        qCritical(oculusLog) << "Unable to count swap chain textures" << ovr::getError();
         return;
     }
     for (int i = 0; i < length; ++i) {
@@ -164,8 +166,8 @@ void OculusDisplayPlugin::hmdPresent() {
         auto result = ovr_CommitTextureSwapChain(_session, _textureSwapChain);
         Q_ASSERT(OVR_SUCCESS(result));
         _sceneLayer.SensorSampleTime = _currentPresentFrameInfo.sensorSampleTime;
-        _sceneLayer.RenderPose[ovrEyeType::ovrEye_Left] = ovrPoseFromGlm(_currentPresentFrameInfo.renderPose);
-        _sceneLayer.RenderPose[ovrEyeType::ovrEye_Right] = ovrPoseFromGlm(_currentPresentFrameInfo.renderPose);
+        _sceneLayer.RenderPose[ovrEyeType::ovrEye_Left] = ovr::poseFromGlm(_currentPresentFrameInfo.renderPose);
+        _sceneLayer.RenderPose[ovrEyeType::ovrEye_Right] = ovr::poseFromGlm(_currentPresentFrameInfo.renderPose);
 
         auto submitStart = usecTimestampNow();
         uint64_t nonSubmitInterval = 0;
@@ -192,7 +194,7 @@ void OculusDisplayPlugin::hmdPresent() {
         }
 
         if (!OVR_SUCCESS(result)) {
-            logWarning("Failed to present");
+            qWarning(oculusLog) << "Failed to present" << ovr::getError();
         }
 
         static int compositorDroppedFrames = 0;
@@ -234,9 +236,7 @@ QJsonObject OculusDisplayPlugin::getHardwareStats() const {
 }
 
 bool OculusDisplayPlugin::isHmdMounted() const {
-    ovrSessionStatus status;
-    return (OVR_SUCCESS(ovr_GetSessionStatus(_session, &status)) &&
-        (ovrFalse != status.HmdMounted));
+    return ovr::hmdMounted();
 }
 
 QString OculusDisplayPlugin::getPreferredAudioInDevice() const {
diff --git a/plugins/oculus/src/OculusHelpers.cpp b/plugins/oculus/src/OculusHelpers.cpp
index 4632c8ab76..511984c657 100644
--- a/plugins/oculus/src/OculusHelpers.cpp
+++ b/plugins/oculus/src/OculusHelpers.cpp
@@ -24,41 +24,17 @@
 #include <NumericalConstants.h>
 
 Q_LOGGING_CATEGORY(displayplugins, "hifi.plugins.display")
-Q_LOGGING_CATEGORY(oculus, "hifi.plugins.display.oculus")
-
-static std::atomic<uint32_t> refCount { 0 };
-static ovrSession session { nullptr };
-
-static bool _quitRequested { false };
-static bool _reorientRequested { false };
-
-inline ovrErrorInfo getError() {
-    ovrErrorInfo error;
-    ovr_GetLastErrorInfo(&error);
-    return error;
-}
-
-void logWarning(const char* what) {
-    qWarning(oculus) << what << ":" << getError().ErrorString;
-}
-
-void logCritical(const char* what) {
-    std::string error("[oculus] ");
-    error += what;
-    error += ": ";
-    error += getError().ErrorString;
-    qCritical(error.c_str());
-}
+Q_LOGGING_CATEGORY(oculusLog, "hifi.plugins.display.oculus")
 
+using namespace hifi;
 
 static wchar_t* REQUIRED_OCULUS_DLL = L"LibOVRRT64_1.dll";
 static wchar_t FOUND_PATH[MAX_PATH];
 
-bool oculusAvailable() {
+bool ovr::available() {
     static std::once_flag once;
-    static bool result { false };
+    static bool result{ false };
     std::call_once(once, [&] {
-
         static const QString DEBUG_FLAG("HIFI_DEBUG_OPENVR");
         static bool enableDebugOpenVR = QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG);
         if (enableDebugOpenVR) {
@@ -81,113 +57,107 @@ bool oculusAvailable() {
     return result;
 }
 
-ovrSession acquireOculusSession() {
-    if (!session && !oculusAvailable()) {
-        qCDebug(oculus) << "oculus: no runtime or HMD present";
+class ovrImpl {
+    using Mutex = std::mutex;
+    using Lock = std::unique_lock<Mutex>;
+    std::mutex mutex;
+    ovrSession session{ nullptr };
+    size_t renderCount{ 0 };
+
+private:
+    void setupSession(bool render) {
+        if (session) {
+            return;
+        }
+        ovrInitParams initParams{ ovrInit_RequestVersion | ovrInit_FocusAware, OVR_MINOR_VERSION, nullptr, 0, 0 };
+        if (render) {
+            initParams.Flags |= ovrInit_MixedRendering;
+        } else {
+            initParams.Flags |= ovrInit_Invisible;
+        }
+
+        if (!OVR_SUCCESS(ovr_Initialize(&initParams))) {
+            qCWarning(oculusLog) << "Failed to initialze Oculus SDK" << ovr::getError();
+            return;
+        }
+
+        ovrGraphicsLuid luid;
+        if (!OVR_SUCCESS(ovr_Create(&session, &luid))) {
+            qCWarning(oculusLog) << "Failed to acquire Oculus session" << ovr::getError();
+            return;
+        }
+    }
+
+    void releaseSession() {
+        if (!session) {
+            return;
+        }
+        ovr_Destroy(session);
+        session = nullptr;
+        ovr_Shutdown();
+    }
+
+public:
+    void withSession(const std::function<void(ovrSession)>& f) {
+        Lock lock(mutex);
+        if (!session) {
+            setupSession(false);
+        }
+        f(session);
+    }
+
+    ovrSession acquireRenderSession() {
+        Lock lock(mutex);
+        if (renderCount++ == 0) {
+            releaseSession();
+            setupSession(true);
+        }
         return session;
     }
 
-    if (!session) {
-        ovrInitParams initParams {
-            ovrInit_RequestVersion | ovrInit_MixedRendering, OVR_MINOR_VERSION, nullptr, 0, 0
-        };
-
-        if (!OVR_SUCCESS(ovr_Initialize(&initParams))) {
-            logWarning("Failed to initialize Oculus SDK");
-            return session;
-        }
-
-#ifdef OCULUS_APP_ID
-        if (qApp->property(hifi::properties::OCULUS_STORE).toBool()) {
-            if (ovr_PlatformInitializeWindows(OCULUS_APP_ID) != ovrPlatformInitialize_Success) {
-                // we were unable to initialize the platform for entitlement check - fail the check
-                _quitRequested = true;
-            } else {
-                qCDebug(oculus) << "Performing Oculus Platform entitlement check";
-                ovr_Entitlement_GetIsViewerEntitled();
-            }
-        }
-#endif
-
-        Q_ASSERT(0 == refCount);
-        ovrGraphicsLuid luid;
-        if (!OVR_SUCCESS(ovr_Create(&session, &luid))) {
-            logWarning("Failed to acquire Oculus session");
-            return session;
+    void releaseRenderSession(ovrSession session) {
+        Lock lock(mutex);
+        if (--renderCount == 0) {
+            releaseSession();
         }
     }
+} _ovr;
 
-    ++refCount;
-    return session;
+ovrSession ovr::acquireRenderSession() {
+    return _ovr.acquireRenderSession();
 }
 
-void releaseOculusSession() {
-    Q_ASSERT(refCount > 0 && session);
-    // HACK the Oculus runtime doesn't seem to play well with repeated shutdown / restart.
-    // So for now we'll just hold on to the session
-#if 0
-    if (!--refCount) {
-        qCDebug(oculus) << "oculus: zero refcount, shutdown SDK and session";
-        ovr_Destroy(session);
-        ovr_Shutdown();
-        session = nullptr;
-    }
-#endif
+void ovr::releaseRenderSession(ovrSession session) {
+    _ovr.releaseRenderSession(session);
 }
 
-void handleOVREvents() {
-    if (!session) {
-        return;
-    }
+void ovr::withSession(const std::function<void(ovrSession)>& f) {
+    _ovr.withSession(f);
+}
 
-    ovrSessionStatus status;
-    if (!OVR_SUCCESS(ovr_GetSessionStatus(session, &status))) {
-        return;
-    }
-
-    _quitRequested = status.ShouldQuit;
-    _reorientRequested = status.ShouldRecenter;
-
- #ifdef OCULUS_APP_ID
-
-    if (qApp->property(hifi::properties::OCULUS_STORE).toBool()) {
-        // pop messages to see if we got a return for an entitlement check
-        ovrMessageHandle message = ovr_PopMessage();
-
-        while (message) {
-            switch (ovr_Message_GetType(message)) {
-                case ovrMessage_Entitlement_GetIsViewerEntitled: {
-                    if (!ovr_Message_IsError(message)) {
-                        // this viewer is entitled, no need to flag anything
-                        qCDebug(oculus) << "Oculus Platform entitlement check succeeded, proceeding normally";
-                    } else {
-                        // we failed the entitlement check, set our flag so the app can stop
-                        qCDebug(oculus) << "Oculus Platform entitlement check failed, app will now quit" << OCULUS_APP_ID;
-                        _quitRequested = true;
-                    }
-                }
-            }
-
-            // free the message handle to cleanup and not leak
-            ovr_FreeMessage(message);
-
-            // pop the next message to check, if there is one
-            message = ovr_PopMessage();
+ovrSessionStatus ovr::getStatus() {
+    ovrSessionStatus status{};
+    withSession([&](ovrSession session) {
+        if (!OVR_SUCCESS(ovr_GetSessionStatus(session, &status))) {
+            qCWarning(oculusLog) << "Failed to get session status" << ovr::getError();
         }
-    }
-#endif
+    });
+    return status;
 }
 
-bool quitRequested() {
-    return _quitRequested;
-}
-bool reorientRequested() {
-    return _reorientRequested;
+ovrTrackingState ovr::getTrackingState() {
+    ovrTrackingState result{};
+    withSession([&](ovrSession session) { result = ovr_GetTrackingState(session, 0, ovrFalse); });
+    return result;
 }
 
-controller::Pose ovrControllerPoseToHandPose(
-    ovrHandType hand,
-    const ovrPoseStatef& handPose) {
+QString ovr::getError() {
+    static ovrErrorInfo error;
+    ovr_GetLastErrorInfo(&error);
+    return QString(error.ErrorString);
+}
+
+controller::Pose hifi::ovr::toControllerPose(ovrHandType hand, const ovrPoseStatef& handPose) {
     // When the sensor-to-world rotation is identity the coordinate axes look like this:
     //
     //                       user
@@ -247,9 +217,8 @@ controller::Pose ovrControllerPoseToHandPose(
     static const glm::quat rightRotationOffset = glm::inverse(rightQuarterZ) * touchToHand;
 
     static const float CONTROLLER_LENGTH_OFFSET = 0.0762f;  // three inches
-    static const glm::vec3 CONTROLLER_OFFSET = glm::vec3(CONTROLLER_LENGTH_OFFSET / 2.0f,
-        -CONTROLLER_LENGTH_OFFSET / 2.0f,
-        CONTROLLER_LENGTH_OFFSET * 1.5f);
+    static const glm::vec3 CONTROLLER_OFFSET =
+        glm::vec3(CONTROLLER_LENGTH_OFFSET / 2.0f, -CONTROLLER_LENGTH_OFFSET / 2.0f, CONTROLLER_LENGTH_OFFSET * 1.5f);
     static const glm::vec3 leftTranslationOffset = glm::vec3(-1.0f, 1.0f, 1.0f) * CONTROLLER_OFFSET;
     static const glm::vec3 rightTranslationOffset = CONTROLLER_OFFSET;
 
@@ -268,12 +237,13 @@ controller::Pose ovrControllerPoseToHandPose(
     return pose;
 }
 
-controller::Pose ovrControllerRotationToHandRotation(ovrHandType hand, const ovrPoseStatef& handPose,
-                                                    const ovrPoseStatef& lastHandPose) {
+controller::Pose hifi::ovr::toControllerPose(ovrHandType hand,
+                                             const ovrPoseStatef& handPose,
+                                             const ovrPoseStatef& lastHandPose) {
     static const glm::quat yFlip = glm::angleAxis(PI, Vectors::UNIT_Y);
     static const glm::quat quarterX = glm::angleAxis(PI_OVER_TWO, Vectors::UNIT_X);
     static const glm::quat touchToHand = yFlip * quarterX;
-    
+
     static const glm::quat leftQuarterZ = glm::angleAxis(-PI_OVER_TWO, Vectors::UNIT_Z);
     static const glm::quat rightQuarterZ = glm::angleAxis(PI_OVER_TWO, Vectors::UNIT_Z);
 
@@ -281,9 +251,8 @@ controller::Pose ovrControllerRotationToHandRotation(ovrHandType hand, const ovr
     static const glm::quat rightRotationOffset = glm::inverse(rightQuarterZ) * touchToHand;
 
     static const float CONTROLLER_LENGTH_OFFSET = 0.0762f;  // three inches
-    static const glm::vec3 CONTROLLER_OFFSET = glm::vec3(CONTROLLER_LENGTH_OFFSET / 2.0f,
-        -CONTROLLER_LENGTH_OFFSET / 2.0f,
-        CONTROLLER_LENGTH_OFFSET * 1.5f);
+    static const glm::vec3 CONTROLLER_OFFSET =
+        glm::vec3(CONTROLLER_LENGTH_OFFSET / 2.0f, -CONTROLLER_LENGTH_OFFSET / 2.0f, CONTROLLER_LENGTH_OFFSET * 1.5f);
     static const glm::vec3 leftTranslationOffset = glm::vec3(-1.0f, 1.0f, 1.0f) * CONTROLLER_OFFSET;
     static const glm::vec3 rightTranslationOffset = CONTROLLER_OFFSET;
 
@@ -301,3 +270,52 @@ controller::Pose ovrControllerRotationToHandRotation(ovrHandType hand, const ovr
     pose.valid = true;
     return pose;
 }
+
+// FIXME These should be moved to an oculusPlatform plugin, they don't interact with the controller or session state
+#if 0 
+void handleOVREvents() {
+    updateSessionStatus(true);
+
+#ifdef OCULUS_APP_ID
+
+    if (qApp->property(hifi::properties::OCULUS_STORE).toBool()) {
+        // pop messages to see if we got a return for an entitlement check
+        ovrMessageHandle message = ovr_PopMessage();
+
+        while (message) {
+            switch (ovr_Message_GetType(message)) {
+            case ovrMessage_Entitlement_GetIsViewerEntitled:
+            {
+                if (!ovr_Message_IsError(message)) {
+                    // this viewer is entitled, no need to flag anything
+                    qCDebug(oculus) << "Oculus Platform entitlement check succeeded, proceeding normally";
+                } else {
+                    // we failed the entitlement check, set our flag so the app can stop
+                    qCDebug(oculus) << "Oculus Platform entitlement check failed, app will now quit" << OCULUS_APP_ID;
+                    _quitRequested = true;
+                }
+            }
+            }
+
+            // free the message handle to cleanup and not leak
+            ovr_FreeMessage(message);
+
+            // pop the next message to check, if there is one
+            message = ovr_PopMessage();
+        }
+    }
+#endif
+}
+
+#ifdef OCULUS_APP_ID
+if (qApp->property(hifi::properties::OCULUS_STORE).toBool()) {
+    if (ovr_PlatformInitializeWindows(OCULUS_APP_ID) != ovrPlatformInitialize_Success) {
+        // we were unable to initialize the platform for entitlement check - fail the check
+        _quitRequested = true;
+    } else {
+        qCDebug(oculusLog) << "Performing Oculus Platform entitlement check";
+        ovr_Entitlement_GetIsViewerEntitled();
+    }
+}
+#endif
+#endif
diff --git a/plugins/oculus/src/OculusHelpers.h b/plugins/oculus/src/OculusHelpers.h
index 5743f8576b..6588d9754b 100644
--- a/plugins/oculus/src/OculusHelpers.h
+++ b/plugins/oculus/src/OculusHelpers.h
@@ -7,10 +7,9 @@
 //
 #pragma once
 
-
 #include <QtCore/QLoggingCategory>
 
-#include <OVR_CAPI_GL.h>
+#include <ovr_capi.h>
 #include <GLMHelpers.h>
 #include <glm/gtc/type_ptr.hpp>
 #include <glm/gtc/matrix_transform.hpp>
@@ -18,106 +17,107 @@
 #include <controllers/Forward.h>
 
 Q_DECLARE_LOGGING_CATEGORY(displayplugins)
-Q_DECLARE_LOGGING_CATEGORY(oculus)
+Q_DECLARE_LOGGING_CATEGORY(oculusLog)
 
-void logWarning(const char* what);
-void logCritical(const char* what);
-bool oculusAvailable();
-ovrSession acquireOculusSession();
-void releaseOculusSession();
+namespace hifi { 
+    
+struct ovr {
+    static bool available();
+    static ovrSession acquireRenderSession();
+    static void releaseRenderSession(ovrSession session);
+    static void withSession(const std::function<void(ovrSession)>& f);
+    static ovrSessionStatus getStatus();
+    static ovrTrackingState getTrackingState();
+    static QString getError();
 
-void handleOVREvents();
-bool quitRequested();
-bool reorientRequested();
+    static inline bool quitRequested() { return quitRequested(getStatus()); }
+    static inline bool reorientRequested() { return reorientRequested(getStatus()); }
+    static inline bool hmdMounted() { return hmdMounted(getStatus()); }
+    static inline bool hasInputFocus() { return hasInputFocus(getStatus()); }
 
-// Convenience method for looping over each eye with a lambda
-template <typename Function>
-inline void ovr_for_each_eye(Function function) {
-    for (ovrEyeType eye = ovrEyeType::ovrEye_Left;
-        eye < ovrEyeType::ovrEye_Count;
-        eye = static_cast<ovrEyeType>(eye + 1)) {
-        function(eye);
+    static inline bool quitRequested(const ovrSessionStatus& status) { return status.ShouldQuit != ovrFalse; }
+    static inline bool reorientRequested(const ovrSessionStatus& status) { return status.ShouldRecenter != ovrFalse; }
+    static inline bool hmdMounted(const ovrSessionStatus& status) { return status.HmdMounted != ovrFalse; }
+    static inline bool hasInputFocus(const ovrSessionStatus& status) { return status.HasInputFocus != ovrFalse; }
+
+    // Convenience method for looping over each eye with a lambda
+    static inline void for_each_eye(const std::function<void(ovrEyeType eye)>& f) {
+        for (ovrEyeType eye = ovrEye_Left; eye < ovrEye_Count; eye = static_cast<ovrEyeType>(eye + 1)) {
+            f(eye);
+        }
     }
-}
 
-template <typename Function>
-inline void ovr_for_each_hand(Function function) {
-    for (ovrHandType hand = ovrHandType::ovrHand_Left;
-        hand <= ovrHandType::ovrHand_Right;
-        hand = static_cast<ovrHandType>(hand + 1)) {
-        function(hand);
+    static inline void for_each_hand(const std::function<void(ovrHandType eye)>& f) {
+        for (ovrHandType hand = ovrHand_Left; hand < ovrHand_Count; hand = static_cast<ovrHandType>(hand + 1)) {
+            f(hand);
+        }
     }
-}
 
+    static inline glm::mat4 toGlm(const ovrMatrix4f& om) {
+        return glm::transpose(glm::make_mat4(&om.M[0][0]));
+    }
 
+    static inline glm::mat4 toGlm(const ovrFovPort& fovport, float nearPlane = 0.01f, float farPlane = 10000.0f) {
+        return toGlm(ovrMatrix4f_Projection(fovport, nearPlane, farPlane, true));
+    }
 
+    static inline glm::vec3 toGlm(const ovrVector3f& ov) {
+        return glm::make_vec3(&ov.x);
+    }
 
+    static inline glm::vec2 toGlm(const ovrVector2f& ov) {
+        return glm::make_vec2(&ov.x);
+    }
 
-inline glm::mat4 toGlm(const ovrMatrix4f & om) {
-    return glm::transpose(glm::make_mat4(&om.M[0][0]));
-}
+    static inline glm::uvec2 toGlm(const ovrSizei& ov) {
+        return glm::uvec2(ov.w, ov.h);
+    }
 
-inline glm::mat4 toGlm(const ovrFovPort & fovport, float nearPlane = 0.01f, float farPlane = 10000.0f) {
-    return toGlm(ovrMatrix4f_Projection(fovport, nearPlane, farPlane, true));
-}
+    static inline glm::quat toGlm(const ovrQuatf& oq) {
+        return glm::make_quat(&oq.x);
+    }
 
-inline glm::vec3 toGlm(const ovrVector3f & ov) {
-    return glm::make_vec3(&ov.x);
-}
+    static inline glm::mat4 toGlm(const ovrPosef& op) {
+        glm::mat4 orientation = glm::mat4_cast(toGlm(op.Orientation));
+        glm::mat4 translation = glm::translate(glm::mat4(), toGlm(op.Position));
+        return translation * orientation;
+    }
 
-inline glm::vec2 toGlm(const ovrVector2f & ov) {
-    return glm::make_vec2(&ov.x);
-}
+    static inline ovrMatrix4f fromGlm(const glm::mat4& m) {
+        ovrMatrix4f result;
+        glm::mat4 transposed(glm::transpose(m));
+        memcpy(result.M, &(transposed[0][0]), sizeof(float) * 16);
+        return result;
+    }
 
-inline glm::uvec2 toGlm(const ovrSizei & ov) {
-    return glm::uvec2(ov.w, ov.h);
-}
+    static inline ovrVector3f fromGlm(const glm::vec3& v) {
+        return { v.x, v.y, v.z };
+    }
 
-inline glm::quat toGlm(const ovrQuatf & oq) {
-    return glm::make_quat(&oq.x);
-}
+    static inline ovrVector2f fromGlm(const glm::vec2& v) {
+        return { v.x, v.y };
+    }
 
-inline glm::mat4 toGlm(const ovrPosef & op) {
-    glm::mat4 orientation = glm::mat4_cast(toGlm(op.Orientation));
-    glm::mat4 translation = glm::translate(glm::mat4(), toGlm(op.Position));
-    return translation * orientation;
-}
+    static inline ovrSizei fromGlm(const glm::uvec2& v) {
+        return { (int)v.x, (int)v.y };
+    }
 
-inline ovrMatrix4f ovrFromGlm(const glm::mat4 & m) {
-    ovrMatrix4f result;
-    glm::mat4 transposed(glm::transpose(m));
-    memcpy(result.M, &(transposed[0][0]), sizeof(float) * 16);
-    return result;
-}
+    static inline ovrQuatf fromGlm(const glm::quat& q) {
+        return { q.x, q.y, q.z, q.w };
+    }
 
-inline ovrVector3f ovrFromGlm(const glm::vec3 & v) {
-    return{ v.x, v.y, v.z };
-}
+    static inline ovrPosef poseFromGlm(const glm::mat4& m) {
+        glm::vec3 translation = glm::vec3(m[3]) / m[3].w;
+        glm::quat orientation = glm::quat_cast(m);
+        ovrPosef result;
+        result.Orientation = fromGlm(orientation);
+        result.Position = fromGlm(translation);
+        return result;
+    }
 
-inline ovrVector2f ovrFromGlm(const glm::vec2 & v) {
-    return{ v.x, v.y };
-}
+    static controller::Pose toControllerPose(ovrHandType hand, const ovrPoseStatef& handPose);
+    static controller::Pose toControllerPose(ovrHandType hand, const ovrPoseStatef& handPose, const ovrPoseStatef& lastHandPose);
 
-inline ovrSizei ovrFromGlm(const glm::uvec2 & v) {
-    return{ (int)v.x, (int)v.y };
-}
+};
 
-inline ovrQuatf ovrFromGlm(const glm::quat & q) {
-    return{ q.x, q.y, q.z, q.w };
-}
-
-inline ovrPosef ovrPoseFromGlm(const glm::mat4 & m) {
-    glm::vec3 translation = glm::vec3(m[3]) / m[3].w;
-    glm::quat orientation = glm::quat_cast(m);
-    ovrPosef result;
-    result.Orientation = ovrFromGlm(orientation);
-    result.Position = ovrFromGlm(translation);
-    return result; 
-}
-
-controller::Pose ovrControllerPoseToHandPose(
-    ovrHandType hand,
-    const ovrPoseStatef& handPose);
-
-controller::Pose ovrControllerRotationToHandRotation(ovrHandType hand,
-                                         const ovrPoseStatef& handPose, const ovrPoseStatef& lastHandPose);
+}  // namespace hifi