From 7045680bc720ec361891d4d0e07850d6bc7a9171 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Wed, 16 Mar 2016 16:58:59 -0700 Subject: [PATCH] Reduce crashes on switching display plugins --- interface/src/Application.cpp | 93 +++++-------- interface/src/Application.h | 1 + interface/src/PluginContainerProxy.cpp | 4 +- interface/src/PluginContainerProxy.h | 2 +- interface/src/ui/DialogsManager.cpp | 4 +- .../Basic2DWindowOpenGLDisplayPlugin.cpp | 8 +- .../Basic2DWindowOpenGLDisplayPlugin.h | 8 +- .../src/display-plugins/CompositorHelper.cpp | 34 +++-- .../src/display-plugins/CompositorHelper.h | 2 + .../src/display-plugins/NullDisplayPlugin.cpp | 2 - .../src/display-plugins/NullDisplayPlugin.h | 2 - .../display-plugins/OpenGLDisplayPlugin.cpp | 123 +++++++++++------- .../src/display-plugins/OpenGLDisplayPlugin.h | 28 ++-- .../WindowOpenGLDisplayPlugin.cpp | 43 ------ .../WindowOpenGLDisplayPlugin.h | 25 ---- .../display-plugins/hmd/HmdDisplayPlugin.cpp | 12 +- .../display-plugins/hmd/HmdDisplayPlugin.h | 9 +- .../stereo/InterleavedStereoDisplayPlugin.cpp | 2 +- .../stereo/InterleavedStereoDisplayPlugin.h | 1 + .../stereo/SideBySideStereoDisplayPlugin.cpp | 5 +- .../stereo/SideBySideStereoDisplayPlugin.h | 2 +- .../stereo/StereoDisplayPlugin.cpp | 10 +- .../stereo/StereoDisplayPlugin.h | 12 +- libraries/gl/src/gl/GLEscrow.h | 88 +++++++++++-- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 7 +- .../plugins/src/plugins/DisplayPlugin.cpp | 26 ++++ libraries/plugins/src/plugins/DisplayPlugin.h | 8 +- .../plugins/src/plugins/PluginContainer.h | 2 +- .../oculus/src/OculusBaseDisplayPlugin.cpp | 16 +-- plugins/oculus/src/OculusBaseDisplayPlugin.h | 11 +- plugins/oculus/src/OculusDisplayPlugin.cpp | 8 +- plugins/oculus/src/OculusDisplayPlugin.h | 1 - plugins/openvr/src/OpenVrDisplayPlugin.cpp | 13 +- plugins/openvr/src/OpenVrDisplayPlugin.h | 7 +- tests/controllers/src/main.cpp | 2 +- 35 files changed, 305 insertions(+), 316 deletions(-) delete mode 100644 libraries/display-plugins/src/display-plugins/WindowOpenGLDisplayPlugin.cpp delete mode 100644 libraries/display-plugins/src/display-plugins/WindowOpenGLDisplayPlugin.h create mode 100644 libraries/plugins/src/plugins/DisplayPlugin.cpp diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index bd2a43a678..8059ffbcc6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -698,6 +698,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : ResourceCache::setRequestLimit(3); _glWidget = new GLCanvas(); + getApplicationCompositor().setRenderingWidget(_glWidget); _window->setCentralWidget(_glWidget); _window->restoreGeometry(); @@ -4684,10 +4685,12 @@ qreal Application::getDevicePixelRatio() { } DisplayPlugin* Application::getActiveDisplayPlugin() { - if (nullptr == _displayPlugin) { + std::unique_lock lock(_displayPluginLock); + if (nullptr == _displayPlugin && QThread::currentThread() == thread()) { updateDisplayMode(); Q_ASSERT(_displayPlugin); } + return _displayPlugin.get(); } @@ -4733,6 +4736,19 @@ static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool acti } void Application::updateDisplayMode() { + // Unsafe to call this method from anything but the main thread + if (QThread::currentThread() != thread()) { + qFatal("Attempted to switch display plugins from a non-main thread"); + } + + // 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 + // The current oculus runtime doesn't do this anymore + if (_inPaint) { + qFatal("Attempted to switch display plugins while in painting"); + } + auto menu = Menu::getInstance(); auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins(); @@ -4789,70 +4805,25 @@ void Application::updateDisplayMode() { } } + if (newDisplayPlugin == _displayPlugin) { + return; + } + + if (_displayPlugin) { + _displayPlugin->deactivate(); + } + auto offscreenUi = DependencyManager::get(); - DisplayPluginPointer oldDisplayPlugin = _displayPlugin; - 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(); - QTimer* timer = new QTimer(); - timer->singleShot(500, [this, timer] { - timer->deleteLater(); - updateDisplayMode(); - }); - return; - } - - - if (!_pluginContainer->currentDisplayActions().isEmpty()) { - auto menu = Menu::getInstance(); - foreach(auto itemInfo, _pluginContainer->currentDisplayActions()) { - menu->removeMenuItem(itemInfo.first, itemInfo.second); - } - _pluginContainer->currentDisplayActions().clear(); - } - - if (newDisplayPlugin) { - _offscreenContext->makeCurrent(); - newDisplayPlugin->activate(); - _offscreenContext->makeCurrent(); - offscreenUi->resize(fromGlm(newDisplayPlugin->getRecommendedUiSize())); - _offscreenContext->makeCurrent(); - } - - oldDisplayPlugin = _displayPlugin; + // FIXME probably excessive and useless context switching + _offscreenContext->makeCurrent(); + newDisplayPlugin->activate(); + _offscreenContext->makeCurrent(); + offscreenUi->resize(fromGlm(newDisplayPlugin->getRecommendedUiSize())); + _offscreenContext->makeCurrent(); + getApplicationCompositor().setDisplayPlugin(newDisplayPlugin); _displayPlugin = newDisplayPlugin; - getApplicationCompositor().setDisplayPlugin(_displayPlugin); - // If the displayPlugin is a screen based HMD, then it will want the HMDTools displayed - // Direct Mode HMDs (like windows Oculus) will be isHmd() but will have a screen of -1 - bool newPluginWantsHMDTools = newDisplayPlugin ? - (newDisplayPlugin->isHmd() && (newDisplayPlugin->getHmdScreen() >= 0)) : false; - bool oldPluginWantedHMDTools = oldDisplayPlugin ? - (oldDisplayPlugin->isHmd() && (oldDisplayPlugin->getHmdScreen() >= 0)) : false; - - // Only show the hmd tools after the correct plugin has - // been activated so that it's UI is setup correctly - if (newPluginWantsHMDTools) { - _pluginContainer->showDisplayPluginsTools(); - } - - if (oldDisplayPlugin) { - oldDisplayPlugin->deactivate(); - _offscreenContext->makeCurrent(); - - // if the old plugin was HMD and the new plugin is not HMD, then hide our hmdtools - if (oldPluginWantedHMDTools && !newPluginWantsHMDTools) { - DependencyManager::get()->hmdTools(false); - } - } emit activeDisplayPluginChanged(); // reset the avatar, to set head and hand palms back to a resonable default pose. diff --git a/interface/src/Application.h b/interface/src/Application.h index 029590966c..5b4ccbd001 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -385,6 +385,7 @@ private: OffscreenGLCanvas* _offscreenContext { nullptr }; DisplayPluginPointer _displayPlugin; + std::recursive_mutex _displayPluginLock; InputPluginList _activeInputPlugins; bool _activatingDisplayPlugin { false }; diff --git a/interface/src/PluginContainerProxy.cpp b/interface/src/PluginContainerProxy.cpp index 574acbe586..c3d186f190 100644 --- a/interface/src/PluginContainerProxy.cpp +++ b/interface/src/PluginContainerProxy.cpp @@ -38,8 +38,8 @@ void PluginContainerProxy::requestReset() { qApp->resetSensors(true); } -void PluginContainerProxy::showDisplayPluginsTools() { - DependencyManager::get()->hmdTools(true); +void PluginContainerProxy::showDisplayPluginsTools(bool show) { + DependencyManager::get()->hmdTools(show); } GLWidget* PluginContainerProxy::getPrimaryWidget() { diff --git a/interface/src/PluginContainerProxy.h b/interface/src/PluginContainerProxy.h index d6ee354192..3ec2489c54 100644 --- a/interface/src/PluginContainerProxy.h +++ b/interface/src/PluginContainerProxy.h @@ -14,7 +14,7 @@ class PluginContainerProxy : public QObject, PluginContainer { Q_OBJECT PluginContainerProxy(); virtual ~PluginContainerProxy(); - virtual void showDisplayPluginsTools() override; + virtual void showDisplayPluginsTools(bool show = true) override; virtual void requestReset() override; virtual bool makeRenderingContextCurrent() override; virtual void releaseSceneTexture(const gpu::TexturePointer& texture) override; diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 41d7a0eb13..2f826146ae 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -143,7 +143,9 @@ void DialogsManager::hmdTools(bool showTools) { } void DialogsManager::hmdToolsClosed() { - _hmdToolsDialog->hide(); + if (_hmdToolsDialog) { + _hmdToolsDialog->hide(); + } } void DialogsManager::showScriptEditor() { diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index 208307b49b..63cb1b80a4 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -19,8 +19,8 @@ const QString Basic2DWindowOpenGLDisplayPlugin::NAME("Desktop"); static const QString FULLSCREEN = "Fullscreen"; -void Basic2DWindowOpenGLDisplayPlugin::activate() { - WindowOpenGLDisplayPlugin::activate(); +void Basic2DWindowOpenGLDisplayPlugin::internalActivate() { + Parent::internalActivate(); _framerateActions.clear(); _container->addMenuItem(PluginType::DISPLAY_PLUGIN, MENU_PATH(), FULLSCREEN, @@ -37,14 +37,14 @@ void Basic2DWindowOpenGLDisplayPlugin::activate() { void Basic2DWindowOpenGLDisplayPlugin::submitSceneTexture(uint32_t frameIndex, const gpu::TexturePointer& sceneTexture) { _wantVsync = true; // always - WindowOpenGLDisplayPlugin::submitSceneTexture(frameIndex, sceneTexture); + Parent::submitSceneTexture(frameIndex, sceneTexture); } void Basic2DWindowOpenGLDisplayPlugin::internalPresent() { if (_wantVsync != isVsyncEnabled()) { enableVsync(_wantVsync); } - WindowOpenGLDisplayPlugin::internalPresent(); + Parent::internalPresent(); } static const uint32_t MIN_THROTTLE_CHECK_FRAMES = 60; diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h index 9c1ea204f3..90b32a1924 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h @@ -7,22 +7,22 @@ // #pragma once -#include "WindowOpenGLDisplayPlugin.h" +#include "OpenGLDisplayPlugin.h" const float TARGET_FRAMERATE_Basic2DWindowOpenGL = 60.0f; class QScreen; class QAction; -class Basic2DWindowOpenGLDisplayPlugin : public WindowOpenGLDisplayPlugin { +class Basic2DWindowOpenGLDisplayPlugin : public OpenGLDisplayPlugin { Q_OBJECT - + using Parent = OpenGLDisplayPlugin; public: virtual const QString& getName() const override { return NAME; } virtual float getTargetFrameRate() override { return _framerateTarget ? (float) _framerateTarget : TARGET_FRAMERATE_Basic2DWindowOpenGL; } - virtual void activate() override; + virtual void internalActivate() override; virtual void submitSceneTexture(uint32_t frameIndex, const gpu::TexturePointer& sceneTexture) override; diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp index 860ed6ba37..f2040eaa43 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -188,16 +187,15 @@ void CompositorHelper::handleLeaveEvent() { if (shouldCaptureMouse()) { //QWidget* mainWidget = (QWidget*)qApp->getWindow(); - static auto renderingWidget = PluginContainer::getInstance().getPrimaryWidget(); static QWidget* mainWidget = nullptr; - if (mainWidget == nullptr) { - mainWidget = renderingWidget->parentWidget(); + if (mainWidget == nullptr && _renderingWidget != nullptr) { + mainWidget = _renderingWidget->parentWidget(); } QRect mainWidgetFrame; { - mainWidgetFrame = renderingWidget->geometry(); + mainWidgetFrame = _renderingWidget->geometry(); auto topLeft = mainWidgetFrame.topLeft(); - auto topLeftScreen = renderingWidget->mapToGlobal(topLeft); + auto topLeftScreen = _renderingWidget->mapToGlobal(topLeft); mainWidgetFrame.moveTopLeft(topLeftScreen); } QRect uncoveredRect = mainWidgetFrame; @@ -293,16 +291,17 @@ void CompositorHelper::sendFakeMouseEvent() { return; } + if (_renderingWidget) { // in HMD mode we need to fake our mouse moves... - QPoint globalPos(_reticlePositionInHMD.x, _reticlePositionInHMD.y); - auto button = Qt::NoButton; - auto buttons = QApplication::mouseButtons(); - auto modifiers = QApplication::keyboardModifiers(); - static auto renderingWidget = PluginContainer::getInstance().getPrimaryWidget(); - QMouseEvent event(QEvent::MouseMove, globalPos, button, buttons, modifiers); - _fakeMouseEvent = true; - qApp->sendEvent(renderingWidget, &event); - _fakeMouseEvent = false; + QPoint globalPos(_reticlePositionInHMD.x, _reticlePositionInHMD.y); + auto button = Qt::NoButton; + auto buttons = QApplication::mouseButtons(); + auto modifiers = QApplication::keyboardModifiers(); + QMouseEvent event(QEvent::MouseMove, globalPos, button, buttons, modifiers); + _fakeMouseEvent = true; + qApp->sendEvent(_renderingWidget, &event); + _fakeMouseEvent = false; + } } void CompositorHelper::setReticlePosition(const glm::vec2& position, bool sendFakeEvent) { @@ -496,9 +495,8 @@ glm::mat4 CompositorHelper::getReticleTransform(const glm::mat4& eyePose, const result = glm::scale(pointerTransform, reticleScale); } else { static const float CURSOR_PIXEL_SIZE = 32.0f; - static auto renderingWidget = PluginContainer::getInstance().getPrimaryWidget(); - const auto canvasSize = vec2(toGlm(renderingWidget->size()));; - vec2 mousePosition = toGlm(renderingWidget->mapFromGlobal(QCursor::pos())); + const auto canvasSize = vec2(toGlm(_renderingWidget->size()));; + vec2 mousePosition = toGlm(_renderingWidget->mapFromGlobal(QCursor::pos())); mousePosition /= canvasSize; mousePosition *= 2.0; mousePosition -= 1.0; diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.h b/libraries/display-plugins/src/display-plugins/CompositorHelper.h index ebc0171752..47433bf419 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.h +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.h @@ -48,6 +48,7 @@ public: static const vec2 MOUSE_EXTENTS_PIXELS; CompositorHelper(); + void setRenderingWidget(QWidget* widget) { _renderingWidget = widget; } bool calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const; @@ -126,6 +127,7 @@ private: DisplayPluginPointer _currentDisplayPlugin; glm::mat4 _currentCamera; uint32_t _currentFrame { 0 }; + QWidget* _renderingWidget{ nullptr }; //// Support for hovering and tooltips //static EntityItemID _noItemId; diff --git a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp index 6a8a69f634..3f642072a0 100644 --- a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp @@ -30,8 +30,6 @@ void NullDisplayPlugin::submitOverlayTexture(const gpu::TexturePointer& overlayT _container->releaseOverlayTexture(overlayTexture); } -void NullDisplayPlugin::stop() {} - QImage NullDisplayPlugin::getScreenshot() const { return QImage(); } diff --git a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h index ef0100f0b2..dfa4232a86 100644 --- a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h @@ -16,8 +16,6 @@ public: virtual const QString& getName() const override { return NAME; } virtual grouping getGrouping() const override { return DEVELOPER; } - void stop() override; - virtual glm::uvec2 getRecommendedRenderSize() const override; virtual bool hasFocus() const override; virtual void submitSceneTexture(uint32_t frameIndex, const gpu::TexturePointer& sceneTexture) override; diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 9d5c00ec2b..ca36ab35f0 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -54,6 +54,9 @@ public: void shutdown() { if (isRunning()) { + // First ensure that we turn off any current display plugin + setNewDisplayPlugin(nullptr); + Lock lock(_mutex); _shutdown = true; _condition.wait(lock, [&] { return !_shutdown; }); @@ -64,7 +67,10 @@ public: void setNewDisplayPlugin(OpenGLDisplayPlugin* plugin) { Lock lock(_mutex); - _newPlugin = plugin; + if (isRunning()) { + _newPluginQueue.push(plugin); + _condition.wait(lock, [=]()->bool { return _newPluginQueue.empty(); }); + } } void setContext(QGLContext * context) { @@ -98,37 +104,42 @@ public: } } - // Check before lock - if (_newPlugin != nullptr) { + // Check for a new display plugin + { Lock lock(_mutex); _context->makeCurrent(); // Check if we have a new plugin to activate - if (_newPlugin != nullptr) { - // Deactivate the old plugin - if (currentPlugin != nullptr) { - try { - currentPlugin->uncustomizeContext(); - } catch (const oglplus::Error& error) { - qWarning() << "OpenGL error in uncustomizeContext: " << error.what(); + while (!_newPluginQueue.empty()) { + auto newPlugin = _newPluginQueue.front(); + if (newPlugin != currentPlugin) { + // Deactivate the old plugin + if (currentPlugin != nullptr) { + try { + currentPlugin->uncustomizeContext(); + } catch (const oglplus::Error& error) { + qWarning() << "OpenGL error in uncustomizeContext: " << error.what(); + } } - currentPlugin->enableDeactivate(); - } - try { - _newPlugin->customizeContext(); - } catch (const oglplus::Error& error) { - qWarning() << "OpenGL error in customizeContext: " << error.what(); + if (newPlugin) { + try { + newPlugin->customizeContext(); + } catch (const oglplus::Error& error) { + qWarning() << "OpenGL error in customizeContext: " << error.what(); + } + } + currentPlugin = newPlugin; + _newPluginQueue.pop(); + _condition.notify_one(); } - currentPlugin = _newPlugin; - _newPlugin = nullptr; } _context->doneCurrent(); - lock.unlock(); } // If there's no active plugin, just sleep if (currentPlugin == nullptr) { - QThread::usleep(100); + // Minimum sleep ends up being about 2 ms anyway + QThread::msleep(1); continue; } @@ -146,15 +157,8 @@ public: } } - _context->makeCurrent(); - if (currentPlugin) { - currentPlugin->uncustomizeContext(); - currentPlugin->enableDeactivate(); - } - _context->doneCurrent(); - _context->moveToThread(qApp->thread()); - Lock lock(_mutex); + _context->moveToThread(qApp->thread()); _shutdown = false; _condition.notify_one(); } @@ -192,7 +196,7 @@ private: bool _pendingMainThreadOperation { false }; bool _finishedMainThreadOperation { false }; QThread* _mainThread { nullptr }; - OpenGLDisplayPlugin* _newPlugin { nullptr }; + std::queue _newPluginQueue; QGLContext* _context { nullptr }; }; @@ -231,6 +235,12 @@ void OpenGLDisplayPlugin::activate() { } _vsyncSupported = _container->getPrimaryWidget()->isVsyncSupported(); + + // Child classes may override this in order to do things like initialize + // libraries, etc + internalActivate(); + + #if THREADED_PRESENT // Start the present thread if necessary auto presentThread = DependencyManager::get(); @@ -243,6 +253,9 @@ void OpenGLDisplayPlugin::activate() { // Start execution presentThread->start(); } + + // This should not return until the new context has been customized + // and the old context (if any) has been uncustomized presentThread->setNewDisplayPlugin(this); #else static auto widget = _container->getPrimaryWidget(); @@ -253,28 +266,25 @@ void OpenGLDisplayPlugin::activate() { DisplayPlugin::activate(); } -void OpenGLDisplayPlugin::stop() { -} - void OpenGLDisplayPlugin::deactivate() { + #if THREADED_PRESENT - { - Lock lock(_mutex); - _deactivateWait.wait(lock, [&]{ return _uncustomized; }); - } + auto presentThread = DependencyManager::get(); + // Does not return until the GL transition has completeed + presentThread->setNewDisplayPlugin(nullptr); #else static auto widget = _container->getPrimaryWidget(); widget->makeCurrent(); uncustomizeContext(); _container->makeRenderingContextCurrent(); #endif + internalDeactivate(); DisplayPlugin::deactivate(); } void OpenGLDisplayPlugin::customizeContext() { #if THREADED_PRESENT - _uncustomized = false; auto presentThread = DependencyManager::get(); Q_ASSERT(thread() == presentThread->thread()); #endif @@ -393,13 +403,12 @@ void OpenGLDisplayPlugin::submitOverlayTexture(const gpu::TexturePointer& overla } void OpenGLDisplayPlugin::updateTextures() { - auto oldSceneTexture = _currentSceneTexture; - _currentSceneTexture = _sceneTextureEscrow.fetchAndRelease(_currentSceneTexture); - if (oldSceneTexture != _currentSceneTexture) { + // FIXME intrduce a GPU wait instead of a CPU/GPU sync point? + if (_sceneTextureEscrow.fetchSignaledAndRelease(_currentSceneTexture)) { updateFrameData(); } - _currentOverlayTexture = _overlayTextureEscrow.fetchAndRelease(_currentOverlayTexture); + _overlayTextureEscrow.fetchSignaledAndRelease(_currentOverlayTexture); } void OpenGLDisplayPlugin::updateFrameData() { @@ -407,7 +416,6 @@ void OpenGLDisplayPlugin::updateFrameData() { _currentRenderFrameIndex = _sceneTextureToFrameIndexMap[_currentSceneTexture]; } - void OpenGLDisplayPlugin::updateFramerate() { uint64_t now = usecTimestampNow(); static uint64_t lastSwapEnd { now }; @@ -593,14 +601,6 @@ QImage OpenGLDisplayPlugin::getScreenshot() const { return result; } -#if THREADED_PRESENT -void OpenGLDisplayPlugin::enableDeactivate() { - Lock lock(_mutex); - _uncustomized = true; - _deactivateWait.notify_one(); -} -#endif - uint32_t OpenGLDisplayPlugin::getSceneTextureId() const { if (!_currentSceneTexture) { return 0; @@ -625,3 +625,26 @@ void OpenGLDisplayPlugin::eyeViewport(Eye eye) const { } Context::Viewport(vpPos.x, vpPos.y, vpSize.x, vpSize.y); } + +glm::uvec2 OpenGLDisplayPlugin::getSurfacePixels() const { + uvec2 result; + auto window = _container->getPrimaryWidget(); + if (window) { + result = toGlm(window->geometry().size() * window->devicePixelRatio()); + } + return result; +} + +glm::uvec2 OpenGLDisplayPlugin::getSurfaceSize() const { + uvec2 result; + auto window = _container->getPrimaryWidget(); + if (window) { + result = toGlm(window->geometry().size()); + } + return result; +} + +bool OpenGLDisplayPlugin::hasFocus() const { + auto window = _container->getPrimaryWidget(); + return window ? window->hasFocus() : false; +} diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 985747bc95..501232f7e7 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -29,9 +29,12 @@ protected: using TextureEscrow = GLEscrow; public: OpenGLDisplayPlugin(); - void activate() override; - void deactivate() override; - void stop() override; + + // These must be final to ensure proper ordering of operations + // between the main thread and the presentation thread + void activate() override final; + void deactivate() override final; + bool eventFilter(QObject* receiver, QEvent* event) override; bool isDisplayVisible() const override { return true; } @@ -56,13 +59,15 @@ protected: #endif uint32_t getSceneTextureId() const; uint32_t getOverlayTextureId() const; - + + glm::uvec2 getSurfaceSize() const; + glm::uvec2 getSurfacePixels() const; + void compositeLayers(); virtual void compositeOverlay(); virtual void compositePointer(); - virtual glm::uvec2 getSurfaceSize() const = 0; - virtual glm::uvec2 getSurfacePixels() const = 0; + virtual bool hasFocus() const override; // FIXME make thread safe? virtual bool isVsyncEnabled(); @@ -71,6 +76,9 @@ protected: // These functions must only be called on the presentation thread virtual void customizeContext(); virtual void uncustomizeContext(); + + virtual void internalActivate() {} + virtual void internalDeactivate() {} virtual void cleanupForSceneTexture(const gpu::TexturePointer& sceneTexture); // Plugin specific functionality to send the composed scene to the output window or device virtual void internalPresent(); @@ -113,14 +121,6 @@ protected: std::map _cursorsData; BasicFramebufferWrapperPtr _compositeFramebuffer; - -private: -#if THREADED_PRESENT - void enableDeactivate(); - Condition _deactivateWait; - bool _uncustomized{ false }; -#endif - }; diff --git a/libraries/display-plugins/src/display-plugins/WindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/WindowOpenGLDisplayPlugin.cpp deleted file mode 100644 index c1922599a5..0000000000 --- a/libraries/display-plugins/src/display-plugins/WindowOpenGLDisplayPlugin.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// -// Created by Bradley Austin Davis on 2015/05/29 -// Copyright 2015 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 -// -#include "WindowOpenGLDisplayPlugin.h" - -#include - -#include "plugins/PluginContainer.h" - -glm::uvec2 WindowOpenGLDisplayPlugin::getSurfacePixels() const { - uvec2 result; - if (_window) { - result = toGlm(_window->geometry().size() * _window->devicePixelRatio()); - } - return result; -} - -glm::uvec2 WindowOpenGLDisplayPlugin::getSurfaceSize() const { - uvec2 result; - if (_window) { - result = toGlm(_window->geometry().size()); - } - return result; -} - -bool WindowOpenGLDisplayPlugin::hasFocus() const { - return _window ? _window->hasFocus() : false; -} - -void WindowOpenGLDisplayPlugin::activate() { - _window = _container->getPrimaryWidget(); - OpenGLDisplayPlugin::activate(); -} - -void WindowOpenGLDisplayPlugin::deactivate() { - OpenGLDisplayPlugin::deactivate(); - _window = nullptr; -} - diff --git a/libraries/display-plugins/src/display-plugins/WindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/WindowOpenGLDisplayPlugin.h deleted file mode 100644 index 51e5d32503..0000000000 --- a/libraries/display-plugins/src/display-plugins/WindowOpenGLDisplayPlugin.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// Created by Bradley Austin Davis on 2015/05/29 -// Copyright 2015 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 -// -#pragma once - -#include "OpenGLDisplayPlugin.h" - -class QWidget; - -class WindowOpenGLDisplayPlugin : public OpenGLDisplayPlugin { -public: - virtual bool hasFocus() const override; - virtual void activate() override; - virtual void deactivate() override; - -protected: - virtual glm::uvec2 getSurfaceSize() const override final; - virtual glm::uvec2 getSurfacePixels() const override final; - - QWidget* _window { nullptr }; -}; diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index e3d92d5761..67bd0fb369 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include "../Logging.h" #include "../CompositorHelper.h" @@ -30,7 +31,7 @@ glm::uvec2 HmdDisplayPlugin::getRecommendedUiSize() const { return CompositorHelper::VIRTUAL_SCREEN_SIZE; } -void HmdDisplayPlugin::activate() { +void HmdDisplayPlugin::internalActivate() { _monoPreview = _container->getBoolSetting("monoPreview", DEFAULT_MONO_VIEW); _container->addMenuItem(PluginType::DISPLAY_PLUGIN, MENU_PATH(), MONO_PREVIEW, @@ -39,11 +40,7 @@ void HmdDisplayPlugin::activate() { _container->setBoolSetting("monoPreview", _monoPreview); }, true, _monoPreview); _container->removeMenu(FRAMERATE); - Parent::activate(); -} - -void HmdDisplayPlugin::deactivate() { - Parent::deactivate(); + Parent::internalActivate(); } void HmdDisplayPlugin::customizeContext() { @@ -114,7 +111,8 @@ void HmdDisplayPlugin::internalPresent() { // screen preview mirroring if (_enablePreview) { - auto windowSize = toGlm(_window->size()); + auto window = _container->getPrimaryWidget(); + auto windowSize = toGlm(window->size()); float windowAspect = aspect(windowSize); float sceneAspect = aspect(_renderTargetSize); if (_monoPreview) { diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h index 74f4641bad..2d1b995ee6 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h @@ -9,10 +9,10 @@ #include -#include "../WindowOpenGLDisplayPlugin.h" +#include "../OpenGLDisplayPlugin.h" -class HmdDisplayPlugin : public WindowOpenGLDisplayPlugin { - using Parent = WindowOpenGLDisplayPlugin; +class HmdDisplayPlugin : public OpenGLDisplayPlugin { + using Parent = OpenGLDisplayPlugin; public: bool isHmd() const override final { return true; } float getIPD() const override final { return _ipd; } @@ -25,13 +25,12 @@ public: bool isDisplayVisible() const override { return isHmdMounted(); } - void activate() override; - void deactivate() override; protected: virtual void hmdPresent() = 0; virtual bool isHmdMounted() const = 0; + void internalActivate() override; void compositeOverlay() override; void compositePointer() override; void internalPresent() override; diff --git a/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.cpp index b7aa680984..62268afb47 100644 --- a/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.cpp @@ -58,7 +58,7 @@ void InterleavedStereoDisplayPlugin::uncustomizeContext() { } glm::uvec2 InterleavedStereoDisplayPlugin::getRecommendedRenderSize() const { - uvec2 result = WindowOpenGLDisplayPlugin::getRecommendedRenderSize(); + uvec2 result = Parent::getRecommendedRenderSize(); result.x *= 2; result.y /= 2; return result; diff --git a/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h index 8c133fc877..5eeda951e5 100644 --- a/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h @@ -11,6 +11,7 @@ class InterleavedStereoDisplayPlugin : public StereoDisplayPlugin { Q_OBJECT + using Parent = StereoDisplayPlugin; public: const QString& getName() const override { return NAME; } grouping getGrouping() const override { return ADVANCED; } diff --git a/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.cpp index 46533d1c16..5f55841be1 100644 --- a/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.cpp @@ -15,11 +15,8 @@ const QString SideBySideStereoDisplayPlugin::NAME("3D TV - Side by Side Stereo"); -SideBySideStereoDisplayPlugin::SideBySideStereoDisplayPlugin() { -} - glm::uvec2 SideBySideStereoDisplayPlugin::getRecommendedRenderSize() const { - uvec2 result = WindowOpenGLDisplayPlugin::getRecommendedRenderSize(); + uvec2 result = Parent::getRecommendedRenderSize(); result.x *= 2; return result; } diff --git a/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.h index ab4e37f4da..d4d20243ea 100644 --- a/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.h @@ -13,8 +13,8 @@ class QScreen; class SideBySideStereoDisplayPlugin : public StereoDisplayPlugin { Q_OBJECT + using Parent = StereoDisplayPlugin; public: - SideBySideStereoDisplayPlugin(); virtual const QString& getName() const override { return NAME; } virtual grouping getGrouping() const override { return ADVANCED; } virtual glm::uvec2 getRecommendedRenderSize() const override; diff --git a/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.cpp index 13df8d519b..ae9f18e20d 100644 --- a/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.cpp @@ -58,7 +58,7 @@ glm::mat4 StereoDisplayPlugin::getEyeProjection(Eye eye, const glm::mat4& basePr static const QString FRAMERATE = DisplayPlugin::MENU_PATH() + ">Framerate"; std::vector _screenActions; -void StereoDisplayPlugin::activate() { +void StereoDisplayPlugin::internalActivate() { auto screens = qApp->screens(); _screenActions.resize(screens.size()); for (int i = 0; i < screens.size(); ++i) { @@ -77,7 +77,7 @@ void StereoDisplayPlugin::activate() { _screen = qApp->primaryScreen(); _container->setFullscreen(_screen); - WindowOpenGLDisplayPlugin::activate(); + Parent::internalActivate(); } void StereoDisplayPlugin::updateScreen() { @@ -90,15 +90,15 @@ void StereoDisplayPlugin::updateScreen() { } } -void StereoDisplayPlugin::deactivate() { +void StereoDisplayPlugin::internalDeactivate() { _screenActions.clear(); _container->unsetFullscreen(); - WindowOpenGLDisplayPlugin::deactivate(); + Parent::internalDeactivate(); } // Derived classes will override the recommended render size based on the window size, // so here we want to fix the aspect ratio based on the window, not on the render size float StereoDisplayPlugin::getRecommendedAspectRatio() const { - return aspect(WindowOpenGLDisplayPlugin::getRecommendedRenderSize()); + return aspect(Parent::getRecommendedRenderSize()); } diff --git a/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.h index 1f650bd3d6..6563c2ae89 100644 --- a/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.h @@ -7,19 +7,16 @@ // #pragma once -#include "../WindowOpenGLDisplayPlugin.h" +#include "../OpenGLDisplayPlugin.h" class QScreen; -class StereoDisplayPlugin : public WindowOpenGLDisplayPlugin { +class StereoDisplayPlugin : public OpenGLDisplayPlugin { Q_OBJECT - using Parent = WindowOpenGLDisplayPlugin; + using Parent = OpenGLDisplayPlugin; public: virtual bool isStereo() const override final { return true; } virtual bool isSupported() const override final; - virtual void activate() override; - virtual void deactivate() override; - virtual float getRecommendedAspectRatio() const override; virtual glm::mat4 getEyeProjection(Eye eye, const glm::mat4& baseProjection) const override; @@ -32,7 +29,10 @@ public: // virtual glm::mat4 getEyeToHeadTransform(Eye eye) const override; protected: + virtual void internalActivate() override; + virtual void internalDeactivate() override; void updateScreen(); + float _ipd{ 0.064f }; QScreen* _screen; }; diff --git a/libraries/gl/src/gl/GLEscrow.h b/libraries/gl/src/gl/GLEscrow.h index f3332a2482..357398c79b 100644 --- a/libraries/gl/src/gl/GLEscrow.h +++ b/libraries/gl/src/gl/GLEscrow.h @@ -138,34 +138,100 @@ public: // Returns the next available resource provided by the submitter, // or if none is available (which could mean either the submission // list is empty or that the first item on the list isn't yet signaled - T fetch() { - T result = invalid(); + // Deprecated... will inject an unecessary GPU bubble + bool fetchSignaled(T& t) { + bool result = false; // On the one hand using try_lock() reduces the chance of blocking the consumer thread, // but if the produce thread is going fast enough, it could effectively // starve the consumer out of ever actually getting resources. - tryLock([&]{ + tryLock([&] { // May be called on any thread, but must be inside a locked section if (signaled(_submits, 0)) { - result = _submits.at(0)._value; + result = true; + t = _submits.at(0)._value; _submits.pop_front(); } }); return result; } + // Populates t with the next available resource provided by the submitter + // and sync with a fence that will be signaled when all write commands for the + // item have completed. Returns false if no resources are available + bool fetchWithFence(T& t, GLsync& sync) { + bool result = false; + // On the one hand using try_lock() reduces the chance of blocking the consumer thread, + // but if the produce thread is going fast enough, it could effectively + // starve the consumer out of ever actually getting resources. + tryLock([&] { + if (!_submits.empty()) { + result = true; + // When fetching with sync, we only want the latest item + auto item = _submits.back(); + _submits.pop_back(); + + // Throw everything else in the trash + for (const auto& oldItem : _submits) { + _trash.push_front(oldItem); + } + _submits.clear(); + + t = item._value; + sync = item._sync; + } + }); + return result; + } + + bool fetchWithGpuWait(T& t) { + GLsync sync { 0 }; + if (fetchWithFence(t, sync)) { + // Texture was updated, inject a wait into the GL command stream to ensure + // commands on this context until the commands to generate t are finished. + if (sync != 0) { + glWaitSync(sync, 0, GL_TIMEOUT_IGNORED); + glDeleteSync(sync); + } + return true; + } + return false; + } + // Returns the next available resource provided by the submitter, // or if none is available (which could mean either the submission // list is empty or that the first item on the list isn't yet signaled // Also releases any previous texture held by the caller - T fetchAndRelease(const T& oldValue) { - T result = fetch(); - if (!result) { - return oldValue; + bool fetchSignaledAndRelease(T& value) { + T originalValue = value; + if (fetchSignaled(value)) { + if (originalValue != invalid()) { + release(originalValue); + } + return true; } - if (oldValue) { - release(oldValue); + return false; + } + + bool fetchAndReleaseWithFence(T& value, GLsync& sync) { + T originalValue = value; + if (fetchWithFence(value, sync)) { + if (originalValue != invalid()) { + release(originalValue); + } + return true; } - return result; + return false; + } + + bool fetchAndReleaseWithGpuWait(T& value) { + T originalValue = value; + if (fetchWithGpuWait(value)) { + if (originalValue != invalid()) { + release(originalValue); + } + return true; + } + return false; } // If fetch returns a non-zero value, it's the responsibility of the diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index 2088273e0e..6a780d74e2 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -498,12 +498,7 @@ void OffscreenQmlSurface::updateQuick() { _render = false; } - GLuint newTexture = _renderer->_escrow.fetch(); - if (newTexture) { - if (_currentTexture) { - _renderer->_escrow.release(_currentTexture); - } - _currentTexture = newTexture; + if (_renderer->_escrow.fetchSignaledAndRelease(_currentTexture)) { emit textureUpdated(_currentTexture); } } diff --git a/libraries/plugins/src/plugins/DisplayPlugin.cpp b/libraries/plugins/src/plugins/DisplayPlugin.cpp new file mode 100644 index 0000000000..3860639614 --- /dev/null +++ b/libraries/plugins/src/plugins/DisplayPlugin.cpp @@ -0,0 +1,26 @@ +#include "DisplayPlugin.h" + +#include + +#include "PluginContainer.h" + +void DisplayPlugin::activate() { + Parent::activate(); + if (isHmd() && (getHmdScreen() >= 0)) { + _container->showDisplayPluginsTools(); + } +} + +void DisplayPlugin::deactivate() { + _container->showDisplayPluginsTools(false); + if (!_container->currentDisplayActions().isEmpty()) { + auto menu = _container->getPrimaryMenu(); + foreach(auto itemInfo, _container->currentDisplayActions()) { + menu->removeMenuItem(itemInfo.first, itemInfo.second); + } + _container->currentDisplayActions().clear(); + } + Parent::deactivate(); +} + + diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index e1e50b2b32..76db1ecbe2 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -57,7 +57,10 @@ namespace gpu { class DisplayPlugin : public Plugin { Q_OBJECT + using Parent = Plugin; public: + void activate() override; + void deactivate() override; virtual bool isHmd() const { return false; } virtual int getHmdScreen() const { return -1; } /// By default, all HMDs are stereo @@ -73,11 +76,6 @@ public: // 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; - /** * Sends the scene texture to the display plugin. */ diff --git a/libraries/plugins/src/plugins/PluginContainer.h b/libraries/plugins/src/plugins/PluginContainer.h index 991b8260c2..feaabf83e1 100644 --- a/libraries/plugins/src/plugins/PluginContainer.h +++ b/libraries/plugins/src/plugins/PluginContainer.h @@ -55,7 +55,7 @@ public: void unsetFullscreen(const QScreen* avoidScreen = nullptr); virtual ui::Menu* getPrimaryMenu() = 0; - virtual void showDisplayPluginsTools() = 0; + virtual void showDisplayPluginsTools(bool show = true) = 0; virtual void requestReset() = 0; virtual bool makeRenderingContextCurrent() = 0; virtual void releaseSceneTexture(const gpu::TexturePointer& texture) = 0; diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp index 513ea0e0df..f1613176df 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp @@ -34,16 +34,10 @@ void OculusBaseDisplayPlugin::customizeContext() { glewExperimental = true; GLenum err = glewInit(); glGetError(); - HmdDisplayPlugin::customizeContext(); + Parent::customizeContext(); } -void OculusBaseDisplayPlugin::init() { -} - -void OculusBaseDisplayPlugin::deinit() { -} - -void OculusBaseDisplayPlugin::activate() { +void OculusBaseDisplayPlugin::internalActivate() { _session = acquireOculusSession(); _hmdDesc = ovr_GetHmdDesc(_session); @@ -90,11 +84,11 @@ void OculusBaseDisplayPlugin::activate() { // This must come after the initialization, so that the values calculated // above are available during the customizeContext call (when not running // in threaded present mode) - HmdDisplayPlugin::activate(); + Parent::internalActivate(); } -void OculusBaseDisplayPlugin::deactivate() { - HmdDisplayPlugin::deactivate(); +void OculusBaseDisplayPlugin::internalDeactivate() { + Parent::internalDeactivate(); releaseOculusSession(); _session = nullptr; } diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.h b/plugins/oculus/src/OculusBaseDisplayPlugin.h index 74558f2ee6..e6f0b265a2 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.h +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.h @@ -14,21 +14,18 @@ #include class OculusBaseDisplayPlugin : public HmdDisplayPlugin { + using Parent = HmdDisplayPlugin; public: virtual bool isSupported() const override; - virtual void init() override final; - virtual void deinit() override final; - - virtual void activate() override; - virtual void deactivate() override; - // Stereo specific methods virtual void resetSensors() override final; virtual glm::mat4 getHeadPose(uint32_t frameIndex) const override; protected: - virtual void customizeContext() override; + void customizeContext() override; + void internalActivate() override; + void internalDeactivate() override; protected: ovrSession _session; diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp index dbad725cf6..5ab56e1659 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDisplayPlugin.cpp @@ -10,12 +10,8 @@ const QString OculusDisplayPlugin::NAME("Oculus Rift"); -void OculusDisplayPlugin::activate() { - OculusBaseDisplayPlugin::activate(); -} - void OculusDisplayPlugin::customizeContext() { - OculusBaseDisplayPlugin::customizeContext(); + Parent::customizeContext(); _sceneFbo = SwapFboPtr(new SwapFramebufferWrapper(_session)); _sceneFbo->Init(getRecommendedRenderSize()); @@ -34,7 +30,7 @@ void OculusDisplayPlugin::uncustomizeContext() { #if (OVR_MAJOR_VERSION >= 6) _sceneFbo.reset(); #endif - OculusBaseDisplayPlugin::uncustomizeContext(); + Parent::uncustomizeContext(); } diff --git a/plugins/oculus/src/OculusDisplayPlugin.h b/plugins/oculus/src/OculusDisplayPlugin.h index 1e93d9f823..9b6b922f69 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.h +++ b/plugins/oculus/src/OculusDisplayPlugin.h @@ -17,7 +17,6 @@ const float TARGET_RATE_Oculus = 75.0f; class OculusDisplayPlugin : public OculusBaseDisplayPlugin { using Parent = OculusBaseDisplayPlugin; public: - void activate() override; const QString& getName() const override { return NAME; } float getTargetFrameRate() override { return TARGET_RATE_Oculus; } diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 47b3e233cf..69fb40d7e1 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -41,7 +41,8 @@ bool OpenVrDisplayPlugin::isSupported() const { return vr::VR_IsHmdPresent(); } -void OpenVrDisplayPlugin::activate() { +void OpenVrDisplayPlugin::internalActivate() { + Parent::internalActivate(); _container->setIsOptionChecked(StandingHMDSensorMode, true); if (!_system) { @@ -67,7 +68,6 @@ void OpenVrDisplayPlugin::activate() { _compositor = vr::VRCompositor(); Q_ASSERT(_compositor); - HmdDisplayPlugin::activate(); // set up default sensor space such that the UI overlay will align with the front of the room. auto chaperone = vr::VRChaperone(); @@ -85,11 +85,8 @@ void OpenVrDisplayPlugin::activate() { } } -void OpenVrDisplayPlugin::deactivate() { - // Base class deactivate must come before our local deactivate - // because the OpenGL base class handles the wait for the present - // thread before continuing - HmdDisplayPlugin::deactivate(); +void OpenVrDisplayPlugin::internalDeactivate() { + Parent::internalDeactivate(); _container->setIsOptionChecked(StandingHMDSensorMode, false); if (_system) { releaseOpenVrSystem(); @@ -106,7 +103,7 @@ void OpenVrDisplayPlugin::customizeContext() { GLenum err = glewInit(); glGetError(); }); - HmdDisplayPlugin::customizeContext(); + Parent::customizeContext(); } void OpenVrDisplayPlugin::resetSensors() { diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.h b/plugins/openvr/src/OpenVrDisplayPlugin.h index affc12a383..c7577fd53f 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.h +++ b/plugins/openvr/src/OpenVrDisplayPlugin.h @@ -16,15 +16,13 @@ const float TARGET_RATE_OpenVr = 90.0f; // FIXME: get from sdk tracked device property? This number is vive-only. class OpenVrDisplayPlugin : public HmdDisplayPlugin { + using Parent = HmdDisplayPlugin; public: virtual bool isSupported() const override; virtual const QString& getName() const override { return NAME; } virtual float getTargetFrameRate() override { return TARGET_RATE_OpenVr; } - virtual void activate() override; - virtual void deactivate() override; - virtual void customizeContext() override; // Stereo specific methods @@ -32,6 +30,9 @@ public: virtual glm::mat4 getHeadPose(uint32_t frameIndex) const override; protected: + void internalActivate() override; + void internalDeactivate() override; + void hmdPresent() override; bool isHmdMounted() const override; diff --git a/tests/controllers/src/main.cpp b/tests/controllers/src/main.cpp index 9bf74fc501..81acf2594d 100644 --- a/tests/controllers/src/main.cpp +++ b/tests/controllers/src/main.cpp @@ -81,7 +81,7 @@ class PluginContainerProxy : public QObject, PluginContainer { Q_OBJECT public: virtual ~PluginContainerProxy() {} - virtual void showDisplayPluginsTools() override {} + virtual void showDisplayPluginsTools(bool show) override {} virtual void requestReset() override {} virtual bool makeRenderingContextCurrent() override { return true; } virtual void releaseSceneTexture(const gpu::TexturePointer& texture) override {}