From e0c9c70b229e6b5dbe99e3cfb258206e4a5570b3 Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Wed, 15 Feb 2017 16:18:23 +0200 Subject: Optional support for QSGMapboxGLRenderNode QSGMapboxGLRenderNode support is experimental: It doesn't support QQuickItem transforms nor stencil clipping. By default, QSGMapboxGLTextureNode is enabled. The user can select QSGMapboxGLRenderNode by setting 'mapboxgl.use_fbo' plugin parameter to 'false'. Change-Id: I3d5338990458f62fdbe7b8dc00317a85ee1ff188 Reviewed-by: Paolo Angelelli --- .../geoservices/mapboxgl/qgeomapmapboxgl.cpp | 45 ++++++++++++---- src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.h | 1 + .../mapboxgl/qgeomappingmanagerenginemapboxgl.cpp | 5 ++ .../mapboxgl/qgeomappingmanagerenginemapboxgl.h | 1 + .../geoservices/mapboxgl/qsgmapboxglnode.cpp | 60 +++++++++++++++++++--- src/plugins/geoservices/mapboxgl/qsgmapboxglnode.h | 25 +++++++-- 6 files changed, 114 insertions(+), 23 deletions(-) (limited to 'src/plugins/geoservices/mapboxgl') diff --git a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp index b0987c73..eab7b88a 100644 --- a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp +++ b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp @@ -146,6 +146,7 @@ public: Q_DECLARE_FLAGS(SyncStates, SyncState); QMapboxGLSettings m_settings; + bool m_useFBO = true; bool m_developmentMode = false; QTimer m_refresh; @@ -183,7 +184,7 @@ QGeoMapMapboxGLPrivate::~QGeoMapMapboxGLPrivate() { } -QSGNode *QGeoMapMapboxGLPrivate::updateSceneGraph(QSGNode *oldNode, QQuickWindow *window) +QSGNode *QGeoMapMapboxGLPrivate::updateSceneGraph(QSGNode *node, QQuickWindow *window) { Q_Q(QGeoMapMapboxGL); @@ -196,15 +197,25 @@ QSGNode *QGeoMapMapboxGLPrivate::updateSceneGraph(QSGNode *oldNode, QQuickWindow m_warned = true; } - QSGMapboxGLNode *mbglNode = static_cast(oldNode); - if (!mbglNode) { - mbglNode = new QSGMapboxGLNode(m_settings, m_viewportSize, window->devicePixelRatio(), q); - QObject::connect(mbglNode->map(), &QMapboxGL::mapChanged, q, &QGeoMapMapboxGL::onMapChanged); - m_syncState = MapTypeSync | CameraDataSync | ViewportSync; + QMapboxGL *map = 0; + if (m_useFBO) { + if (!node) { + QSGMapboxGLTextureNode *mbglNode = new QSGMapboxGLTextureNode(m_settings, m_viewportSize, window->devicePixelRatio(), q); + QObject::connect(mbglNode->map(), &QMapboxGL::mapChanged, q, &QGeoMapMapboxGL::onMapChanged); + m_syncState = MapTypeSync | CameraDataSync | ViewportSync; + node = mbglNode; + } + map = static_cast(node)->map(); + } else { + if (!node) { + QSGMapboxGLRenderNode *mbglNode = new QSGMapboxGLRenderNode(m_settings, m_viewportSize, window->devicePixelRatio(), q); + QObject::connect(mbglNode->map(), &QMapboxGL::mapChanged, q, &QGeoMapMapboxGL::onMapChanged); + m_syncState = MapTypeSync | CameraDataSync | ViewportSync; + node = mbglNode; + } + map = static_cast(node)->map(); } - QMapboxGL *map = mbglNode->map(); - if (m_syncState & MapTypeSync) { m_developmentMode = m_activeMapType.name().startsWith("mapbox://") && m_settings.accessToken() == developmentToken; @@ -319,14 +330,20 @@ QSGNode *QGeoMapMapboxGLPrivate::updateSceneGraph(QSGNode *oldNode, QQuickWindow } if (m_syncState & ViewportSync) { - mbglNode->resize(m_viewportSize, window->devicePixelRatio()); + if (m_useFBO) { + static_cast(node)->resize(m_viewportSize, window->devicePixelRatio()); + } else { + map->resize(m_viewportSize, m_viewportSize * window->devicePixelRatio()); + } } - mbglNode->render(); + if (m_useFBO) { + static_cast(node)->render(window); + } m_syncState = NoSync; - return mbglNode; + return node; } QGeoMap::ItemTypes QGeoMapMapboxGLPrivate::supportedMapItemTypes() const @@ -465,6 +482,12 @@ void QGeoMapMapboxGL::setMapboxGLSettings(const QMapboxGLSettings& settings) } } +void QGeoMapMapboxGL::setUseFBO(bool useFBO) +{ + Q_D(QGeoMapMapboxGL); + d->m_useFBO = useFBO; +} + QSGNode *QGeoMapMapboxGL::updateSceneGraph(QSGNode *oldNode, QQuickWindow *window) { Q_D(QGeoMapMapboxGL); diff --git a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.h b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.h index 8386ae44..c43a1e28 100644 --- a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.h +++ b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.h @@ -53,6 +53,7 @@ public: QString copyrightsStyleSheet() const Q_DECL_OVERRIDE; void setMapboxGLSettings(const QMapboxGLSettings &); + void setUseFBO(bool); private Q_SLOTS: // QMapboxGL diff --git a/src/plugins/geoservices/mapboxgl/qgeomappingmanagerenginemapboxgl.cpp b/src/plugins/geoservices/mapboxgl/qgeomappingmanagerenginemapboxgl.cpp index 04a800aa..0196c703 100644 --- a/src/plugins/geoservices/mapboxgl/qgeomappingmanagerenginemapboxgl.cpp +++ b/src/plugins/geoservices/mapboxgl/qgeomappingmanagerenginemapboxgl.cpp @@ -133,6 +133,10 @@ QGeoMappingManagerEngineMapboxGL::QGeoMappingManagerEngineMapboxGL(const QVarian m_settings.setCacheDatabaseMaximumSize(cacheSize); } + if (parameters.contains(QStringLiteral("mapboxgl.use_fbo"))) { + m_useFBO = parameters.value(QStringLiteral("mapboxgl.use_fbo")).toBool(); + } + engineInitialized(); } @@ -144,6 +148,7 @@ QGeoMap *QGeoMappingManagerEngineMapboxGL::createMap() { QGeoMapMapboxGL* map = new QGeoMapMapboxGL(this, 0); map->setMapboxGLSettings(m_settings); + map->setUseFBO(m_useFBO); return map; } diff --git a/src/plugins/geoservices/mapboxgl/qgeomappingmanagerenginemapboxgl.h b/src/plugins/geoservices/mapboxgl/qgeomappingmanagerenginemapboxgl.h index 1bf44064..c5923cda 100644 --- a/src/plugins/geoservices/mapboxgl/qgeomappingmanagerenginemapboxgl.h +++ b/src/plugins/geoservices/mapboxgl/qgeomappingmanagerenginemapboxgl.h @@ -58,6 +58,7 @@ public: private: QMapboxGLSettings m_settings; + bool m_useFBO = true; }; QT_END_NAMESPACE diff --git a/src/plugins/geoservices/mapboxgl/qsgmapboxglnode.cpp b/src/plugins/geoservices/mapboxgl/qsgmapboxglnode.cpp index 4e331afb..4a76ac29 100644 --- a/src/plugins/geoservices/mapboxgl/qsgmapboxglnode.cpp +++ b/src/plugins/geoservices/mapboxgl/qsgmapboxglnode.cpp @@ -35,16 +35,19 @@ ** ****************************************************************************/ -#include -#include +#include "qsgmapboxglnode.h" +#include "qgeomapmapboxgl.h" #include #include -QSGMapboxGLNode::QSGMapboxGLNode(const QMapboxGLSettings &settings, const QSize &size, qreal pixelRatio, QGeoMapMapboxGL *geoMap) +// QSGMapboxGLTextureNode + +QSGMapboxGLTextureNode::QSGMapboxGLTextureNode(const QMapboxGLSettings &settings, const QSize &size, qreal pixelRatio, QGeoMapMapboxGL *geoMap) : QSGSimpleTextureNode() { setTextureCoordinatesTransform(QSGSimpleTextureNode::MirrorVertically); + setFiltering(QSGTexture::Linear); m_map.reset(new QMapboxGL(nullptr, settings, size, pixelRatio)); @@ -53,7 +56,7 @@ QSGMapboxGLNode::QSGMapboxGLNode(const QMapboxGLSettings &settings, const QSize static_cast(&QGeoMapMapboxGL::copyrightsChanged)); } -void QSGMapboxGLNode::resize(const QSize &size, qreal pixelRatio) +void QSGMapboxGLTextureNode::resize(const QSize &size, qreal pixelRatio) { const QSize fbSize = size * pixelRatio; m_map->resize(size, fbSize); @@ -76,20 +79,61 @@ void QSGMapboxGLNode::resize(const QSize &size, qreal pixelRatio) markDirty(QSGNode::DirtyGeometry); } -void QSGMapboxGLNode::render() +void QSGMapboxGLTextureNode::render(QQuickWindow *window) { - QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); + window->setClearBeforeRendering(false); + + QOpenGLFunctions *f = window->openglContext()->functions(); f->glViewport(0, 0, m_fbo->width(), m_fbo->height()); m_fbo->bind(); - m_map->render(m_fbo.data()); + m_map->render(); m_fbo->release(); + window->resetOpenGLState(); markDirty(QSGNode::DirtyMaterial); } -QMapboxGL* QSGMapboxGLNode::map() const +QMapboxGL* QSGMapboxGLTextureNode::map() const { return m_map.data(); } +// QSGMapboxGLRenderNode + +QSGMapboxGLRenderNode::QSGMapboxGLRenderNode(const QMapboxGLSettings &settings, const QSize &size, qreal pixelRatio, QGeoMapMapboxGL *geoMap) + : QSGRenderNode() +{ + m_map.reset(new QMapboxGL(nullptr, settings, size, pixelRatio)); + QObject::connect(m_map.data(), &QMapboxGL::needsRendering, geoMap, &QGeoMap::sgNodeChanged); + QObject::connect(m_map.data(), &QMapboxGL::copyrightsChanged, geoMap, + static_cast(&QGeoMapMapboxGL::copyrightsChanged)); +} + +QMapboxGL* QSGMapboxGLRenderNode::map() const +{ + return m_map.data(); +} + +void QSGMapboxGLRenderNode::render(const RenderState *state) +{ + // QMapboxGL assumes we've prepared the viewport prior to render(). + QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); + f->glViewport(state->scissorRect().x(), state->scissorRect().y(), state->scissorRect().width(), state->scissorRect().height()); + f->glScissor(state->scissorRect().x(), state->scissorRect().y(), state->scissorRect().width(), state->scissorRect().height()); + f->glEnable(GL_SCISSOR_TEST); + + m_map->render(); +} + +QSGRenderNode::StateFlags QSGMapboxGLRenderNode::changedStates() const +{ + return QSGRenderNode::DepthState + | QSGRenderNode::StencilState + | QSGRenderNode::ScissorState + | QSGRenderNode::ColorState + | QSGRenderNode::BlendState + | QSGRenderNode::ViewportState + | QSGRenderNode::RenderTargetState; +} + diff --git a/src/plugins/geoservices/mapboxgl/qsgmapboxglnode.h b/src/plugins/geoservices/mapboxgl/qsgmapboxglnode.h index bd7cc4b3..5805a76c 100644 --- a/src/plugins/geoservices/mapboxgl/qsgmapboxglnode.h +++ b/src/plugins/geoservices/mapboxgl/qsgmapboxglnode.h @@ -38,6 +38,8 @@ #ifndef QSGMAPBOXGLNODE_H #define QSGMAPBOXGLNODE_H +#include +#include #include #include #include @@ -46,19 +48,34 @@ class QGeoMapMapboxGL; -class QSGMapboxGLNode : public QSGSimpleTextureNode +class QSGMapboxGLTextureNode : public QSGSimpleTextureNode { public: - QSGMapboxGLNode(const QMapboxGLSettings &, const QSize &, qreal pixelRatio, QGeoMapMapboxGL *geoMap); + QSGMapboxGLTextureNode(const QMapboxGLSettings &, const QSize &, qreal pixelRatio, QGeoMapMapboxGL *geoMap); + + QMapboxGL* map() const; void resize(const QSize &size, qreal pixelRatio); - void render(); + void render(QQuickWindow *); + +private: + QScopedPointer m_map; + QScopedPointer m_fbo; +}; + +class QSGMapboxGLRenderNode : public QSGRenderNode +{ +public: + QSGMapboxGLRenderNode(const QMapboxGLSettings &, const QSize &, qreal pixelRatio, QGeoMapMapboxGL *geoMap); QMapboxGL* map() const; + // QSGRenderNode + void render(const RenderState *state) Q_DECL_OVERRIDE; + StateFlags changedStates() const Q_DECL_OVERRIDE; + private: QScopedPointer m_map; - QScopedPointer m_fbo; }; #endif // QSGMAPBOXGLNODE_H -- cgit v1.2.1