mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-29 19:22:57 +02:00
Merge pull request #5697 from jherico/maggie
Fix oculus crash on switching display plugin to something else
This commit is contained in:
commit
01b6bbe40f
11 changed files with 148 additions and 89 deletions
|
@ -64,6 +64,7 @@
|
||||||
|
|
||||||
#include <EntityScriptingInterface.h>
|
#include <EntityScriptingInterface.h>
|
||||||
#include <ErrorDialog.h>
|
#include <ErrorDialog.h>
|
||||||
|
#include <Finally.h>
|
||||||
#include <FramebufferCache.h>
|
#include <FramebufferCache.h>
|
||||||
#include <gpu/Batch.h>
|
#include <gpu/Batch.h>
|
||||||
#include <gpu/Context.h>
|
#include <gpu/Context.h>
|
||||||
|
@ -1009,6 +1010,16 @@ void Application::paintGL() {
|
||||||
if (nullptr == _displayPlugin) {
|
if (nullptr == _displayPlugin) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Some plugins process message events, potentially leading to
|
||||||
|
// re-entering a paint event. don't allow further processing if this
|
||||||
|
// happens
|
||||||
|
if (_inPaint) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_inPaint = true;
|
||||||
|
Finally clearFlagLambda([this] { _inPaint = false; });
|
||||||
|
|
||||||
auto displayPlugin = getActiveDisplayPlugin();
|
auto displayPlugin = getActiveDisplayPlugin();
|
||||||
displayPlugin->preRender();
|
displayPlugin->preRender();
|
||||||
_offscreenContext->makeCurrent();
|
_offscreenContext->makeCurrent();
|
||||||
|
@ -1219,7 +1230,6 @@ void Application::paintGL() {
|
||||||
_frameCount++;
|
_frameCount++;
|
||||||
Stats::getInstance()->setRenderDetails(renderArgs._details);
|
Stats::getInstance()->setRenderDetails(renderArgs._details);
|
||||||
|
|
||||||
|
|
||||||
// Reset the gpu::Context Stages
|
// Reset the gpu::Context Stages
|
||||||
// Back to the default framebuffer;
|
// Back to the default framebuffer;
|
||||||
gpu::Batch batch;
|
gpu::Batch batch;
|
||||||
|
@ -4703,7 +4713,23 @@ void Application::updateDisplayMode() {
|
||||||
|
|
||||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
DisplayPluginPointer oldDisplayPlugin = _displayPlugin;
|
DisplayPluginPointer oldDisplayPlugin = _displayPlugin;
|
||||||
if (oldDisplayPlugin != newDisplayPlugin) {
|
if (newDisplayPlugin == oldDisplayPlugin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some plugins *cough* Oculus *cough* process message events from inside their
|
||||||
|
// display function, and we don't want to change the display plugin underneath
|
||||||
|
// the paintGL call, so we need to guard against that
|
||||||
|
if (_inPaint) {
|
||||||
|
qDebug() << "Deferring plugin switch until out of painting";
|
||||||
|
// Have the old plugin stop requesting renders
|
||||||
|
oldDisplayPlugin->stop();
|
||||||
|
QCoreApplication::postEvent(this, new LambdaEvent([this] {
|
||||||
|
updateDisplayMode();
|
||||||
|
}));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!_currentDisplayPluginActions.isEmpty()) {
|
if (!_currentDisplayPluginActions.isEmpty()) {
|
||||||
auto menu = Menu::getInstance();
|
auto menu = Menu::getInstance();
|
||||||
foreach(auto itemInfo, _currentDisplayPluginActions) {
|
foreach(auto itemInfo, _currentDisplayPluginActions) {
|
||||||
|
@ -4749,7 +4775,6 @@ void Application::updateDisplayMode() {
|
||||||
}
|
}
|
||||||
emit activeDisplayPluginChanged();
|
emit activeDisplayPluginChanged();
|
||||||
resetSensors();
|
resetSensors();
|
||||||
}
|
|
||||||
Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin");
|
Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5052,3 +5077,15 @@ void Application::crashApplication() {
|
||||||
|
|
||||||
qCDebug(interfaceapp) << "Intentionally crashed Interface";
|
qCDebug(interfaceapp) << "Intentionally crashed Interface";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::setActiveDisplayPlugin(const QString& pluginName) {
|
||||||
|
auto menu = Menu::getInstance();
|
||||||
|
foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) {
|
||||||
|
QString name = displayPlugin->getName();
|
||||||
|
QAction* action = menu->getActionForOption(name);
|
||||||
|
if (pluginName == name) {
|
||||||
|
action->setChecked(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateDisplayMode();
|
||||||
|
}
|
||||||
|
|
|
@ -673,6 +673,7 @@ private:
|
||||||
int _simsPerSecondReport = 0;
|
int _simsPerSecondReport = 0;
|
||||||
quint64 _lastSimsPerSecondUpdate = 0;
|
quint64 _lastSimsPerSecondUpdate = 0;
|
||||||
bool _isForeground = true; // starts out assumed to be in foreground
|
bool _isForeground = true; // starts out assumed to be in foreground
|
||||||
|
bool _inPaint = false;
|
||||||
|
|
||||||
friend class PluginContainerProxy;
|
friend class PluginContainerProxy;
|
||||||
};
|
};
|
||||||
|
|
|
@ -147,15 +147,3 @@ void PluginContainerProxy::showDisplayPluginsTools() {
|
||||||
QGLWidget* PluginContainerProxy::getPrimarySurface() {
|
QGLWidget* PluginContainerProxy::getPrimarySurface() {
|
||||||
return qApp->_glWidget;
|
return qApp->_glWidget;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::setActiveDisplayPlugin(const QString& pluginName) {
|
|
||||||
auto menu = Menu::getInstance();
|
|
||||||
foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) {
|
|
||||||
QString name = displayPlugin->getName();
|
|
||||||
QAction* action = menu->getActionForOption(name);
|
|
||||||
if (pluginName == name) {
|
|
||||||
action->setChecked(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updateDisplayMode();
|
|
||||||
}
|
|
||||||
|
|
|
@ -57,6 +57,11 @@ public:
|
||||||
|
|
||||||
// Rendering support
|
// Rendering support
|
||||||
|
|
||||||
|
// Stop requesting renders, but don't do full deactivation
|
||||||
|
// needed to work around the issues caused by Oculus
|
||||||
|
// processing messages in the middle of submitFrame
|
||||||
|
virtual void stop() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by the application before the frame rendering. Can be used for
|
* Called by the application before the frame rendering. Can be used for
|
||||||
* render timing related calls (for instance, the Oculus begin frame timing
|
* render timing related calls (for instance, the Oculus begin frame timing
|
||||||
|
@ -120,6 +125,7 @@ public:
|
||||||
virtual void resetSensors() {}
|
virtual void resetSensors() {}
|
||||||
virtual float devicePixelRatio() { return 1.0; }
|
virtual float devicePixelRatio() { return 1.0; }
|
||||||
|
|
||||||
|
|
||||||
static const QString& MENU_PATH();
|
static const QString& MENU_PATH();
|
||||||
signals:
|
signals:
|
||||||
void recommendedFramebufferSizeChanged(const QSize & size);
|
void recommendedFramebufferSizeChanged(const QSize & size);
|
||||||
|
|
|
@ -30,3 +30,4 @@ void NullDisplayPlugin::finishFrame() {}
|
||||||
|
|
||||||
void NullDisplayPlugin::activate() {}
|
void NullDisplayPlugin::activate() {}
|
||||||
void NullDisplayPlugin::deactivate() {}
|
void NullDisplayPlugin::deactivate() {}
|
||||||
|
void NullDisplayPlugin::stop() {}
|
||||||
|
|
|
@ -17,6 +17,7 @@ public:
|
||||||
|
|
||||||
void activate() override;
|
void activate() override;
|
||||||
void deactivate() override;
|
void deactivate() override;
|
||||||
|
void stop() override;
|
||||||
|
|
||||||
virtual glm::uvec2 getRecommendedRenderSize() const override;
|
virtual glm::uvec2 getRecommendedRenderSize() const override;
|
||||||
virtual bool hasFocus() const override;
|
virtual bool hasFocus() const override;
|
||||||
|
|
|
@ -16,7 +16,9 @@
|
||||||
|
|
||||||
OpenGLDisplayPlugin::OpenGLDisplayPlugin() {
|
OpenGLDisplayPlugin::OpenGLDisplayPlugin() {
|
||||||
connect(&_timer, &QTimer::timeout, this, [&] {
|
connect(&_timer, &QTimer::timeout, this, [&] {
|
||||||
|
if (_active) {
|
||||||
emit requestRender();
|
emit requestRender();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,10 +58,17 @@ void OpenGLDisplayPlugin::customizeContext() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayPlugin::activate() {
|
void OpenGLDisplayPlugin::activate() {
|
||||||
|
_active = true;
|
||||||
_timer.start(1);
|
_timer.start(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenGLDisplayPlugin::stop() {
|
||||||
|
_active = false;
|
||||||
|
_timer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
void OpenGLDisplayPlugin::deactivate() {
|
void OpenGLDisplayPlugin::deactivate() {
|
||||||
|
_active = false;
|
||||||
_timer.stop();
|
_timer.stop();
|
||||||
|
|
||||||
makeCurrent();
|
makeCurrent();
|
||||||
|
|
|
@ -25,7 +25,7 @@ public:
|
||||||
|
|
||||||
virtual void activate() override;
|
virtual void activate() override;
|
||||||
virtual void deactivate() override;
|
virtual void deactivate() override;
|
||||||
|
virtual void stop() override;
|
||||||
virtual bool eventFilter(QObject* receiver, QEvent* event) override;
|
virtual bool eventFilter(QObject* receiver, QEvent* event) override;
|
||||||
|
|
||||||
virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize) override;
|
virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize) override;
|
||||||
|
@ -44,6 +44,7 @@ protected:
|
||||||
mutable QTimer _timer;
|
mutable QTimer _timer;
|
||||||
ProgramPtr _program;
|
ProgramPtr _program;
|
||||||
ShapeWrapperPtr _plane;
|
ShapeWrapperPtr _plane;
|
||||||
|
bool _active{ false };
|
||||||
bool _vsyncSupported{ false };
|
bool _vsyncSupported{ false };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -325,19 +325,18 @@ void OculusDisplayPlugin::customizeContext() {
|
||||||
//_texture = DependencyManager::get<TextureCache>()->
|
//_texture = DependencyManager::get<TextureCache>()->
|
||||||
// getImageTexture(PathUtils::resourcesPath() + "/images/cube_texture.png");
|
// getImageTexture(PathUtils::resourcesPath() + "/images/cube_texture.png");
|
||||||
uvec2 mirrorSize = toGlm(_window->geometry().size());
|
uvec2 mirrorSize = toGlm(_window->geometry().size());
|
||||||
_mirrorFbo = MirrorFboPtr(new MirrorFramebufferWrapper(_hmd));
|
|
||||||
_mirrorFbo->Init(mirrorSize);
|
|
||||||
|
|
||||||
_sceneFbo = SwapFboPtr(new SwapFramebufferWrapper(_hmd));
|
_sceneFbo = SwapFboPtr(new SwapFramebufferWrapper(_hmd));
|
||||||
_sceneFbo->Init(getRecommendedRenderSize());
|
_sceneFbo->Init(getRecommendedRenderSize());
|
||||||
#endif
|
#endif
|
||||||
|
enableVsync(false);
|
||||||
|
isVsyncEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OculusDisplayPlugin::deactivate() {
|
void OculusDisplayPlugin::deactivate() {
|
||||||
#if (OVR_MAJOR_VERSION >= 6)
|
#if (OVR_MAJOR_VERSION >= 6)
|
||||||
makeCurrent();
|
makeCurrent();
|
||||||
_sceneFbo.reset();
|
_sceneFbo.reset();
|
||||||
_mirrorFbo.reset();
|
|
||||||
doneCurrent();
|
doneCurrent();
|
||||||
PerformanceTimer::setActive(false);
|
PerformanceTimer::setActive(false);
|
||||||
|
|
||||||
|
@ -350,11 +349,6 @@ void OculusDisplayPlugin::deactivate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OculusDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSize) {
|
void OculusDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSize) {
|
||||||
static bool inDisplay = false;
|
|
||||||
if (inDisplay) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
inDisplay = true;
|
|
||||||
#if (OVR_MAJOR_VERSION >= 6)
|
#if (OVR_MAJOR_VERSION >= 6)
|
||||||
using namespace oglplus;
|
using namespace oglplus;
|
||||||
// Need to make sure only the display plugin is responsible for
|
// Need to make sure only the display plugin is responsible for
|
||||||
|
@ -383,12 +377,14 @@ void OculusDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSi
|
||||||
the UI visible in the output window (unlikely). This should be done before
|
the UI visible in the output window (unlikely). This should be done before
|
||||||
_sceneFbo->Increment or we're be using the wrong texture
|
_sceneFbo->Increment or we're be using the wrong texture
|
||||||
*/
|
*/
|
||||||
|
if (_enableMirror) {
|
||||||
_sceneFbo->Bound(Framebuffer::Target::Read, [&] {
|
_sceneFbo->Bound(Framebuffer::Target::Read, [&] {
|
||||||
glBlitFramebuffer(
|
glBlitFramebuffer(
|
||||||
0, 0, _sceneFbo->size.x, _sceneFbo->size.y,
|
0, 0, _sceneFbo->size.x, _sceneFbo->size.y,
|
||||||
0, 0, windowSize.x, windowSize.y,
|
0, 0, windowSize.x, windowSize.y,
|
||||||
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceTimer("OculusSubmit");
|
PerformanceTimer("OculusSubmit");
|
||||||
|
@ -409,6 +405,7 @@ void OculusDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSi
|
||||||
The other alternative for mirroring is to use the Oculus mirror texture support, which
|
The other alternative for mirroring is to use the Oculus mirror texture support, which
|
||||||
will contain the post-distorted and fully composited scene regardless of how many layers
|
will contain the post-distorted and fully composited scene regardless of how many layers
|
||||||
we send.
|
we send.
|
||||||
|
Currently generates an error.
|
||||||
*/
|
*/
|
||||||
//auto mirrorSize = _mirrorFbo->size;
|
//auto mirrorSize = _mirrorFbo->size;
|
||||||
//_mirrorFbo->Bound(Framebuffer::Target::Read, [&] {
|
//_mirrorFbo->Bound(Framebuffer::Target::Read, [&] {
|
||||||
|
@ -420,21 +417,10 @@ void OculusDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSi
|
||||||
|
|
||||||
++_frameIndex;
|
++_frameIndex;
|
||||||
#endif
|
#endif
|
||||||
inDisplay = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass input events on to the application
|
// Pass input events on to the application
|
||||||
bool OculusDisplayPlugin::eventFilter(QObject* receiver, QEvent* event) {
|
bool OculusDisplayPlugin::eventFilter(QObject* receiver, QEvent* event) {
|
||||||
#if (OVR_MAJOR_VERSION >= 6)
|
|
||||||
if (event->type() == QEvent::Resize) {
|
|
||||||
QResizeEvent* resizeEvent = static_cast<QResizeEvent*>(event);
|
|
||||||
qDebug() << resizeEvent->size().width() << " x " << resizeEvent->size().height();
|
|
||||||
auto newSize = toGlm(resizeEvent->size());
|
|
||||||
makeCurrent();
|
|
||||||
_mirrorFbo->Resize(newSize);
|
|
||||||
doneCurrent();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return WindowOpenGLDisplayPlugin::eventFilter(receiver, event);
|
return WindowOpenGLDisplayPlugin::eventFilter(receiver, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,7 +430,9 @@ bool OculusDisplayPlugin::eventFilter(QObject* receiver, QEvent* event) {
|
||||||
otherwise the swapbuffer delay will interefere with the framerate of the headset
|
otherwise the swapbuffer delay will interefere with the framerate of the headset
|
||||||
*/
|
*/
|
||||||
void OculusDisplayPlugin::finishFrame() {
|
void OculusDisplayPlugin::finishFrame() {
|
||||||
//swapBuffers();
|
if (_enableMirror) {
|
||||||
|
swapBuffers();
|
||||||
|
}
|
||||||
doneCurrent();
|
doneCurrent();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,7 @@ private:
|
||||||
mat4 _compositeEyeProjections[2];
|
mat4 _compositeEyeProjections[2];
|
||||||
uvec2 _desiredFramebufferSize;
|
uvec2 _desiredFramebufferSize;
|
||||||
ovrTrackingState _trackingState;
|
ovrTrackingState _trackingState;
|
||||||
|
bool _enableMirror{ false };
|
||||||
|
|
||||||
#if (OVR_MAJOR_VERSION >= 6)
|
#if (OVR_MAJOR_VERSION >= 6)
|
||||||
ovrHmd _hmd;
|
ovrHmd _hmd;
|
||||||
|
@ -70,7 +71,6 @@ private:
|
||||||
ovrLayerEyeFov& getSceneLayer();
|
ovrLayerEyeFov& getSceneLayer();
|
||||||
ovrHmdDesc _hmdDesc;
|
ovrHmdDesc _hmdDesc;
|
||||||
SwapFboPtr _sceneFbo;
|
SwapFboPtr _sceneFbo;
|
||||||
MirrorFboPtr _mirrorFbo;
|
|
||||||
ovrLayerEyeFov _sceneLayer;
|
ovrLayerEyeFov _sceneLayer;
|
||||||
#endif
|
#endif
|
||||||
#if (OVR_MAJOR_VERSION == 7)
|
#if (OVR_MAJOR_VERSION == 7)
|
||||||
|
|
27
libraries/shared/src/Finally.h
Normal file
27
libraries/shared/src/Finally.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2015/09/01
|
||||||
|
// Copyright 2013-2105 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
// Simulates a java finally block by executing a lambda when an instance leaves
|
||||||
|
// scope
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef hifi_Finally_h
|
||||||
|
#define hifi_Finally_h
|
||||||
|
|
||||||
|
class Finally {
|
||||||
|
public:
|
||||||
|
template <typename F>
|
||||||
|
Finally(F f) : _f(f) {}
|
||||||
|
~Finally() { _f(); }
|
||||||
|
private:
|
||||||
|
std::function<void()> _f;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue