From e82c41d35ddd6ef0d14e1d01ea1dfd46742bc0fe Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Thu, 26 Dec 2019 21:31:03 +0100 Subject: Fix Map*ObjectsQSG implementation triggering QSGBatchRenderer crashes The new approach introduces a root node for all objects, that is repopulated at every repaint. Change-Id: I4562e1aaa18999a03e8c38fe3bf59fe41f14dd70 Reviewed-by: Alex Blasche --- src/location/labs/qsg/qgeomapobjectqsgsupport.cpp | 12 +++++++++--- src/location/labs/qsg/qgeomapobjectqsgsupport_p.h | 3 ++- src/location/labs/qsg/qmapcircleobjectqsg.cpp | 14 +++++++++----- src/location/labs/qsg/qmapiconobjectqsg.cpp | 5 +---- src/location/labs/qsg/qmappolygonobjectqsg.cpp | 14 ++++++++------ src/location/labs/qsg/qmappolylineobjectqsg.cpp | 11 ++++++----- 6 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/location/labs/qsg/qgeomapobjectqsgsupport.cpp b/src/location/labs/qsg/qgeomapobjectqsgsupport.cpp index 1a1b102b..6cb2c44a 100644 --- a/src/location/labs/qsg/qgeomapobjectqsgsupport.cpp +++ b/src/location/labs/qsg/qgeomapobjectqsgsupport.cpp @@ -154,10 +154,15 @@ void QGeoMapObjectQSGSupport::removeMapObject(QGeoMapObject *obj) void QGeoMapObjectQSGSupport::updateMapObjects(QSGNode *root, QQuickWindow *window) { + if (!m_mapObjectsRootNode) { + m_mapObjectsRootNode = new QDeclarativePolygonMapItemPrivateOpenGL::RootNode(); + root->appendChildNode(m_mapObjectsRootNode); + } + + m_mapObjectsRootNode->removeAllChildNodes(); for (int i = 0; i < m_removedMapObjects.size(); ++i) { MapObject mo = m_removedMapObjects[i]; if (mo.qsgNode) { - root->removeChildNode(mo.qsgNode); delete mo.qsgNode; mo.qsgNode = nullptr; // mo.sgObject is now invalid as it is destroyed right after appending @@ -176,7 +181,7 @@ void QGeoMapObjectQSGSupport::updateMapObjects(QSGNode *root, QQuickWindow *wind MapObject &mo = m_mapObjects[i]; QQSGMapObject *sgo = mo.sgObject; QSGNode *oldNode = mo.qsgNode; - mo.qsgNode = sgo->updateMapObjectNode(oldNode, &mo.visibleNode, root, window); + mo.qsgNode = sgo->updateMapObjectNode(oldNode, &mo.visibleNode, m_mapObjectsRootNode, window); if (Q_UNLIKELY(!mo.qsgNode)) { qWarning() << "updateMapObjectNode for "<type() << " returned NULL"; } else if (mo.visibleNode && (mo.visibleNode->visible() != mo.object->visible())) { @@ -192,7 +197,7 @@ void QGeoMapObjectQSGSupport::updateMapObjects(QSGNode *root, QQuickWindow *wind QQSGMapObject *sgo = mo.sgObject; QSGNode *oldNode = mo.qsgNode; sgo->updateGeometry(); // or subtree will be blocked - mo.qsgNode = sgo->updateMapObjectNode(oldNode, &mo.visibleNode, root, window); + mo.qsgNode = sgo->updateMapObjectNode(oldNode, &mo.visibleNode, m_mapObjectsRootNode, window); if (mo.qsgNode) { if (mo.visibleNode && (mo.visibleNode->visible() != mo.object->visible())) { mo.visibleNode->setVisible(mo.object->visible()); @@ -208,6 +213,7 @@ void QGeoMapObjectQSGSupport::updateMapObjects(QSGNode *root, QQuickWindow *wind for (int i: qAsConst(toRemove)) m_pendingMapObjects.removeAt(i); + m_mapObjectsRootNode->setSubtreeBlocked(false); } void QGeoMapObjectQSGSupport::updateObjectsGeometry() diff --git a/src/location/labs/qsg/qgeomapobjectqsgsupport_p.h b/src/location/labs/qsg/qgeomapobjectqsgsupport_p.h index bb0477c5..1ec966fa 100644 --- a/src/location/labs/qsg/qgeomapobjectqsgsupport_p.h +++ b/src/location/labs/qsg/qgeomapobjectqsgsupport_p.h @@ -57,10 +57,10 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE - struct Q_LOCATION_PRIVATE_EXPORT MapObject { MapObject(QPointer &o, QQSGMapObject *sgo) : object(o), sgObject(sgo) {} @@ -85,6 +85,7 @@ public: QList m_pendingMapObjects; QList m_removedMapObjects; QGeoMap *m_map = nullptr; + QDeclarativePolygonMapItemPrivateOpenGL::RootNode *m_mapObjectsRootNode = nullptr; }; QT_END_NAMESPACE diff --git a/src/location/labs/qsg/qmapcircleobjectqsg.cpp b/src/location/labs/qsg/qmapcircleobjectqsg.cpp index f79be136..6c69ce5a 100644 --- a/src/location/labs/qsg/qmapcircleobjectqsg.cpp +++ b/src/location/labs/qsg/qmapcircleobjectqsg.cpp @@ -154,15 +154,16 @@ QSGNode *QMapCircleObjectPrivateQSG::updateMapObjectNode(QSGNode *oldNode, // Q_UNUSED(visibleNode); // coz of -Werror=unused-but-set-parameter MapPolygonNode *node = static_cast(oldNode); - bool created = false; if (!node) { + if (!m_geometry.size() && !m_borderGeometry.size()) { + return nullptr; + } node = new MapPolygonNode(); *visibleNode = static_cast(node); - created = true; } //TODO: update only material - if (m_geometry.isScreenDirty() || !m_borderGeometry.isScreenDirty() || !oldNode || created) { + if (m_geometry.isScreenDirty() || !m_borderGeometry.isScreenDirty() || !oldNode) { //QMapPolygonObject *p = static_cast(q); node->update(color(), borderColor(), &m_geometry, &m_borderGeometry); m_geometry.setPreserveGeometry(false); @@ -171,9 +172,12 @@ QSGNode *QMapCircleObjectPrivateQSG::updateMapObjectNode(QSGNode *oldNode, m_borderGeometry.markClean(); } - if (created) + if (m_geometry.size() || m_borderGeometry.size()) { root->appendChildNode(node); - + } else { + delete node; + return nullptr; + } return node; } diff --git a/src/location/labs/qsg/qmapiconobjectqsg.cpp b/src/location/labs/qsg/qmapiconobjectqsg.cpp index d9a80c91..10948d82 100644 --- a/src/location/labs/qsg/qmapiconobjectqsg.cpp +++ b/src/location/labs/qsg/qmapiconobjectqsg.cpp @@ -102,7 +102,6 @@ QSGNode *QMapIconObjectPrivateQSG::updateMapObjectNode(QSGNode *oldNode, QQuickWindow *window) { Q_UNUSED(visibleNode); - bool created = false; RootNode *node = static_cast(oldNode); if (!node) { node = new RootNode(); @@ -110,7 +109,6 @@ QSGNode *QMapIconObjectPrivateQSG::updateMapObjectNode(QSGNode *oldNode, m_imageNode->setOwnsTexture(true); node->appendChildNode(m_imageNode); *visibleNode = static_cast(node); - created = true; } if (m_imageDirty) { @@ -131,8 +129,7 @@ QSGNode *QMapIconObjectPrivateQSG::updateMapObjectNode(QSGNode *oldNode, } } - if (created) - root->appendChildNode(node); + root->appendChildNode(node); return node; } diff --git a/src/location/labs/qsg/qmappolygonobjectqsg.cpp b/src/location/labs/qsg/qmappolygonobjectqsg.cpp index 9963cac9..25473478 100644 --- a/src/location/labs/qsg/qmappolygonobjectqsg.cpp +++ b/src/location/labs/qsg/qmappolygonobjectqsg.cpp @@ -85,17 +85,16 @@ QSGNode *QMapPolygonObjectPrivateQSG::updateMapObjectNode(QSGNode *oldNode, Q_UNUSED(visibleNode); MapPolygonNode *node = static_cast(oldNode); - bool created = false; if (!node) { - if (!m_geometry.size() && !m_borderGeometry.size()) + if (!m_geometry.size() && !m_borderGeometry.size()) { return nullptr; + } node = new MapPolygonNode(); *visibleNode = static_cast(node); - created = true; } //TODO: update only material - if (m_geometry.isScreenDirty() || !m_borderGeometry.isScreenDirty() || !oldNode || created) { + if (m_geometry.isScreenDirty() || !m_borderGeometry.isScreenDirty() || !oldNode) { node->update(fillColor(), borderColor(), &m_geometry, &m_borderGeometry); m_geometry.setPreserveGeometry(false); m_borderGeometry.setPreserveGeometry(false); @@ -103,9 +102,12 @@ QSGNode *QMapPolygonObjectPrivateQSG::updateMapObjectNode(QSGNode *oldNode, m_borderGeometry.markClean(); } - if (created) + if (m_geometry.size() || m_borderGeometry.size()) { root->appendChildNode(node); - + } else { + delete node; + return nullptr; + } return node; } diff --git a/src/location/labs/qsg/qmappolylineobjectqsg.cpp b/src/location/labs/qsg/qmappolylineobjectqsg.cpp index 2bf5b287..96f66565 100644 --- a/src/location/labs/qsg/qmappolylineobjectqsg.cpp +++ b/src/location/labs/qsg/qmappolylineobjectqsg.cpp @@ -107,25 +107,26 @@ QSGNode *QMapPolylineObjectPrivateQSG::updateMapObjectNode(QSGNode *oldNode, Q_UNUSED(visibleNode); MapPolylineNode *node = static_cast(oldNode); - bool created = false; if (!node) { if (!m_geometry.size()) // condition to block the subtree return nullptr; node = new MapPolylineNode(); *visibleNode = static_cast(node); - created = true; } //TODO: update only material - if (m_geometry.isScreenDirty() || !oldNode || created) { + if (m_geometry.isScreenDirty() || !oldNode) { node->update(color(), &m_geometry); m_geometry.setPreserveGeometry(false); m_geometry.markClean(); } - if (created) + if (m_geometry.size()) { root->appendChildNode(node); - + } else { + delete node; + return nullptr; + } return node; } -- cgit v1.2.1