summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar.sletta@jollamobile.com>2014-03-13 11:38:27 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-24 13:47:05 +0100
commit979a0406f0013560efbdcc486b32ba93ce8c946f (patch)
tree3226cb4c86a868ec8920196436540dc272a20aea
parentbacc237f032bebe51c436760d31e4a804c3ee034 (diff)
downloadqtlocation-979a0406f0013560efbdcc486b32ba93ce8c946f.tar.gz
Replace Qt3D with scene graph API for map rendering.
QtLocation now links against QtQuick and the QGeoMap has a updateSceneGraph(QSGNode *, QQuickWindow *) function to populate the scene graph with map content in what ever style the implementation decides. The only implementation right now is the QGeoTileMapData (same as with the Qt3D code). Camera positioning, zooming, panning, etc has been preserved in the interest of minimzing the change and keeping things "as they were". All rendering logic is moved into the updateSceneGraph function, where we find the delta between what is shown in the scene graph and what the scene things should be visible. Nodes are added removed accordingly. This logic is isolated from the rest of the code as it primarily lives in the scene graph render thread and may be released at an arbitrary time. Doing this every frame might seem daunting, but for the most, it is a couple of checks on a few tens of nodes, compared to rendering millions of pixels afterwards, so this is not going to be a bottleneck. Texture uploads are now done in the scene graph's rendering phase, so the map item's sync is fast. This means the map element doesn't block both GUI and render threads for extended time periods. In contrast, the Qt3D code path uploaded tiles and rendered them to an FBO in the sync phase, resulting in very poor parallelization. We cache the textures designated as visible and nothing else. Primarily in the interest of simplicity, but also because uploading 256x256 textures is a no-brainer on modern GPU's, including lower-end mobile and embedded. The QGeoTileTexture sits on a QImage instead of an actual texture to keep a strict separation between render thread and GUI thread clean. Texture cleanup is done by the scene graph structure. The Qt3D codepath rendered to an FBO, so it was implicitly clipped to its bounds. To preserve this behavior, the scene graph implementation does the same. Not doing so looks a bit odd, at least when zooming all the way out so the world is significantly smaller than the viewport. The scene graph code also adds a rectangle of solid 0.9 gray to match the default color of the old FBO code. Change-Id: Ia736cea6e3616721c2de6beb5d72e570adcb21e6 Reviewed-by: Fabian Bumberger <fbumberger@rim.com> Reviewed-by: Robin Burchell <robin+qt@viroteck.net> Reviewed-by: Alex Blasche <alexander.blasche@digia.com>
-rw-r--r--src/imports/location/location.pro4
-rw-r--r--src/imports/location/mapnode.cpp247
-rw-r--r--src/imports/location/mapnode_p.h100
-rw-r--r--src/imports/location/qdeclarativegeomap.cpp43
-rw-r--r--src/imports/location/qdeclarativegeomap_p.h8
-rw-r--r--src/location/maps/maps.pri2
-rw-r--r--src/location/maps/qgeomap.cpp18
-rw-r--r--src/location/maps/qgeomap_p.h9
-rw-r--r--src/location/maps/qgeomapdata.cpp22
-rw-r--r--src/location/maps/qgeomapdata_p.h8
-rw-r--r--src/location/maps/qgeomapdata_p_p.h6
-rw-r--r--src/location/maps/qgeomapscene.cpp438
-rw-r--r--src/location/maps/qgeomapscene_p.h11
-rw-r--r--src/location/maps/qgeotilecache.cpp43
-rw-r--r--src/location/maps/qgeotilecache_p.h11
-rw-r--r--src/location/maps/qgeotiledmapdata.cpp18
-rw-r--r--src/location/maps/qgeotiledmapdata_p.h6
-rw-r--r--src/location/maps/qgeotiledmapdata_p_p.h5
-rw-r--r--src/src.pro7
-rw-r--r--tests/auto/qgeocameratiles/qgeocameratiles.pro2
-rw-r--r--tests/auto/qgeomapscene/qgeomapscene.pro2
-rw-r--r--tests/auto/qgeomapscene/tst_qgeomapscene.cpp83
22 files changed, 246 insertions, 847 deletions
diff --git a/src/imports/location/location.pro b/src/imports/location/location.pro
index 1538fe55..c04a16e0 100644
--- a/src/imports/location/location.pro
+++ b/src/imports/location/location.pro
@@ -1,4 +1,4 @@
-QT += quick-private network positioning-private location-private qml-private 3d core-private gui-private
+QT += quick-private network positioning-private location-private qml-private core-private gui-private
INCLUDEPATH += ../../location
INCLUDEPATH += ../../location/maps
@@ -27,7 +27,6 @@ HEADERS += \
qdeclarativegeomaptype_p.h \
qdeclarativegeomapitembase_p.h \
qdeclarativegeomapquickitem_p.h \
- mapnode_p.h \
qdeclarativecirclemapitem_p.h \
qdeclarativerectanglemapitem_p.h \
qdeclarativepolygonmapitem_p.h \
@@ -52,7 +51,6 @@ SOURCES += \
qdeclarativegeomaptype.cpp \
qdeclarativegeomapitembase.cpp \
qdeclarativegeomapquickitem.cpp \
- mapnode.cpp \
qdeclarativecirclemapitem.cpp \
qdeclarativerectanglemapitem.cpp \
qdeclarativepolygonmapitem.cpp \
diff --git a/src/imports/location/mapnode.cpp b/src/imports/location/mapnode.cpp
deleted file mode 100644
index 3c557d35..00000000
--- a/src/imports/location/mapnode.cpp
+++ /dev/null
@@ -1,247 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtLocation module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "mapnode_p.h"
-#include "qgeomap_p.h"
-#include <Qt3D/qglpainter.h>
-#include <Qt3D/QGLFramebufferObjectSurface>
-#include <QtGui/QOpenGLFramebufferObject>
-#include <QtQuick/private/qsgtexture_p.h>
-
-#ifndef GL_MULTISAMPLE
-#define GL_MULTISAMPLE 0x809D
-#endif
-
-MapNode::MapNode(QGeoMap *map): QSGGeometryNode(),
- m_fbo(0),
- m_fboSurface(0),
- m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4),
- m_texture(0),
- m_map(map),
- m_initialized(false),
- m_dirtyFBO(false)
-{
- setMaterial(&m_material);
- setOpaqueMaterial(&m_opaqueMaterial);
- setGeometry(&m_geometry);
- // setFlag(UsePreprocess);
-}
-
-MapNode::~MapNode()
-{
- delete m_fboSurface;
- delete m_fbo;
-}
-
-void MapNode::saveRenderState()
-{
- //TODO: implement me
-}
-
-void MapNode::restoreRenderState()
-{
- //TODO: implement me
-}
-
-void
-MapNode::preprocess()
-{
- restoreRenderState();
- //TODO: implement me , texture update
- saveRenderState();
-}
-
-void MapNode::update()
-{
- restoreRenderState();
-
- if (!m_initialized)
- init();
-
- if (m_dirtyFBO)
- updateFBO();
-
- saveRenderState();
-}
-
-void MapNode::updateFBO()
-{
- QGLPainter painter;
-
- if (!painter.begin()) {
- qWarning() << "GL graphics system is not active, can not update FBO for map";
- return;
- }
-
- painter.pushSurface(m_fboSurface);
-
- glClearColor(0.9, 0.9, 0.9, 0.0);
- glClear(GL_COLOR_BUFFER_BIT);
- painter.disableEffect();
-#ifdef GL_RESCALE_NORMAL
- // Scale normals by a scale factor derived from modelview matrix.
- // Note: normals need to be unit length.
- glEnable(GL_RESCALE_NORMAL);
-#endif
-
-#if !defined(QT_OPENGL_ES_2)
- glShadeModel(GL_SMOOTH);
- glEnable(GL_MULTISAMPLE);
-#endif
-
- // Set the default effect for the scene.
- painter.setStandardEffect(QGL::LitMaterial);
- painter.setFaceColor(QGL::AllFaces, Qt::white);
-
-#if defined(QT_OPENGL_ES)
- glClearDepthf(1);
-#else
- glClearDepth(1);
-#endif
-
-#if defined(GL_LINE_SMOOTH) && defined(GL_LINE_SMOOTH_HINT)
- glEnable(GL_LINE_SMOOTH);
- glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
-#endif
-
-#ifdef QSGSHADEREFFECTSOURCE_AVAILABLE
- // Update any map objects that may have dirty textures
- for (int i = 0; i < mapItems_.count(); ++i) {
- mapItems_.at(i)->updateItem();
- }
-#endif
-
- // No stereo rendering, set the eye as neutral
- painter.setEye(QGL::NoEye);
- // TODO this needs to be figured out (or confirmed as invalid thing).
- // Currently applied transforms for this Map3D object - how to get/apply current transforms?
- // QTransform transform = painter->combinedTransform();
- // Then we get the rectangle that is gotten by applying the QTransform on the rect
- // --> this is the viewport for Map3D
- // QRect viewport = transform.mapRect(boundingRect()).toRect();
-
- // boundingRect is in local coordinates. We need to map it to the scene coordinates
- // in order to render to correct area.
-
- if (m_map->glCamera()) {
- painter.setCamera(m_map->glCamera());
- } else {
- QGLCamera defCamera;
- painter.setCamera(&defCamera);
- }
- m_map->paintGL(&painter);
-
- restoreDefaults(&painter);
-
- // Draw the children items
- painter.popSurface();
- // QSG does not expect anyone to alter gl context state; restore defaults.
- // Default heaps of things, because we cannot be sure what the Qt3D internally
- // sets.
-
-#if defined(QT_OPENGL_ES)
- glClearDepthf(0);
-#else
- glClearDepth(0);
-#endif
-
- painter.end();
-
- QSGGeometry::updateTexturedRectGeometry(&m_geometry,
- QRectF(QPointF(0, m_fbo->size().height()), QPointF(m_fbo->size().width(), 0)),
- QRectF(0, 0, 1, 1));
- delete m_texture;
- m_texture = new QSGPlainTexture();
- m_texture->setOwnsTexture(false);
- m_texture->setTextureSize(m_fbo->size());
- m_texture->setTextureId(m_fbo->texture());
- m_opaqueMaterial.setTexture(m_texture);
- m_material.setTexture(m_texture);
-
- markDirty(DirtyMaterial);
-}
-
-void MapNode::setSize(const QSize &size)
-{
- if (size == m_size)
- return;
- m_size = size;
- m_dirtyFBO = true;
- m_initialized = false;
- markDirty(DirtyGeometry);
-}
-
-void MapNode::init()
-{
- delete m_fboSurface;
- delete m_fbo;
- m_fbo = new QOpenGLFramebufferObject(m_size.width(), m_size.height());
- m_fboSurface = new QGLFramebufferObjectSurface(m_fbo);
- m_initialized = true;
-}
-
-void MapNode::restoreDefaults(QGLPainter *painter)
-{
- // Disable the effect to return control to the GL paint engine.
- painter->disableEffect();
-
- // Try to restore the default options
- glDisable(GL_CULL_FACE);
- glDisable(GL_DEPTH_TEST);
- // Set the default depth buffer options.
- glDepthFunc(GL_LESS);
- glDepthMask(GL_TRUE);
-#if defined(QT_OPENGL_ES)
- glDepthRangef(0.0f, 1.0f);
-#else
- glDepthRange(0.0f, 1.0f);
-#endif
- // Set the default blend options.
- glDisable(GL_BLEND);
- if (painter->hasOpenGLFeature(QOpenGLFunctions::BlendColor))
- painter->glBlendColor(0, 0, 0, 0);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- if (painter->hasOpenGLFeature(QOpenGLFunctions::BlendEquation))
- painter->glBlendEquation(GL_FUNC_ADD);
- else if (painter->hasOpenGLFeature(QOpenGLFunctions::BlendEquationSeparate))
- painter->glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
-}
-
diff --git a/src/imports/location/mapnode_p.h b/src/imports/location/mapnode_p.h
deleted file mode 100644
index 911b8f77..00000000
--- a/src/imports/location/mapnode_p.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtLocation module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef MAPNODE_H
-#define MAPNODE_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtQuick/QSGNode>
-#include <QtQuick/QSGTextureMaterial>
-
-QT_BEGIN_NAMESPACE
-
-class QGeoMap;
-class QOpenGLFramebufferObject;
-class QGLFramebufferObjectSurface;
-class QGLPainter;
-class QSGPlainTexture;
-
-class MapNode : public QSGGeometryNode
-{
-public:
- explicit MapNode(QGeoMap *m_map);
- ~MapNode();
-
- void setSize(const QSize &size);
- QSize size() const { return m_size; }
- void update();
- void preprocess();
-
-private:
- void init();
- void updateFBO();
- void saveRenderState();
- void restoreRenderState();
- void restoreDefaults(QGLPainter *painter);
-
-private:
- QOpenGLFramebufferObject *m_fbo;
- QGLFramebufferObjectSurface *m_fboSurface;
- QSGOpaqueTextureMaterial m_opaqueMaterial;
- QSGTextureMaterial m_material;
- QSGGeometry m_geometry;
- QSGPlainTexture *m_texture;
- QGeoMap *m_map;
- QSize m_size;
- bool m_initialized;
- bool m_dirtyFBO;
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/imports/location/qdeclarativegeomap.cpp b/src/imports/location/qdeclarativegeomap.cpp
index 9e2e4ebb..59590309 100644
--- a/src/imports/location/qdeclarativegeomap.cpp
+++ b/src/imports/location/qdeclarativegeomap.cpp
@@ -53,7 +53,6 @@
#include "qgeocameradata_p.h"
#include "qgeocameracapabilities_p.h"
#include "qgeomapcontroller_p.h"
-#include "mapnode_p.h"
#include <cmath>
#include <QtPositioning/QGeoCoordinate>
@@ -68,6 +67,7 @@
#include <QtQml/qqmlinfo.h>
#include <QModelIndex>
#include <QtQuick/QQuickWindow>
+#include <QtQuick/QSGSimpleRectNode>
#include <QtGui/QGuiApplication>
#include <QCoreApplication>
@@ -191,7 +191,6 @@ QDeclarativeGeoMap::QDeclarativeGeoMap(QQuickItem *parent)
activeMapType_(0),
componentCompleted_(false),
mappingManagerInitialized_(false),
- window_(0),
touchTimer_(-1),
map_(0)
{
@@ -368,16 +367,6 @@ QDeclarativeGeoMapGestureArea *QDeclarativeGeoMap::gesture()
/*!
\internal
*/
-void QDeclarativeGeoMap::itemChange(ItemChange change, const ItemChangeData & data)
-{
- QLOC_TRACE0;
- if (change == ItemSceneChange)
- window_ = data.window;
-}
-
-/*!
- \internal
-*/
void QDeclarativeGeoMap::populateMap()
{
QObjectList kids = children();
@@ -407,29 +396,27 @@ void QDeclarativeGeoMap::setupMapView(QDeclarativeGeoMapItemView *view)
}
/*!
- \internal
-*/
-QSGNode *QDeclarativeGeoMap::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
+ * \internal
+ */
+QSGNode *QDeclarativeGeoMap::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
- Q_UNUSED(data)
- if (width() <= 0 || height() <= 0) {
+ if (!map_) {
delete oldNode;
return 0;
}
- MapNode *node = static_cast<MapNode *>(oldNode);
-
- if (!node) {
- node = new MapNode(map_);
- }
-
- if (!mappingManagerInitialized_)
- return 0;
+ QSGSimpleRectNode *root = static_cast<QSGSimpleRectNode *>(oldNode);
+ if (!root)
+ root = new QSGSimpleRectNode(boundingRect(), QColor::fromRgbF(0.9, 0.9, 0.9));
+ else
+ root->setRect(boundingRect());
- node->setSize(QSize(width(), height()));
- node->update();
+ QSGNode *content = root->childCount() ? root->firstChild() : 0;
+ content = map_->updateSceneGraph(content, window());
+ if (content && root->childCount() == 0)
+ root->appendChildNode(content);
- return node;
+ return root;
}
diff --git a/src/imports/location/qdeclarativegeomap_p.h b/src/imports/location/qdeclarativegeomap_p.h
index fb00e1b7..01fec865 100644
--- a/src/imports/location/qdeclarativegeomap_p.h
+++ b/src/imports/location/qdeclarativegeomap_p.h
@@ -75,7 +75,6 @@
QT_BEGIN_NAMESPACE
-class QGLPainter;
class QGLSceneNode;
class QGeoTileCache;
class Tile;
@@ -120,8 +119,6 @@ public:
virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
- void itemChange(ItemChange change, const ItemChangeData & data);
-
void setPlugin(QDeclarativeGeoServiceProvider *plugin);
QDeclarativeGeoServiceProvider *plugin() const;
@@ -210,11 +207,6 @@ private:
QDeclarativeGeoMapGestureArea *gestureArea_;
- void paintGL(QGLPainter *painter);
- void earlyDraw(QGLPainter *painter);
- void restoreDefaults(QGLPainter *painter);
-
- QQuickWindow *window_;
int touchTimer_;
QGeoMap *map_;
diff --git a/src/location/maps/maps.pri b/src/location/maps/maps.pri
index 3a43c5ea..4ad7f0d6 100644
--- a/src/location/maps/maps.pri
+++ b/src/location/maps/maps.pri
@@ -1,7 +1,7 @@
INCLUDEPATH += maps
-QT_PRIVATE += gui 3d
+QT += gui quick
PUBLIC_HEADERS += \
maps/qgeocodereply.h \
diff --git a/src/location/maps/qgeomap.cpp b/src/location/maps/qgeomap.cpp
index f937c29b..a521f0a2 100644
--- a/src/location/maps/qgeomap.cpp
+++ b/src/location/maps/qgeomap.cpp
@@ -62,14 +62,7 @@
#include <qnumeric.h>
-#include <Qt3D/qglscenenode.h>
-#include <Qt3D/qgeometrydata.h>
-#include <Qt3D/qglbuilder.h>
-#include <Qt3D/qglpainter.h>
-#include <Qt3D/qgeometrydata.h>
-#include <Qt3D/qglbuilder.h>
-#include <Qt3D/qglcamera.h>
-#include <Qt3D/qglsubsurface.h>
+#include <QtQuick/QSGNode>
#include <cmath>
@@ -95,14 +88,9 @@ QGeoMapController *QGeoMap::mapController()
return mapData_->mapController();
}
-QGLCamera *QGeoMap::glCamera() const
+QSGNode *QGeoMap::updateSceneGraph(QSGNode *oldNode, QQuickWindow *window)
{
- return mapData_->glCamera();
-}
-
-void QGeoMap::paintGL(QGLPainter *painter)
-{
- mapData_->paintGL(painter);
+ return mapData_->updateSceneGraph(oldNode, window);
}
void QGeoMap::resize(int width, int height)
diff --git a/src/location/maps/qgeomap_p.h b/src/location/maps/qgeomap_p.h
index e956d886..4ade6931 100644
--- a/src/location/maps/qgeomap_p.h
+++ b/src/location/maps/qgeomap_p.h
@@ -64,14 +64,14 @@ class QGeoCoordinate;
class QGeoMappingManager;
-class MapItem;
class QGeoMapController;
class QGeoCameraCapabilities;
-class QGLCamera;
-class QGLPainter;
class QGeoMapData;
+class QSGNode;
+class QQuickWindow;
+
class QPointF;
class Q_LOCATION_EXPORT QGeoMap : public QObject
@@ -87,8 +87,7 @@ public:
QGeoMapController *mapController();
- QGLCamera *glCamera() const;
- void paintGL(QGLPainter *painter);
+ QSGNode *updateSceneGraph(QSGNode *oldNode, QQuickWindow *window);
void resize(int width, int height);
int width() const;
diff --git a/src/location/maps/qgeomapdata.cpp b/src/location/maps/qgeomapdata.cpp
index e6d7b68f..ce5579ba 100644
--- a/src/location/maps/qgeomapdata.cpp
+++ b/src/location/maps/qgeomapdata.cpp
@@ -63,15 +63,6 @@
#include <qnumeric.h>
-#include <Qt3D/qglscenenode.h>
-#include <Qt3D/qgeometrydata.h>
-#include <Qt3D/qglbuilder.h>
-#include <Qt3D/qglpainter.h>
-#include <Qt3D/qgeometrydata.h>
-#include <Qt3D/qglbuilder.h>
-#include <Qt3D/qglcamera.h>
-#include <Qt3D/qglsubsurface.h>
-
#include <cmath>
QT_BEGIN_NAMESPACE
@@ -91,12 +82,6 @@ QGeoMapController *QGeoMapData::mapController()
return d->mapController();
}
-QGLCamera *QGeoMapData::glCamera() const
-{
- Q_D(const QGeoMapData);
- return d->glCamera();
-}
-
void QGeoMapData::resize(int width, int height)
{
Q_D(QGeoMapData);
@@ -178,7 +163,6 @@ QGeoMapDataPrivate::QGeoMapDataPrivate(QGeoMappingManagerEngine *engine, QGeoMap
: width_(0),
height_(0),
aspectRatio_(0.0),
- camera_(new QGLCamera()),
map_(parent),
engine_(engine),
controller_(0),
@@ -191,7 +175,6 @@ QGeoMapDataPrivate::~QGeoMapDataPrivate()
{
// controller_ is a child of map_, don't need to delete it here
- delete camera_;
// TODO map items are not deallocated!
// However: how to ensure this is done in rendering thread?
}
@@ -213,11 +196,6 @@ QGeoMapController *QGeoMapDataPrivate::mapController()
return controller_;
}
-QGLCamera *QGeoMapDataPrivate::glCamera() const
-{
- return camera_;
-}
-
void QGeoMapDataPrivate::setCameraData(const QGeoCameraData &cameraData)
{
QGeoCameraData oldCameraData = cameraData_;
diff --git a/src/location/maps/qgeomapdata_p.h b/src/location/maps/qgeomapdata_p.h
index 35ed32c2..59140b73 100644
--- a/src/location/maps/qgeomapdata_p.h
+++ b/src/location/maps/qgeomapdata_p.h
@@ -68,8 +68,9 @@ class MapItem;
class QGeoMapController;
class QGeoCameraCapabilities;
-class QGLCamera;
-class QGLPainter;
+class QSGNode;
+class QQuickWindow;
+
class QGeoMap;
class QPointF;
@@ -83,8 +84,7 @@ public:
QGeoMapController *mapController();
- QGLCamera *glCamera() const;
- virtual void paintGL(QGLPainter *painter) = 0;
+ virtual QSGNode *updateSceneGraph(QSGNode *, QQuickWindow *window) = 0;
void resize(int width, int height);
int width() const;
diff --git a/src/location/maps/qgeomapdata_p_p.h b/src/location/maps/qgeomapdata_p_p.h
index 5e81d457..d11deee1 100644
--- a/src/location/maps/qgeomapdata_p_p.h
+++ b/src/location/maps/qgeomapdata_p_p.h
@@ -74,9 +74,6 @@ class QGeoMappingManagerEngine;
class QGeoMapData;
class QGeoMapController;
-class QGLCamera;
-class QGLPainter;
-
class QGeoMapDataPrivate
{
public:
@@ -87,8 +84,6 @@ public:
QGeoMapController *mapController();
- QGLCamera *glCamera() const;
-
void setCameraData(const QGeoCameraData &cameraData);
QGeoCameraData cameraData() const;
@@ -106,7 +101,6 @@ private:
int height_;
double aspectRatio_;
- QGLCamera *camera_;
QGeoMapData *map_;
QGeoMappingManagerEngine *engine_;
QString pluginString_;
diff --git a/src/location/maps/qgeomapscene.cpp b/src/location/maps/qgeomapscene.cpp
index cb24861f..3d256734 100644
--- a/src/location/maps/qgeomapscene.cpp
+++ b/src/location/maps/qgeomapscene.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtLocation module of the Qt Toolkit.
@@ -49,15 +50,8 @@
#include <QtPositioning/private/qdoublevector2d_p.h>
#include <QtPositioning/private/qdoublevector3d_p.h>
-#include <Qt3D/qglscenenode.h>
-#include <Qt3D/qglbuilder.h>
-#include <Qt3D/qglmaterial.h>
-#include <Qt3D/qgltexture2d.h>
-#include <Qt3D/qgeometrydata.h>
-#include <Qt3D/qglcamera.h>
-#include <Qt3D/qglpainter.h>
-#include <Qt3D/QGLLightParameters>
-
+#include <QtQuick/QSGSimpleTextureNode>
+#include <QtQuick/QQuickWindow>
#include <QHash>
@@ -78,9 +72,10 @@ public:
QGeoCameraData cameraData_;
QSet<QGeoTileSpec> visibleTiles_;
- QGLCamera *camera_;
- QGLSceneNode *sceneNode_;
- QGLLightParameters* light_;
+ QDoubleVector3D cameraUp_;
+ QDoubleVector3D cameraEye_;
+ QDoubleVector3D cameraCenter_;
+ QMatrix4x4 projectionMatrix_;
// scales up the tile geometry and the camera altitude, resulting in no visible effect
// other than to control the accuracy of the render by keeping the values in a sensible range
@@ -94,9 +89,7 @@ public:
// it is 1<<zoomLevel
int sideLength_;
- QHash<QGeoTileSpec, QGLSceneNode *> nodes_;
QHash<QGeoTileSpec, QSharedPointer<QGeoTileTexture> > textures_;
- QList<QSharedPointer<QGeoTileTexture> > newUploads_;
// tilesToGrid transform
int minTileX_; // the minimum tile index, i.e. 0 to sideLength which is 1<< zoomLevel
@@ -130,14 +123,9 @@ public:
void setVisibleTiles(const QSet<QGeoTileSpec> &tiles);
void removeTiles(const QSet<QGeoTileSpec> &oldTiles);
- void updateTiles(const QSet<QGeoTileSpec> &tiles);
- QGeometryData buildGeometry(const QGeoTileSpec &spec);
- QGLSceneNode *buildSceneNodeFromGeometry(const QGeometryData &geom);
+ bool buildGeometry(const QGeoTileSpec &spec, QSGGeometry::TexturedPoint2D *vertices);
void setTileBounds(const QSet<QGeoTileSpec> &tiles);
void setupCamera();
- void setScalingOnTextures();
-
- void paintGL(QGLPainter *painter);
private:
QGeoMapScene *q_ptr;
@@ -177,13 +165,7 @@ void QGeoMapScene::setCameraData(const QGeoCameraData &cameraData)
d->cameraData_ = cameraData;
d->intZoomLevel_ = static_cast<int>(std::floor(d->cameraData_.zoomLevel()));
float delta = cameraData.zoomLevel() - d->intZoomLevel_;
- if (qAbs(delta) < 0.05) {
- d->linearScaling_ = false;
- d->setScalingOnTextures();
- } else {
- d->linearScaling_ = true;
- d->setScalingOnTextures();
- }
+ d->linearScaling_ = qAbs(delta) > 0.05;
d->sideLength_ = 1 << d->intZoomLevel_;
}
@@ -211,30 +193,12 @@ QDoubleVector2D QGeoMapScene::mercatorToScreenPosition(const QDoubleVector2D &me
return d->mercatorToScreenPosition(mercator);
}
-QGLCamera *QGeoMapScene::camera() const
-{
- Q_D(const QGeoMapScene);
- return d->camera_;
-}
-
-QGLSceneNode *QGeoMapScene::sceneNode() const
-{
- Q_D(const QGeoMapScene);
- return d->sceneNode_;
-}
-
bool QGeoMapScene::verticalLock() const
{
Q_D(const QGeoMapScene);
return d->verticalLock_;
}
-void QGeoMapScene::paintGL(QGLPainter *painter)
-{
- Q_D(QGeoMapScene);
- d->paintGL(painter);
-}
-
QSet<QGeoTileSpec> QGeoMapScene::texturedTiles()
{
Q_D(QGeoMapScene);
@@ -247,9 +211,6 @@ QSet<QGeoTileSpec> QGeoMapScene::texturedTiles()
QGeoMapScenePrivate::QGeoMapScenePrivate(QGeoMapScene *scene)
: tileSize_(0),
- camera_(new QGLCamera()),
- sceneNode_(new QGLSceneNode()),
- light_(new QGLLightParameters()),
scaleFactor_(10.0),
intZoomLevel_(0),
sideLength_(0),
@@ -269,14 +230,11 @@ QGeoMapScenePrivate::QGeoMapScenePrivate(QGeoMapScene *scene)
screenHeight_(0.0),
useVerticalLock_(false),
verticalLock_(false),
- linearScaling_(true),
+ linearScaling_(false),
q_ptr(scene) {}
QGeoMapScenePrivate::~QGeoMapScenePrivate()
{
- delete sceneNode_;
- delete camera_;
- delete light_;
}
QDoubleVector2D QGeoMapScenePrivate::screenPositionToMercator(const QDoubleVector2D &pos) const
@@ -340,7 +298,7 @@ QDoubleVector2D QGeoMapScenePrivate::mercatorToScreenPosition(const QDoubleVecto
return QDoubleVector2D(x + screenOffsetX_, y + screenOffsetY_);
}
-QGeometryData QGeoMapScenePrivate::buildGeometry(const QGeoTileSpec &spec)
+bool QGeoMapScenePrivate::buildGeometry(const QGeoTileSpec &spec, QSGGeometry::TexturedPoint2D *vertices)
{
int x = spec.x();
@@ -352,7 +310,7 @@ QGeometryData QGeoMapScenePrivate::buildGeometry(const QGeoTileSpec &spec)
|| (spec.y() < minTileY_)
|| (maxTileY_ < spec.y())
|| (spec.zoom() != tileZ_)) {
- return 0;
+ return false;
}
double edge = scaleFactor_ * tileSize_;
@@ -368,102 +326,21 @@ QGeometryData QGeoMapScenePrivate::buildGeometry(const QGeoTileSpec &spec)
y1 *= edge;
y2 *= edge;
- QGeometryData g;
-
- QDoubleVector3D n = QDoubleVector3D(0, 0, 1);
-
//Texture coordinate order for veritcal flip of texture
- g.appendVertex(QVector3D(x1, y1, 0.0));
- g.appendNormal(n);
- g.appendTexCoord(QVector2D(0.0, 0.0));
-
- g.appendVertex(QVector3D(x1, y2, 0.0));
- g.appendNormal(n);
- g.appendTexCoord(QVector2D(0.0, 1.0));
-
- g.appendVertex(QVector3D(x2, y2, 0.0));
- g.appendNormal(n);
- g.appendTexCoord(QVector2D(1.0, 1.0));
+ vertices[0].set(x1, y1, 0, 0);
+ vertices[1].set(x1, y2, 0, 1);
+ vertices[2].set(x2, y1, 1, 0);
+ vertices[3].set(x2, y2, 1, 1);
- g.appendVertex(QVector3D(x2, y1, 0.0));
- g.appendNormal(n);
- g.appendTexCoord(QVector2D(1.0, 0.0));
-
- return g;
-}
-
-QGLSceneNode *QGeoMapScenePrivate::buildSceneNodeFromGeometry(const QGeometryData &geom)
-{
- QGLBuilder builder;
- builder.addQuads(geom);
- return builder.finalizedSceneNode();
-}
-
-
-void QGeoMapScenePrivate::setScalingOnTextures()
-{
- if (!linearScaling_) {
- foreach (const QSharedPointer<QGeoTileTexture> &tex, textures_.values()) {
- tex->texture->setBindOptions(tex->texture->bindOptions() &
- (~QGLTexture2D::LinearFilteringBindOption));
- }
- } else {
- foreach (const QSharedPointer<QGeoTileTexture> &tex, textures_.values()) {
- tex->texture->setBindOptions(tex->texture->bindOptions() |
- (QGLTexture2D::LinearFilteringBindOption));
- }
- }
+ return true;
}
void QGeoMapScenePrivate::addTile(const QGeoTileSpec &spec, QSharedPointer<QGeoTileTexture> texture)
{
if (!visibleTiles_.contains(spec)) // Don't add the geometry if it isn't visible
return;
- if (linearScaling_) {
- texture->texture->setBindOptions(texture->texture->bindOptions() |
- (QGLTexture2D::LinearFilteringBindOption));
- } else {
- texture->texture->setBindOptions(texture->texture->bindOptions() &
- (~QGLTexture2D::LinearFilteringBindOption));
- }
- //Avoid expensive conversion of ARGB32_Premultiplied to ARGB32
- if (texture->texture->image().format() == QImage::Format_ARGB32_Premultiplied) {
- texture->texture->setBindOptions(texture->texture->bindOptions() |
- (QGLTexture2D::PremultipliedAlphaBindOption));
- }
-
- //There are tiles for different zoom levels, no need for mipmaps
- texture->texture->setBindOptions(texture->texture->bindOptions() & (~QGLTexture2D::MipmapBindOption));
-
- //We flip the texture coordinates instead of the texture
- texture->texture->setBindOptions(texture->texture->bindOptions() & (~QGLTexture2D::InvertedYBindOption));
-
- QGLSceneNode *node = nodes_.value(spec, 0);
- if (!node) {
- QGeometryData geom = buildGeometry(spec);
- node = buildSceneNodeFromGeometry(geom);
- if (!node)
- return;
-
- QGLMaterial *mat = new QGLMaterial(node);
- mat->setTexture(texture->texture);
- node->setEffect(QGL::LitDecalTexture2D);
- node->setMaterial(mat);
-
- sceneNode_->addNode(node);
- nodes_.insert(spec, node);
- textures_.insert(spec, texture);
- newUploads_ << texture;
-
- } else {
- // TODO handle texture updates when we make node removal more efficient
- if (textures_[spec].data() != texture.data()) {
- textures_.insert(spec, texture);
- node->material()->setTexture(texture->texture);
- newUploads_ << texture;
- }
- }
+ textures_.insert(spec, texture);
}
// return true if new tiles introduced in [tiles]
@@ -485,51 +362,11 @@ void QGeoMapScenePrivate::setVisibleTiles(const QSet<QGeoTileSpec> &tiles)
if (!toRemove.isEmpty())
removeTiles(toRemove);
- // only need to update tiles when the bounds have changed,
- if (visibleTiles_ != tiles && !toUpdate.isEmpty())
- updateTiles(toUpdate);
-
visibleTiles_ = tiles;
if (newTilesIntroduced)
emit q->newTilesVisible(visibleTiles_);
}
-void QGeoMapScenePrivate::updateTiles(const QSet<QGeoTileSpec> &tiles)
-{
- typedef QSet<QGeoTileSpec>::const_iterator iter;
- iter i = tiles.constBegin();
- iter end = tiles.constEnd();
- for (; i != end; ++i) {
- QGeoTileSpec tile = *i;
- QGLSceneNode *node = nodes_.value(tile, 0);
-
- if (node) {
- QGeometryData geom = buildGeometry(tile);
- // if the new geometry (after wrapping) is the same as the old one,
- // it can be reused
- if ( node->children().size() > 0) {
- if (node->children().front()->geometry() == geom)
- continue;
- }
-
- sceneNode_->removeNode(node);
- QGLSceneNode *newNode = buildSceneNodeFromGeometry(geom);
- if (newNode) {
- QGLMaterial *mat = new QGLMaterial(newNode);
- mat->setTexture(textures_[tile]->texture);
- newNode->setEffect(QGL::LitDecalTexture2D);
- newNode->setMaterial(mat);
- sceneNode_->addNode(newNode);
- nodes_.insert(tile, newNode);
- } else {
- nodes_.remove(tile);
- textures_.remove(tile);
- }
- delete node;
- }
- }
-}
-
void QGeoMapScenePrivate::removeTiles(const QSet<QGeoTileSpec> &oldTiles)
{
typedef QSet<QGeoTileSpec>::const_iterator iter;
@@ -538,14 +375,7 @@ void QGeoMapScenePrivate::removeTiles(const QSet<QGeoTileSpec> &oldTiles)
for (; i != end; ++i) {
QGeoTileSpec tile = *i;
- QGLSceneNode *node = nodes_.value(tile, 0);
- if (node) {
- // TODO protect with mutex?
- sceneNode_->removeNode(node);
- nodes_.remove(tile);
- textures_.remove(tile);
- delete node;
- }
+ textures_.remove(tile);
}
}
@@ -629,7 +459,6 @@ void QGeoMapScenePrivate::setTileBounds(const QSet<QGeoTileSpec> &tiles)
void QGeoMapScenePrivate::setupCamera()
{
-
double f = 1.0 * qMin(screenSize_.width(), screenSize_.height());
// fraction of zoom level
@@ -734,81 +563,204 @@ void QGeoMapScenePrivate::setupCamera()
double nearPlane = 1.0;
double farPlane = 4.0 * edge;
- // TODO protect with mutex?
- // set glcamera parameters
- camera_->setCenter(center);
- camera_->setEye(eye);
- camera_->setUpVector(up);
- camera_->setNearPlane(nearPlane);
- camera_->setFarPlane(farPlane);
+ cameraUp_ = up;
+ cameraCenter_ = center;
+ cameraEye_ = eye;
+
+ float halfWidth = 1;
+ float halfHeight = 1;
+ if (aspectRatio > 1.0) {
+ halfWidth *= aspectRatio;
+ } else if (aspectRatio > 0.0f && aspectRatio < 1.0f) {
+ halfHeight /= aspectRatio;
+ }
+ projectionMatrix_.setToIdentity();
+ projectionMatrix_.frustum(-halfWidth, halfWidth, -halfHeight, halfHeight, nearPlane, farPlane);
}
-void QGeoMapScenePrivate::paintGL(QGLPainter *painter)
+class QGeoMapTileContainerNode : public QSGTransformNode
{
- // TODO protect with mutex?
-
- // TODO add a shortcut here for when we don't need to repeat and clip the map
- // NOTE- this is important as the repeat code below removes a lot of accuracy
- // by converting to float and adding/removing large numbers when at high zoom
-
- // do any pending upload/releases
- while (!newUploads_.isEmpty()) {
- if (!newUploads_.front()->textureBound) {
- newUploads_.front()->texture->bind();
- newUploads_.front()->texture->clearImage();
- newUploads_.front()->textureBound = true;
- }
- newUploads_.pop_front();
+public:
+ void addChild(const QGeoTileSpec &spec, QSGSimpleTextureNode *node)
+ {
+ tiles.insert(spec, node);
+ appendChildNode(node);
}
+ QHash<QGeoTileSpec, QSGSimpleTextureNode *> tiles;
+};
- glEnable(GL_SCISSOR_TEST);
+class QGeoMapRootNode : public QSGClipNode
+{
+public:
+ QGeoMapRootNode()
+ : isTextureLinear(false)
+ , geometry(QSGGeometry::defaultAttributes_Point2D(), 4)
+ , root(new QSGTransformNode())
+ , tiles(new QGeoMapTileContainerNode())
+ , wrapLeft(new QGeoMapTileContainerNode())
+ , wrapRight(new QGeoMapTileContainerNode())
+ {
+ setIsRectangular(true);
+ setGeometry(&geometry);
+ root->appendChildNode(tiles);
+ root->appendChildNode(wrapLeft);
+ root->appendChildNode(wrapRight);
+ appendChildNode(root);
+ }
- painter->setScissor(QRect(screenOffsetX_, screenOffsetY_, screenWidth_, screenHeight_));
+ ~QGeoMapRootNode()
+ {
+ qDeleteAll(textures.values());
+ }
- painter->setCamera(camera_);
+ void setClipRect(const QRect &rect)
+ {
+ if (rect != clipRect) {
+ QSGGeometry::updateRectGeometry(&geometry, rect);
+ QSGClipNode::setClipRect(rect);
+ clipRect = rect;
+ markDirty(DirtyGeometry);
+ }
+ }
- painter->setMainLight(light_);
+ void updateTiles(QGeoMapTileContainerNode *root, QGeoMapScenePrivate *d, double camAdjust);
- sceneNode_->draw(painter);
+ bool isTextureLinear;
- QGLCamera *camera = camera_;
+ QSGGeometry geometry;
+ QRect clipRect;
- bool old = camera->blockSignals(true);
+ QSGTransformNode *root;
- glDisable(GL_DEPTH_TEST);
+ QGeoMapTileContainerNode *tiles; // The majority of the tiles
+ QGeoMapTileContainerNode *wrapLeft; // When zoomed out, the tiles that wrap around on the left.
+ QGeoMapTileContainerNode *wrapRight; // When zoomed out, the tiles that wrap around on the right
- double sideLength = scaleFactor_ * tileSize_ * sideLength_;
+ QHash<QGeoTileSpec, QSGTexture *> textures;
+};
- QDoubleVector3D c = QDoubleVector3D(camera->center());
- c.setX(c.x() + sideLength);
- camera->setCenter(c);
+static bool qgeomapscene_isTileInViewport(const QSGGeometry::TexturedPoint2D *tp, const QMatrix4x4 &matrix) {
+ QPolygonF polygon; polygon.reserve(4);
+ for (int i=0; i<4; ++i)
+ polygon << matrix * QPointF(tp[i].x, tp[i].y);
+ return QRectF(-1, -1, 2, 2).intersects(polygon.boundingRect());
+}
- QDoubleVector3D e = QDoubleVector3D(camera->eye());
- e.setX(e.x() + sideLength);
- camera->setEye(e);
+void QGeoMapRootNode::updateTiles(QGeoMapTileContainerNode *root,
+ QGeoMapScenePrivate *d,
+ double camAdjust)
+{
+ // Set up the matrix...
+ QDoubleVector3D eye = d->cameraEye_;
+ eye.setX(eye.x() + camAdjust);
+ QDoubleVector3D center = d->cameraCenter_;
+ center.setX(center.x() + camAdjust);
+ QMatrix4x4 cameraMatrix;
+ cameraMatrix.lookAt(eye, center, d->cameraUp_);
+ root->setMatrix(d->projectionMatrix_ * cameraMatrix);
+
+ QSet<QGeoTileSpec> tilesInSG = QSet<QGeoTileSpec>::fromList(root->tiles.keys());
+ QSet<QGeoTileSpec> toRemove = tilesInSG - d->visibleTiles_;
+ QSet<QGeoTileSpec> toAdd = d->visibleTiles_ - tilesInSG;
+
+ foreach (const QGeoTileSpec &s, toRemove)
+ delete root->tiles.take(s);
+
+ for (QHash<QGeoTileSpec, QSGSimpleTextureNode *>::iterator it = root->tiles.begin();
+ it != root->tiles.end(); ) {
+ QSGGeometry visualGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4);
+ QSGGeometry::TexturedPoint2D *v = visualGeometry.vertexDataAsTexturedPoint2D();
+ bool ok = d->buildGeometry(it.key(), v) && qgeomapscene_isTileInViewport(v, root->matrix());
+ QSGSimpleTextureNode *node = it.value();
+ QSGNode::DirtyState dirtyBits = 0;
+
+ // Check and handle changes to vertex data.
+ if (ok && memcmp(node->geometry()->vertexData(), v, 4 * sizeof(QSGGeometry::TexturedPoint2D)) != 0) {
+ if (v[0].x == v[3].x || v[0].y == v[3].y) { // top-left == bottom-right => invalid => remove
+ ok = false;
+ } else {
+ memcpy(node->geometry()->vertexData(), v, 4 * sizeof(QSGGeometry::TexturedPoint2D));
+ dirtyBits |= QSGNode::DirtyGeometry;
+ }
+ }
- painter->setCamera(camera);
- sceneNode_->draw(painter);
+ if (!ok) {
+ it = root->tiles.erase(it);
+ delete node;
+ } else {
+ if (isTextureLinear != d->linearScaling_) {
+ node->setFiltering(d->linearScaling_ ? QSGTexture::Linear : QSGTexture::Nearest);
+ dirtyBits |= QSGNode::DirtyMaterial;
+ }
+ if (dirtyBits != 0)
+ node->markDirty(dirtyBits);
+ it++;
+ }
+ }
- c.setX(c.x() - 2 * sideLength);
- camera->setCenter(c);
- e.setX(e.x() - 2 * sideLength);
- camera->setEye(e);
+ foreach (const QGeoTileSpec &s, toAdd) {
+ QGeoTileTexture *tileTexture = d->textures_.value(s).data();
+ if (!tileTexture || tileTexture->image.isNull())
+ continue;
+ QSGSimpleTextureNode *tileNode = new QSGSimpleTextureNode();
+ // note: setTexture will update coordinates so do it here, before we buildGeometry
+ tileNode->setTexture(textures.value(s));
+ Q_ASSERT(tileNode->geometry());
+ Q_ASSERT(tileNode->geometry()->attributes() == QSGGeometry::defaultAttributes_TexturedPoint2D().attributes);
+ Q_ASSERT(tileNode->geometry()->vertexCount() == 4);
+ if (d->buildGeometry(s, tileNode->geometry()->vertexDataAsTexturedPoint2D())
+ && qgeomapscene_isTileInViewport(tileNode->geometry()->vertexDataAsTexturedPoint2D(), root->matrix())) {
+ tileNode->setFiltering(d->linearScaling_ ? QSGTexture::Linear : QSGTexture::Nearest);
+ root->addChild(s, tileNode);
+ } else {
+ delete tileNode;
+ }
+ }
+}
- painter->setCamera(camera);
- sceneNode_->draw(painter);
+QSGNode *QGeoMapScene::updateSceneGraph(QSGNode *oldNode, QQuickWindow *window)
+{
+ Q_D(QGeoMapScene);
+ float w = d->screenSize_.width();
+ float h = d->screenSize_.height();
+ if (w <= 0 || h <= 0) {
+ delete oldNode;
+ return 0;
+ }
- c.setX(c.x() + sideLength);
- camera->setCenter(c);
- e.setX(e.x() + sideLength);
- camera->setEye(e);
+ QGeoMapRootNode *mapRoot = static_cast<QGeoMapRootNode *>(oldNode);
+ if (!mapRoot)
+ mapRoot = new QGeoMapRootNode();
+
+ mapRoot->setClipRect(QRect(d->screenOffsetX_, d->screenOffsetY_, d->screenWidth_, d->screenHeight_));
+
+ QMatrix4x4 itemSpaceMatrix;
+ itemSpaceMatrix.scale(w / 2, h / 2);
+ itemSpaceMatrix.translate(1, 1);
+ itemSpaceMatrix.scale(1, -1);
+ mapRoot->root->setMatrix(itemSpaceMatrix);
+
+ QSet<QGeoTileSpec> textures = QSet<QGeoTileSpec>::fromList(mapRoot->textures.keys());
+ QSet<QGeoTileSpec> toRemove = textures - d->visibleTiles_;
+ QSet<QGeoTileSpec> toAdd = d->visibleTiles_ - textures;
+
+ foreach (const QGeoTileSpec &spec, toRemove)
+ mapRoot->textures.take(spec)->deleteLater();
+ foreach (const QGeoTileSpec &spec, toAdd) {
+ QGeoTileTexture *tileTexture = d->textures_.value(spec).data();
+ if (!tileTexture || tileTexture->image.isNull())
+ continue;
+ mapRoot->textures.insert(spec, window->createTextureFromImage(tileTexture->image));
+ }
- painter->setCamera(camera);
- sceneNode_->draw(painter);
+ double sideLength = d->scaleFactor_ * d->tileSize_ * d->sideLength_;
+ mapRoot->updateTiles(mapRoot->tiles, d, 0);
+ mapRoot->updateTiles(mapRoot->wrapLeft, d, +sideLength);
+ mapRoot->updateTiles(mapRoot->wrapRight, d, -sideLength);
- glEnable(GL_DEPTH_TEST);
+ mapRoot->isTextureLinear = d->linearScaling_;
- camera->blockSignals(old);
+ return mapRoot;
}
QT_END_NAMESPACE
diff --git a/src/location/maps/qgeomapscene_p.h b/src/location/maps/qgeomapscene_p.h
index 203eeb8a..bfef71ee 100644
--- a/src/location/maps/qgeomapscene_p.h
+++ b/src/location/maps/qgeomapscene_p.h
@@ -67,12 +67,11 @@ class QGeoTileSpec;
class QDoubleVector2D;
-class QGLSceneNode;
-class QGLCamera;
-class QGLPainter;
-class QGLTexture2D;
class QGeoTileTexture;
+class QSGNode;
+class QQuickWindow;
+
class QPointF;
class QGeoMapScenePrivate;
@@ -97,9 +96,7 @@ public:
QDoubleVector2D screenPositionToMercator(const QDoubleVector2D &pos) const;
QDoubleVector2D mercatorToScreenPosition(const QDoubleVector2D &mercator) const;
- QGLCamera *camera() const;
- QGLSceneNode *sceneNode() const;
- void paintGL(QGLPainter *painter);
+ QSGNode *updateSceneGraph(QSGNode *oldNode, QQuickWindow *window);
bool verticalLock() const;
QSet<QGeoTileSpec> texturedTiles();
diff --git a/src/location/maps/qgeotilecache.cpp b/src/location/maps/qgeotilecache.cpp
index 3bcb2275..a51ce815 100644
--- a/src/location/maps/qgeotilecache.cpp
+++ b/src/location/maps/qgeotilecache.cpp
@@ -50,14 +50,10 @@
#include <QPixmap>
#include <QDebug>
-#include <Qt3D/qgltexture2d.h>
-
Q_DECLARE_METATYPE(QList<QGeoTileSpec>)
Q_DECLARE_METATYPE(QSet<QGeoTileSpec>)
QT_BEGIN_NAMESPACE
-QMutex QGeoTileCache::cleanupMutex_;
-QList<QGLTexture2D*> QGeoTileCache::cleanupList_;
class QGeoCachedTileMemory
{
@@ -75,8 +71,7 @@ public:
};
QGeoTileTexture::QGeoTileTexture()
- : texture(0),
- textureBound(false) {}
+ : textureBound(false) {}
void QCache3QTileEvictionPolicy::aboutToBeRemoved(const QGeoTileSpec &key, QSharedPointer<QGeoCachedTileDisk> obj)
{
@@ -100,7 +95,6 @@ QGeoCachedTileDisk::~QGeoCachedTileDisk()
QGeoTileTexture::~QGeoTileTexture()
{
- QGeoTileCache::evictFromTextureCache(this);
}
QGeoTileCache::QGeoTileCache(const QString &directory, QObject *parent)
@@ -274,25 +268,6 @@ int QGeoTileCache::textureUsage() const
return textureCache_.totalCost();
}
-void QGeoTileCache::GLContextAvailable()
-{
- QMutexLocker ml(&cleanupMutex_);
-
- /* Throttle the cleanup to 10 items/frame to avoid blocking the render
- * for too long. Normally only 6-20 tiles are on screen at a time so
- * eviction rates shouldn't be much higher than this. */
- int todo = qMin(cleanupList_.size(), 10);
- for (int i = 0; i < todo; ++i) {
- QGLTexture2D *texture = cleanupList_.front();
- if (texture) {
- texture->release();
- texture->cleanupResources();
- delete texture;
- }
- cleanupList_.pop_front();
- }
-}
-
QSharedPointer<QGeoTileTexture> QGeoTileCache::get(const QGeoTileSpec &spec)
{
QSharedPointer<QGeoTileTexture> tt = textureCache_.object(spec);
@@ -372,12 +347,6 @@ void QGeoTileCache::evictFromMemoryCache(QGeoCachedTileMemory * /* tm */)
{
}
-void QGeoTileCache::evictFromTextureCache(QGeoTileTexture *tt)
-{
- QMutexLocker ml(&cleanupMutex_);
- cleanupList_ << tt->texture;
-}
-
QSharedPointer<QGeoCachedTileDisk> QGeoTileCache::addToDiskCache(const QGeoTileSpec &spec, const QString &filename)
{
QSharedPointer<QGeoCachedTileDisk> td(new QGeoCachedTileDisk);
@@ -409,15 +378,9 @@ QSharedPointer<QGeoTileTexture> QGeoTileCache::addToTextureCache(const QGeoTileS
{
QSharedPointer<QGeoTileTexture> tt(new QGeoTileTexture);
tt->spec = spec;
- tt->texture = new QGLTexture2D();
- tt->texture->setPixmap(pixmap);
- tt->texture->setHorizontalWrap(QGL::ClampToEdge);
- tt->texture->setVerticalWrap(QGL::ClampToEdge);
-
- /* Do not bind/cleanImage on the texture here -- it needs to be done
- * in the render thread (by qgeomapscene) */
+ tt->image = pixmap.toImage();
- int textureCost = pixmap.width() * pixmap.height() * pixmap.depth() / 8;
+ int textureCost = tt->image.width() * tt->image.height() * tt->image.depth() / 8;
textureCache_.insert(spec, tt, textureCost);
return tt;
diff --git a/src/location/maps/qgeotilecache_p.h b/src/location/maps/qgeotilecache_p.h
index eee09de3..b9d98e98 100644
--- a/src/location/maps/qgeotilecache_p.h
+++ b/src/location/maps/qgeotilecache_p.h
@@ -64,6 +64,8 @@
#include "qgeotilespec_p.h"
#include "qgeotiledmappingmanagerengine_p.h"
+#include <QImage>
+
QT_BEGIN_NAMESPACE
class QGeoMappingManager;
@@ -71,7 +73,6 @@ class QGeoMappingManager;
class QGeoTile;
class QGeoCachedTileMemory;
class QGeoTileCache;
-class QGLTexture2D;
class QPixmap;
class QThread;
@@ -98,7 +99,7 @@ public:
~QGeoTileTexture();
QGeoTileSpec spec;
- QGLTexture2D *texture;
+ QImage image;
bool textureBound;
};
@@ -132,15 +133,12 @@ public:
int minTextureUsage() const;
int textureUsage() const;
- void GLContextAvailable();
-
QSharedPointer<QGeoTileTexture> get(const QGeoTileSpec &spec);
QString directory() const;
// can be called without a specific tileCache pointer
static void evictFromDiskCache(QGeoCachedTileDisk *td);
static void evictFromMemoryCache(QGeoCachedTileMemory *tm);
- static void evictFromTextureCache(QGeoTileTexture *tt);
void insert(const QGeoTileSpec &spec,
const QByteArray &bytes,
@@ -168,9 +166,6 @@ private:
int minTextureUsage_;
int extraTextureUsage_;
-
- static QMutex cleanupMutex_;
- static QList<QGLTexture2D*> cleanupList_;
};
QT_END_NAMESPACE
diff --git a/src/location/maps/qgeotiledmapdata.cpp b/src/location/maps/qgeotiledmapdata.cpp
index 204414f8..f9a8adc6 100644
--- a/src/location/maps/qgeotiledmapdata.cpp
+++ b/src/location/maps/qgeotiledmapdata.cpp
@@ -55,15 +55,6 @@
#include <qnumeric.h>
-#include <Qt3D/qglscenenode.h>
-#include <Qt3D/qgeometrydata.h>
-#include <Qt3D/qglbuilder.h>
-#include <Qt3D/qglpainter.h>
-#include <Qt3D/qgeometrydata.h>
-#include <Qt3D/qglbuilder.h>
-#include <Qt3D/qglcamera.h>
-#include <Qt3D/qglsubsurface.h>
-
#include <QtPositioning/private/qgeoprojection_p.h>
#include <QtPositioning/private/qdoublevector2d_p.h>
@@ -109,10 +100,10 @@ QGeoTileCache *QGeoTiledMapData::tileCache()
return d->tileCache();
}
-void QGeoTiledMapData::paintGL(QGLPainter *painter)
+QSGNode *QGeoTiledMapData::updateSceneGraph(QSGNode *oldNode, QQuickWindow *window)
{
Q_D(QGeoTiledMapData);
- d->paintGL(painter);
+ return d->updateSceneGraph(oldNode, window);
}
void QGeoTiledMapData::mapResized(int width, int height)
@@ -330,10 +321,9 @@ QSet<QGeoTileSpec> QGeoTiledMapDataPrivate::visibleTiles()
return cameraTiles_->tiles();
}
-void QGeoTiledMapDataPrivate::paintGL(QGLPainter *painter)
+QSGNode *QGeoTiledMapDataPrivate::updateSceneGraph(QSGNode *oldNode, QQuickWindow *window)
{
- mapScene_->paintGL(painter);
- cache_->GLContextAvailable();
+ return mapScene_->updateSceneGraph(oldNode, window);
}
QGeoCoordinate QGeoTiledMapDataPrivate::screenPositionToCoordinate(const QDoubleVector2D &pos) const
diff --git a/src/location/maps/qgeotiledmapdata_p.h b/src/location/maps/qgeotiledmapdata_p.h
index 5a282a8c..9310fded 100644
--- a/src/location/maps/qgeotiledmapdata_p.h
+++ b/src/location/maps/qgeotiledmapdata_p.h
@@ -68,9 +68,11 @@ class QGeoTileTexture;
class QGeoTileCache;
class QGeoTiledMapDataPrivate;
class QGeoTiledMappingManagerEngine;
-class MapItem;
class QGeoTileRequestManager;
+class QQuickWindow;
+class QSGNode;
+
class QPointF;
class Q_LOCATION_EXPORT QGeoTiledMapData : public QGeoMapData
@@ -82,7 +84,7 @@ public:
QGeoTileCache *tileCache();
- void paintGL(QGLPainter *painter);
+ QSGNode *updateSceneGraph(QSGNode *, QQuickWindow *window);
void newTileFetched(const QGeoTileSpec &spec);
diff --git a/src/location/maps/qgeotiledmapdata_p_p.h b/src/location/maps/qgeotiledmapdata_p_p.h
index 446b2872..5f30611b 100644
--- a/src/location/maps/qgeotiledmapdata_p_p.h
+++ b/src/location/maps/qgeotiledmapdata_p_p.h
@@ -81,9 +81,6 @@ class QGeoTileRequestManager;
class QGeoMapScene;
class QGeoTiledMapData;
class QGeoTiledMappingManagerEngine;
-class QGLPainter;
-
-class QGLSceneNode;
class QGeoTiledMapDataPrivate
{
@@ -93,7 +90,7 @@ public:
QGeoTileCache *tileCache();
- void paintGL(QGLPainter *painter);
+ QSGNode *updateSceneGraph(QSGNode *node, QQuickWindow *window);
void changeCameraData(const QGeoCameraData &oldCameraData);
void changeActiveMapType(const QGeoMapType mapType);
diff --git a/src/src.pro b/src/src.pro
index 72274cdc..c00a4b8a 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -9,22 +9,19 @@ positioning_doc_snippets.subdir = positioning/doc/snippets
positioning_doc_snippets.depends = positioning
SUBDIRS += positioning_doc_snippets
-#no point in building QtLocation without Qt3D
-qtHaveModule(3d) {
+qtHaveModule(quick) {
SUBDIRS += 3rdparty
location.depends = positioning 3rdparty
SUBDIRS += location
plugins.depends += location
- qtHaveModule(quick):imports.depends += location
+ imports.depends += location
location_doc_snippets.subdir = location/doc/snippets
location_doc_snippets.depends = location
SUBDIRS += location_doc_snippets
-}
-qtHaveModule(quick) {
imports.depends += positioning
SUBDIRS += imports
}
diff --git a/tests/auto/qgeocameratiles/qgeocameratiles.pro b/tests/auto/qgeocameratiles/qgeocameratiles.pro
index 1c53e627..0abfa9bf 100644
--- a/tests/auto/qgeocameratiles/qgeocameratiles.pro
+++ b/tests/auto/qgeocameratiles/qgeocameratiles.pro
@@ -5,5 +5,5 @@ INCLUDEPATH += ../../../src/location/maps
SOURCES += tst_qgeocameratiles.cpp
-QT += location positioning-private testlib 3d
+QT += location positioning-private testlib
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/qgeomapscene/qgeomapscene.pro b/tests/auto/qgeomapscene/qgeomapscene.pro
index a1bacb05..822f0586 100644
--- a/tests/auto/qgeomapscene/qgeomapscene.pro
+++ b/tests/auto/qgeomapscene/qgeomapscene.pro
@@ -5,5 +5,5 @@ INCLUDEPATH += ../../../src/location/maps
SOURCES += tst_qgeomapscene.cpp
-QT += location positioning-private 3d testlib
+QT += location positioning-private testlib
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/qgeomapscene/tst_qgeomapscene.cpp b/tests/auto/qgeomapscene/tst_qgeomapscene.cpp
index 4303dd0f..6a69c6d1 100644
--- a/tests/auto/qgeomapscene/tst_qgeomapscene.cpp
+++ b/tests/auto/qgeomapscene/tst_qgeomapscene.cpp
@@ -50,9 +50,6 @@
#include <QtPositioning/private/qgeoprojection_p.h>
#include <QtPositioning/private/qdoublevector2d_p.h>
-#include <Qt3D/qglscenenode.h>
-#include <Qt3D/qgltexture2d.h>
-
#include <qtest.h>
#include <QList>
@@ -397,86 +394,6 @@ class tst_QGeoMapScene : public QObject
populateScreenMercatorData();
}
- void cameraMovementAndTileUpdate(){
- QGeoCameraData camera;
- camera.setZoomLevel(4.0);
- camera.setCenter(QGeoProjection::mercatorToCoord(QDoubleVector2D(0.5, 0.5)));
-
- QGeoMapScene mapGeometry;
- mapGeometry.setTileSize(16);
- mapGeometry.setScreenSize(QSize(16,16));
- mapGeometry.setCameraData(camera);
-
- QGeoCameraTiles ct;
- ct.setMaximumZoomLevel(8);
- ct.setTileSize(16);
- ct.setCamera(camera);
- ct.setScreenSize(QSize(16,16));
- mapGeometry.setVisibleTiles(ct.tiles());
-
- int sideLength = 1 << static_cast<int>(floor(camera.zoomLevel()));
- double quaterTile = 1.0 / (sideLength * 4.0);
-
- // test that there are no scene nodes initially
- QGLSceneNode* node = mapGeometry.sceneNode();
- QCOMPARE(node->children().count(), 0);
-
- // the camera is currently centered on top-left corner of the middle tile
- // (so 4 tiles should be visible and added to map geometry)
- QSharedPointer<QGeoTileTexture> tt(new QGeoTileTexture);
- tt->texture = new QGLTexture2D();
- foreach (QGeoTileSpec spec, ct.tiles())
- mapGeometry.addTile(spec, tt); // add tiles with empty texture
- QGLSceneNode* node2 = mapGeometry.sceneNode();
- QCOMPARE(node2->children().count(), ct.tiles().count());
- QCOMPARE(node2->children().count(), 4);
-
- // move camera slightly in x direction but within the same tile bounds
- // and verify that no new tiles are added through addTile
- camera.setCenter(QGeoProjection::mercatorToCoord(QDoubleVector2D(0.5 + quaterTile, 0.5)));
- mapGeometry.setCameraData(camera);
- ct.setCamera(camera);
- mapGeometry.setVisibleTiles(ct.tiles());
- foreach (QGeoTileSpec spec, ct.tiles())
- mapGeometry.addTile(spec, tt);
- QGLSceneNode* node3 = mapGeometry.sceneNode();
- // test to see that there are still only 4 tiles in the map geometry
- QCOMPARE(node3->children().count(), ct.tiles().count());
- QCOMPARE(node3->children().count(), 4);
-
- // move camera further in x to align with edges of middle tile so that 6 tiles are fetched
- camera.setCenter(QGeoProjection::mercatorToCoord(QDoubleVector2D(0.5 + quaterTile*2, 0.5)));
- mapGeometry.setCameraData(camera);
- ct.setCamera(camera);
- mapGeometry.setVisibleTiles(ct.tiles());
- foreach (QGeoTileSpec spec, ct.tiles())
- mapGeometry.addTile(spec, tt);
- QGLSceneNode* node4 = mapGeometry.sceneNode();
- QCOMPARE(node4->children().count(), ct.tiles().count());
- QCOMPARE(node4->children().count(), 6);
-
- // move camera further in x so that the 2 tiles on the left are now removed
- camera.setCenter(QGeoProjection::mercatorToCoord(QDoubleVector2D(0.5 + quaterTile*4, 0.5)));
- mapGeometry.setCameraData(camera);
- ct.setCamera(camera);
- mapGeometry.setVisibleTiles(ct.tiles());
- foreach (QGeoTileSpec spec, ct.tiles())
- mapGeometry.addTile(spec, tt);
- QGLSceneNode* node5 = mapGeometry.sceneNode();
- QCOMPARE(node5->children().count(), ct.tiles().count());
- QCOMPARE(node5->children().count(), 4);
-
- // test adding tiles with wrapping and clipping
- camera.setCenter(QGeoProjection::mercatorToCoord(QDoubleVector2D(0.0, 0.0)));
- mapGeometry.setCameraData(camera);
- ct.setCamera(camera);
- mapGeometry.setVisibleTiles(ct.tiles());
- foreach (QGeoTileSpec spec, ct.tiles())
- mapGeometry.addTile(spec, tt);
- QGLSceneNode* node6 = mapGeometry.sceneNode();
- QCOMPARE(node6->children().count(), ct.tiles().count());
- QCOMPARE(node6->children().count(), 2);
- }
};
QTEST_GUILESS_MAIN(tst_QGeoMapScene)