diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index eb8c275123..588c43d534 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -33,18 +33,6 @@ bool Basic2DWindowOpenGLDisplayPlugin::internalActivate() { return Parent::internalActivate(); } -void Basic2DWindowOpenGLDisplayPlugin::submitFrame(const gpu::FramePointer& newFrame) { - _wantVsync = true; // always - Parent::submitFrame(newFrame); -} - -void Basic2DWindowOpenGLDisplayPlugin::internalPresent() { - if (_wantVsync != isVsyncEnabled()) { - enableVsync(_wantVsync); - } - Parent::internalPresent(); -} - static const uint32_t MIN_THROTTLE_CHECK_FRAMES = 60; bool Basic2DWindowOpenGLDisplayPlugin::isThrottled() const { diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h index 6321bb6d79..2e4e57e15a 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h @@ -24,10 +24,6 @@ public: virtual bool internalActivate() override; - void submitFrame(const gpu::FramePointer& newFrame) override; - - virtual void internalPresent() override; - virtual bool isThrottled() const override; protected: @@ -40,5 +36,4 @@ private: QAction* _vsyncAction { nullptr }; uint32_t _framerateTarget { 0 }; int _fullscreenTarget{ -1 }; - bool _wantVsync { true }; }; diff --git a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp index 05dacea385..23e4a9dd6a 100644 --- a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp @@ -12,6 +12,7 @@ #include #include #include +#include const QString NullDisplayPlugin::NAME("NullDisplayPlugin"); @@ -24,6 +25,9 @@ bool NullDisplayPlugin::hasFocus() const { } void NullDisplayPlugin::submitFrame(const gpu::FramePointer& resultFramebuffer) { + if (resultFramebuffer) { + resultFramebuffer->preRender(); + } } QImage NullDisplayPlugin::getScreenshot() const { diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 6dadcb2466..d969daf231 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -133,8 +133,6 @@ public: // Main thread does it's thing while we wait on the lock to release Lock lock(_mutex); _condition.wait(lock, [&] { return _finishedMainThreadOperation; }); - _context->makeCurrent(); - Q_ASSERT(isCurrentContext(_context->contextHandle())); } } @@ -147,13 +145,34 @@ public: if (newPlugin != currentPlugin) { // Deactivate the old plugin if (currentPlugin != nullptr) { + _context->makeCurrent(); currentPlugin->uncustomizeContext(); CHECK_GL_ERROR(); + _context->doneCurrent(); } if (newPlugin) { + bool hasVsync = true; + bool wantVsync = newPlugin->wantVsync(); + _context->makeCurrent(); +#if defined(Q_OS_WIN) + wglSwapIntervalEXT(wantVsync ? 1 : 0); + hasVsync = wglGetSwapIntervalEXT() != 0; +#elif defined(Q_OS_MAC) + GLint interval = wantVsync ? 1 : 0; + newPlugin->swapBuffers(); + CGLSetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &interval); + newPlugin->swapBuffers(); + CGLGetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &interval); + hasVsync = interval != 0; +#else + // TODO: Fill in for linux + Q_UNUSED(wantVsync); +#endif + newPlugin->setVsyncEnabled(hasVsync); newPlugin->customizeContext(); CHECK_GL_ERROR(); + _context->doneCurrent(); } currentPlugin = newPlugin; _newPluginQueue.pop(); @@ -176,8 +195,8 @@ public: currentPlugin->present(); CHECK_GL_ERROR(); } + _context->doneCurrent(); } - _context->doneCurrent(); Lock lock(_mutex); _context->moveToThread(qApp->thread()); @@ -239,7 +258,6 @@ bool OpenGLDisplayPlugin::activate() { if (!_container) { return false; } - _vsyncSupported = _container->getPrimaryWidget()->isVsyncSupported(); // Start the present thread if necessary QSharedPointer presentThread; @@ -309,7 +327,6 @@ void OpenGLDisplayPlugin::deactivate() { void OpenGLDisplayPlugin::customizeContext() { auto presentThread = DependencyManager::get(); Q_ASSERT(thread() == presentThread->thread()); - enableVsync(); getGLBackend()->setCameraCorrection(mat4()); @@ -619,37 +636,6 @@ float OpenGLDisplayPlugin::presentRate() const { return _presentRate.rate(); } -void OpenGLDisplayPlugin::enableVsync(bool enable) { - if (!_vsyncSupported) { - return; - } -#if defined(Q_OS_WIN) - wglSwapIntervalEXT(enable ? 1 : 0); -#elif defined(Q_OS_MAC) - GLint interval = enable ? 1 : 0; - CGLSetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &interval); -#else - // TODO: Fill in for linux - return; -#endif -} - -bool OpenGLDisplayPlugin::isVsyncEnabled() { - if (!_vsyncSupported) { - return true; - } -#if defined(Q_OS_WIN) - return wglGetSwapIntervalEXT() != 0; -#elif defined(Q_OS_MAC) - GLint interval; - CGLGetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &interval); - return interval != 0; -#else - // TODO: Fill in for linux - return true; -#endif -} - void OpenGLDisplayPlugin::swapBuffers() { static auto widget = _container->getPrimaryWidget(); widget->swapBuffers(); diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 1ab7be2511..48f9a78eda 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -63,6 +63,11 @@ public: float droppedFrameRate() const override; bool beginFrameRender(uint32_t frameIndex) override; + + virtual bool wantVsync() const { return true; } + void setVsyncEnabled(bool vsyncEnabled) { _vsyncEnabled = vsyncEnabled; } + bool isVsyncEnabled() const { return _vsyncEnabled; } + protected: friend class PresentThread; @@ -77,10 +82,6 @@ protected: virtual bool hasFocus() const override; - // FIXME make thread safe? - virtual bool isVsyncEnabled(); - virtual void enableVsync(bool enable = true); - // These functions must only be called on the presentation thread virtual void customizeContext(); virtual void uncustomizeContext(); @@ -97,11 +98,12 @@ protected: void withMainThreadContext(std::function f) const; void present(); - void swapBuffers(); + virtual void swapBuffers(); ivec4 eyeViewport(Eye eye) const; void render(std::function f); + bool _vsyncEnabled { true }; QThread* _presentThread{ nullptr }; std::queue _newFrameQueue; RateCounter<> _droppedFrameRate; @@ -116,9 +118,6 @@ protected: gpu::PipelinePointer _cursorPipeline; float _compositeOverlayAlpha { 1.0f }; - - bool _vsyncSupported { false }; - struct CursorData { QImage image; vec2 hotSpot; diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index 2f999965f8..82cd08db39 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -63,7 +63,24 @@ QRect HmdDisplayPlugin::getRecommendedOverlayRect() const { return CompositorHelper::VIRTUAL_SCREEN_RECOMMENDED_OVERLAY_RECT; } +bool HmdDisplayPlugin::beginFrameRender(uint32_t frameIndex) { + if (!_vsyncEnabled && !_disablePreviewItemAdded) { + _container->addMenuItem(PluginType::DISPLAY_PLUGIN, MENU_PATH(), DISABLE_PREVIEW, + [this](bool clicked) { + _disablePreview = clicked; + _container->setBoolSetting("disableHmdPreview", _disablePreview); + if (_disablePreview) { + _clearPreviewFlag = true; + } + }, true, _disablePreview); + _disablePreviewItemAdded = true; + } + return Parent::beginFrameRender(frameIndex); +} + + bool HmdDisplayPlugin::internalActivate() { + _disablePreviewItemAdded = false; _monoPreview = _container->getBoolSetting("monoPreview", DEFAULT_MONO_VIEW); _clearPreviewFlag = true; _container->addMenuItem(PluginType::DISPLAY_PLUGIN, MENU_PATH(), MONO_PREVIEW, @@ -74,17 +91,7 @@ bool HmdDisplayPlugin::internalActivate() { #if defined(Q_OS_MAC) _disablePreview = true; #else - _disablePreview = _container->getBoolSetting("disableHmdPreview", DEFAULT_DISABLE_PREVIEW || !_vsyncSupported); - if (_vsyncSupported) { - _container->addMenuItem(PluginType::DISPLAY_PLUGIN, MENU_PATH(), DISABLE_PREVIEW, - [this](bool clicked) { - _disablePreview = clicked; - _container->setBoolSetting("disableHmdPreview", _disablePreview); - if (_disablePreview) { - _clearPreviewFlag = true; - } - }, true, _disablePreview); - } + _disablePreview = _container->getBoolSetting("disableHmdPreview", DEFAULT_DISABLE_PREVIEW || _vsyncEnabled); #endif _container->removeMenu(FRAMERATE); @@ -103,15 +110,20 @@ void HmdDisplayPlugin::internalDeactivate() { void HmdDisplayPlugin::customizeContext() { Parent::customizeContext(); - // Only enable mirroring if we know vsync is disabled - // On Mac, this won't work due to how the contexts are handled, so don't try -#if !defined(Q_OS_MAC) - enableVsync(false); -#endif _overlayRenderer.build(); } void HmdDisplayPlugin::uncustomizeContext() { + // This stops the weirdness where if the preview was disabled, on switching back to 2D, + // the vsync was stuck in the disabled state. No idea why that happens though. + _disablePreview = false; + render([&](gpu::Batch& batch) { + batch.enableStereo(false); + batch.clearViewTransform(); + batch.setFramebuffer(_compositeFramebuffer); + batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, vec4(0)); + }); + internalPresent(); _overlayRenderer = OverlayRenderer(); Parent::uncustomizeContext(); } diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h index fc3b40670a..a5710b6077 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h @@ -38,12 +38,17 @@ public: bool setHandLaser(uint32_t hands, HandLaserMode mode, const vec4& color, const vec3& direction) override; + bool wantVsync() const override { + return false; + } + protected: virtual void hmdPresent() = 0; virtual bool isHmdMounted() const = 0; virtual void postPreview() {}; virtual void updatePresentPose(); + bool beginFrameRender(uint32_t frameIndex) override; bool internalActivate() override; void internalDeactivate() override; void compositeOverlay() override; @@ -94,10 +99,11 @@ protected: FrameInfo _currentPresentFrameInfo; FrameInfo _currentRenderFrameInfo; + bool _disablePreview{ true }; private: ivec4 getViewportForSourceSize(const uvec2& size) const; - bool _disablePreview{ true }; + bool _disablePreviewItemAdded { false }; bool _monoPreview { true }; bool _clearPreviewFlag { false }; gpu::TexturePointer _previewTexture; diff --git a/libraries/gpu/src/gpu/Buffer.cpp b/libraries/gpu/src/gpu/Buffer.cpp index 0604980ddb..bed02035bb 100644 --- a/libraries/gpu/src/gpu/Buffer.cpp +++ b/libraries/gpu/src/gpu/Buffer.cpp @@ -118,7 +118,6 @@ Buffer::Update::Update(const Buffer& parent) : buffer(parent) { void Buffer::Update::apply() const { // Make sure we're loaded in order ++buffer._applyUpdateCount; - assert(isRenderThread()); assert(buffer._applyUpdateCount.load() == updateNumber); const auto pageSize = buffer._pages._pageSize; buffer._renderSysmem.resize(size); diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp index b5d39b8589..0c19a62585 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDisplayPlugin.cpp @@ -83,11 +83,6 @@ void OculusDisplayPlugin::customizeContext() { _sceneLayer.ColorTexture[0] = _textureSwapChain; // not needed since the structure was zeroed on init, but explicit _sceneLayer.ColorTexture[1] = nullptr; - - enableVsync(false); - // Only enable mirroring if we know vsync is disabled - _enablePreview = !isVsyncEnabled(); - } void OculusDisplayPlugin::uncustomizeContext() { diff --git a/plugins/oculus/src/OculusDisplayPlugin.h b/plugins/oculus/src/OculusDisplayPlugin.h index bcd8f5d8ab..80705319c6 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.h +++ b/plugins/oculus/src/OculusDisplayPlugin.h @@ -29,8 +29,6 @@ protected: private: static const QString NAME; - bool _enablePreview { false }; - bool _monoPreview { true }; ovrTextureSwapChain _textureSwapChain; gpu::FramebufferPointer _outputFramebuffer; }; diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 950f01496e..41f8df6d1b 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -297,7 +297,6 @@ bool OpenVrDisplayPlugin::internalActivate() { _submitThread = std::make_shared(*this); }); _submitThread->setObjectName("OpenVR Submit Thread"); - _submitThread->start(QThread::TimeCriticalPriority); #endif return Parent::internalActivate(); @@ -306,11 +305,6 @@ bool OpenVrDisplayPlugin::internalActivate() { void OpenVrDisplayPlugin::internalDeactivate() { Parent::internalDeactivate(); -#if OPENVR_THREADED_SUBMIT - _submitThread->_quit = true; - _submitThread->wait(); -#endif - _openVrDisplayActive = false; _container->setIsOptionChecked(StandingHMDSensorMode, false); if (_system) { @@ -339,10 +333,17 @@ void OpenVrDisplayPlugin::customizeContext() { } _compositeInfos[i].textureID = getGLBackend()->getTextureID(_compositeInfos[i].texture, false); } + + _submitThread->start(QThread::HighPriority); } void OpenVrDisplayPlugin::uncustomizeContext() { Parent::uncustomizeContext(); + +#if OPENVR_THREADED_SUBMIT + _submitThread->_quit = true; + _submitThread->wait(); +#endif } void OpenVrDisplayPlugin::resetSensors() {