mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 18:13:05 +02:00
Make threaded present optional
This commit is contained in:
parent
63afa8c1ed
commit
390df78327
2 changed files with 73 additions and 22 deletions
|
@ -21,11 +21,13 @@
|
||||||
#include <gl/GLWidget.h>
|
#include <gl/GLWidget.h>
|
||||||
#include <NumericalConstants.h>
|
#include <NumericalConstants.h>
|
||||||
#include <DependencyManager.h>
|
#include <DependencyManager.h>
|
||||||
|
|
||||||
#include <plugins/PluginContainer.h>
|
#include <plugins/PluginContainer.h>
|
||||||
#include <gl/Config.h>
|
#include <gl/Config.h>
|
||||||
#include <gl/GLEscrow.h>
|
#include <gl/GLEscrow.h>
|
||||||
#include <GLMHelpers.h>
|
#include <GLMHelpers.h>
|
||||||
|
|
||||||
|
#if THREADED_PRESENT
|
||||||
class PresentThread : public QThread, public Dependency {
|
class PresentThread : public QThread, public Dependency {
|
||||||
using Mutex = std::mutex;
|
using Mutex = std::mutex;
|
||||||
using Condition = std::condition_variable;
|
using Condition = std::condition_variable;
|
||||||
|
@ -33,16 +35,25 @@ class PresentThread : public QThread, public Dependency {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
PresentThread() {
|
PresentThread() {
|
||||||
connect(qApp, &QCoreApplication::aboutToQuit, [this]{
|
connect(qApp, &QCoreApplication::aboutToQuit, [this] {
|
||||||
_shutdown = true;
|
shutdown();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
~PresentThread() {
|
~PresentThread() {
|
||||||
_shutdown = true;
|
shutdown();
|
||||||
wait();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void shutdown() {
|
||||||
|
if (isRunning()) {
|
||||||
|
Lock lock(_mutex);
|
||||||
|
_shutdown = true;
|
||||||
|
_condition.wait(lock, [&] { return !_shutdown; });
|
||||||
|
qDebug() << "Present thread shutdown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void setNewDisplayPlugin(OpenGLDisplayPlugin* plugin) {
|
void setNewDisplayPlugin(OpenGLDisplayPlugin* plugin) {
|
||||||
Lock lock(_mutex);
|
Lock lock(_mutex);
|
||||||
_newPlugin = plugin;
|
_newPlugin = plugin;
|
||||||
|
@ -120,6 +131,10 @@ public:
|
||||||
}
|
}
|
||||||
_context->doneCurrent();
|
_context->doneCurrent();
|
||||||
_context->moveToThread(qApp->thread());
|
_context->moveToThread(qApp->thread());
|
||||||
|
|
||||||
|
Lock lock(_mutex);
|
||||||
|
_shutdown = false;
|
||||||
|
_condition.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
void withMainThreadContext(std::function<void()> f) {
|
void withMainThreadContext(std::function<void()> f) {
|
||||||
|
@ -159,16 +174,14 @@ private:
|
||||||
QGLContext* _context { nullptr };
|
QGLContext* _context { nullptr };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
OpenGLDisplayPlugin::OpenGLDisplayPlugin() {
|
OpenGLDisplayPlugin::OpenGLDisplayPlugin() {
|
||||||
_sceneTextureEscrow.setRecycler([this](GLuint texture){
|
_sceneTextureEscrow.setRecycler([this](GLuint texture){
|
||||||
cleanupForSceneTexture(texture);
|
cleanupForSceneTexture(texture);
|
||||||
_container->releaseSceneTexture(texture);
|
_container->releaseSceneTexture(texture);
|
||||||
});
|
});
|
||||||
|
|
||||||
_overlayTextureEscrow.setRecycler([this](GLuint texture) {
|
|
||||||
_container->releaseOverlayTexture(texture);
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(&_timer, &QTimer::timeout, this, [&] {
|
connect(&_timer, &QTimer::timeout, this, [&] {
|
||||||
#ifdef Q_OS_MAC
|
#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)
|
// 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() {
|
void OpenGLDisplayPlugin::activate() {
|
||||||
_timer.start(1);
|
|
||||||
_vsyncSupported = _container->getPrimaryWidget()->isVsyncSupported();
|
_vsyncSupported = _container->getPrimaryWidget()->isVsyncSupported();
|
||||||
|
|
||||||
|
#if THREADED_PRESENT
|
||||||
|
_timer.start(1);
|
||||||
// Start the present thread if necessary
|
// Start the present thread if necessary
|
||||||
auto presentThread = DependencyManager::get<PresentThread>();
|
auto presentThread = DependencyManager::get<PresentThread>();
|
||||||
if (!presentThread) {
|
if (!presentThread) {
|
||||||
|
@ -208,7 +222,15 @@ void OpenGLDisplayPlugin::activate() {
|
||||||
presentThread->start();
|
presentThread->start();
|
||||||
}
|
}
|
||||||
presentThread->setNewDisplayPlugin(this);
|
presentThread->setNewDisplayPlugin(this);
|
||||||
|
#else
|
||||||
|
static auto widget = _container->getPrimaryWidget();
|
||||||
|
widget->makeCurrent();
|
||||||
|
customizeContext();
|
||||||
|
_container->makeRenderingContextCurrent();
|
||||||
|
#endif
|
||||||
DisplayPlugin::activate();
|
DisplayPlugin::activate();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayPlugin::stop() {
|
void OpenGLDisplayPlugin::stop() {
|
||||||
|
@ -216,19 +238,27 @@ void OpenGLDisplayPlugin::stop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayPlugin::deactivate() {
|
void OpenGLDisplayPlugin::deactivate() {
|
||||||
|
#if THREADED_PRESENT
|
||||||
{
|
{
|
||||||
Lock lock(_mutex);
|
Lock lock(_mutex);
|
||||||
_deactivateWait.wait(lock, [&]{ return _uncustomized; });
|
_deactivateWait.wait(lock, [&]{ return _uncustomized; });
|
||||||
}
|
}
|
||||||
_timer.stop();
|
_timer.stop();
|
||||||
|
#else
|
||||||
|
static auto widget = _container->getPrimaryWidget();
|
||||||
|
widget->makeCurrent();
|
||||||
|
uncustomizeContext();
|
||||||
|
_container->makeRenderingContextCurrent();
|
||||||
|
#endif
|
||||||
DisplayPlugin::deactivate();
|
DisplayPlugin::deactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayPlugin::customizeContext() {
|
void OpenGLDisplayPlugin::customizeContext() {
|
||||||
|
#if THREADED_PRESENT
|
||||||
_uncustomized = false;
|
_uncustomized = false;
|
||||||
auto presentThread = DependencyManager::get<PresentThread>();
|
auto presentThread = DependencyManager::get<PresentThread>();
|
||||||
Q_ASSERT(thread() == presentThread->thread());
|
Q_ASSERT(thread() == presentThread->thread());
|
||||||
|
#endif
|
||||||
enableVsync();
|
enableVsync();
|
||||||
|
|
||||||
using namespace oglplus;
|
using namespace oglplus;
|
||||||
|
@ -297,16 +327,23 @@ void OpenGLDisplayPlugin::submitSceneTexture(uint32_t frameIndex, uint32_t scene
|
||||||
|
|
||||||
// Submit it to the presentation thread via escrow
|
// Submit it to the presentation thread via escrow
|
||||||
_sceneTextureEscrow.submit(sceneTexture);
|
_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
|
// Submit it to the presentation thread via escrow
|
||||||
_overlayTextureEscrow.submit(sceneTexture);
|
_currentOverlayTexture = overlayTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayPlugin::updateTextures() {
|
void OpenGLDisplayPlugin::updateTextures() {
|
||||||
_currentSceneTexture = _sceneTextureEscrow.fetchAndRelease(_currentSceneTexture);
|
_currentSceneTexture = _sceneTextureEscrow.fetchAndRelease(_currentSceneTexture);
|
||||||
_currentOverlayTexture = _overlayTextureEscrow.fetchAndRelease(_currentOverlayTexture);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayPlugin::updateFramerate() {
|
void OpenGLDisplayPlugin::updateFramerate() {
|
||||||
|
@ -337,6 +374,11 @@ void OpenGLDisplayPlugin::present() {
|
||||||
internalPresent();
|
internalPresent();
|
||||||
updateFramerate();
|
updateFramerate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if THREADED_PRESENT
|
||||||
|
#else
|
||||||
|
emit requestRender();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
float OpenGLDisplayPlugin::presentRate() {
|
float OpenGLDisplayPlugin::presentRate() {
|
||||||
|
@ -351,12 +393,8 @@ float OpenGLDisplayPlugin::presentRate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayPlugin::drawUnitQuad() {
|
void OpenGLDisplayPlugin::drawUnitQuad() {
|
||||||
try {
|
_program->Bind();
|
||||||
_program->Bind();
|
_plane->Draw();
|
||||||
_plane->Draw();
|
|
||||||
} catch (const oglplus::Error& error) {
|
|
||||||
qWarning() << "The present thread encountered an error writing the scene texture to the output: " << error.what();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayPlugin::enableVsync(bool enable) {
|
void OpenGLDisplayPlugin::enableVsync(bool enable) {
|
||||||
|
@ -385,9 +423,16 @@ void OpenGLDisplayPlugin::swapBuffers() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayPlugin::withMainThreadContext(std::function<void()> f) const {
|
void OpenGLDisplayPlugin::withMainThreadContext(std::function<void()> f) const {
|
||||||
|
#if THREADED_PRESENT
|
||||||
static auto presentThread = DependencyManager::get<PresentThread>();
|
static auto presentThread = DependencyManager::get<PresentThread>();
|
||||||
presentThread->withMainThreadContext(f);
|
presentThread->withMainThreadContext(f);
|
||||||
_container->makeRenderingContextCurrent();
|
_container->makeRenderingContextCurrent();
|
||||||
|
#else
|
||||||
|
static auto widget = _container->getPrimaryWidget();
|
||||||
|
widget->makeCurrent();
|
||||||
|
f();
|
||||||
|
_container->makeRenderingContextCurrent();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage OpenGLDisplayPlugin::getScreenshot() const {
|
QImage OpenGLDisplayPlugin::getScreenshot() const {
|
||||||
|
@ -399,8 +444,10 @@ QImage OpenGLDisplayPlugin::getScreenshot() const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if THREADED_PRESENT
|
||||||
void OpenGLDisplayPlugin::enableDeactivate() {
|
void OpenGLDisplayPlugin::enableDeactivate() {
|
||||||
Lock lock(_mutex);
|
Lock lock(_mutex);
|
||||||
_uncustomized = true;
|
_uncustomized = true;
|
||||||
_deactivateWait.notify_one();
|
_deactivateWait.notify_one();
|
||||||
}
|
}
|
||||||
|
#endif
|
|
@ -18,6 +18,8 @@
|
||||||
#include <gl/OglplusHelpers.h>
|
#include <gl/OglplusHelpers.h>
|
||||||
#include <gl/GLEscrow.h>
|
#include <gl/GLEscrow.h>
|
||||||
|
|
||||||
|
#define THREADED_PRESENT 1
|
||||||
|
|
||||||
class OpenGLDisplayPlugin : public DisplayPlugin {
|
class OpenGLDisplayPlugin : public DisplayPlugin {
|
||||||
protected:
|
protected:
|
||||||
using Mutex = std::mutex;
|
using Mutex = std::mutex;
|
||||||
|
@ -45,8 +47,9 @@ public:
|
||||||
virtual QImage getScreenshot() const override;
|
virtual QImage getScreenshot() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
#if THREADED_PRESENT
|
||||||
friend class PresentThread;
|
friend class PresentThread;
|
||||||
|
#endif
|
||||||
|
|
||||||
virtual glm::uvec2 getSurfaceSize() const = 0;
|
virtual glm::uvec2 getSurfaceSize() const = 0;
|
||||||
virtual glm::uvec2 getSurfacePixels() const = 0;
|
virtual glm::uvec2 getSurfacePixels() const = 0;
|
||||||
|
@ -81,15 +84,16 @@ protected:
|
||||||
GLuint _currentSceneTexture { 0 };
|
GLuint _currentSceneTexture { 0 };
|
||||||
GLuint _currentOverlayTexture { 0 };
|
GLuint _currentOverlayTexture { 0 };
|
||||||
|
|
||||||
GLTextureEscrow _overlayTextureEscrow;
|
|
||||||
GLTextureEscrow _sceneTextureEscrow;
|
GLTextureEscrow _sceneTextureEscrow;
|
||||||
|
|
||||||
bool _vsyncSupported { false };
|
bool _vsyncSupported { false };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
#if THREADED_PRESENT
|
||||||
void enableDeactivate();
|
void enableDeactivate();
|
||||||
Condition _deactivateWait;
|
Condition _deactivateWait;
|
||||||
bool _uncustomized{ false };
|
bool _uncustomized{ false };
|
||||||
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue