mirror of
https://github.com/lubosz/overte.git
synced 2025-04-07 15:22:09 +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?
|
||||
_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
|
||||
getMyAvatar()->updateFromHMDSensorMatrix(getHMDSensorPose());
|
||||
|
@ -5098,9 +5104,17 @@ void Application::updateDisplayMode() {
|
|||
|
||||
foreach(auto displayPlugin, standard) {
|
||||
addDisplayPluginToMenu(displayPlugin, first);
|
||||
auto displayPluginName = displayPlugin->getName();
|
||||
QObject::connect(displayPlugin.get(), &DisplayPlugin::recommendedFramebufferSizeChanged, [this](const QSize & size) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -5116,6 +5130,10 @@ void Application::updateDisplayMode() {
|
|||
foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) {
|
||||
QString name = displayPlugin->getName();
|
||||
QAction* action = menu->getActionForOption(name);
|
||||
// Menu might have been removed if the display plugin lost
|
||||
if (!action) {
|
||||
continue;
|
||||
}
|
||||
if (action->isChecked()) {
|
||||
newDisplayPlugin = displayPlugin;
|
||||
break;
|
||||
|
|
|
@ -137,7 +137,7 @@ public:
|
|||
}
|
||||
|
||||
// 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
|
||||
virtual glm::mat4 getHeadPose() const {
|
||||
|
@ -170,6 +170,10 @@ public:
|
|||
|
||||
signals:
|
||||
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:
|
||||
void incrementPresentCount();
|
||||
|
|
|
@ -62,11 +62,10 @@ PluginManager::PluginManager() {
|
|||
extern DisplayPluginList getDisplayPlugins();
|
||||
extern InputPluginList getInputPlugins();
|
||||
extern void saveInputPluginSettings(const InputPluginList& plugins);
|
||||
static DisplayPluginList displayPlugins;
|
||||
|
||||
const DisplayPluginList& PluginManager::getDisplayPlugins() {
|
||||
static DisplayPluginList displayPlugins;
|
||||
static std::once_flag once;
|
||||
|
||||
std::call_once(once, [&] {
|
||||
// Grab the built in plugins
|
||||
displayPlugins = ::getDisplayPlugins();
|
||||
|
@ -90,6 +89,16 @@ const DisplayPluginList& PluginManager::getDisplayPlugins() {
|
|||
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() {
|
||||
static InputPluginList inputPlugins;
|
||||
static std::once_flag once;
|
||||
|
|
|
@ -17,6 +17,7 @@ public:
|
|||
PluginManager();
|
||||
|
||||
const DisplayPluginList& getDisplayPlugins();
|
||||
void disableDisplayPlugin(const QString& name);
|
||||
const InputPluginList& getInputPlugins();
|
||||
void saveSettings();
|
||||
};
|
||||
|
|
|
@ -17,7 +17,7 @@ void OculusBaseDisplayPlugin::resetSensors() {
|
|||
_currentRenderFrameInfo.renderPose = glm::mat4(); // identity
|
||||
}
|
||||
|
||||
void OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||
bool OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||
_currentRenderFrameInfo = FrameInfo();
|
||||
_currentRenderFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds();;
|
||||
_currentRenderFrameInfo.predictedDisplayTime = ovr_GetPredictedDisplayTime(_session, frameIndex);
|
||||
|
@ -26,6 +26,7 @@ void OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
|||
_currentRenderFrameInfo.presentPose = _currentRenderFrameInfo.renderPose;
|
||||
Lock lock(_mutex);
|
||||
_frameInfos[frameIndex] = _currentRenderFrameInfo;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OculusBaseDisplayPlugin::isSupported() const {
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
class OculusBaseDisplayPlugin : public HmdDisplayPlugin {
|
||||
using Parent = HmdDisplayPlugin;
|
||||
public:
|
||||
virtual bool isSupported() const override;
|
||||
bool isSupported() const override;
|
||||
|
||||
// Stereo specific methods
|
||||
virtual void resetSensors() override final;
|
||||
virtual void beginFrameRender(uint32_t frameIndex) override;
|
||||
void resetSensors() override final;
|
||||
bool beginFrameRender(uint32_t frameIndex) override;
|
||||
float getTargetFrameRate() const override { return _hmdDesc.DisplayRefreshRate; }
|
||||
|
||||
|
||||
|
|
|
@ -40,13 +40,14 @@ void OculusLegacyDisplayPlugin::resetSensors() {
|
|||
ovrHmd_RecenterPose(_hmd);
|
||||
}
|
||||
|
||||
void OculusLegacyDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||
bool OculusLegacyDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||
_currentRenderFrameInfo = FrameInfo();
|
||||
_currentRenderFrameInfo.predictedDisplayTime = _currentRenderFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds();
|
||||
_trackingState = ovrHmd_GetTrackingState(_hmd, _currentRenderFrameInfo.predictedDisplayTime);
|
||||
_currentRenderFrameInfo.rawRenderPose = _currentRenderFrameInfo.renderPose = toGlm(_trackingState.HeadPose.ThePose);
|
||||
Lock lock(_mutex);
|
||||
_frameInfos[frameIndex] = _currentRenderFrameInfo;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OculusLegacyDisplayPlugin::isSupported() const {
|
||||
|
|
|
@ -27,7 +27,7 @@ public:
|
|||
|
||||
// Stereo specific methods
|
||||
void resetSensors() override;
|
||||
void beginFrameRender(uint32_t frameIndex) override;
|
||||
bool beginFrameRender(uint32_t frameIndex) 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 frameDuration = 1.f / displayFrequency;
|
||||
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);
|
||||
_frameInfos[frameIndex] = _currentRenderFrameInfo;
|
||||
return true;
|
||||
}
|
||||
|
||||
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 {
|
||||
using Parent = HmdDisplayPlugin;
|
||||
public:
|
||||
virtual bool isSupported() const override;
|
||||
virtual const QString& getName() const override { return NAME; }
|
||||
bool isSupported() const override;
|
||||
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
|
||||
virtual void resetSensors() override;
|
||||
virtual void beginFrameRender(uint32_t frameIndex) override;
|
||||
void resetSensors() override;
|
||||
bool beginFrameRender(uint32_t frameIndex) override;
|
||||
void cycleDebugOutput() override { _lockCurrentTexture = !_lockCurrentTexture; }
|
||||
|
||||
protected:
|
||||
|
|
|
@ -26,6 +26,11 @@ using Lock = std::unique_lock<Mutex>;
|
|||
static int refCount { 0 };
|
||||
static Mutex mutex;
|
||||
static vr::IVRSystem* activeHmd { nullptr };
|
||||
static bool _openVrQuitRequested { false };
|
||||
|
||||
bool openVrQuitRequested() {
|
||||
return _openVrQuitRequested;
|
||||
}
|
||||
|
||||
static const uint32_t RELEASE_OPENVR_HMD_DELAY_MS = 5000;
|
||||
|
||||
|
@ -56,17 +61,17 @@ vr::IVRSystem* acquireOpenVrSystem() {
|
|||
if (hmdPresent) {
|
||||
Lock lock(mutex);
|
||||
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;
|
||||
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) {
|
||||
qCDebug(displayplugins) << "openvr: incrementing refcount";
|
||||
qCDebug(displayplugins) << "OpenVR: incrementing refcount";
|
||||
++refCount;
|
||||
}
|
||||
} else {
|
||||
qCDebug(displayplugins) << "openvr: no hmd present";
|
||||
qCDebug(displayplugins) << "OpenVR: no hmd present";
|
||||
}
|
||||
return activeHmd;
|
||||
}
|
||||
|
@ -74,12 +79,38 @@ vr::IVRSystem* acquireOpenVrSystem() {
|
|||
void releaseOpenVrSystem() {
|
||||
if (activeHmd) {
|
||||
Lock lock(mutex);
|
||||
qCDebug(displayplugins) << "openvr: decrementing refcount";
|
||||
qCDebug(displayplugins) << "OpenVR: decrementing refcount";
|
||||
--refCount;
|
||||
if (0 == refCount) {
|
||||
qCDebug(displayplugins) << "openvr: zero refcount, deallocate VR system";
|
||||
qCDebug(displayplugins) << "OpenVR: zero refcount, deallocate VR system";
|
||||
vr::VR_Shutdown();
|
||||
_openVrQuitRequested = false;
|
||||
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();
|
||||
void releaseOpenVrSystem();
|
||||
void handleOpenVrEvents();
|
||||
bool openVrQuitRequested();
|
||||
|
||||
template<typename 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) {
|
||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||
handleOpenVrEvents();
|
||||
if (openVrQuitRequested()) {
|
||||
deactivate();
|
||||
return;
|
||||
}
|
||||
|
||||
// because update mutates the internal state we need to lock
|
||||
userInputMapper->withLock([&, this]() {
|
||||
|
|
Loading…
Reference in a new issue