mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-05-29 20:34:47 +02:00
Merge pull request #12398 from jherico/fix/spectator_cam
Fix spectator camera crash
This commit is contained in:
commit
9ba29028e3
7 changed files with 59 additions and 20 deletions
|
@ -2338,6 +2338,7 @@ void Application::initializeGL() {
|
||||||
qFatal("Unable to make offscreen context current");
|
qFatal("Unable to make offscreen context current");
|
||||||
}
|
}
|
||||||
_offscreenContext->doneCurrent();
|
_offscreenContext->doneCurrent();
|
||||||
|
_offscreenContext->setThreadContext();
|
||||||
_renderEventHandler = new RenderEventHandler(_glWidget->qglContext());
|
_renderEventHandler = new RenderEventHandler(_glWidget->qglContext());
|
||||||
|
|
||||||
// The UI can't be created until the primary OpenGL
|
// The UI can't be created until the primary OpenGL
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <gl/GLWidget.h>
|
#include <gl/GLWidget.h>
|
||||||
#include <gl/GLEscrow.h>
|
#include <gl/GLEscrow.h>
|
||||||
#include <gl/Context.h>
|
#include <gl/Context.h>
|
||||||
|
#include <gl/OffscreenGLCanvas.h>
|
||||||
|
|
||||||
#include <gpu/Texture.h>
|
#include <gpu/Texture.h>
|
||||||
#include <gpu/StandardShaderLib.h>
|
#include <gpu/StandardShaderLib.h>
|
||||||
|
@ -130,14 +131,14 @@ public:
|
||||||
CHECK_GL_ERROR();
|
CHECK_GL_ERROR();
|
||||||
_context->doneCurrent();
|
_context->doneCurrent();
|
||||||
while (!_shutdown) {
|
while (!_shutdown) {
|
||||||
if (_pendingMainThreadOperation) {
|
if (_pendingOtherThreadOperation) {
|
||||||
PROFILE_RANGE(render, "MainThreadOp")
|
PROFILE_RANGE(render, "MainThreadOp")
|
||||||
{
|
{
|
||||||
Lock lock(_mutex);
|
Lock lock(_mutex);
|
||||||
_context->doneCurrent();
|
_context->doneCurrent();
|
||||||
// Move the context to the main thread
|
// Move the context to the main thread
|
||||||
_context->moveToThread(qApp->thread());
|
_context->moveToThread(_targetOperationThread);
|
||||||
_pendingMainThreadOperation = false;
|
_pendingOtherThreadOperation = 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();
|
||||||
}
|
}
|
||||||
|
@ -146,7 +147,7 @@ public:
|
||||||
{
|
{
|
||||||
// Main thread does it's thing while we wait on the lock to release
|
// Main thread does it's thing while we wait on the lock to release
|
||||||
Lock lock(_mutex);
|
Lock lock(_mutex);
|
||||||
_condition.wait(lock, [&] { return _finishedMainThreadOperation; });
|
_condition.wait(lock, [&] { return _finishedOtherThreadOperation; });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,23 +215,25 @@ public:
|
||||||
_condition.notify_one();
|
_condition.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
void withMainThreadContext(std::function<void()> f) {
|
void withOtherThreadContext(std::function<void()> f) {
|
||||||
// Signal to the thread that there is work to be done on the main thread
|
// Signal to the thread that there is work to be done on the main thread
|
||||||
Lock lock(_mutex);
|
Lock lock(_mutex);
|
||||||
_pendingMainThreadOperation = true;
|
_targetOperationThread = QThread::currentThread();
|
||||||
_finishedMainThreadOperation = false;
|
_pendingOtherThreadOperation = true;
|
||||||
_condition.wait(lock, [&] { return !_pendingMainThreadOperation; });
|
_finishedOtherThreadOperation = false;
|
||||||
|
_condition.wait(lock, [&] { return !_pendingOtherThreadOperation; });
|
||||||
|
|
||||||
_context->makeCurrent();
|
_context->makeCurrent();
|
||||||
f();
|
f();
|
||||||
_context->doneCurrent();
|
_context->doneCurrent();
|
||||||
|
|
||||||
|
_targetOperationThread = nullptr;
|
||||||
// Move the context back to the presentation thread
|
// Move the context back to the presentation thread
|
||||||
_context->moveToThread(this);
|
_context->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
|
||||||
_finishedMainThreadOperation = true;
|
_finishedOtherThreadOperation = true;
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
_condition.notify_one();
|
_condition.notify_one();
|
||||||
}
|
}
|
||||||
|
@ -244,9 +247,11 @@ private:
|
||||||
Mutex _mutex;
|
Mutex _mutex;
|
||||||
// Used to allow the main thread to perform context operations
|
// Used to allow the main thread to perform context operations
|
||||||
Condition _condition;
|
Condition _condition;
|
||||||
bool _pendingMainThreadOperation { false };
|
|
||||||
bool _finishedMainThreadOperation { false };
|
|
||||||
QThread* _mainThread { nullptr };
|
QThread* _targetOperationThread { nullptr };
|
||||||
|
bool _pendingOtherThreadOperation { false };
|
||||||
|
bool _finishedOtherThreadOperation { false };
|
||||||
std::queue<OpenGLDisplayPlugin*> _newPluginQueue;
|
std::queue<OpenGLDisplayPlugin*> _newPluginQueue;
|
||||||
gl::Context* _context { nullptr };
|
gl::Context* _context { nullptr };
|
||||||
};
|
};
|
||||||
|
@ -744,10 +749,12 @@ void OpenGLDisplayPlugin::swapBuffers() {
|
||||||
context->swapBuffers();
|
context->swapBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDisplayPlugin::withMainThreadContext(std::function<void()> f) const {
|
void OpenGLDisplayPlugin::withOtherThreadContext(std::function<void()> f) const {
|
||||||
static auto presentThread = DependencyManager::get<PresentThread>();
|
static auto presentThread = DependencyManager::get<PresentThread>();
|
||||||
presentThread->withMainThreadContext(f);
|
presentThread->withOtherThreadContext(f);
|
||||||
_container->makeRenderingContextCurrent();
|
if (!OffscreenGLCanvas::restoreThreadContext()) {
|
||||||
|
qWarning("Unable to restore original OpenGL context");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenGLDisplayPlugin::setDisplayTexture(const QString& name) {
|
bool OpenGLDisplayPlugin::setDisplayTexture(const QString& name) {
|
||||||
|
@ -784,7 +791,7 @@ QImage OpenGLDisplayPlugin::getScreenshot(float aspectRatio) const {
|
||||||
}
|
}
|
||||||
auto glBackend = const_cast<OpenGLDisplayPlugin&>(*this).getGLBackend();
|
auto glBackend = const_cast<OpenGLDisplayPlugin&>(*this).getGLBackend();
|
||||||
QImage screenshot(bestSize.x, bestSize.y, QImage::Format_ARGB32);
|
QImage screenshot(bestSize.x, bestSize.y, QImage::Format_ARGB32);
|
||||||
withMainThreadContext([&] {
|
withOtherThreadContext([&] {
|
||||||
glBackend->downloadFramebuffer(_compositeFramebuffer, ivec4(corner, bestSize), screenshot);
|
glBackend->downloadFramebuffer(_compositeFramebuffer, ivec4(corner, bestSize), screenshot);
|
||||||
});
|
});
|
||||||
return screenshot.mirrored(false, true);
|
return screenshot.mirrored(false, true);
|
||||||
|
@ -797,7 +804,7 @@ QImage OpenGLDisplayPlugin::getSecondaryCameraScreenshot() const {
|
||||||
|
|
||||||
auto glBackend = const_cast<OpenGLDisplayPlugin&>(*this).getGLBackend();
|
auto glBackend = const_cast<OpenGLDisplayPlugin&>(*this).getGLBackend();
|
||||||
QImage screenshot(region.z, region.w, QImage::Format_ARGB32);
|
QImage screenshot(region.z, region.w, QImage::Format_ARGB32);
|
||||||
withMainThreadContext([&] {
|
withOtherThreadContext([&] {
|
||||||
glBackend->downloadFramebuffer(secondaryCameraFramebuffer, region, screenshot);
|
glBackend->downloadFramebuffer(secondaryCameraFramebuffer, region, screenshot);
|
||||||
});
|
});
|
||||||
return screenshot.mirrored(false, true);
|
return screenshot.mirrored(false, true);
|
||||||
|
@ -886,7 +893,7 @@ void OpenGLDisplayPlugin::updateCompositeFramebuffer() {
|
||||||
void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer networkTexture, QOpenGLFramebufferObject* target, GLsync* fenceSync) {
|
void OpenGLDisplayPlugin::copyTextureToQuickFramebuffer(NetworkTexturePointer networkTexture, QOpenGLFramebufferObject* target, GLsync* fenceSync) {
|
||||||
#if !defined(USE_GLES)
|
#if !defined(USE_GLES)
|
||||||
auto glBackend = const_cast<OpenGLDisplayPlugin&>(*this).getGLBackend();
|
auto glBackend = const_cast<OpenGLDisplayPlugin&>(*this).getGLBackend();
|
||||||
withMainThreadContext([&] {
|
withOtherThreadContext([&] {
|
||||||
GLuint sourceTexture = glBackend->getTextureID(networkTexture->getGPUTexture());
|
GLuint sourceTexture = glBackend->getTextureID(networkTexture->getGPUTexture());
|
||||||
GLuint targetTexture = target->texture();
|
GLuint targetTexture = target->texture();
|
||||||
GLuint fbo[2] {0, 0};
|
GLuint fbo[2] {0, 0};
|
||||||
|
|
|
@ -119,7 +119,7 @@ protected:
|
||||||
void renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer texture, glm::ivec4 viewport, const glm::ivec4 scissor);
|
void renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer texture, glm::ivec4 viewport, const glm::ivec4 scissor);
|
||||||
virtual void updateFrameData();
|
virtual void updateFrameData();
|
||||||
|
|
||||||
void withMainThreadContext(std::function<void()> f) const;
|
void withOtherThreadContext(std::function<void()> f) const;
|
||||||
|
|
||||||
void present();
|
void present();
|
||||||
virtual void swapBuffers();
|
virtual void swapBuffers();
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include <QtCore/QProcessEnvironment>
|
#include <QtCore/QProcessEnvironment>
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
|
#include <QtCore/QThread>
|
||||||
#include <QtGui/QOffscreenSurface>
|
#include <QtGui/QOffscreenSurface>
|
||||||
#include <QtGui/QOpenGLContext>
|
#include <QtGui/QOpenGLContext>
|
||||||
#include <QtGui/QOpenGLDebugLogger>
|
#include <QtGui/QOpenGLDebugLogger>
|
||||||
|
@ -119,3 +120,29 @@ void OffscreenGLCanvas::moveToThreadWithContext(QThread* thread) {
|
||||||
moveToThread(thread);
|
moveToThread(thread);
|
||||||
_context->moveToThread(thread);
|
_context->moveToThread(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char* THREAD_CONTEXT_PROPERTY = "offscreenGlCanvas";
|
||||||
|
|
||||||
|
void OffscreenGLCanvas::setThreadContext() {
|
||||||
|
QThread::currentThread()->setProperty(THREAD_CONTEXT_PROPERTY, QVariant::fromValue<QObject*>(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OffscreenGLCanvas::restoreThreadContext() {
|
||||||
|
// Restore the rendering context for this thread
|
||||||
|
auto threadCanvasVariant = QThread::currentThread()->property(THREAD_CONTEXT_PROPERTY);
|
||||||
|
if (!threadCanvasVariant.isValid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto threadCanvasObject = qvariant_cast<QObject*>(threadCanvasVariant);
|
||||||
|
auto threadCanvas = static_cast<OffscreenGLCanvas*>(threadCanvasObject);
|
||||||
|
if (!threadCanvas) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!threadCanvas->makeCurrent()) {
|
||||||
|
qFatal("Unable to restore Offscreen rendering context");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -32,6 +32,9 @@ public:
|
||||||
}
|
}
|
||||||
QObject* getContextObject();
|
QObject* getContextObject();
|
||||||
|
|
||||||
|
void setThreadContext();
|
||||||
|
static bool restoreThreadContext();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onMessageLogged(const QOpenGLDebugMessage &debugMessage);
|
void onMessageLogged(const QOpenGLDebugMessage &debugMessage);
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,7 @@ void RenderEventHandler::onInitalize() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_canvas.setThreadContext();
|
||||||
if (!_canvas.makeCurrent()) {
|
if (!_canvas.makeCurrent()) {
|
||||||
qFatal("Unable to make QML rendering context current on render thread");
|
qFatal("Unable to make QML rendering context current on render thread");
|
||||||
}
|
}
|
||||||
|
|
|
@ -485,7 +485,7 @@ bool OpenVrDisplayPlugin::internalActivate() {
|
||||||
if (_threadedSubmit) {
|
if (_threadedSubmit) {
|
||||||
_submitThread = std::make_shared<OpenVrSubmitThread>(*this);
|
_submitThread = std::make_shared<OpenVrSubmitThread>(*this);
|
||||||
if (!_submitCanvas) {
|
if (!_submitCanvas) {
|
||||||
withMainThreadContext([&] {
|
withOtherThreadContext([&] {
|
||||||
_submitCanvas = std::make_shared<gl::OffscreenContext>();
|
_submitCanvas = std::make_shared<gl::OffscreenContext>();
|
||||||
_submitCanvas->create();
|
_submitCanvas->create();
|
||||||
_submitCanvas->doneCurrent();
|
_submitCanvas->doneCurrent();
|
||||||
|
|
Loading…
Reference in a new issue