summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMäättä Antti <antti.maatta@qt.io>2018-02-05 16:36:44 +0200
committerSean Harmer <sean.harmer@kdab.com>2018-02-06 10:22:17 +0000
commit13f340c92bdf725d214ab4840fc2e071d12d6e00 (patch)
tree9d2372537e274eb0127af0f85c9581a83836a8c6
parent564dfd87c5b1317dcf9fbc4d1c8d858c72513421 (diff)
Fix crash if sharecontext is requested before initailization
Scene2D can sometimes receive the render initialization event before the qt3d renderer has been initialized. This causes crash because the sharecontext hasn't been set yet. Add safeguard against this. Task-number: QT3DS-904 Change-Id: Ib50a60ed89c12ac54c9165266466d9804affe77c Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io> Reviewed-by: Paul Lemire <paul.lemire@kdab.com> Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
-rw-r--r--src/render/backend/renderer.cpp75
-rw-r--r--src/render/backend/renderer_p.h1
2 files changed, 42 insertions, 34 deletions
diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp
index c004e464e..0512fbdd2 100644
--- a/src/render/backend/renderer.cpp
+++ b/src/render/backend/renderer.cpp
@@ -293,7 +293,11 @@ NodeManagers *Renderer::nodeManagers() const
*/
QOpenGLContext *Renderer::shareContext() const
{
- return m_shareContext ? m_shareContext : m_graphicsContext->openGLContext()->shareContext();
+ QMutexLocker lock(&m_shareContextMutex);
+ return m_shareContext ? m_shareContext
+ : (m_graphicsContext->openGLContext()
+ ? m_graphicsContext->openGLContext()->shareContext()
+ : nullptr);
}
void Renderer::setOpenGLContext(QOpenGLContext *context)
@@ -311,45 +315,48 @@ void Renderer::initialize()
QOpenGLContext* ctx = m_glContext;
- // If we are using our own context (not provided by QtQuick),
- // we need to create it
- if (!m_glContext) {
- ctx = new QOpenGLContext;
- ctx->setShareContext(qt_gl_global_share_context());
-
- // TO DO: Shouldn't we use the highest context available and trust
- // QOpenGLContext to fall back on the best lowest supported ?
- const QByteArray debugLoggingMode = qgetenv("QT3DRENDER_DEBUG_LOGGING");
+ {
+ QMutexLocker lock(&m_shareContextMutex);
+ // If we are using our own context (not provided by QtQuick),
+ // we need to create it
+ if (!m_glContext) {
+ ctx = new QOpenGLContext;
+ ctx->setShareContext(qt_gl_global_share_context());
+
+ // TO DO: Shouldn't we use the highest context available and trust
+ // QOpenGLContext to fall back on the best lowest supported ?
+ const QByteArray debugLoggingMode = qgetenv("QT3DRENDER_DEBUG_LOGGING");
+
+ if (!debugLoggingMode.isEmpty()) {
+ QSurfaceFormat sf = ctx->format();
+ sf.setOption(QSurfaceFormat::DebugContext);
+ ctx->setFormat(sf);
+ }
- if (!debugLoggingMode.isEmpty()) {
- QSurfaceFormat sf = ctx->format();
- sf.setOption(QSurfaceFormat::DebugContext);
- ctx->setFormat(sf);
+ // Create OpenGL context
+ if (ctx->create())
+ qCDebug(Backend) << "OpenGL context created with actual format" << ctx->format();
+ else
+ qCWarning(Backend) << Q_FUNC_INFO << "OpenGL context creation failed";
+ m_ownedContext = true;
+ } else {
+ // Context is not owned by us, so we need to know if it gets destroyed
+ m_contextConnection = QObject::connect(m_glContext, &QOpenGLContext::aboutToBeDestroyed,
+ [this] { releaseGraphicsResources(); });
}
- // Create OpenGL context
- if (ctx->create())
- qCDebug(Backend) << "OpenGL context created with actual format" << ctx->format();
- else
- qCWarning(Backend) << Q_FUNC_INFO << "OpenGL context creation failed";
- m_ownedContext = true;
- } else {
- // Context is not owned by us, so we need to know if it gets destroyed
- m_contextConnection = QObject::connect(m_glContext, &QOpenGLContext::aboutToBeDestroyed,
- [this] { releaseGraphicsResources(); });
- }
+ if (!ctx->shareContext()) {
+ m_shareContext = new QOpenGLContext;
+ m_shareContext->setFormat(ctx->format());
+ m_shareContext->setShareContext(ctx);
+ m_shareContext->create();
+ }
- if (!ctx->shareContext()) {
- m_shareContext = new QOpenGLContext;
- m_shareContext->setFormat(ctx->format());
- m_shareContext->setShareContext(ctx);
- m_shareContext->create();
+ // Note: we don't have a surface at this point
+ // The context will be made current later on (at render time)
+ m_graphicsContext->setOpenGLContext(ctx);
}
- // Note: we don't have a surface at this point
- // The context will be made current later on (at render time)
- m_graphicsContext->setOpenGLContext(ctx);
-
// Store the format used by the context and queue up creating an
// offscreen surface in the main thread so that it is available
// for use when we want to shutdown the renderer. We need to create
diff --git a/src/render/backend/renderer_p.h b/src/render/backend/renderer_p.h
index b18b78a7c..dc9f778dd 100644
--- a/src/render/backend/renderer_p.h
+++ b/src/render/backend/renderer_p.h
@@ -308,6 +308,7 @@ private:
QAtomicInt m_lastFrameCorrect;
QOpenGLContext *m_glContext;
QOpenGLContext *m_shareContext;
+ mutable QMutex m_shareContextMutex;
PickBoundingVolumeJobPtr m_pickBoundingVolumeJob;
qint64 m_time;