diff options
Diffstat (limited to 'src/location')
-rw-r--r-- | src/location/maps/maps.pri | 2 | ||||
-rw-r--r-- | src/location/maps/qgeomap.cpp | 18 | ||||
-rw-r--r-- | src/location/maps/qgeomap_p.h | 9 | ||||
-rw-r--r-- | src/location/maps/qgeomapdata.cpp | 22 | ||||
-rw-r--r-- | src/location/maps/qgeomapdata_p.h | 8 | ||||
-rw-r--r-- | src/location/maps/qgeomapdata_p_p.h | 6 | ||||
-rw-r--r-- | src/location/maps/qgeomapscene.cpp | 445 | ||||
-rw-r--r-- | src/location/maps/qgeomapscene_p.h | 11 | ||||
-rw-r--r-- | src/location/maps/qgeotilecache.cpp | 43 | ||||
-rw-r--r-- | src/location/maps/qgeotilecache_p.h | 11 | ||||
-rw-r--r-- | src/location/maps/qgeotiledmapdata.cpp | 18 | ||||
-rw-r--r-- | src/location/maps/qgeotiledmapdata_p.h | 6 | ||||
-rw-r--r-- | src/location/maps/qgeotiledmapdata_p_p.h | 5 |
13 files changed, 232 insertions, 372 deletions
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..568bcb57 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 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)); + 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(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)); - - 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,209 @@ 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; +}; + +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); } - glEnable(GL_SCISSOR_TEST); + ~QGeoMapRootNode() + { + qDeleteAll(textures.values()); + } - painter->setScissor(QRect(screenOffsetX_, screenOffsetY_, screenWidth_, screenHeight_)); + void setClipRect(const QRect &rect) + { + if (rect != clipRect) { + QSGGeometry::updateRectGeometry(&geometry, rect); + QSGClipNode::setClipRect(rect); + clipRect = rect; + markDirty(DirtyGeometry); + } + } - painter->setCamera(camera_); + void updateTiles(QGeoMapTileContainerNode *root, QGeoMapScenePrivate *d, double camAdjust); - painter->setMainLight(light_); + bool isTextureLinear; - sceneNode_->draw(painter); + QSGGeometry geometry; + QRect clipRect; - QGLCamera *camera = camera_; + QSGTransformNode *root; - bool old = camera->blockSignals(true); + 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 - glDisable(GL_DEPTH_TEST); + QHash<QGeoTileSpec, QSGTexture *> textures; +}; - double sideLength = scaleFactor_ * tileSize_ * sideLength_; +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 c = QDoubleVector3D(camera->center()); - c.setX(c.x() + sideLength); - camera->setCenter(c); +static QVector3D toVector3D(const QDoubleVector3D& in) +{ + return QVector3D(in.x(), in.y(), in.z()); +} - 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(toVector3D(eye), toVector3D(center), toVector3D(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); |