mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 12:38:27 +02:00
Refactoring present thread / GL base plugin for saner context management
This commit is contained in:
parent
d8bb9f8d18
commit
7262a10e62
6 changed files with 42 additions and 69 deletions
|
@ -26,17 +26,17 @@ DisplayPluginList getDisplayPlugins() {
|
||||||
DisplayPlugin* PLUGIN_POOL[] = {
|
DisplayPlugin* PLUGIN_POOL[] = {
|
||||||
new Basic2DWindowOpenGLDisplayPlugin(),
|
new Basic2DWindowOpenGLDisplayPlugin(),
|
||||||
new NullDisplayPlugin(),
|
new NullDisplayPlugin(),
|
||||||
//#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
//#endif
|
#endif
|
||||||
//
|
|
||||||
// // Stereo modes
|
// Stereo modes
|
||||||
//
|
|
||||||
// // SBS left/right
|
// SBS left/right
|
||||||
// new SideBySideStereoDisplayPlugin(),
|
new SideBySideStereoDisplayPlugin(),
|
||||||
// // Interleaved left/right
|
// Interleaved left/right
|
||||||
// new InterleavedStereoDisplayPlugin(),
|
new InterleavedStereoDisplayPlugin(),
|
||||||
//
|
|
||||||
// // HMDs
|
// HMDs
|
||||||
//#ifdef Q_OS_WIN
|
//#ifdef Q_OS_WIN
|
||||||
// // SteamVR SDK
|
// // SteamVR SDK
|
||||||
// new OpenVrDisplayPlugin(),
|
// new OpenVrDisplayPlugin(),
|
||||||
|
|
|
@ -28,8 +28,6 @@ class PresentThread : public QThread, public Dependency {
|
||||||
using Mutex = std::mutex;
|
using Mutex = std::mutex;
|
||||||
using Condition = std::condition_variable;
|
using Condition = std::condition_variable;
|
||||||
using Lock = std::unique_lock<Mutex>;
|
using Lock = std::unique_lock<Mutex>;
|
||||||
|
|
||||||
friend class OpenGLDisplayPlugin;
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
~PresentThread() {
|
~PresentThread() {
|
||||||
|
@ -42,6 +40,14 @@ public:
|
||||||
_newPlugin = plugin;
|
_newPlugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setContext(QGLContext * context) {
|
||||||
|
// Move the OpenGL context to the present thread
|
||||||
|
// Extra code because of the widget 'wrapper' context
|
||||||
|
_context = context;
|
||||||
|
_context->moveToThread(this);
|
||||||
|
_context->contextHandle()->moveToThread(this);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void run() override {
|
virtual void run() override {
|
||||||
Q_ASSERT(_context);
|
Q_ASSERT(_context);
|
||||||
while (!_shutdown) {
|
while (!_shutdown) {
|
||||||
|
@ -50,7 +56,7 @@ public:
|
||||||
Lock lock(_mutex);
|
Lock lock(_mutex);
|
||||||
// Move the context to the main thread
|
// Move the context to the main thread
|
||||||
_context->moveToThread(qApp->thread());
|
_context->moveToThread(qApp->thread());
|
||||||
_widgetContext->moveToThread(qApp->thread());
|
_context->contextHandle()->moveToThread(qApp->thread());
|
||||||
_pendingMainThreadOperation = false;
|
_pendingMainThreadOperation = false;
|
||||||
// Release the main thread to do it's action
|
// Release the main thread to do it's action
|
||||||
_condition.notify_one();
|
_condition.notify_one();
|
||||||
|
@ -67,6 +73,7 @@ public:
|
||||||
// Check before lock
|
// Check before lock
|
||||||
if (_newPlugin != nullptr) {
|
if (_newPlugin != nullptr) {
|
||||||
Lock lock(_mutex);
|
Lock lock(_mutex);
|
||||||
|
_context->makeCurrent();
|
||||||
// Check if we have a new plugin to activate
|
// Check if we have a new plugin to activate
|
||||||
if (_newPlugin != nullptr) {
|
if (_newPlugin != nullptr) {
|
||||||
// Deactivate the old plugin
|
// Deactivate the old plugin
|
||||||
|
@ -77,8 +84,8 @@ public:
|
||||||
_newPlugin->customizeContext();
|
_newPlugin->customizeContext();
|
||||||
_activePlugin = _newPlugin;
|
_activePlugin = _newPlugin;
|
||||||
_newPlugin = nullptr;
|
_newPlugin = nullptr;
|
||||||
_context->doneCurrent();
|
|
||||||
}
|
}
|
||||||
|
_context->doneCurrent();
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,12 +96,14 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// take the latest texture and present it
|
// take the latest texture and present it
|
||||||
|
_context->makeCurrent();
|
||||||
_activePlugin->present();
|
_activePlugin->present();
|
||||||
|
_context->doneCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
_context->doneCurrent();
|
_context->doneCurrent();
|
||||||
_widgetContext->moveToThread(qApp->thread());
|
|
||||||
_context->moveToThread(qApp->thread());
|
_context->moveToThread(qApp->thread());
|
||||||
|
_context->contextHandle()->moveToThread(qApp->thread());
|
||||||
}
|
}
|
||||||
|
|
||||||
void withMainThreadContext(std::function<void()> f) {
|
void withMainThreadContext(std::function<void()> f) {
|
||||||
|
@ -104,14 +113,16 @@ public:
|
||||||
_finishedMainThreadOperation = false;
|
_finishedMainThreadOperation = false;
|
||||||
_condition.wait(lock, [&] { return !_pendingMainThreadOperation; });
|
_condition.wait(lock, [&] { return !_pendingMainThreadOperation; });
|
||||||
|
|
||||||
_widgetContext->makeCurrent();
|
_context->makeCurrent();
|
||||||
f();
|
f();
|
||||||
_widgetContext->doneCurrent();
|
_context->doneCurrent();
|
||||||
|
|
||||||
|
// Move the context back to the presentation thread
|
||||||
|
_context->moveToThread(this);
|
||||||
|
_context->contextHandle()->moveToThread(this);
|
||||||
|
|
||||||
// restore control of the context to the presentation thread and signal
|
// restore control of the context to the presentation thread and signal
|
||||||
// the end of the operation
|
// the end of the operation
|
||||||
_widgetContext->moveToThread(this);
|
|
||||||
_context->moveToThread(this);
|
|
||||||
_finishedMainThreadOperation = true;
|
_finishedMainThreadOperation = true;
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
_condition.notify_one();
|
_condition.notify_one();
|
||||||
|
@ -119,6 +130,9 @@ public:
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void makeCurrent();
|
||||||
|
void doneCurrent();
|
||||||
|
|
||||||
bool _shutdown { false };
|
bool _shutdown { false };
|
||||||
Mutex _mutex;
|
Mutex _mutex;
|
||||||
// Used to allow the main thread to perform context operations
|
// Used to allow the main thread to perform context operations
|
||||||
|
@ -128,8 +142,7 @@ private:
|
||||||
QThread* _mainThread { nullptr };
|
QThread* _mainThread { nullptr };
|
||||||
OpenGLDisplayPlugin* _newPlugin { nullptr };
|
OpenGLDisplayPlugin* _newPlugin { nullptr };
|
||||||
OpenGLDisplayPlugin* _activePlugin { nullptr };
|
OpenGLDisplayPlugin* _activePlugin { nullptr };
|
||||||
QOpenGLContext* _context { nullptr };
|
QGLContext* _context { nullptr };
|
||||||
QGLContext* _widgetContext { nullptr };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
OpenGLDisplayPlugin::OpenGLDisplayPlugin() {
|
OpenGLDisplayPlugin::OpenGLDisplayPlugin() {
|
||||||
|
@ -165,16 +178,8 @@ void OpenGLDisplayPlugin::activate() {
|
||||||
DependencyManager::set<PresentThread>();
|
DependencyManager::set<PresentThread>();
|
||||||
presentThread = DependencyManager::get<PresentThread>();
|
presentThread = DependencyManager::get<PresentThread>();
|
||||||
presentThread->setObjectName("Presentation Thread");
|
presentThread->setObjectName("Presentation Thread");
|
||||||
|
|
||||||
auto widget = _container->getPrimaryWidget();
|
auto widget = _container->getPrimaryWidget();
|
||||||
|
presentThread->setContext(widget->context());
|
||||||
// Move the OpenGL context to the present thread
|
|
||||||
// Extra code because of the widget 'wrapper' context
|
|
||||||
presentThread->_widgetContext = widget->context();
|
|
||||||
presentThread->_widgetContext->moveToThread(presentThread.data());
|
|
||||||
presentThread->_context = presentThread->_widgetContext->contextHandle();
|
|
||||||
presentThread->_context->moveToThread(presentThread.data());
|
|
||||||
|
|
||||||
// Start execution
|
// Start execution
|
||||||
presentThread->start();
|
presentThread->start();
|
||||||
}
|
}
|
||||||
|
@ -196,9 +201,6 @@ void OpenGLDisplayPlugin::customizeContext() {
|
||||||
auto presentThread = DependencyManager::get<PresentThread>();
|
auto presentThread = DependencyManager::get<PresentThread>();
|
||||||
Q_ASSERT(thread() == presentThread->thread());
|
Q_ASSERT(thread() == presentThread->thread());
|
||||||
|
|
||||||
bool makeCurrentResult = makeCurrent();
|
|
||||||
Q_ASSERT(makeCurrentResult);
|
|
||||||
|
|
||||||
// TODO: write the proper code for linux
|
// TODO: write the proper code for linux
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
_vsyncSupported = wglewGetExtension("WGL_EXT_swap_control");
|
_vsyncSupported = wglewGetExtension("WGL_EXT_swap_control");
|
||||||
|
@ -213,15 +215,11 @@ void OpenGLDisplayPlugin::customizeContext() {
|
||||||
|
|
||||||
_program = loadDefaultShader();
|
_program = loadDefaultShader();
|
||||||
_plane = loadPlane(_program);
|
_plane = loadPlane(_program);
|
||||||
|
|
||||||
doneCurrent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayPlugin::uncustomizeContext() {
|
void OpenGLDisplayPlugin::uncustomizeContext() {
|
||||||
makeCurrent();
|
|
||||||
_program.reset();
|
_program.reset();
|
||||||
_plane.reset();
|
_plane.reset();
|
||||||
doneCurrent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pressing Alt (and Meta) key alone activates the menubar because its style inherits the
|
// Pressing Alt (and Meta) key alone activates the menubar because its style inherits the
|
||||||
|
@ -310,19 +308,11 @@ void OpenGLDisplayPlugin::internalPresent() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayPlugin::present() {
|
void OpenGLDisplayPlugin::present() {
|
||||||
auto makeCurrentResult = makeCurrent();
|
|
||||||
Q_ASSERT(makeCurrentResult);
|
|
||||||
if (!makeCurrentResult) {
|
|
||||||
qDebug() << "Failed to make current";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateTextures();
|
updateTextures();
|
||||||
if (_currentSceneTexture) {
|
if (_currentSceneTexture) {
|
||||||
internalPresent();
|
internalPresent();
|
||||||
updateFramerate();
|
updateFramerate();
|
||||||
}
|
}
|
||||||
doneCurrent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float OpenGLDisplayPlugin::presentRate() {
|
float OpenGLDisplayPlugin::presentRate() {
|
||||||
|
@ -360,18 +350,6 @@ bool OpenGLDisplayPlugin::isVsyncEnabled() {
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
bool OpenGLDisplayPlugin::makeCurrent() {
|
|
||||||
static auto widget = _container->getPrimaryWidget();
|
|
||||||
widget->makeCurrent();
|
|
||||||
auto result = widget->context()->contextHandle() == QOpenGLContext::currentContext();
|
|
||||||
Q_ASSERT(result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenGLDisplayPlugin::doneCurrent() {
|
|
||||||
static auto widget = _container->getPrimaryWidget();
|
|
||||||
widget->doneCurrent();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OpenGLDisplayPlugin::swapBuffers() {
|
void OpenGLDisplayPlugin::swapBuffers() {
|
||||||
static auto widget = _container->getPrimaryWidget();
|
static auto widget = _container->getPrimaryWidget();
|
||||||
|
|
|
@ -63,8 +63,6 @@ protected:
|
||||||
void updateTextures();
|
void updateTextures();
|
||||||
void updateFramerate();
|
void updateFramerate();
|
||||||
void drawUnitQuad();
|
void drawUnitQuad();
|
||||||
bool makeCurrent();
|
|
||||||
void doneCurrent();
|
|
||||||
void swapBuffers();
|
void swapBuffers();
|
||||||
// Plugin specific functionality to composite the scene and overlay and present the result
|
// Plugin specific functionality to composite the scene and overlay and present the result
|
||||||
virtual void internalPresent();
|
virtual void internalPresent();
|
||||||
|
|
|
@ -67,5 +67,9 @@ glm::uvec2 InterleavedStereoDisplayPlugin::getRecommendedRenderSize() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void InterleavedStereoDisplayPlugin::internalPresent() {
|
void InterleavedStereoDisplayPlugin::internalPresent() {
|
||||||
// FIXME
|
using namespace oglplus;
|
||||||
|
_program->Bind();
|
||||||
|
auto sceneSize = getRecommendedRenderSize();
|
||||||
|
Uniform<ivec2>(*_program, "textureSize").SetValue(sceneSize);
|
||||||
|
WindowOpenGLDisplayPlugin::internalPresent();
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,11 +55,9 @@ bool OculusBaseDisplayPlugin::isSupported() const {
|
||||||
|
|
||||||
// DLL based display plugins MUST initialize GLEW inside the DLL code.
|
// DLL based display plugins MUST initialize GLEW inside the DLL code.
|
||||||
void OculusBaseDisplayPlugin::customizeContext() {
|
void OculusBaseDisplayPlugin::customizeContext() {
|
||||||
makeCurrent();
|
|
||||||
glewExperimental = true;
|
glewExperimental = true;
|
||||||
GLenum err = glewInit();
|
GLenum err = glewInit();
|
||||||
glGetError();
|
glGetError();
|
||||||
doneCurrent();
|
|
||||||
WindowOpenGLDisplayPlugin::customizeContext();
|
WindowOpenGLDisplayPlugin::customizeContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -154,8 +154,6 @@ void OculusDisplayPlugin::activate() {
|
||||||
|
|
||||||
void OculusDisplayPlugin::customizeContext() {
|
void OculusDisplayPlugin::customizeContext() {
|
||||||
OculusBaseDisplayPlugin::customizeContext();
|
OculusBaseDisplayPlugin::customizeContext();
|
||||||
bool makeCurrentResult = makeCurrent();
|
|
||||||
Q_ASSERT(makeCurrentResult);
|
|
||||||
#if (OVR_MAJOR_VERSION >= 6)
|
#if (OVR_MAJOR_VERSION >= 6)
|
||||||
_sceneFbo = SwapFboPtr(new SwapFramebufferWrapper(_hmd));
|
_sceneFbo = SwapFboPtr(new SwapFramebufferWrapper(_hmd));
|
||||||
_sceneFbo->Init(getRecommendedRenderSize());
|
_sceneFbo->Init(getRecommendedRenderSize());
|
||||||
|
@ -169,14 +167,11 @@ void OculusDisplayPlugin::customizeContext() {
|
||||||
enableVsync(false);
|
enableVsync(false);
|
||||||
// Only enable mirroring if we know vsync is disabled
|
// Only enable mirroring if we know vsync is disabled
|
||||||
_enablePreview = !isVsyncEnabled();
|
_enablePreview = !isVsyncEnabled();
|
||||||
doneCurrent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OculusDisplayPlugin::uncustomizeContext() {
|
void OculusDisplayPlugin::uncustomizeContext() {
|
||||||
#if (OVR_MAJOR_VERSION >= 6)
|
#if (OVR_MAJOR_VERSION >= 6)
|
||||||
makeCurrent();
|
|
||||||
_sceneFbo.reset();
|
_sceneFbo.reset();
|
||||||
doneCurrent();
|
|
||||||
#endif
|
#endif
|
||||||
OculusBaseDisplayPlugin::uncustomizeContext();
|
OculusBaseDisplayPlugin::uncustomizeContext();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue