diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2017-05-05 11:23:46 +0200 |
---|---|---|
committer | Jani Heikkinen <jani.heikkinen@qt.io> | 2017-05-06 19:15:53 +0000 |
commit | bb0f4b48390b5ddc9758f04f6ecd692072fb279f (patch) | |
tree | 780e7f75bf1b708b5c5c2de85a61c4431302102d | |
parent | 4baec347253b14a934cb9f6bcba420adbb09ee35 (diff) |
Scene3DRenderer: fix race conditionv5.9.0-beta4
When the window geometry changes, the Scene3DRenderer was updating
a Qt3D frontend node's property from the QSGRenderThread.
This resulted in the QPostman::notifyBackend being called from possibly two threads at the same time,
resulting in a race condition where the changes would never be submitted again to the backend.
Change-Id: I842aaa54637d85d4d45eb54620749efb36168e2a
Task-number: QTBUG-54900
Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Reviewed-by: Oleg Evseev <ev.mipt@gmail.com>
-rw-r--r-- | src/quick3d/imports/scene3d/scene3ditem.cpp | 2 | ||||
-rw-r--r-- | src/quick3d/imports/scene3d/scene3ditem_p.h | 2 | ||||
-rw-r--r-- | src/quick3d/imports/scene3d/scene3drenderer.cpp | 18 |
3 files changed, 18 insertions, 4 deletions
diff --git a/src/quick3d/imports/scene3d/scene3ditem.cpp b/src/quick3d/imports/scene3d/scene3ditem.cpp index 6c285e133..c31f4aa97 100644 --- a/src/quick3d/imports/scene3d/scene3ditem.cpp +++ b/src/quick3d/imports/scene3d/scene3ditem.cpp @@ -223,7 +223,7 @@ void Scene3DItem::setWindowSurface(QObject *rootObject) } } -void Scene3DItem::setItemArea(const QSize &area) +void Scene3DItem::setItemArea(QSize area) { Qt3DRender::QRenderSurfaceSelector *surfaceSelector = Qt3DRender::QRenderSurfaceSelectorPrivate::find(m_entity); if (surfaceSelector) diff --git a/src/quick3d/imports/scene3d/scene3ditem_p.h b/src/quick3d/imports/scene3d/scene3ditem_p.h index eb14645c3..e0ce3addc 100644 --- a/src/quick3d/imports/scene3d/scene3ditem_p.h +++ b/src/quick3d/imports/scene3d/scene3ditem_p.h @@ -88,7 +88,7 @@ public: bool multisample() const; void setMultisample(bool enable); - void setItemArea(const QSize &area); + Q_INVOKABLE void setItemArea(QSize area); bool isHoverEnabled() const; enum CameraAspectRatioMode { diff --git a/src/quick3d/imports/scene3d/scene3drenderer.cpp b/src/quick3d/imports/scene3d/scene3drenderer.cpp index 88f3be3c1..b32191391 100644 --- a/src/quick3d/imports/scene3d/scene3drenderer.cpp +++ b/src/quick3d/imports/scene3d/scene3drenderer.cpp @@ -57,6 +57,17 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { +namespace { + +inline QMetaMethod setItemAreaMethod() +{ + const int idx = Scene3DItem::staticMetaObject.indexOfMethod("setItemArea(QSize)"); + Q_ASSERT(idx != -1); + return Scene3DItem::staticMetaObject.method(idx); +} + +} // anonymous + class ContextSaver { public: @@ -250,8 +261,11 @@ void Scene3DRenderer::render() const bool multisampleHasChanged = m_multisample != m_lastMultisample; const bool forceRecreate = sizeHasChanged || multisampleHasChanged; - if (sizeHasChanged) - m_item->setItemArea(boundingRectSize); + if (sizeHasChanged) { + // We are in the QSGRenderThread (doing a direct call would result in a race) + static const QMetaMethod setItemArea = setItemAreaMethod(); + setItemArea.invoke(m_item, Qt::QueuedConnection, Q_ARG(QSize, boundingRectSize)); + } // Rebuild FBO and textures if never created or a resize has occurred if ((m_multisampledFBO.isNull() || forceRecreate) && m_multisample) { |