diff options
author | Paolo Angelelli <paolo.angelelli.qt@gmail.com> | 2019-12-26 21:31:03 +0100 |
---|---|---|
committer | paolo <paolo.angelelli.qt@gmail.com> | 2020-02-11 19:35:27 +0100 |
commit | e82c41d35ddd6ef0d14e1d01ea1dfd46742bc0fe (patch) | |
tree | 17772318d8b51e3eb4bc19dc3d5fee120c137a90 | |
parent | d055098540df99a5d426360e9322c659e678e5ee (diff) |
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 <alexander.blasche@qt.io>
-rw-r--r-- | src/location/labs/qsg/qgeomapobjectqsgsupport.cpp | 12 | ||||
-rw-r--r-- | src/location/labs/qsg/qgeomapobjectqsgsupport_p.h | 3 | ||||
-rw-r--r-- | src/location/labs/qsg/qmapcircleobjectqsg.cpp | 14 | ||||
-rw-r--r-- | src/location/labs/qsg/qmapiconobjectqsg.cpp | 5 | ||||
-rw-r--r-- | src/location/labs/qsg/qmappolygonobjectqsg.cpp | 14 | ||||
-rw-r--r-- | 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 "<<mo.object->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 <QtLocation/private/qmaprouteobjectqsg_p_p.h> #include <QtLocation/private/qmapiconobjectqsg_p_p.h> #include <QtLocation/private/qdeclarativepolylinemapitem_p.h> +#include <QtLocation/private/qdeclarativepolygonmapitem_p_p.h> #include <QtCore/qpointer.h> QT_BEGIN_NAMESPACE - struct Q_LOCATION_PRIVATE_EXPORT MapObject { MapObject(QPointer<QGeoMapObject> &o, QQSGMapObject *sgo) : object(o), sgObject(sgo) {} @@ -85,6 +85,7 @@ public: QList<MapObject> m_pendingMapObjects; QList<MapObject> 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<MapPolygonNode *>(oldNode); - bool created = false; if (!node) { + if (!m_geometry.size() && !m_borderGeometry.size()) { + return nullptr; + } node = new MapPolygonNode(); *visibleNode = static_cast<VisibleNode *>(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<QMapPolygonObject *>(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<RootNode *>(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<VisibleNode *>(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<MapPolygonNode *>(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<VisibleNode *>(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<MapPolylineNode *>(oldNode); - bool created = false; if (!node) { if (!m_geometry.size()) // condition to block the subtree return nullptr; node = new MapPolylineNode(); *visibleNode = static_cast<VisibleNode *>(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; } |