diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 75a9f598f7..0e235af98a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2867,8 +2867,10 @@ void Application::initializeDisplayPlugins() { [this](const QSize& size) { resizeGL(); }); QObject::connect(displayPlugin.get(), &DisplayPlugin::resetSensorsRequested, this, &Application::requestReset); if (displayPlugin->isHmd()) { - QObject::connect(dynamic_cast(displayPlugin.get()), &HmdDisplayPlugin::hmdMountedChanged, + auto hmdDisplayPlugin = dynamic_cast(displayPlugin.get()); + QObject::connect(hmdDisplayPlugin, &HmdDisplayPlugin::hmdMountedChanged, DependencyManager::get().data(), &HMDScriptingInterface::mountedChanged); + QObject::connect(hmdDisplayPlugin, &HmdDisplayPlugin::hmdVisibleChanged, this, &Application::hmdVisibleChanged); } } @@ -6521,6 +6523,14 @@ void Application::resetSensors(bool andReload) { QMetaObject::invokeMethod(DependencyManager::get().data(), "reset", Qt::QueuedConnection); } +void Application::hmdVisibleChanged(bool visible) { + if (visible) { + QMetaObject::invokeMethod(DependencyManager::get().data(), "start", Qt::QueuedConnection); + } else { + QMetaObject::invokeMethod(DependencyManager::get().data(), "stop", Qt::QueuedConnection); + } +} + void Application::updateWindowTitle() const { auto nodeList = DependencyManager::get(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 14e30b8006..b2a41dc421 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -382,6 +382,8 @@ public slots: void resetSensors(bool andReload = false); void setActiveFaceTracker() const; + void hmdVisibleChanged(bool visible); + #if (PR_BUILD || DEV_BUILD) void sendWrongProtocolVersionsSignature(bool checked) { ::sendWrongProtocolVersionsSignature(checked); } #endif diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 729bfd9e45..b6fffbb4bd 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include "Application.h" #include "ui/DialogsManager.h" @@ -309,7 +310,13 @@ QString LODManager::getLODFeedbackText() { void LODManager::loadSettings() { setDesktopLODTargetFPS(desktopLODDecreaseFPS.get()); - setHMDLODTargetFPS(hmdLODDecreaseFPS.get()); + Setting::Handle firstRun { Settings::firstRun, true }; + if (qApp->property(hifi::properties::OCULUS_STORE).toBool() && firstRun.get()) { + const float LOD_HIGH_QUALITY_LEVEL = 0.75f; + setHMDLODTargetFPS(LOD_HIGH_QUALITY_LEVEL * LOD_MAX_LIKELY_HMD_FPS); + } else { + setHMDLODTargetFPS(hmdLODDecreaseFPS.get()); + } } void LODManager::saveSettings() { diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h index ea11832e94..a56daaad83 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h @@ -48,6 +48,7 @@ public: signals: void hmdMountedChanged(); + void hmdVisibleChanged(bool visible); protected: virtual void hmdPresent() = 0; diff --git a/libraries/qml/src/qml/OffscreenSurface.cpp b/libraries/qml/src/qml/OffscreenSurface.cpp index cbcafe9c7d..91532534e3 100644 --- a/libraries/qml/src/qml/OffscreenSurface.cpp +++ b/libraries/qml/src/qml/OffscreenSurface.cpp @@ -317,7 +317,7 @@ void OffscreenSurface::loadInternal(const QUrl& qmlSource, { PROFILE_RANGE(app, "new QQmlComponent"); qmlComponent = new QQmlComponent(getSurfaceContext()->engine(), finalQmlSource, QQmlComponent::PreferSynchronous); - } + } if (qmlComponent->isLoading()) { connect(qmlComponent, &QQmlComponent::statusChanged, this, [=](QQmlComponent::Status) { finishQmlLoad(qmlComponent, targetContext, parent, callback); }); diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp index 0e4dac796d..f10aba7920 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp @@ -23,13 +23,14 @@ void OculusBaseDisplayPlugin::resetSensors() { } bool OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) { - ovrSessionStatus status{}; - if (!OVR_SUCCESS(ovr_GetSessionStatus(_session, &status))) { + ovrResult getStatusResult; + ovrSessionStatus status = ovr::getStatus(getStatusResult); + if (!OVR_SUCCESS(getStatusResult)) { qCWarning(oculusLog) << "Unable to fetch Oculus session status" << ovr::getError(); return false; } - if (ovr::quitRequested(status)) { + if (ovr::quitRequested(status) || ovr::displayLost(status) || !ovr::handleOVREvents()) { QMetaObject::invokeMethod(qApp, "quit"); return false; } @@ -40,11 +41,15 @@ bool OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) { _hmdMounted = !_hmdMounted; emit hmdMountedChanged(); } + if (ovr::isVisible(status) != _visible) { + _visible = !_visible; + emit hmdVisibleChanged(_visible); + } _currentRenderFrameInfo = FrameInfo(); _currentRenderFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds(); _currentRenderFrameInfo.predictedDisplayTime = ovr_GetPredictedDisplayTime(_session, frameIndex); - auto trackingState = ovr_GetTrackingState(_session, _currentRenderFrameInfo.predictedDisplayTime, ovrTrue); + auto trackingState = ovr::getTrackingState(_currentRenderFrameInfo.predictedDisplayTime, ovrTrue); _currentRenderFrameInfo.renderPose = ovr::toGlm(trackingState.HeadPose.ThePose); _currentRenderFrameInfo.presentPose = _currentRenderFrameInfo.renderPose; @@ -167,7 +172,7 @@ void OculusBaseDisplayPlugin::updatePresentPose() { ovrTrackingState trackingState; _currentPresentFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds(); _currentPresentFrameInfo.predictedDisplayTime = ovr_GetPredictedDisplayTime(_session, 0); - trackingState = ovr_GetTrackingState(_session, _currentRenderFrameInfo.predictedDisplayTime, ovrFalse); + trackingState = ovr::getTrackingState(_currentRenderFrameInfo.predictedDisplayTime); _currentPresentFrameInfo.presentPose = ovr::toGlm(trackingState.HeadPose.ThePose); _currentPresentFrameInfo.renderPose = _currentPresentFrameInfo.presentPose; } diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.h b/plugins/oculus/src/OculusBaseDisplayPlugin.h index f71fb8ece8..547d3ee5fe 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.h +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.h @@ -48,4 +48,5 @@ protected: ovrViewScaleDesc _viewScaleDesc; // ovrLayerEyeFovDepth _depthLayer; bool _hmdMounted { false }; + bool _visible { true }; }; diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp index 308652cacd..a34e647a5e 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDisplayPlugin.cpp @@ -134,6 +134,10 @@ void OculusDisplayPlugin::hmdPresent() { return; } + if (!_visible) { + return; + } + PROFILE_RANGE_EX(render, __FUNCTION__, 0xff00ff00, (uint64_t)_currentFrame->frameIndex) { @@ -195,6 +199,10 @@ void OculusDisplayPlugin::hmdPresent() { if (!OVR_SUCCESS(result)) { qWarning(oculusLog) << "Failed to present" << ovr::getError(); + if (result == ovrError_DisplayLost) { + qWarning(oculusLog) << "Display lost, shutting down"; + return; + } } static int compositorDroppedFrames = 0; diff --git a/plugins/oculus/src/OculusHelpers.cpp b/plugins/oculus/src/OculusHelpers.cpp index 402b05f39c..29691e73a5 100644 --- a/plugins/oculus/src/OculusHelpers.cpp +++ b/plugins/oculus/src/OculusHelpers.cpp @@ -81,6 +81,18 @@ private: return; } +#ifdef OCULUS_APP_ID + if (qApp->property(hifi::properties::OCULUS_STORE).toBool()) { + if (ovr_PlatformInitializeWindows(OCULUS_APP_ID) != ovrPlatformInitialize_Success) { + qCWarning(oculusLog) << "Unable to initialize the platform for entitlement check - fail the check" << ovr::getError(); + return; + } else { + qCDebug(oculusLog) << "Performing Oculus Platform entitlement check"; + ovr_Entitlement_GetIsViewerEntitled(); + } + } +#endif + ovrGraphicsLuid luid; if (!OVR_SUCCESS(ovr_Create(&session, &luid))) { qCWarning(oculusLog) << "Failed to acquire Oculus session" << ovr::getError(); @@ -141,18 +153,24 @@ void ovr::withSession(const std::function& f) { } ovrSessionStatus ovr::getStatus() { + ovrResult result; + return ovr::getStatus(result); +} + +ovrSessionStatus ovr::getStatus(ovrResult& result) { ovrSessionStatus status{}; withSession([&](ovrSession session) { - if (!OVR_SUCCESS(ovr_GetSessionStatus(session, &status))) { + result = ovr_GetSessionStatus(session, &status); + if (!OVR_SUCCESS(result)) { qCWarning(oculusLog) << "Failed to get session status" << ovr::getError(); } }); return status; } -ovrTrackingState ovr::getTrackingState() { +ovrTrackingState ovr::getTrackingState(double absTime, ovrBool latencyMarker) { ovrTrackingState result{}; - withSession([&](ovrSession session) { result = ovr_GetTrackingState(session, 0, ovrFalse); }); + withSession([&](ovrSession session) { result = ovr_GetTrackingState(session, absTime, latencyMarker); }); return result; } @@ -276,31 +294,25 @@ controller::Pose hifi::ovr::toControllerPose(ovrHandType hand, 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); - +bool hifi::ovr::handleOVREvents() { #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; + case ovrMessage_Entitlement_GetIsViewerEntitled: { + if (!ovr_Message_IsError(message)) { + // this viewer is entitled, no need to flag anything + qCDebug(oculusLog) << "Oculus Platform entitlement check succeeded, proceeding normally"; + } else { + // we failed the entitlement check, quit + qCDebug(oculusLog) << "Oculus Platform entitlement check failed, app will now quit" << OCULUS_APP_ID; + return false; + } } } - } // free the message handle to cleanup and not leak ovr_FreeMessage(message); @@ -310,17 +322,5 @@ void handleOVREvents() { } } #endif + return true; } - -#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 6588d9754b..bdfc4434bb 100644 --- a/plugins/oculus/src/OculusHelpers.h +++ b/plugins/oculus/src/OculusHelpers.h @@ -27,8 +27,10 @@ struct ovr { static void releaseRenderSession(ovrSession session); static void withSession(const std::function& f); static ovrSessionStatus getStatus(); - static ovrTrackingState getTrackingState(); + static ovrSessionStatus getStatus(ovrResult& result); + static ovrTrackingState getTrackingState(double absTime = 0.0, ovrBool latencyMarker = ovrFalse); static QString getError(); + static bool handleOVREvents(); static inline bool quitRequested() { return quitRequested(getStatus()); } static inline bool reorientRequested() { return reorientRequested(getStatus()); } @@ -36,6 +38,8 @@ struct ovr { static inline bool hasInputFocus() { return hasInputFocus(getStatus()); } static inline bool quitRequested(const ovrSessionStatus& status) { return status.ShouldQuit != ovrFalse; } + static inline bool displayLost(const ovrSessionStatus& status) { return status.DisplayLost != ovrFalse; } + static inline bool isVisible(const ovrSessionStatus& status) { return status.IsVisible != 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; }