summaryrefslogtreecommitdiff
path: root/platform/qt/src/qmapboxgl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'platform/qt/src/qmapboxgl.cpp')
-rw-r--r--platform/qt/src/qmapboxgl.cpp177
1 files changed, 131 insertions, 46 deletions
diff --git a/platform/qt/src/qmapboxgl.cpp b/platform/qt/src/qmapboxgl.cpp
index f094e2a0ec..2675d87862 100644
--- a/platform/qt/src/qmapboxgl.cpp
+++ b/platform/qt/src/qmapboxgl.cpp
@@ -1,5 +1,6 @@
#include "qmapboxgl.hpp"
#include "qmapboxgl_p.hpp"
+#include "qmapboxgl_renderer_frontend_p.hpp"
#include "qt_conversion.hpp"
#include "qt_geojson.hpp"
@@ -7,16 +8,28 @@
#include <mbgl/annotation/annotation.hpp>
#include <mbgl/map/camera.hpp>
#include <mbgl/map/map.hpp>
-#include <mbgl/map/backend_scope.hpp>
+#include <mbgl/math/log2.hpp>
#include <mbgl/math/minmax.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/layer.hpp>
#include <mbgl/style/conversion/source.hpp>
+#include <mbgl/style/conversion/filter.hpp>
+#include <mbgl/style/conversion/geojson.hpp>
+#include <mbgl/style/filter.hpp>
#include <mbgl/style/layers/custom_layer.hpp>
+#include <mbgl/style/layers/background_layer.hpp>
+#include <mbgl/style/layers/circle_layer.hpp>
+#include <mbgl/style/layers/fill_layer.hpp>
+#include <mbgl/style/layers/fill_extrusion_layer.hpp>
+#include <mbgl/style/layers/line_layer.hpp>
+#include <mbgl/style/layers/raster_layer.hpp>
+#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/sources/geojson_source.hpp>
#include <mbgl/style/transition_options.hpp>
#include <mbgl/style/image.hpp>
+#include <mbgl/renderer/renderer.hpp>
+#include <mbgl/renderer/backend_scope.hpp>
#include <mbgl/storage/network_status.hpp>
#include <mbgl/util/color.hpp>
#include <mbgl/util/constants.hpp>
@@ -26,6 +39,7 @@
#include <mbgl/util/run_loop.hpp>
#include <mbgl/util/shared_thread_pool.hpp>
#include <mbgl/util/traits.hpp>
+#include <mbgl/actor/scheduler.hpp>
#if QT_VERSION >= 0x050000
#include <QGuiApplication>
@@ -70,6 +84,19 @@ namespace {
QThreadStorage<std::shared_ptr<mbgl::util::RunLoop>> loop;
+std::shared_ptr<mbgl::DefaultFileSource> sharedDefaultFileSource(
+ const std::string& cachePath, const std::string& assetRoot, uint64_t maximumCacheSize) {
+ static std::weak_ptr<mbgl::DefaultFileSource> weak;
+ auto fs = weak.lock();
+
+ if (!fs) {
+ weak = fs = std::make_shared<mbgl::DefaultFileSource>(
+ cachePath, assetRoot, maximumCacheSize);
+ }
+
+ return fs;
+}
+
// Conversion helper functions.
mbgl::Size sanitizedSize(const QSize& size) {
@@ -84,8 +111,13 @@ std::unique_ptr<mbgl::style::Image> toStyleImage(const QString &id, const QImage
.rgbSwapped()
.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+#if QT_VERSION >= 0x051000
+ auto img = std::make_unique<uint8_t[]>(swapped.sizeInBytes());
+ memcpy(img.get(), swapped.constBits(), swapped.sizeInBytes());
+#else
auto img = std::make_unique<uint8_t[]>(swapped.byteCount());
memcpy(img.get(), swapped.constBits(), swapped.byteCount());
+#endif
return std::make_unique<mbgl::style::Image>(
id.toStdString(),
@@ -106,6 +138,11 @@ std::unique_ptr<mbgl::style::Image> toStyleImage(const QString &id, const QImage
QMapboxGLSettings is used to configure QMapboxGL at the moment of its creation.
Once created, the QMapboxGLSettings of a QMapboxGL can no longer be changed.
+ Cache-related settings are shared between all QMapboxGL instances because different
+ maps will share the same cache database file. The first map to configure cache properties
+ such as size and path will force the configuration to all newly instantiated QMapboxGL
+ objects.
+
\since 4.7
*/
@@ -118,9 +155,11 @@ std::unique_ptr<mbgl::style::Image> toStyleImage(const QString &id, const QImage
reset before each rendering. Use this mode if the intention is to only draw a
fullscreen map.
- \value SharedGLContext The OpenGL context is shared and the state will be restored
- before rendering. This mode is safer when OpenGL calls are performed prior of after
- we call QMapboxGL::render for rendering a map.
+ \value SharedGLContext The OpenGL context is shared and the state will be
+ marked dirty - which invalidates any previously assumed GL state. The
+ embedder is responsible for clearing up the viewport prior to calling
+ QMapboxGL::render. The embedder is also responsible for resetting its own
+ GL state after QMapboxGL::render has finished, if needed.
\sa contextMode()
*/
@@ -341,6 +380,27 @@ void QMapboxGLSettings::setApiBaseUrl(const QString& url)
}
/*!
+ Returns resource transformation callback used to transform requested URLs.
+*/
+std::function<std::string(const std::string &&)> QMapboxGLSettings::resourceTransform() const
+{
+ return m_resourceTransform;
+}
+
+/*!
+ Sets the resource \a transform callback.
+
+ When given, resource transformation callback will be used to transform the
+ requested resource URLs before they are requested from internet. This can be
+ used add or remove custom parameters, or reroute certain requests to other
+ servers or endpoints.
+*/
+void QMapboxGLSettings::setResourceTransform(const std::function<std::string(const std::string &&)> &transform)
+{
+ m_resourceTransform = transform;
+}
+
+/*!
\class QMapboxGL
\brief The QMapboxGL class is a Qt wrapper for the Mapbox GL Native engine.
@@ -426,13 +486,13 @@ void QMapboxGLSettings::setApiBaseUrl(const QString& url)
*/
/*!
- Constructs a QMapboxGL object with \a settings and sets \a parent as the parent
+ Constructs a QMapboxGL object with \a settings and sets \a parent_ as the parent
object. The \a settings cannot be changed after the object is constructed. The
\a size represents the size of the viewport and the \a pixelRatio the initial pixel
density of the screen.
*/
-QMapboxGL::QMapboxGL(QObject *parent, const QMapboxGLSettings &settings, const QSize& size, qreal pixelRatio)
- : QObject(parent)
+QMapboxGL::QMapboxGL(QObject *parent_, const QMapboxGLSettings &settings, const QSize& size, qreal pixelRatio)
+ : QObject(parent_)
{
assert(!size.isEmpty());
@@ -563,7 +623,7 @@ double QMapboxGL::scale() const
void QMapboxGL::setScale(double scale_, const QPointF &center)
{
- d_ptr->mapObj->setZoom(std::log2(scale_), mbgl::ScreenCoordinate { center.x(), center.y() });
+ d_ptr->mapObj->setZoom(mbgl::util::log2(scale_), mbgl::ScreenCoordinate { center.x(), center.y() });
}
/*!
@@ -755,21 +815,21 @@ void QMapboxGL::setTransitionOptions(qint64 duration, qint64 delay) {
d_ptr->mapObj->getStyle().setTransitionOptions(mbgl::style::TransitionOptions{ convert(duration), convert(delay) });
}
-mbgl::Annotation asMapboxGLAnnotation(const QMapbox::Annotation & annotation) {
+mbgl::optional<mbgl::Annotation> asMapboxGLAnnotation(const QMapbox::Annotation & annotation) {
auto asMapboxGLGeometry = [](const QMapbox::ShapeAnnotationGeometry &geometry) {
mbgl::ShapeAnnotationGeometry result;
switch (geometry.type) {
case QMapbox::ShapeAnnotationGeometry::LineStringType:
- result = { asMapboxGLLineString(geometry.geometry.first().first()) };
+ result = asMapboxGLLineString(geometry.geometry.first().first());
break;
case QMapbox::ShapeAnnotationGeometry::PolygonType:
- result = { asMapboxGLPolygon(geometry.geometry.first()) };
+ result = asMapboxGLPolygon(geometry.geometry.first());
break;
case QMapbox::ShapeAnnotationGeometry::MultiLineStringType:
- result = { asMapboxGLMultiLineString(geometry.geometry.first()) };
+ result = asMapboxGLMultiLineString(geometry.geometry.first());
break;
case QMapbox::ShapeAnnotationGeometry::MultiPolygonType:
- result = { asMapboxGLMultiPolygon(geometry.geometry) };
+ result = asMapboxGLMultiPolygon(geometry.geometry);
break;
}
return result;
@@ -778,19 +838,19 @@ mbgl::Annotation asMapboxGLAnnotation(const QMapbox::Annotation & annotation) {
if (annotation.canConvert<QMapbox::SymbolAnnotation>()) {
QMapbox::SymbolAnnotation symbolAnnotation = annotation.value<QMapbox::SymbolAnnotation>();
QMapbox::Coordinate& pair = symbolAnnotation.geometry;
- return mbgl::SymbolAnnotation { mbgl::Point<double> { pair.second, pair.first }, symbolAnnotation.icon.toStdString() };
+ return { mbgl::SymbolAnnotation(mbgl::Point<double> { pair.second, pair.first }, symbolAnnotation.icon.toStdString()) };
} else if (annotation.canConvert<QMapbox::LineAnnotation>()) {
QMapbox::LineAnnotation lineAnnotation = annotation.value<QMapbox::LineAnnotation>();
auto color = mbgl::Color::parse(lineAnnotation.color.name().toStdString());
- return mbgl::LineAnnotation { asMapboxGLGeometry(lineAnnotation.geometry), lineAnnotation.opacity, lineAnnotation.width, { *color } };
+ return { mbgl::LineAnnotation(asMapboxGLGeometry(lineAnnotation.geometry), lineAnnotation.opacity, lineAnnotation.width, { *color }) };
} else if (annotation.canConvert<QMapbox::FillAnnotation>()) {
QMapbox::FillAnnotation fillAnnotation = annotation.value<QMapbox::FillAnnotation>();
auto color = mbgl::Color::parse(fillAnnotation.color.name().toStdString());
if (fillAnnotation.outlineColor.canConvert<QColor>()) {
auto outlineColor = mbgl::Color::parse(fillAnnotation.outlineColor.value<QColor>().name().toStdString());
- return mbgl::FillAnnotation { asMapboxGLGeometry(fillAnnotation.geometry), fillAnnotation.opacity, { *color }, { *outlineColor } };
+ return { mbgl::FillAnnotation(asMapboxGLGeometry(fillAnnotation.geometry), fillAnnotation.opacity, { *color }, { *outlineColor }) };
} else {
- return mbgl::FillAnnotation { asMapboxGLGeometry(fillAnnotation.geometry), fillAnnotation.opacity, { *color }, {} };
+ return { mbgl::FillAnnotation(asMapboxGLGeometry(fillAnnotation.geometry), fillAnnotation.opacity, { *color }, {}) };
}
}
@@ -807,7 +867,7 @@ mbgl::Annotation asMapboxGLAnnotation(const QMapbox::Annotation & annotation) {
*/
QMapbox::AnnotationID QMapboxGL::addAnnotation(const QMapbox::Annotation &annotation)
{
- return d_ptr->mapObj->addAnnotation(asMapboxGLAnnotation(annotation));
+ return d_ptr->mapObj->addAnnotation(*asMapboxGLAnnotation(annotation));
}
/*!
@@ -817,7 +877,7 @@ QMapbox::AnnotationID QMapboxGL::addAnnotation(const QMapbox::Annotation &annota
*/
void QMapboxGL::updateAnnotation(QMapbox::AnnotationID id, const QMapbox::Annotation &annotation)
{
- d_ptr->mapObj->updateAnnotation(id, asMapboxGLAnnotation(annotation));
+ d_ptr->mapObj->updateAnnotation(id, *asMapboxGLAnnotation(annotation));
}
/*!
@@ -829,7 +889,7 @@ void QMapboxGL::removeAnnotation(QMapbox::AnnotationID id)
}
/*!
- Sets a layout \a property \a value to an existing \a layer. The \a property string can be any
+ Sets a layout \a property_ \a value to an existing \a layer. The \a property_ string can be any
as defined by the \l {https://www.mapbox.com/mapbox-gl-style-spec/} {Mapbox style specification}
for layout properties.
@@ -863,7 +923,7 @@ void QMapboxGL::removeAnnotation(QMapbox::AnnotationID id)
\li QVariantList
\endtable
*/
-void QMapboxGL::setLayoutProperty(const QString& layer, const QString& property, const QVariant& value)
+void QMapboxGL::setLayoutProperty(const QString& layer, const QString& property_, const QVariant& value)
{
using namespace mbgl::style;
@@ -873,14 +933,14 @@ void QMapboxGL::setLayoutProperty(const QString& layer, const QString& property,
return;
}
- if (conversion::setLayoutProperty(*layer_, property.toStdString(), value)) {
- qWarning() << "Error setting layout property:" << layer << "-" << property;
+ if (conversion::setLayoutProperty(*layer_, property_.toStdString(), value)) {
+ qWarning() << "Error setting layout property:" << layer << "-" << property_;
return;
}
}
/*!
- Sets a paint \a property \a value to an existing \a layer. The \a property string can be any
+ Sets a paint \a property_ \a value to an existing \a layer. The \a property_ string can be any
as defined by the \l {https://www.mapbox.com/mapbox-gl-style-spec/} {Mapbox style specification}
for paint properties.
@@ -929,7 +989,7 @@ void QMapboxGL::setLayoutProperty(const QString& layer, const QString& property,
map->setPaintProperty("route","line-dasharray", lineDashArray);
\endcode
*/
-void QMapboxGL::setPaintProperty(const QString& layer, const QString& property, const QVariant& value)
+void QMapboxGL::setPaintProperty(const QString& layer, const QString& property_, const QVariant& value)
{
using namespace mbgl::style;
@@ -939,8 +999,8 @@ void QMapboxGL::setPaintProperty(const QString& layer, const QString& property,
return;
}
- if (conversion::setPaintProperty(*layer_, property.toStdString(), value)) {
- qWarning() << "Error setting paint property:" << layer << "-" << property;
+ if (conversion::setPaintProperty(*layer_, property_.toStdString(), value)) {
+ qWarning() << "Error setting paint property:" << layer << "-" << property_;
return;
}
}
@@ -971,7 +1031,7 @@ void QMapboxGL::moveBy(const QPointF &offset)
can be used for implementing a pinch gesture.
*/
void QMapboxGL::scaleBy(double scale_, const QPointF &center) {
- d_ptr->mapObj->setZoom(d_ptr->mapObj->getZoom() + std::log2(scale_), mbgl::ScreenCoordinate { center.x(), center.y() });
+ d_ptr->mapObj->setZoom(d_ptr->mapObj->getZoom() + mbgl::util::log2(scale_), mbgl::ScreenCoordinate { center.x(), center.y() });
}
/*!
@@ -1009,7 +1069,7 @@ void QMapboxGL::resize(const QSize& size, const QSize& framebufferSize)
}
/*!
- If Mapbox GL needs to rebind the default framebuffer, it will use the
+ If Mapbox GL needs to rebind the default \a fbo, it will use the
ID supplied here.
*/
void QMapboxGL::setFramebufferObject(quint32 fbo) {
@@ -1033,11 +1093,11 @@ void QMapboxGL::addAnnotationIcon(const QString &name, const QImage &icon)
}
/*!
- Returns the amount of meters per pixel from a given \a latitude and \a zoom.
+ Returns the amount of meters per pixel from a given \a latitude_ and \a zoom_.
*/
-double QMapboxGL::metersPerPixelAtLatitude(double latitude, double zoom) const
+double QMapboxGL::metersPerPixelAtLatitude(double latitude_, double zoom_) const
{
- return mbgl::Projection::getMetersPerPixelAtLatitude(latitude, zoom);
+ return mbgl::Projection::getMetersPerPixelAtLatitude(latitude_, zoom_);
}
/*!
@@ -1408,10 +1468,10 @@ void QMapboxGL::setFilter(const QString& layer, const QVariant& filter)
}
/*!
- Renders the map using OpenGL draw calls. If \a fbo is passed, it will
- make sure to bind the framebuffer object before drawing; otherwise a
- valid OpenGL context is expected with an appropriate OpenGL viewport state set
- for the size of the canvas.
+ Renders the map using OpenGL draw calls. It will make sure to bind the
+ framebuffer object before drawing; otherwise a valid OpenGL context is
+ expected with an appropriate OpenGL viewport state set for the size of
+ the canvas.
This function should be called only after the signal needsRendering() is
emitted at least once.
@@ -1426,11 +1486,8 @@ void QMapboxGL::render()
}
#endif
- // The OpenGL implementation automatically enables the OpenGL context for us.
- mbgl::BackendScope scope { *d_ptr, mbgl::BackendScope::ScopeType::Implicit };
-
d_ptr->dirty = false;
- d_ptr->mapObj->render(*d_ptr);
+ d_ptr->render();
}
/*!
@@ -1469,21 +1526,42 @@ void QMapboxGL::connectionEstablished()
\a copyrightsHtml is a string with a HTML snippet.
*/
+class QMapboxGLRendererFrontend;
+
QMapboxGLPrivate::QMapboxGLPrivate(QMapboxGL *q, const QMapboxGLSettings &settings, const QSize &size_, qreal pixelRatio)
: QObject(q)
, size(size_)
, q_ptr(q)
- , fileSourceObj(std::make_unique<mbgl::DefaultFileSource>(
+ , fileSourceObj(sharedDefaultFileSource(
settings.cacheDatabasePath().toStdString(),
settings.assetPath().toStdString(),
settings.cacheDatabaseMaximumSize()))
, threadPool(mbgl::sharedThreadPool())
{
+ // Setup resource transform if needed
+ if (settings.resourceTransform()) {
+ m_resourceTransform =
+ std::make_unique< mbgl::Actor<mbgl::ResourceTransform> >( *mbgl::Scheduler::GetCurrent(),
+ [callback = settings.resourceTransform()]
+ (mbgl::Resource::Kind , const std::string&& url_) -> std::string {
+ return callback(std::move(url_));
+ }
+ );
+ fileSourceObj->setResourceTransform(m_resourceTransform->self());
+ }
+
+ // Setup and connect the renderer frontend
+ frontend = std::make_unique<QMapboxGLRendererFrontend>(
+ std::make_unique<mbgl::Renderer>(*this, pixelRatio, *fileSourceObj, *threadPool,
+ static_cast<mbgl::GLContextMode>(settings.contextMode())),
+ *this);
+ connect(frontend.get(), SIGNAL(updated()), this, SLOT(invalidate()));
+
mapObj = std::make_unique<mbgl::Map>(
+ *frontend,
*this, sanitizedSize(size),
pixelRatio, *fileSourceObj, *threadPool,
mbgl::MapMode::Continuous,
- static_cast<mbgl::GLContextMode>(settings.contextMode()),
static_cast<mbgl::ConstrainMode>(settings.constrainMode()),
static_cast<mbgl::ViewportMode>(settings.viewportMode()));
@@ -1501,18 +1579,20 @@ QMapboxGLPrivate::~QMapboxGLPrivate()
{
}
-mbgl::Size QMapboxGLPrivate::framebufferSize() const {
+mbgl::Size QMapboxGLPrivate::getFramebufferSize() const {
return sanitizedSize(fbSize);
}
void QMapboxGLPrivate::updateAssumedState() {
assumeFramebufferBinding(fbObject);
- assumeViewport(0, 0, framebufferSize());
+#if QT_VERSION >= 0x050600
+ assumeViewport(0, 0, getFramebufferSize());
+#endif
}
void QMapboxGLPrivate::bind() {
setFramebufferBinding(fbObject);
- setViewport(0, 0, framebufferSize());
+ setViewport(0, 0, getFramebufferSize());
}
void QMapboxGLPrivate::invalidate()
@@ -1523,6 +1603,11 @@ void QMapboxGLPrivate::invalidate()
}
}
+void QMapboxGLPrivate::render()
+{
+ frontend->render();
+}
+
void QMapboxGLPrivate::onCameraWillChange(mbgl::MapObserver::CameraChangeMode mode)
{
if (mode == mbgl::MapObserver::CameraChangeMode::Immediate) {
@@ -1610,7 +1695,7 @@ void QMapboxGLPrivate::onSourceChanged(mbgl::style::Source&)
Initializes an OpenGL extension function such as Vertex Array Objects (VAOs),
required by Mapbox GL Native engine.
*/
-mbgl::gl::ProcAddress QMapboxGLPrivate::initializeExtension(const char* name) {
+mbgl::gl::ProcAddress QMapboxGLPrivate::getExtensionFunctionPointer(const char* name) {
#if QT_VERSION >= 0x050000
QOpenGLContext* thisContext = QOpenGLContext::currentContext();
return thisContext->getProcAddress(name);