From bb0f4b48390b5ddc9758f04f6ecd692072fb279f Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Fri, 5 May 2017 11:23:46 +0200 Subject: Scene3DRenderer: fix race condition 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 Reviewed-by: Oleg Evseev --- src/quick3d/imports/scene3d/scene3ditem.cpp | 2 +- src/quick3d/imports/scene3d/scene3ditem_p.h | 2 +- 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) { -- cgit v1.2.3