mirror of
https://github.com/overte-org/overte.git
synced 2025-04-14 03:47:13 +02:00
Fix crash on shutdown of SteamVR
This commit is contained in:
parent
76940bad34
commit
ac5912df01
13 changed files with 101 additions and 23 deletions
|
@ -1503,7 +1503,13 @@ void Application::paintGL() {
|
||||||
// FIXME not needed anymore?
|
// FIXME not needed anymore?
|
||||||
_offscreenContext->makeCurrent();
|
_offscreenContext->makeCurrent();
|
||||||
|
|
||||||
displayPlugin->beginFrameRender(_frameCount);
|
// If a display plugin loses it's underlying support, it
|
||||||
|
// needs to be able to signal us to not use it
|
||||||
|
if (!displayPlugin->beginFrameRender(_frameCount)) {
|
||||||
|
_inPaint = false;
|
||||||
|
updateDisplayMode();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// update the avatar with a fresh HMD pose
|
// update the avatar with a fresh HMD pose
|
||||||
getMyAvatar()->updateFromHMDSensorMatrix(getHMDSensorPose());
|
getMyAvatar()->updateFromHMDSensorMatrix(getHMDSensorPose());
|
||||||
|
@ -5098,9 +5104,17 @@ void Application::updateDisplayMode() {
|
||||||
|
|
||||||
foreach(auto displayPlugin, standard) {
|
foreach(auto displayPlugin, standard) {
|
||||||
addDisplayPluginToMenu(displayPlugin, first);
|
addDisplayPluginToMenu(displayPlugin, first);
|
||||||
|
auto displayPluginName = displayPlugin->getName();
|
||||||
QObject::connect(displayPlugin.get(), &DisplayPlugin::recommendedFramebufferSizeChanged, [this](const QSize & size) {
|
QObject::connect(displayPlugin.get(), &DisplayPlugin::recommendedFramebufferSizeChanged, [this](const QSize & size) {
|
||||||
resizeGL();
|
resizeGL();
|
||||||
});
|
});
|
||||||
|
QObject::connect(displayPlugin.get(), &DisplayPlugin::outputDeviceLost, [this, displayPluginName] {
|
||||||
|
PluginManager::getInstance()->disableDisplayPlugin(displayPluginName);
|
||||||
|
auto menu = Menu::getInstance();
|
||||||
|
if (menu->menuItemExists(MenuOption::OutputMenu, displayPluginName)) {
|
||||||
|
menu->removeMenuItem(MenuOption::OutputMenu, displayPluginName);
|
||||||
|
}
|
||||||
|
});
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5116,6 +5130,10 @@ void Application::updateDisplayMode() {
|
||||||
foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) {
|
foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) {
|
||||||
QString name = displayPlugin->getName();
|
QString name = displayPlugin->getName();
|
||||||
QAction* action = menu->getActionForOption(name);
|
QAction* action = menu->getActionForOption(name);
|
||||||
|
// Menu might have been removed if the display plugin lost
|
||||||
|
if (!action) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (action->isChecked()) {
|
if (action->isChecked()) {
|
||||||
newDisplayPlugin = displayPlugin;
|
newDisplayPlugin = displayPlugin;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -137,7 +137,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// will query the underlying hmd api to compute the most recent head pose
|
// will query the underlying hmd api to compute the most recent head pose
|
||||||
virtual void beginFrameRender(uint32_t frameIndex) {}
|
virtual bool beginFrameRender(uint32_t frameIndex) { return true; }
|
||||||
|
|
||||||
// returns a copy of the most recent head pose, computed via updateHeadPose
|
// returns a copy of the most recent head pose, computed via updateHeadPose
|
||||||
virtual glm::mat4 getHeadPose() const {
|
virtual glm::mat4 getHeadPose() const {
|
||||||
|
@ -170,6 +170,10 @@ public:
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void recommendedFramebufferSizeChanged(const QSize & size);
|
void recommendedFramebufferSizeChanged(const QSize & size);
|
||||||
|
// Indicates that this display plugin is no longer valid for use.
|
||||||
|
// For instance if a user exits Oculus Home or Steam VR while
|
||||||
|
// using the corresponding plugin, that plugin should be disabled.
|
||||||
|
void outputDeviceLost();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void incrementPresentCount();
|
void incrementPresentCount();
|
||||||
|
|
|
@ -62,11 +62,10 @@ PluginManager::PluginManager() {
|
||||||
extern DisplayPluginList getDisplayPlugins();
|
extern DisplayPluginList getDisplayPlugins();
|
||||||
extern InputPluginList getInputPlugins();
|
extern InputPluginList getInputPlugins();
|
||||||
extern void saveInputPluginSettings(const InputPluginList& plugins);
|
extern void saveInputPluginSettings(const InputPluginList& plugins);
|
||||||
|
static DisplayPluginList displayPlugins;
|
||||||
|
|
||||||
const DisplayPluginList& PluginManager::getDisplayPlugins() {
|
const DisplayPluginList& PluginManager::getDisplayPlugins() {
|
||||||
static DisplayPluginList displayPlugins;
|
|
||||||
static std::once_flag once;
|
static std::once_flag once;
|
||||||
|
|
||||||
std::call_once(once, [&] {
|
std::call_once(once, [&] {
|
||||||
// Grab the built in plugins
|
// Grab the built in plugins
|
||||||
displayPlugins = ::getDisplayPlugins();
|
displayPlugins = ::getDisplayPlugins();
|
||||||
|
@ -90,6 +89,16 @@ const DisplayPluginList& PluginManager::getDisplayPlugins() {
|
||||||
return displayPlugins;
|
return displayPlugins;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PluginManager::disableDisplayPlugin(const QString& name) {
|
||||||
|
for (size_t i = 0; i < displayPlugins.size(); ++i) {
|
||||||
|
if (displayPlugins[i]->getName() == name) {
|
||||||
|
displayPlugins.erase(displayPlugins.begin() + i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const InputPluginList& PluginManager::getInputPlugins() {
|
const InputPluginList& PluginManager::getInputPlugins() {
|
||||||
static InputPluginList inputPlugins;
|
static InputPluginList inputPlugins;
|
||||||
static std::once_flag once;
|
static std::once_flag once;
|
||||||
|
|
|
@ -17,6 +17,7 @@ public:
|
||||||
PluginManager();
|
PluginManager();
|
||||||
|
|
||||||
const DisplayPluginList& getDisplayPlugins();
|
const DisplayPluginList& getDisplayPlugins();
|
||||||
|
void disableDisplayPlugin(const QString& name);
|
||||||
const InputPluginList& getInputPlugins();
|
const InputPluginList& getInputPlugins();
|
||||||
void saveSettings();
|
void saveSettings();
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,7 +17,7 @@ void OculusBaseDisplayPlugin::resetSensors() {
|
||||||
_currentRenderFrameInfo.renderPose = glm::mat4(); // identity
|
_currentRenderFrameInfo.renderPose = glm::mat4(); // identity
|
||||||
}
|
}
|
||||||
|
|
||||||
void OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
bool OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
_currentRenderFrameInfo = FrameInfo();
|
_currentRenderFrameInfo = FrameInfo();
|
||||||
_currentRenderFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds();;
|
_currentRenderFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds();;
|
||||||
_currentRenderFrameInfo.predictedDisplayTime = ovr_GetPredictedDisplayTime(_session, frameIndex);
|
_currentRenderFrameInfo.predictedDisplayTime = ovr_GetPredictedDisplayTime(_session, frameIndex);
|
||||||
|
@ -26,6 +26,7 @@ void OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
_currentRenderFrameInfo.presentPose = _currentRenderFrameInfo.renderPose;
|
_currentRenderFrameInfo.presentPose = _currentRenderFrameInfo.renderPose;
|
||||||
Lock lock(_mutex);
|
Lock lock(_mutex);
|
||||||
_frameInfos[frameIndex] = _currentRenderFrameInfo;
|
_frameInfos[frameIndex] = _currentRenderFrameInfo;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OculusBaseDisplayPlugin::isSupported() const {
|
bool OculusBaseDisplayPlugin::isSupported() const {
|
||||||
|
|
|
@ -16,11 +16,11 @@
|
||||||
class OculusBaseDisplayPlugin : public HmdDisplayPlugin {
|
class OculusBaseDisplayPlugin : public HmdDisplayPlugin {
|
||||||
using Parent = HmdDisplayPlugin;
|
using Parent = HmdDisplayPlugin;
|
||||||
public:
|
public:
|
||||||
virtual bool isSupported() const override;
|
bool isSupported() const override;
|
||||||
|
|
||||||
// Stereo specific methods
|
// Stereo specific methods
|
||||||
virtual void resetSensors() override final;
|
void resetSensors() override final;
|
||||||
virtual void beginFrameRender(uint32_t frameIndex) override;
|
bool beginFrameRender(uint32_t frameIndex) override;
|
||||||
float getTargetFrameRate() const override { return _hmdDesc.DisplayRefreshRate; }
|
float getTargetFrameRate() const override { return _hmdDesc.DisplayRefreshRate; }
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -40,13 +40,14 @@ void OculusLegacyDisplayPlugin::resetSensors() {
|
||||||
ovrHmd_RecenterPose(_hmd);
|
ovrHmd_RecenterPose(_hmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OculusLegacyDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
bool OculusLegacyDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
_currentRenderFrameInfo = FrameInfo();
|
_currentRenderFrameInfo = FrameInfo();
|
||||||
_currentRenderFrameInfo.predictedDisplayTime = _currentRenderFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds();
|
_currentRenderFrameInfo.predictedDisplayTime = _currentRenderFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds();
|
||||||
_trackingState = ovrHmd_GetTrackingState(_hmd, _currentRenderFrameInfo.predictedDisplayTime);
|
_trackingState = ovrHmd_GetTrackingState(_hmd, _currentRenderFrameInfo.predictedDisplayTime);
|
||||||
_currentRenderFrameInfo.rawRenderPose = _currentRenderFrameInfo.renderPose = toGlm(_trackingState.HeadPose.ThePose);
|
_currentRenderFrameInfo.rawRenderPose = _currentRenderFrameInfo.renderPose = toGlm(_trackingState.HeadPose.ThePose);
|
||||||
Lock lock(_mutex);
|
Lock lock(_mutex);
|
||||||
_frameInfos[frameIndex] = _currentRenderFrameInfo;
|
_frameInfos[frameIndex] = _currentRenderFrameInfo;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OculusLegacyDisplayPlugin::isSupported() const {
|
bool OculusLegacyDisplayPlugin::isSupported() const {
|
||||||
|
|
|
@ -27,7 +27,7 @@ public:
|
||||||
|
|
||||||
// Stereo specific methods
|
// Stereo specific methods
|
||||||
void resetSensors() override;
|
void resetSensors() override;
|
||||||
void beginFrameRender(uint32_t frameIndex) override;
|
bool beginFrameRender(uint32_t frameIndex) override;
|
||||||
|
|
||||||
float getTargetFrameRate() const override;
|
float getTargetFrameRate() const override;
|
||||||
|
|
||||||
|
|
|
@ -121,7 +121,12 @@ void OpenVrDisplayPlugin::resetSensors() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
bool OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
|
handleOpenVrEvents();
|
||||||
|
if (openVrQuitRequested()) {
|
||||||
|
emit outputDeviceLost();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
double displayFrequency = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_DisplayFrequency_Float);
|
double displayFrequency = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_DisplayFrequency_Float);
|
||||||
double frameDuration = 1.f / displayFrequency;
|
double frameDuration = 1.f / displayFrequency;
|
||||||
double vsyncToPhotons = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SecondsFromVsyncToPhotons_Float);
|
double vsyncToPhotons = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SecondsFromVsyncToPhotons_Float);
|
||||||
|
@ -148,6 +153,7 @@ void OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
|
|
||||||
Lock lock(_mutex);
|
Lock lock(_mutex);
|
||||||
_frameInfos[frameIndex] = _currentRenderFrameInfo;
|
_frameInfos[frameIndex] = _currentRenderFrameInfo;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenVrDisplayPlugin::hmdPresent() {
|
void OpenVrDisplayPlugin::hmdPresent() {
|
||||||
|
|
|
@ -18,16 +18,16 @@ const float TARGET_RATE_OpenVr = 90.0f; // FIXME: get from sdk tracked device p
|
||||||
class OpenVrDisplayPlugin : public HmdDisplayPlugin {
|
class OpenVrDisplayPlugin : public HmdDisplayPlugin {
|
||||||
using Parent = HmdDisplayPlugin;
|
using Parent = HmdDisplayPlugin;
|
||||||
public:
|
public:
|
||||||
virtual bool isSupported() const override;
|
bool isSupported() const override;
|
||||||
virtual const QString& getName() const override { return NAME; }
|
const QString& getName() const override { return NAME; }
|
||||||
|
|
||||||
virtual float getTargetFrameRate() const override { return TARGET_RATE_OpenVr; }
|
float getTargetFrameRate() const override { return TARGET_RATE_OpenVr; }
|
||||||
|
|
||||||
virtual void customizeContext() override;
|
void customizeContext() override;
|
||||||
|
|
||||||
// Stereo specific methods
|
// Stereo specific methods
|
||||||
virtual void resetSensors() override;
|
void resetSensors() override;
|
||||||
virtual void beginFrameRender(uint32_t frameIndex) override;
|
bool beginFrameRender(uint32_t frameIndex) override;
|
||||||
void cycleDebugOutput() override { _lockCurrentTexture = !_lockCurrentTexture; }
|
void cycleDebugOutput() override { _lockCurrentTexture = !_lockCurrentTexture; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -26,6 +26,11 @@ using Lock = std::unique_lock<Mutex>;
|
||||||
static int refCount { 0 };
|
static int refCount { 0 };
|
||||||
static Mutex mutex;
|
static Mutex mutex;
|
||||||
static vr::IVRSystem* activeHmd { nullptr };
|
static vr::IVRSystem* activeHmd { nullptr };
|
||||||
|
static bool _openVrQuitRequested { false };
|
||||||
|
|
||||||
|
bool openVrQuitRequested() {
|
||||||
|
return _openVrQuitRequested;
|
||||||
|
}
|
||||||
|
|
||||||
static const uint32_t RELEASE_OPENVR_HMD_DELAY_MS = 5000;
|
static const uint32_t RELEASE_OPENVR_HMD_DELAY_MS = 5000;
|
||||||
|
|
||||||
|
@ -56,17 +61,17 @@ vr::IVRSystem* acquireOpenVrSystem() {
|
||||||
if (hmdPresent) {
|
if (hmdPresent) {
|
||||||
Lock lock(mutex);
|
Lock lock(mutex);
|
||||||
if (!activeHmd) {
|
if (!activeHmd) {
|
||||||
qCDebug(displayplugins) << "openvr: No vr::IVRSystem instance active, building";
|
qCDebug(displayplugins) << "OpenVR: No vr::IVRSystem instance active, building";
|
||||||
vr::EVRInitError eError = vr::VRInitError_None;
|
vr::EVRInitError eError = vr::VRInitError_None;
|
||||||
activeHmd = vr::VR_Init(&eError, vr::VRApplication_Scene);
|
activeHmd = vr::VR_Init(&eError, vr::VRApplication_Scene);
|
||||||
qCDebug(displayplugins) << "openvr display: HMD is " << activeHmd << " error is " << eError;
|
qCDebug(displayplugins) << "OpenVR display: HMD is " << activeHmd << " error is " << eError;
|
||||||
}
|
}
|
||||||
if (activeHmd) {
|
if (activeHmd) {
|
||||||
qCDebug(displayplugins) << "openvr: incrementing refcount";
|
qCDebug(displayplugins) << "OpenVR: incrementing refcount";
|
||||||
++refCount;
|
++refCount;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
qCDebug(displayplugins) << "openvr: no hmd present";
|
qCDebug(displayplugins) << "OpenVR: no hmd present";
|
||||||
}
|
}
|
||||||
return activeHmd;
|
return activeHmd;
|
||||||
}
|
}
|
||||||
|
@ -74,12 +79,38 @@ vr::IVRSystem* acquireOpenVrSystem() {
|
||||||
void releaseOpenVrSystem() {
|
void releaseOpenVrSystem() {
|
||||||
if (activeHmd) {
|
if (activeHmd) {
|
||||||
Lock lock(mutex);
|
Lock lock(mutex);
|
||||||
qCDebug(displayplugins) << "openvr: decrementing refcount";
|
qCDebug(displayplugins) << "OpenVR: decrementing refcount";
|
||||||
--refCount;
|
--refCount;
|
||||||
if (0 == refCount) {
|
if (0 == refCount) {
|
||||||
qCDebug(displayplugins) << "openvr: zero refcount, deallocate VR system";
|
qCDebug(displayplugins) << "OpenVR: zero refcount, deallocate VR system";
|
||||||
vr::VR_Shutdown();
|
vr::VR_Shutdown();
|
||||||
|
_openVrQuitRequested = false;
|
||||||
activeHmd = nullptr;
|
activeHmd = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleOpenVrEvents() {
|
||||||
|
if (!activeHmd) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Lock lock(mutex);
|
||||||
|
if (!activeHmd) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vr::VREvent_t event;
|
||||||
|
while (activeHmd->PollNextEvent(&event, sizeof(event))) {
|
||||||
|
switch (event.eventType) {
|
||||||
|
case vr::VREvent_Quit:
|
||||||
|
_openVrQuitRequested = true;
|
||||||
|
activeHmd->AcknowledgeQuit_Exiting();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
qDebug() << "OpenVR: Event " << event.eventType;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@ bool openVrSupported();
|
||||||
|
|
||||||
vr::IVRSystem* acquireOpenVrSystem();
|
vr::IVRSystem* acquireOpenVrSystem();
|
||||||
void releaseOpenVrSystem();
|
void releaseOpenVrSystem();
|
||||||
|
void handleOpenVrEvents();
|
||||||
|
bool openVrQuitRequested();
|
||||||
|
|
||||||
template<typename F>
|
template<typename F>
|
||||||
void openvr_for_each_eye(F f) {
|
void openvr_for_each_eye(F f) {
|
||||||
|
|
|
@ -214,6 +214,11 @@ void ViveControllerManager::renderHand(const controller::Pose& pose, gpu::Batch&
|
||||||
|
|
||||||
void ViveControllerManager::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) {
|
void ViveControllerManager::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) {
|
||||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||||
|
handleOpenVrEvents();
|
||||||
|
if (openVrQuitRequested()) {
|
||||||
|
deactivate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// because update mutates the internal state we need to lock
|
// because update mutates the internal state we need to lock
|
||||||
userInputMapper->withLock([&, this]() {
|
userInputMapper->withLock([&, this]() {
|
||||||
|
|
Loading…
Reference in a new issue