diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 55023eea0e..084a164deb 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -21,11 +21,13 @@ #include #include #include + #include #include #include #include +#if THREADED_PRESENT class PresentThread : public QThread, public Dependency { using Mutex = std::mutex; using Condition = std::condition_variable; @@ -33,16 +35,25 @@ class PresentThread : public QThread, public Dependency { public: PresentThread() { - connect(qApp, &QCoreApplication::aboutToQuit, [this]{ - _shutdown = true; + connect(qApp, &QCoreApplication::aboutToQuit, [this] { + shutdown(); }); } ~PresentThread() { - _shutdown = true; - wait(); + shutdown(); } + void shutdown() { + if (isRunning()) { + Lock lock(_mutex); + _shutdown = true; + _condition.wait(lock, [&] { return !_shutdown; }); + qDebug() << "Present thread shutdown"; + } + } + + void setNewDisplayPlugin(OpenGLDisplayPlugin* plugin) { Lock lock(_mutex); _newPlugin = plugin; @@ -120,6 +131,10 @@ public: } _context->doneCurrent(); _context->moveToThread(qApp->thread()); + + Lock lock(_mutex); + _shutdown = false; + _condition.notify_one(); } void withMainThreadContext(std::function f) { @@ -159,16 +174,14 @@ private: QGLContext* _context { nullptr }; }; +#endif + OpenGLDisplayPlugin::OpenGLDisplayPlugin() { _sceneTextureEscrow.setRecycler([this](GLuint texture){ cleanupForSceneTexture(texture); _container->releaseSceneTexture(texture); }); - _overlayTextureEscrow.setRecycler([this](GLuint texture) { - _container->releaseOverlayTexture(texture); - }); - connect(&_timer, &QTimer::timeout, this, [&] { #ifdef Q_OS_MAC // On Mac, QT thread timing is such that we can miss one or even two cycles quite often, giving a render rate (including update/simulate) @@ -191,9 +204,10 @@ void OpenGLDisplayPlugin::cleanupForSceneTexture(uint32_t sceneTexture) { void OpenGLDisplayPlugin::activate() { - _timer.start(1); _vsyncSupported = _container->getPrimaryWidget()->isVsyncSupported(); +#if THREADED_PRESENT + _timer.start(1); // Start the present thread if necessary auto presentThread = DependencyManager::get(); if (!presentThread) { @@ -208,7 +222,15 @@ void OpenGLDisplayPlugin::activate() { presentThread->start(); } presentThread->setNewDisplayPlugin(this); +#else + static auto widget = _container->getPrimaryWidget(); + widget->makeCurrent(); + customizeContext(); + _container->makeRenderingContextCurrent(); +#endif DisplayPlugin::activate(); + + } void OpenGLDisplayPlugin::stop() { @@ -216,19 +238,27 @@ void OpenGLDisplayPlugin::stop() { } void OpenGLDisplayPlugin::deactivate() { +#if THREADED_PRESENT { Lock lock(_mutex); _deactivateWait.wait(lock, [&]{ return _uncustomized; }); } _timer.stop(); +#else + static auto widget = _container->getPrimaryWidget(); + widget->makeCurrent(); + uncustomizeContext(); + _container->makeRenderingContextCurrent(); +#endif DisplayPlugin::deactivate(); } void OpenGLDisplayPlugin::customizeContext() { +#if THREADED_PRESENT _uncustomized = false; auto presentThread = DependencyManager::get(); Q_ASSERT(thread() == presentThread->thread()); - +#endif enableVsync(); using namespace oglplus; @@ -297,16 +327,23 @@ void OpenGLDisplayPlugin::submitSceneTexture(uint32_t frameIndex, uint32_t scene // Submit it to the presentation thread via escrow _sceneTextureEscrow.submit(sceneTexture); + +#if THREADED_PRESENT +#else + static auto widget = _container->getPrimaryWidget(); + widget->makeCurrent(); + present(); + _container->makeRenderingContextCurrent(); +#endif } -void OpenGLDisplayPlugin::submitOverlayTexture(GLuint sceneTexture, const glm::uvec2& sceneSize) { +void OpenGLDisplayPlugin::submitOverlayTexture(GLuint overlayTexture, const glm::uvec2& overlaySize) { // Submit it to the presentation thread via escrow - _overlayTextureEscrow.submit(sceneTexture); + _currentOverlayTexture = overlayTexture; } void OpenGLDisplayPlugin::updateTextures() { _currentSceneTexture = _sceneTextureEscrow.fetchAndRelease(_currentSceneTexture); - _currentOverlayTexture = _overlayTextureEscrow.fetchAndRelease(_currentOverlayTexture); } void OpenGLDisplayPlugin::updateFramerate() { @@ -337,6 +374,11 @@ void OpenGLDisplayPlugin::present() { internalPresent(); updateFramerate(); } + +#if THREADED_PRESENT +#else + emit requestRender(); +#endif } float OpenGLDisplayPlugin::presentRate() { @@ -351,12 +393,8 @@ float OpenGLDisplayPlugin::presentRate() { } void OpenGLDisplayPlugin::drawUnitQuad() { - try { - _program->Bind(); - _plane->Draw(); - } catch (const oglplus::Error& error) { - qWarning() << "The present thread encountered an error writing the scene texture to the output: " << error.what(); - } + _program->Bind(); + _plane->Draw(); } void OpenGLDisplayPlugin::enableVsync(bool enable) { @@ -385,9 +423,16 @@ void OpenGLDisplayPlugin::swapBuffers() { } void OpenGLDisplayPlugin::withMainThreadContext(std::function f) const { +#if THREADED_PRESENT static auto presentThread = DependencyManager::get(); presentThread->withMainThreadContext(f); _container->makeRenderingContextCurrent(); +#else + static auto widget = _container->getPrimaryWidget(); + widget->makeCurrent(); + f(); + _container->makeRenderingContextCurrent(); +#endif } QImage OpenGLDisplayPlugin::getScreenshot() const { @@ -399,8 +444,10 @@ QImage OpenGLDisplayPlugin::getScreenshot() const { return result; } +#if THREADED_PRESENT void OpenGLDisplayPlugin::enableDeactivate() { Lock lock(_mutex); _uncustomized = true; _deactivateWait.notify_one(); -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 72211056d9..d1000267ef 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -18,6 +18,8 @@ #include #include +#define THREADED_PRESENT 1 + class OpenGLDisplayPlugin : public DisplayPlugin { protected: using Mutex = std::mutex; @@ -45,8 +47,9 @@ public: virtual QImage getScreenshot() const override; protected: +#if THREADED_PRESENT friend class PresentThread; - +#endif virtual glm::uvec2 getSurfaceSize() const = 0; virtual glm::uvec2 getSurfacePixels() const = 0; @@ -81,15 +84,16 @@ protected: GLuint _currentSceneTexture { 0 }; GLuint _currentOverlayTexture { 0 }; - GLTextureEscrow _overlayTextureEscrow; GLTextureEscrow _sceneTextureEscrow; bool _vsyncSupported { false }; private: +#if THREADED_PRESENT void enableDeactivate(); Condition _deactivateWait; bool _uncustomized{ false }; +#endif };