Commit ea811bbf authored by Laszlo Agocs's avatar Laszlo Agocs
Browse files

Fix context creation with threaded render loop


Creating a context that shares with a context that is current on another
thread is not safe, some drivers can reject this.

We work this around by astutely introducing an additional context that
lives on the same thread as the scenegraph's context, shares with it, but
is never current. The main thread's WebGL context will then share with
this extra context.

Task-number: QTBUG-44677
Change-Id: Ic3ba739c8cda4f4382705c19ed452e8e374c73d7
Reviewed-by: default avatarPasi Keränen <pasi.keranen@digia.com>
Showing with 20 additions and 2 deletions
...@@ -89,6 +89,7 @@ Canvas::Canvas(QQuickItem *parent): ...@@ -89,6 +89,7 @@ Canvas::Canvas(QQuickItem *parent):
m_initializedSize(1, 1), m_initializedSize(1, 1),
m_glContext(0), m_glContext(0),
m_glContextQt(0), m_glContextQt(0),
m_glContextShare(0),
m_contextWindow(0), m_contextWindow(0),
m_fps(0), m_fps(0),
m_maxSamples(0), m_maxSamples(0),
...@@ -162,6 +163,8 @@ void Canvas::shutDown() ...@@ -162,6 +163,8 @@ void Canvas::shutDown()
} }
m_glContext = 0; m_glContext = 0;
m_glContextQt = 0; m_glContextQt = 0;
m_glContextShare->deleteLater();
m_glContextShare = 0;
} }
/*! /*!
...@@ -284,7 +287,7 @@ QJSValue Canvas::getContext(const QString &type, const QVariantMap &options) ...@@ -284,7 +287,7 @@ QJSValue Canvas::getContext(const QString &type, const QVariantMap &options)
} }
// Create the offscreen surface // Create the offscreen surface
QSurfaceFormat surfaceFormat = m_glContextQt->format(); QSurfaceFormat surfaceFormat = m_glContextShare->format();
if (!m_isOpenGLES2) { if (!m_isOpenGLES2) {
surfaceFormat.setSwapBehavior(QSurfaceFormat::SingleBuffer); surfaceFormat.setSwapBehavior(QSurfaceFormat::SingleBuffer);
surfaceFormat.setSwapInterval(0); surfaceFormat.setSwapInterval(0);
...@@ -314,7 +317,13 @@ QJSValue Canvas::getContext(const QString &type, const QVariantMap &options) ...@@ -314,7 +317,13 @@ QJSValue Canvas::getContext(const QString &type, const QVariantMap &options)
<< surfaceFormat; << surfaceFormat;
m_glContext = new QOpenGLContext(); m_glContext = new QOpenGLContext();
m_glContext->setFormat(surfaceFormat); m_glContext->setFormat(surfaceFormat);
m_glContext->setShareContext(m_glContextQt);
// Share with m_glContextShare which in turn shares with m_glContextQt.
// In case of threaded rendering both of these live on the render
// thread of the scenegraph. m_glContextQt may be current on that
// thread at this point, which would fail the context creation with
// some drivers. Hence the need for m_glContextShare.
m_glContext->setShareContext(m_glContextShare);
if (!m_glContext->create()) { if (!m_glContext->create()) {
qCWarning(canvas3drendering) << "Failed to create context for FBO"; qCWarning(canvas3drendering) << "Failed to create context for FBO";
return QJSValue(QJSValue::NullValue); return QJSValue(QJSValue::NullValue);
...@@ -575,6 +584,14 @@ QSGNode *Canvas::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data) ...@@ -575,6 +584,14 @@ QSGNode *Canvas::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
m_isOpenGLES2 = m_glContextQt->isOpenGLES(); m_isOpenGLES2 = m_glContextQt->isOpenGLES();
if (!m_isOpenGLES2 || m_glContextQt->format().majorVersion() >= 3) if (!m_isOpenGLES2 || m_glContextQt->format().majorVersion() >= 3)
m_maxSamples = 4; m_maxSamples = 4;
m_glContextShare = new QOpenGLContext;
m_glContextShare->setFormat(m_glContextQt->format());
m_glContextShare->setShareContext(m_glContextQt);
QSurface *surface = m_glContextQt->surface();
m_glContextQt->doneCurrent();
if (!m_glContextShare->create())
qCWarning(canvas3drendering) << "Failed to create share context";
m_glContextQt->makeCurrent(surface);
ready(); ready();
return 0; return 0;
} }
......
...@@ -138,6 +138,7 @@ private: ...@@ -138,6 +138,7 @@ private:
QOpenGLContext *m_glContext; QOpenGLContext *m_glContext;
QOpenGLContext *m_glContextQt; QOpenGLContext *m_glContextQt;
QOpenGLContext *m_glContextShare;
QQuickWindow *m_contextWindow; QQuickWindow *m_contextWindow;
uint m_fps; uint m_fps;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment