diff options
author | Thiago Marcos P. Santos <tmpsantos@gmail.com> | 2018-02-24 18:52:57 +0200 |
---|---|---|
committer | Thiago Marcos P. Santos <tmpsantos@gmail.com> | 2018-02-24 21:15:48 +0200 |
commit | 13d7f66c71eb94d0dbf6604da352605ed0f547da (patch) | |
tree | 5ebf27c566d433fdf785856cfc6811fb6f8c87c4 /platform/qt | |
parent | 8c1be4ec01ef46bf453856531ebf53b48ce3dbe7 (diff) | |
download | qtlocation-mapboxgl-13d7f66c71eb94d0dbf6604da352605ed0f547da.tar.gz |
Bump Mapbox GL Native
mapbox-gl-native @ 5de373fff0e71496b6aa11ecb6556f958a28d80b
Diffstat (limited to 'platform/qt')
-rw-r--r-- | platform/qt/include/QQuickMapboxGL | 1 | ||||
-rw-r--r-- | platform/qt/include/QQuickMapboxGLMapParameter | 1 | ||||
-rw-r--r-- | platform/qt/include/qmapbox.hpp | 24 | ||||
-rw-r--r-- | platform/qt/include/qmapboxgl.hpp | 30 | ||||
-rw-r--r-- | platform/qt/src/qmapbox.cpp | 6 | ||||
-rw-r--r-- | platform/qt/src/qmapboxgl.cpp | 379 | ||||
-rw-r--r-- | platform/qt/src/qmapboxgl_map_observer.cpp | 95 | ||||
-rw-r--r-- | platform/qt/src/qmapboxgl_map_observer.hpp | 45 | ||||
-rw-r--r-- | platform/qt/src/qmapboxgl_map_renderer.cpp | 86 | ||||
-rw-r--r-- | platform/qt/src/qmapboxgl_map_renderer.hpp | 63 | ||||
-rw-r--r-- | platform/qt/src/qmapboxgl_p.hpp | 77 | ||||
-rw-r--r-- | platform/qt/src/qmapboxgl_renderer_backend.cpp | 49 | ||||
-rw-r--r-- | platform/qt/src/qmapboxgl_renderer_backend.hpp | 34 | ||||
-rw-r--r-- | platform/qt/src/qmapboxgl_renderer_frontend_p.cpp | 37 | ||||
-rw-r--r-- | platform/qt/src/qmapboxgl_renderer_frontend_p.hpp | 35 | ||||
-rw-r--r-- | platform/qt/src/qmapboxgl_renderer_observer.hpp | 51 | ||||
-rw-r--r--[-rwxr-xr-x] | platform/qt/src/qt_logging.cpp | 0 | ||||
-rw-r--r-- | platform/qt/src/run_loop.cpp | 7 | ||||
-rw-r--r-- | platform/qt/src/sqlite3.cpp | 4 |
19 files changed, 716 insertions, 308 deletions
diff --git a/platform/qt/include/QQuickMapboxGL b/platform/qt/include/QQuickMapboxGL deleted file mode 100644 index db109a1d3a..0000000000 --- a/platform/qt/include/QQuickMapboxGL +++ /dev/null @@ -1 +0,0 @@ -#include "qquickmapboxgl.hpp" diff --git a/platform/qt/include/QQuickMapboxGLMapParameter b/platform/qt/include/QQuickMapboxGLMapParameter deleted file mode 100644 index 603fb2bd51..0000000000 --- a/platform/qt/include/QQuickMapboxGLMapParameter +++ /dev/null @@ -1 +0,0 @@ -#include "qquickmapboxglmapparameter.hpp" diff --git a/platform/qt/include/qmapbox.hpp b/platform/qt/include/qmapbox.hpp index 2bb5d8705c..5a5198108c 100644 --- a/platform/qt/include/qmapbox.hpp +++ b/platform/qt/include/qmapbox.hpp @@ -9,6 +9,12 @@ // This header follows the Qt coding style: https://wiki.qt.io/Qt_Coding_Style +#if defined(QT_BUILD_MAPBOXGL_LIB) + #define Q_MAPBOXGL_EXPORT Q_DECL_EXPORT +#else + #define Q_MAPBOXGL_EXPORT Q_DECL_IMPORT +#endif + namespace QMapbox { typedef QPair<double, double> Coordinate; @@ -20,7 +26,7 @@ typedef QList<Coordinates> CoordinatesCollection; typedef QList<CoordinatesCollection> CoordinatesCollections; -struct Q_DECL_EXPORT Feature { +struct Q_MAPBOXGL_EXPORT Feature { enum Type { PointType = 1, LineStringType, @@ -38,7 +44,7 @@ struct Q_DECL_EXPORT Feature { QVariant id; }; -struct Q_DECL_EXPORT ShapeAnnotationGeometry { +struct Q_MAPBOXGL_EXPORT ShapeAnnotationGeometry { enum Type { LineStringType = 1, PolygonType, @@ -54,12 +60,12 @@ struct Q_DECL_EXPORT ShapeAnnotationGeometry { CoordinatesCollections geometry; }; -struct Q_DECL_EXPORT SymbolAnnotation { +struct Q_MAPBOXGL_EXPORT SymbolAnnotation { Coordinate geometry; QString icon; }; -struct Q_DECL_EXPORT LineAnnotation { +struct Q_MAPBOXGL_EXPORT LineAnnotation { /*! Class constructor. */ LineAnnotation(const ShapeAnnotationGeometry& geometry_ = ShapeAnnotationGeometry(), float opacity_ = 1.0f, float width_ = 1.0f, const QColor& color_ = Qt::black) @@ -71,7 +77,7 @@ struct Q_DECL_EXPORT LineAnnotation { QColor color; }; -struct Q_DECL_EXPORT FillAnnotation { +struct Q_MAPBOXGL_EXPORT FillAnnotation { /*! Class constructor. */ FillAnnotation(const ShapeAnnotationGeometry& geometry_ = ShapeAnnotationGeometry(), float opacity_ = 1.0f, const QColor& color_ = Qt::black, const QVariant& outlineColor_ = QVariant()) @@ -92,13 +98,13 @@ enum NetworkMode { Offline, }; -Q_DECL_EXPORT QList<QPair<QString, QString> >& defaultStyles(); +Q_MAPBOXGL_EXPORT QList<QPair<QString, QString> >& defaultStyles(); -Q_DECL_EXPORT NetworkMode networkMode(); -Q_DECL_EXPORT void setNetworkMode(NetworkMode); +Q_MAPBOXGL_EXPORT NetworkMode networkMode(); +Q_MAPBOXGL_EXPORT void setNetworkMode(NetworkMode); // This struct is a 1:1 copy of mbgl::CustomLayerRenderParameters. -struct Q_DECL_EXPORT CustomLayerRenderParameters { +struct Q_MAPBOXGL_EXPORT CustomLayerRenderParameters { double width; double height; double latitude; diff --git a/platform/qt/include/qmapboxgl.hpp b/platform/qt/include/qmapboxgl.hpp index ebbd949921..bc18eaba59 100644 --- a/platform/qt/include/qmapboxgl.hpp +++ b/platform/qt/include/qmapboxgl.hpp @@ -16,7 +16,7 @@ class QMapboxGLPrivate; // This header follows the Qt coding style: https://wiki.qt.io/Qt_Coding_Style -class Q_DECL_EXPORT QMapboxGLSettings +class Q_MAPBOXGL_EXPORT QMapboxGLSettings { public: QMapboxGLSettings(); @@ -26,6 +26,11 @@ public: SharedGLContext }; + enum MapMode { + Continuous = 0, + Static + }; + enum ConstrainMode { NoConstrain = 0, ConstrainHeightOnly, @@ -40,6 +45,9 @@ public: GLContextMode contextMode() const; void setContextMode(GLContextMode); + MapMode mapMode() const; + void setMapMode(MapMode); + ConstrainMode constrainMode() const; void setConstrainMode(ConstrainMode); @@ -66,6 +74,7 @@ public: private: GLContextMode m_contextMode; + MapMode m_mapMode; ConstrainMode m_constrainMode; ViewportMode m_viewportMode; @@ -77,7 +86,7 @@ private: std::function<std::string(const std::string &&)> m_resourceTransform; }; -struct Q_DECL_EXPORT QMapboxGLCameraOptions { +struct Q_MAPBOXGL_EXPORT QMapboxGLCameraOptions { QVariant center; // Coordinate QVariant anchor; // QPointF QVariant zoom; // double @@ -85,7 +94,7 @@ struct Q_DECL_EXPORT QMapboxGLCameraOptions { QVariant pitch; // double }; -class Q_DECL_EXPORT QMapboxGL : public QObject +class Q_MAPBOXGL_EXPORT QMapboxGL : public QObject { Q_OBJECT Q_PROPERTY(double latitude READ latitude WRITE setLatitude) @@ -191,8 +200,7 @@ public: void scaleBy(double scale, const QPointF ¢er = QPointF()); void rotateBy(const QPointF &first, const QPointF &second); - void resize(const QSize &size, const QSize &framebufferSize); - void setFramebufferObject(quint32 fbo); + void resize(const QSize &size); double metersPerPixelAtLatitude(double latitude, double zoom) const; QMapbox::ProjectedMeters projectedMetersForCoordinate(const QMapbox::Coordinate &) const; @@ -226,15 +234,27 @@ public: void setFilter(const QString &layer, const QVariant &filter); + // When rendering on a different thread, + // should be called on the render thread. + void createRenderer(); + void destroyRenderer(); + void setFramebufferObject(quint32 fbo, const QSize &size); + public slots: void render(); void connectionEstablished(); + // Commit changes, load all the resources + // and renders the map when completed. + void startStaticRender(); + signals: void needsRendering(); void mapChanged(QMapboxGL::MapChange); void copyrightsChanged(const QString ©rightsHtml); + void staticRenderFinished(const QString &error); + private: Q_DISABLE_COPY(QMapboxGL) diff --git a/platform/qt/src/qmapbox.cpp b/platform/qt/src/qmapbox.cpp index aad32a35dc..ec76ebfe53 100644 --- a/platform/qt/src/qmapbox.cpp +++ b/platform/qt/src/qmapbox.cpp @@ -206,7 +206,7 @@ namespace QMapbox { Returns the current QMapbox::NetworkMode. */ -Q_DECL_EXPORT NetworkMode networkMode() +NetworkMode networkMode() { return static_cast<NetworkMode>(mbgl::NetworkStatus::Get()); } @@ -219,7 +219,7 @@ Q_DECL_EXPORT NetworkMode networkMode() File source requests uses the available network when \a mode is set to \b Online, otherwise scoped to the local cache. */ -Q_DECL_EXPORT void setNetworkMode(NetworkMode mode) +void setNetworkMode(NetworkMode mode) { mbgl::NetworkStatus::Set(static_cast<mbgl::NetworkStatus::Status>(mode)); } @@ -230,7 +230,7 @@ Q_DECL_EXPORT void setNetworkMode(NetworkMode mode) Returns a list containing a pair of string objects, representing the style URL and name, respectively. */ -Q_DECL_EXPORT QList<QPair<QString, QString> >& defaultStyles() +QList<QPair<QString, QString> >& defaultStyles() { static QList<QPair<QString, QString>> styles; diff --git a/platform/qt/src/qmapboxgl.cpp b/platform/qt/src/qmapboxgl.cpp index 2675d87862..414b65255c 100644 --- a/platform/qt/src/qmapboxgl.cpp +++ b/platform/qt/src/qmapboxgl.cpp @@ -1,6 +1,8 @@ #include "qmapboxgl.hpp" #include "qmapboxgl_p.hpp" -#include "qmapboxgl_renderer_frontend_p.hpp" + +#include "qmapboxgl_map_observer.hpp" +#include "qmapboxgl_renderer_observer.hpp" #include "qt_conversion.hpp" #include "qt_geojson.hpp" @@ -43,11 +45,8 @@ #if QT_VERSION >= 0x050000 #include <QGuiApplication> -#include <QWindow> -#include <QOpenGLContext> #else #include <QCoreApplication> -#include <QGLContext> #endif #include <QDebug> @@ -65,6 +64,10 @@ using namespace QMapbox; static_assert(mbgl::underlying_type(QMapboxGLSettings::UniqueGLContext) == mbgl::underlying_type(mbgl::GLContextMode::Unique), "error"); static_assert(mbgl::underlying_type(QMapboxGLSettings::SharedGLContext) == mbgl::underlying_type(mbgl::GLContextMode::Shared), "error"); +// mbgl::MapMode +static_assert(mbgl::underlying_type(QMapboxGLSettings::Continuous) == mbgl::underlying_type(mbgl::MapMode::Continuous), "error"); +static_assert(mbgl::underlying_type(QMapboxGLSettings::Static) == mbgl::underlying_type(mbgl::MapMode::Static), "error"); + // mbgl::ConstrainMode static_assert(mbgl::underlying_type(QMapboxGLSettings::NoConstrain) == mbgl::underlying_type(mbgl::ConstrainMode::None), "error"); static_assert(mbgl::underlying_type(QMapboxGLSettings::ConstrainHeightOnly) == mbgl::underlying_type(mbgl::ConstrainMode::HeightOnly), "error"); @@ -165,6 +168,27 @@ std::unique_ptr<mbgl::style::Image> toStyleImage(const QString &id, const QImage */ /*! + \enum QMapboxGLSettings::MapMode + + This enum sets the map rendering mode + + \value Continuous The map will render as data arrives from the network and + react immediately to state changes. + + This is the default mode and the preferred when the map is intended to be + interactive. + + \value Static The map will no longer react to state changes and will only + be rendered when QMapboxGL::startStaticRender is called. After all the + resources are loaded, the QMapboxGL::staticRenderFinished signal is emitted. + + This mode is useful for taking a snapshot of the finished rendering result + of the map into a QImage. + + \sa mapMode() +*/ + +/*! \enum QMapboxGLSettings::ConstrainMode This enum determines if the map wraps. @@ -200,6 +224,7 @@ std::unique_ptr<mbgl::style::Image> toStyleImage(const QString &id, const QImage */ QMapboxGLSettings::QMapboxGLSettings() : m_contextMode(QMapboxGLSettings::SharedGLContext) + , m_mapMode(QMapboxGLSettings::Continuous) , m_constrainMode(QMapboxGLSettings::ConstrainHeightOnly) , m_viewportMode(QMapboxGLSettings::DefaultViewport) , m_cacheMaximumSize(mbgl::util::DEFAULT_MAX_CACHE_SIZE) @@ -230,6 +255,31 @@ void QMapboxGLSettings::setContextMode(GLContextMode mode) } /*! + Returns the map mode. Static mode will emit a signal for + rendering a map only when the map is fully loaded. + Animations like style transitions and labels fading won't + be seen. + + The Continuous mode will emit the signal for every new + change on the map and it is usually what you expect for + a interactive map. + + By default, it is set to QMapboxGLSettings::Continuous. +*/ +QMapboxGLSettings::MapMode QMapboxGLSettings::mapMode() const +{ + return m_mapMode; +} + +/*! + Sets the map \a mode. +*/ +void QMapboxGLSettings::setMapMode(MapMode mode) +{ + m_mapMode = mode; +} + +/*! Returns the constrain mode. This is used to limit the map to wrap around the globe horizontally. @@ -1048,32 +1098,17 @@ void QMapboxGL::rotateBy(const QPointF &first, const QPointF &second) } /*! - Resize the map to \a size and scale to fit at \a framebufferSize. For - high DPI screens, the size will be smaller than the \a framebufferSize. - - This fallowing example will double the pixel density of the map for - a given \c size: - - \code - map->resize(size / 2, size); - \endcode + Resize the map to \a size_ and scale to fit at the framebuffer. For + high DPI screens, the size will be smaller than the framebuffer. */ -void QMapboxGL::resize(const QSize& size, const QSize& framebufferSize) +void QMapboxGL::resize(const QSize& size_) { - if (d_ptr->size == size && d_ptr->fbSize == framebufferSize) return; - - d_ptr->size = size; - d_ptr->fbSize = framebufferSize; + auto size = sanitizedSize(size_); - d_ptr->mapObj->setSize(sanitizedSize(size)); -} + if (d_ptr->mapObj->getSize() == size) + return; -/*! - If Mapbox GL needs to rebind the default \a fbo, it will use the - ID supplied here. -*/ -void QMapboxGL::setFramebufferObject(quint32 fbo) { - d_ptr->fbObject = fbo; + d_ptr->mapObj->setSize(size); } /*! @@ -1468,6 +1503,51 @@ void QMapboxGL::setFilter(const QString& layer, const QVariant& filter) } /*! + Creates the infrastructure needed for rendering the map. It + should be called before any call to render(). + + Must be called on the render thread. +*/ +void QMapboxGL::createRenderer() +{ + d_ptr->createRenderer(); +} + +/*! + Destroys the infrastructure needed for rendering the map, + releasing resources. + + Must be called on the render thread. +*/ +void QMapboxGL::destroyRenderer() +{ + d_ptr->destroyRenderer(); +} + +/*! + Start a static rendering of the current state of the map. This + should only be called when the map is initialized in static mode. + + \sa QMapboxGLSettings::MapMode +*/ +void QMapboxGL::startStaticRender() +{ + d_ptr->mapObj->renderStill([this](std::exception_ptr err) { + QString what; + + try { + if (err) { + std::rethrow_exception(err); + } + } catch(const std::exception& e) { + what = e.what(); + } + + emit staticRenderFinished(what); + }); +} + +/*! 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 @@ -1475,28 +1555,33 @@ void QMapboxGL::setFilter(const QString& layer, const QVariant& filter) This function should be called only after the signal needsRendering() is emitted at least once. + + Must be called on the render thread. */ void QMapboxGL::render() { -#if defined(__APPLE__) && QT_VERSION < 0x050000 - // FIXME Qt 4.x provides an incomplete FBO at start. - // See https://bugreports.qt.io/browse/QTBUG-36802 for details. - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - return; - } -#endif - - d_ptr->dirty = false; d_ptr->render(); } /*! + If Mapbox GL needs to rebind the default \a fbo, it will use the + ID supplied here. \a size is the size of the framebuffer, which + on high DPI screens is usually bigger than the map size. + + Must be called on the render thread. +*/ +void QMapboxGL::setFramebufferObject(quint32 fbo, const QSize& size) +{ + d_ptr->setFramebufferObject(fbo, size); +} + +/*! Informs the map that the network connection has been established, causing all network requests that previously timed out to be retried immediately. */ void QMapboxGL::connectionEstablished() { - d_ptr->connectionEstablished(); + mbgl::NetworkStatus::Reachable(); } /*! @@ -1510,6 +1595,16 @@ void QMapboxGL::connectionEstablished() */ /*! + \fn void QMapboxGL::staticRenderFinished(const QString &error) + + This signal is emitted when a static map is fully drawn. Usually the next + step is to extract the map from a framebuffer into a container like a + QImage. \a error is set to a message when an error occurs. + + \sa startStaticRender() +*/ + +/*! \fn void QMapboxGL::mapChanged(QMapboxGL::MapChange change) This signal is emitted when the state of the map has changed. This signal @@ -1526,186 +1621,140 @@ 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) +QMapboxGLPrivate::QMapboxGLPrivate(QMapboxGL *q, const QMapboxGLSettings &settings, const QSize &size, qreal pixelRatio_) : QObject(q) - , size(size_) - , q_ptr(q) - , fileSourceObj(sharedDefaultFileSource( + , m_fileSourceObj(sharedDefaultFileSource( settings.cacheDatabasePath().toStdString(), settings.assetPath().toStdString(), settings.cacheDatabaseMaximumSize())) - , threadPool(mbgl::sharedThreadPool()) + , m_threadPool(mbgl::sharedThreadPool()) + , m_mode(settings.contextMode()) + , m_pixelRatio(pixelRatio_) { - // Setup resource transform if needed + // Setup the FileSource + m_fileSourceObj->setAccessToken(settings.accessToken().toStdString()); + m_fileSourceObj->setAPIBaseURL(settings.apiBaseUrl().toStdString()); + 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()); + 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_)); + }); + m_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())); + // Setup MapObserver + m_mapObserver = std::make_unique<QMapboxGLMapObserver>(this); + + qRegisterMetaType<QMapboxGL::MapChange>("QMapboxGL::MapChange"); + + connect(m_mapObserver.get(), SIGNAL(mapChanged(QMapboxGL::MapChange)), q, SIGNAL(mapChanged(QMapboxGL::MapChange))); + connect(m_mapObserver.get(), SIGNAL(copyrightsChanged(QString)), q, SIGNAL(copyrightsChanged(QString))); + // Setup the Map object mapObj = std::make_unique<mbgl::Map>( - *frontend, - *this, sanitizedSize(size), - pixelRatio, *fileSourceObj, *threadPool, - mbgl::MapMode::Continuous, + *this, // RendererFrontend + *m_mapObserver, + sanitizedSize(size), + m_pixelRatio, *m_fileSourceObj, *m_threadPool, + static_cast<mbgl::MapMode>(settings.mapMode()), static_cast<mbgl::ConstrainMode>(settings.constrainMode()), static_cast<mbgl::ViewportMode>(settings.viewportMode())); - qRegisterMetaType<QMapboxGL::MapChange>("QMapboxGL::MapChange"); - - fileSourceObj->setAccessToken(settings.accessToken().toStdString()); - fileSourceObj->setAPIBaseURL(settings.apiBaseUrl().toStdString()); - - connect(this, SIGNAL(needsRendering()), q_ptr, SIGNAL(needsRendering()), Qt::QueuedConnection); - connect(this, SIGNAL(mapChanged(QMapboxGL::MapChange)), q_ptr, SIGNAL(mapChanged(QMapboxGL::MapChange)), Qt::QueuedConnection); - connect(this, SIGNAL(copyrightsChanged(QString)), q_ptr, SIGNAL(copyrightsChanged(QString)), Qt::QueuedConnection); + // Needs to be Queued to give time to discard redundant draw calls via the `renderQueued` flag. + connect(this, SIGNAL(needsRendering()), q, SIGNAL(needsRendering()), Qt::QueuedConnection); } QMapboxGLPrivate::~QMapboxGLPrivate() { } -mbgl::Size QMapboxGLPrivate::getFramebufferSize() const { - return sanitizedSize(fbSize); -} +void QMapboxGLPrivate::update(std::shared_ptr<mbgl::UpdateParameters> parameters) +{ + std::lock_guard<std::recursive_mutex> lock(m_mapRendererMutex); -void QMapboxGLPrivate::updateAssumedState() { - assumeFramebufferBinding(fbObject); -#if QT_VERSION >= 0x050600 - assumeViewport(0, 0, getFramebufferSize()); -#endif -} + if (!m_mapRenderer) { + return; + } -void QMapboxGLPrivate::bind() { - setFramebufferBinding(fbObject); - setViewport(0, 0, getFramebufferSize()); -} + m_mapRenderer->updateParameters(std::move(parameters)); -void QMapboxGLPrivate::invalidate() -{ - if (!dirty) { - emit needsRendering(); - dirty = true; - } + requestRendering(); } -void QMapboxGLPrivate::render() +void QMapboxGLPrivate::setObserver(mbgl::RendererObserver &observer) { - frontend->render(); -} + m_rendererObserver = std::make_shared<QMapboxGLRendererObserver>( + *mbgl::util::RunLoop::Get(), observer); -void QMapboxGLPrivate::onCameraWillChange(mbgl::MapObserver::CameraChangeMode mode) -{ - if (mode == mbgl::MapObserver::CameraChangeMode::Immediate) { - emit mapChanged(QMapboxGL::MapChangeRegionWillChange); - } else { - emit mapChanged(QMapboxGL::MapChangeRegionWillChangeAnimated); + std::lock_guard<std::recursive_mutex> lock(m_mapRendererMutex); + + if (m_mapRenderer) { + m_mapRenderer->setObserver(m_rendererObserver); } } -void QMapboxGLPrivate::onCameraIsChanging() +void QMapboxGLPrivate::createRenderer() { - emit mapChanged(QMapboxGL::MapChangeRegionIsChanging); -} + std::lock_guard<std::recursive_mutex> lock(m_mapRendererMutex); -void QMapboxGLPrivate::onCameraDidChange(mbgl::MapObserver::CameraChangeMode mode) -{ - if (mode == mbgl::MapObserver::CameraChangeMode::Immediate) { - emit mapChanged(QMapboxGL::MapChangeRegionDidChange); - } else { - emit mapChanged(QMapboxGL::MapChangeRegionDidChangeAnimated); + if (m_mapRenderer) { + return; } -} -void QMapboxGLPrivate::onWillStartLoadingMap() -{ - emit mapChanged(QMapboxGL::MapChangeWillStartLoadingMap); -} + m_mapRenderer = std::make_unique<QMapboxGLMapRenderer>( + m_pixelRatio, + *m_fileSourceObj, + *m_threadPool, + m_mode + ); -void QMapboxGLPrivate::onDidFinishLoadingMap() -{ - emit mapChanged(QMapboxGL::MapChangeDidFinishLoadingMap); -} + connect(m_mapRenderer.get(), SIGNAL(needsRendering()), this, SLOT(requestRendering())); -void QMapboxGLPrivate::onDidFailLoadingMap(std::exception_ptr) -{ - emit mapChanged(QMapboxGL::MapChangeDidFailLoadingMap); + m_mapRenderer->setObserver(m_rendererObserver); } -void QMapboxGLPrivate::onWillStartRenderingFrame() +void QMapboxGLPrivate::destroyRenderer() { - emit mapChanged(QMapboxGL::MapChangeWillStartRenderingFrame); -} + std::lock_guard<std::recursive_mutex> lock(m_mapRendererMutex); -void QMapboxGLPrivate::onDidFinishRenderingFrame(mbgl::MapObserver::RenderMode mode) -{ - if (mode == mbgl::MapObserver::RenderMode::Partial) { - emit mapChanged(QMapboxGL::MapChangeDidFinishRenderingFrame); - } else { - emit mapChanged(QMapboxGL::MapChangeDidFinishRenderingFrameFullyRendered); - } + m_mapRenderer.reset(); } -void QMapboxGLPrivate::onWillStartRenderingMap() +void QMapboxGLPrivate::render() { - emit mapChanged(QMapboxGL::MapChangeWillStartLoadingMap); -} + std::lock_guard<std::recursive_mutex> lock(m_mapRendererMutex); -void QMapboxGLPrivate::onDidFinishRenderingMap(mbgl::MapObserver::RenderMode mode) -{ - if (mode == mbgl::MapObserver::RenderMode::Partial) { - emit mapChanged(QMapboxGL::MapChangeDidFinishRenderingMap); - } else { - emit mapChanged(QMapboxGL::MapChangeDidFinishRenderingMapFullyRendered); + if (!m_mapRenderer) { + createRenderer(); } -} -void QMapboxGLPrivate::onDidFinishLoadingStyle() -{ - emit mapChanged(QMapboxGL::MapChangeDidFinishLoadingStyle); +#if defined(__APPLE__) && QT_VERSION < 0x050000 + // FIXME Qt 4.x provides an incomplete FBO at start. + // See https://bugreports.qt.io/browse/QTBUG-36802 for details. + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + return; + } +#endif + + m_renderQueued.clear(); + m_mapRenderer->render(); } -void QMapboxGLPrivate::onSourceChanged(mbgl::style::Source&) +void QMapboxGLPrivate::setFramebufferObject(quint32 fbo, const QSize& size) { - std::string attribution; - for (const auto& source : mapObj->getStyle().getSources()) { - // Avoid duplicates by using the most complete attribution HTML snippet. - if (source->getAttribution() && (attribution.size() < source->getAttribution()->size())) - attribution = *source->getAttribution(); + std::lock_guard<std::recursive_mutex> lock(m_mapRendererMutex); + + if (!m_mapRenderer) { + createRenderer(); } - emit copyrightsChanged(QString::fromStdString(attribution)); - emit mapChanged(QMapboxGL::MapChangeSourceDidChange); -} -/*! - Initializes an OpenGL extension function such as Vertex Array Objects (VAOs), - required by Mapbox GL Native engine. -*/ -mbgl::gl::ProcAddress QMapboxGLPrivate::getExtensionFunctionPointer(const char* name) { -#if QT_VERSION >= 0x050000 - QOpenGLContext* thisContext = QOpenGLContext::currentContext(); - return thisContext->getProcAddress(name); -#else - const QGLContext* thisContext = QGLContext::currentContext(); - return reinterpret_cast<mbgl::gl::ProcAddress>(thisContext->getProcAddress(name)); -#endif + m_mapRenderer->updateFramebuffer(fbo, sanitizedSize(size)); } -void QMapboxGLPrivate::connectionEstablished() +void QMapboxGLPrivate::requestRendering() { - mbgl::NetworkStatus::Reachable(); + if (!m_renderQueued.test_and_set()) { + emit needsRendering(); + } } diff --git a/platform/qt/src/qmapboxgl_map_observer.cpp b/platform/qt/src/qmapboxgl_map_observer.cpp new file mode 100644 index 0000000000..e180ed8fda --- /dev/null +++ b/platform/qt/src/qmapboxgl_map_observer.cpp @@ -0,0 +1,95 @@ +#include "qmapboxgl_map_observer.hpp" + +#include "qmapboxgl_p.hpp" + +QMapboxGLMapObserver::QMapboxGLMapObserver(QMapboxGLPrivate *d) + : d_ptr(d) +{ +} + +QMapboxGLMapObserver::~QMapboxGLMapObserver() +{ +} + +void QMapboxGLMapObserver::onCameraWillChange(mbgl::MapObserver::CameraChangeMode mode) +{ + if (mode == mbgl::MapObserver::CameraChangeMode::Immediate) { + emit mapChanged(QMapboxGL::MapChangeRegionWillChange); + } else { + emit mapChanged(QMapboxGL::MapChangeRegionWillChangeAnimated); + } +} + +void QMapboxGLMapObserver::onCameraIsChanging() +{ + emit mapChanged(QMapboxGL::MapChangeRegionIsChanging); +} + +void QMapboxGLMapObserver::onCameraDidChange(mbgl::MapObserver::CameraChangeMode mode) +{ + if (mode == mbgl::MapObserver::CameraChangeMode::Immediate) { + emit mapChanged(QMapboxGL::MapChangeRegionDidChange); + } else { + emit mapChanged(QMapboxGL::MapChangeRegionDidChangeAnimated); + } +} + +void QMapboxGLMapObserver::onWillStartLoadingMap() +{ + emit mapChanged(QMapboxGL::MapChangeWillStartLoadingMap); +} + +void QMapboxGLMapObserver::onDidFinishLoadingMap() +{ + emit mapChanged(QMapboxGL::MapChangeDidFinishLoadingMap); +} + +void QMapboxGLMapObserver::onDidFailLoadingMap(std::exception_ptr) +{ + emit mapChanged(QMapboxGL::MapChangeDidFailLoadingMap); +} + +void QMapboxGLMapObserver::onWillStartRenderingFrame() +{ + emit mapChanged(QMapboxGL::MapChangeWillStartRenderingFrame); +} + +void QMapboxGLMapObserver::onDidFinishRenderingFrame(mbgl::MapObserver::RenderMode mode) +{ + if (mode == mbgl::MapObserver::RenderMode::Partial) { + emit mapChanged(QMapboxGL::MapChangeDidFinishRenderingFrame); + } else { + emit mapChanged(QMapboxGL::MapChangeDidFinishRenderingFrameFullyRendered); + } +} + +void QMapboxGLMapObserver::onWillStartRenderingMap() +{ + emit mapChanged(QMapboxGL::MapChangeWillStartLoadingMap); +} + +void QMapboxGLMapObserver::onDidFinishRenderingMap(mbgl::MapObserver::RenderMode mode) +{ + if (mode == mbgl::MapObserver::RenderMode::Partial) { + emit mapChanged(QMapboxGL::MapChangeDidFinishRenderingMap); + } else { + emit mapChanged(QMapboxGL::MapChangeDidFinishRenderingMapFullyRendered); + } +} + +void QMapboxGLMapObserver::onDidFinishLoadingStyle() +{ + emit mapChanged(QMapboxGL::MapChangeDidFinishLoadingStyle); +} + +void QMapboxGLMapObserver::onSourceChanged(mbgl::style::Source&) +{ + std::string attribution; + for (const auto& source : d_ptr->mapObj->getStyle().getSources()) { + // Avoid duplicates by using the most complete attribution HTML snippet. + if (source->getAttribution() && (attribution.size() < source->getAttribution()->size())) + attribution = *source->getAttribution(); + } + emit copyrightsChanged(QString::fromStdString(attribution)); + emit mapChanged(QMapboxGL::MapChangeSourceDidChange); +} diff --git a/platform/qt/src/qmapboxgl_map_observer.hpp b/platform/qt/src/qmapboxgl_map_observer.hpp new file mode 100644 index 0000000000..c9d0581a90 --- /dev/null +++ b/platform/qt/src/qmapboxgl_map_observer.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include "qmapboxgl.hpp" + +#include <mbgl/map/map_observer.hpp> +#include <mbgl/style/style.hpp> + +#include <QObject> + +#include <exception> +#include <memory> + +class QMapboxGLPrivate; + +class QMapboxGLMapObserver : public QObject, public mbgl::MapObserver +{ + Q_OBJECT + +public: + explicit QMapboxGLMapObserver(QMapboxGLPrivate *); + virtual ~QMapboxGLMapObserver(); + + // mbgl::MapObserver implementation. + void onCameraWillChange(mbgl::MapObserver::CameraChangeMode) final; + void onCameraIsChanging() final; + void onCameraDidChange(mbgl::MapObserver::CameraChangeMode) final; + void onWillStartLoadingMap() final; + void onDidFinishLoadingMap() final; + void onDidFailLoadingMap(std::exception_ptr) final; + void onWillStartRenderingFrame() final; + void onDidFinishRenderingFrame(mbgl::MapObserver::RenderMode) final; + void onWillStartRenderingMap() final; + void onDidFinishRenderingMap(mbgl::MapObserver::RenderMode) final; + void onDidFinishLoadingStyle() final; + void onSourceChanged(mbgl::style::Source&) final; + +signals: + void mapChanged(QMapboxGL::MapChange); + void copyrightsChanged(const QString ©rightsHtml); + +private: + Q_DISABLE_COPY(QMapboxGLMapObserver) + + QMapboxGLPrivate *d_ptr; +}; diff --git a/platform/qt/src/qmapboxgl_map_renderer.cpp b/platform/qt/src/qmapboxgl_map_renderer.cpp new file mode 100644 index 0000000000..7a9d1f6f78 --- /dev/null +++ b/platform/qt/src/qmapboxgl_map_renderer.cpp @@ -0,0 +1,86 @@ +#include "qmapboxgl_map_renderer.hpp" + +#include <QtGlobal> + +QMapboxGLMapRenderer::QMapboxGLMapRenderer(qreal pixelRatio, + mbgl::DefaultFileSource &fs, mbgl::ThreadPool &tp, QMapboxGLSettings::GLContextMode mode) + : m_renderer(std::make_unique<mbgl::Renderer>(m_backend, pixelRatio, fs, tp, static_cast<mbgl::GLContextMode>(mode))) + , m_threadWithScheduler(Scheduler::GetCurrent() != nullptr) +{ +} + +QMapboxGLMapRenderer::~QMapboxGLMapRenderer() +{ + MBGL_VERIFY_THREAD(tid); +} + +void QMapboxGLMapRenderer::schedule(std::weak_ptr<mbgl::Mailbox> mailbox) +{ + std::lock_guard<std::mutex> lock(m_taskQueueMutex); + m_taskQueue.push(mailbox); + + // Need to force the main thread to wake + // up this thread and process the events. + emit needsRendering(); +} + +void QMapboxGLMapRenderer::updateParameters(std::shared_ptr<mbgl::UpdateParameters> newParameters) +{ + std::lock_guard<std::mutex> lock(m_updateMutex); + m_updateParameters = std::move(newParameters); +} + +void QMapboxGLMapRenderer::updateFramebuffer(quint32 fbo, const mbgl::Size &size) +{ + MBGL_VERIFY_THREAD(tid); + + m_backend.updateFramebuffer(fbo, size); +} + +void QMapboxGLMapRenderer::render() +{ + MBGL_VERIFY_THREAD(tid); + + std::shared_ptr<mbgl::UpdateParameters> params; + { + // Lock on the parameters + std::lock_guard<std::mutex> lock(m_updateMutex); + + if (!m_updateParameters) { + return; + } + + // Hold on to the update parameters during render + params = m_updateParameters; + } + + // The OpenGL implementation automatically enables the OpenGL context for us. + mbgl::BackendScope scope(m_backend, mbgl::BackendScope::ScopeType::Implicit); + + // If we don't have a Scheduler on this thread, which + // is usually the case for render threads, use this + // object as scheduler. + if (!m_threadWithScheduler) { + Scheduler::SetCurrent(this); + } + + m_renderer->render(*params); + + if (!m_threadWithScheduler) { + std::queue<std::weak_ptr<mbgl::Mailbox>> taskQueue; + { + std::unique_lock<std::mutex> lock(m_taskQueueMutex); + std::swap(taskQueue, m_taskQueue); + } + + while (!taskQueue.empty()) { + mbgl::Mailbox::maybeReceive(taskQueue.front()); + taskQueue.pop(); + } + } +} + +void QMapboxGLMapRenderer::setObserver(std::shared_ptr<mbgl::RendererObserver> observer) +{ + m_renderer->setObserver(observer.get()); +} diff --git a/platform/qt/src/qmapboxgl_map_renderer.hpp b/platform/qt/src/qmapboxgl_map_renderer.hpp new file mode 100644 index 0000000000..adba11de51 --- /dev/null +++ b/platform/qt/src/qmapboxgl_map_renderer.hpp @@ -0,0 +1,63 @@ +#pragma once + +#include "qmapboxgl.hpp" +#include "qmapboxgl_renderer_backend.hpp" + +#include <mbgl/renderer/renderer.hpp> +#include <mbgl/renderer/renderer_backend.hpp> +#include <mbgl/renderer/renderer_observer.hpp> +#include <mbgl/storage/default_file_source.hpp> +#include <mbgl/util/shared_thread_pool.hpp> +#include <mbgl/util/util.hpp> + +#include <QtGlobal> + +#include <memory> +#include <mutex> +#include <queue> + +namespace mbgl { +class Renderer; +class UpdateParameters; +} // namespace mbgl + +class QMapboxGLRendererBackend; + +class QMapboxGLMapRenderer : public QObject, public mbgl::Scheduler +{ + Q_OBJECT + +public: + QMapboxGLMapRenderer(qreal pixelRatio, mbgl::DefaultFileSource &, + mbgl::ThreadPool &, QMapboxGLSettings::GLContextMode); + virtual ~QMapboxGLMapRenderer(); + + // mbgl::Scheduler implementation. + void schedule(std::weak_ptr<mbgl::Mailbox> scheduled) final; + + void render(); + void updateFramebuffer(quint32 fbo, const mbgl::Size &size); + void setObserver(std::shared_ptr<mbgl::RendererObserver>); + + // Thread-safe, called by the Frontend + void updateParameters(std::shared_ptr<mbgl::UpdateParameters>); + +signals: + void needsRendering(); + +private: + MBGL_STORE_THREAD(tid) + + Q_DISABLE_COPY(QMapboxGLMapRenderer) + + std::mutex m_updateMutex; + std::shared_ptr<mbgl::UpdateParameters> m_updateParameters; + + QMapboxGLRendererBackend m_backend; + std::unique_ptr<mbgl::Renderer> m_renderer; + + std::mutex m_taskQueueMutex; + std::queue<std::weak_ptr<mbgl::Mailbox>> m_taskQueue; + + bool m_threadWithScheduler; +}; diff --git a/platform/qt/src/qmapboxgl_p.hpp b/platform/qt/src/qmapboxgl_p.hpp index f947c09f48..51c7cb8fc4 100644 --- a/platform/qt/src/qmapboxgl_p.hpp +++ b/platform/qt/src/qmapboxgl_p.hpp @@ -1,22 +1,24 @@ #pragma once #include "qmapboxgl.hpp" -#include "qmapboxgl_renderer_frontend_p.hpp" +#include "qmapboxgl_map_observer.hpp" +#include "qmapboxgl_map_renderer.hpp" #include <mbgl/actor/actor.hpp> #include <mbgl/map/map.hpp> -#include <mbgl/renderer/renderer_backend.hpp> -#include <mbgl/util/default_thread_pool.hpp> +#include <mbgl/renderer/renderer_frontend.hpp> #include <mbgl/storage/default_file_source.hpp> -#include <mbgl/util/geo.hpp> #include <mbgl/storage/resource_transform.hpp> +#include <mbgl/util/default_thread_pool.hpp> +#include <mbgl/util/geo.hpp> #include <QObject> #include <QSize> +#include <atomic> #include <memory> -class QMapboxGLPrivate : public QObject, public mbgl::RendererBackend, public mbgl::MapObserver +class QMapboxGLPrivate : public QObject, public mbgl::RendererFrontend { Q_OBJECT @@ -24,55 +26,40 @@ public: explicit QMapboxGLPrivate(QMapboxGL *, const QMapboxGLSettings &, const QSize &size, qreal pixelRatio); virtual ~QMapboxGLPrivate(); + // mbgl::RendererFrontend implementation. + void reset() final {} + void setObserver(mbgl::RendererObserver &) final; + void update(std::shared_ptr<mbgl::UpdateParameters>) final; - // mbgl::RendererBackend implementation. - void bind() final; - mbgl::Size getFramebufferSize() const final; - void updateAssumedState() final; - void activate() final {} - void deactivate() final {} - - // mbgl::MapObserver implementation. - void onCameraWillChange(mbgl::MapObserver::CameraChangeMode) final; - void onCameraIsChanging() final; - void onCameraDidChange(mbgl::MapObserver::CameraChangeMode) final; - void onWillStartLoadingMap() final; - void onDidFinishLoadingMap() final; - void onDidFailLoadingMap(std::exception_ptr) final; - void onWillStartRenderingFrame() final; - void onDidFinishRenderingFrame(mbgl::MapObserver::RenderMode) final; - void onWillStartRenderingMap() final; - void onDidFinishRenderingMap(mbgl::MapObserver::RenderMode) final; - void onDidFinishLoadingStyle() final; - void onSourceChanged(mbgl::style::Source&) final; + // These need to be called on the same thread. + void createRenderer(); + void destroyRenderer(); + void render(); + void setFramebufferObject(quint32 fbo, const QSize& size); mbgl::EdgeInsets margins; - QSize size { 0, 0 }; - QSize fbSize { 0, 0 }; - quint32 fbObject = 0; - - QMapboxGL *q_ptr { nullptr }; - - std::shared_ptr<mbgl::DefaultFileSource> fileSourceObj; - std::shared_ptr<mbgl::ThreadPool> threadPool; - std::unique_ptr<QMapboxGLRendererFrontend> frontend; std::unique_ptr<mbgl::Map> mapObj; - bool dirty { false }; - -private: - mbgl::gl::ProcAddress getExtensionFunctionPointer(const char*) override; - public slots: - void connectionEstablished(); - void invalidate(); - void render(); + void requestRendering(); signals: void needsRendering(); - void mapChanged(QMapboxGL::MapChange); - void copyrightsChanged(const QString ©rightsHtml); private: - std::unique_ptr< mbgl::Actor<mbgl::ResourceTransform> > m_resourceTransform; + Q_DISABLE_COPY(QMapboxGLPrivate) + + std::recursive_mutex m_mapRendererMutex; + std::shared_ptr<mbgl::RendererObserver> m_rendererObserver; + + std::unique_ptr<QMapboxGLMapObserver> m_mapObserver; + std::shared_ptr<mbgl::DefaultFileSource> m_fileSourceObj; + std::shared_ptr<mbgl::ThreadPool> m_threadPool; + std::unique_ptr<QMapboxGLMapRenderer> m_mapRenderer; + std::unique_ptr<mbgl::Actor<mbgl::ResourceTransform>> m_resourceTransform; + + QMapboxGLSettings::GLContextMode m_mode; + qreal m_pixelRatio; + + std::atomic_flag m_renderQueued = ATOMIC_FLAG_INIT; }; diff --git a/platform/qt/src/qmapboxgl_renderer_backend.cpp b/platform/qt/src/qmapboxgl_renderer_backend.cpp new file mode 100644 index 0000000000..917741f5ce --- /dev/null +++ b/platform/qt/src/qmapboxgl_renderer_backend.cpp @@ -0,0 +1,49 @@ +#include "qmapboxgl_renderer_backend.hpp" + +#include <QtGlobal> + +#if QT_VERSION >= 0x050000 +#include <QOpenGLContext> +#else +#include <QGLContext> +#endif + +void QMapboxGLRendererBackend::updateAssumedState() +{ + assumeFramebufferBinding(ImplicitFramebufferBinding); + assumeViewport(0, 0, m_size); +} + +void QMapboxGLRendererBackend::bind() +{ + assert(mbgl::BackendScope::exists()); + + setFramebufferBinding(m_fbo); + setViewport(0, 0, m_size); +} + +mbgl::Size QMapboxGLRendererBackend::getFramebufferSize() const +{ + return m_size; +} + +void QMapboxGLRendererBackend::updateFramebuffer(quint32 fbo, const mbgl::Size &size) +{ + m_fbo = fbo; + m_size = size; +} + +/*! + Initializes an OpenGL extension function such as Vertex Array Objects (VAOs), + required by Mapbox GL Native engine. +*/ +mbgl::gl::ProcAddress QMapboxGLRendererBackend::getExtensionFunctionPointer(const char* name) +{ +#if QT_VERSION >= 0x050000 + QOpenGLContext* thisContext = QOpenGLContext::currentContext(); + return thisContext->getProcAddress(name); +#else + const QGLContext* thisContext = QGLContext::currentContext(); + return reinterpret_cast<mbgl::gl::ProcAddress>(thisContext->getProcAddress(name)); +#endif +} diff --git a/platform/qt/src/qmapboxgl_renderer_backend.hpp b/platform/qt/src/qmapboxgl_renderer_backend.hpp new file mode 100644 index 0000000000..de66b035fc --- /dev/null +++ b/platform/qt/src/qmapboxgl_renderer_backend.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include "qmapboxgl.hpp" + +#include <mbgl/renderer/renderer_backend.hpp> +#include <mbgl/storage/default_file_source.hpp> +#include <mbgl/util/shared_thread_pool.hpp> + +class QMapboxGLRendererBackend : public mbgl::RendererBackend +{ +public: + QMapboxGLRendererBackend() = default; + virtual ~QMapboxGLRendererBackend() = default; + + // mbgl::RendererBackend implementation + void updateAssumedState() final; + void bind() final; + mbgl::Size getFramebufferSize() const final; + + void updateFramebuffer(quint32 fbo, const mbgl::Size &); + +protected: + mbgl::gl::ProcAddress getExtensionFunctionPointer(const char*) final; + + // No-op, implicit mode. + void activate() final {} + void deactivate() final {} + +private: + quint32 m_fbo = 0; + mbgl::Size m_size = { 0, 0 }; + + Q_DISABLE_COPY(QMapboxGLRendererBackend) +}; diff --git a/platform/qt/src/qmapboxgl_renderer_frontend_p.cpp b/platform/qt/src/qmapboxgl_renderer_frontend_p.cpp deleted file mode 100644 index ea60851eb4..0000000000 --- a/platform/qt/src/qmapboxgl_renderer_frontend_p.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "qmapboxgl_renderer_frontend_p.hpp" - -#include <mbgl/renderer/backend_scope.hpp> -#include <mbgl/renderer/renderer.hpp> - -QMapboxGLRendererFrontend::QMapboxGLRendererFrontend(std::unique_ptr<mbgl::Renderer> renderer_, mbgl::RendererBackend& backend_) - : renderer(std::move(renderer_)) - , backend(backend_) { -} - -QMapboxGLRendererFrontend::~QMapboxGLRendererFrontend() = default; - -void QMapboxGLRendererFrontend::reset() { - if (renderer) { - renderer.reset(); - } -} - -void QMapboxGLRendererFrontend::update(std::shared_ptr<mbgl::UpdateParameters> updateParameters_) { - updateParameters = updateParameters_; - emit updated(); -} - -void QMapboxGLRendererFrontend::setObserver(mbgl::RendererObserver& observer_) { - if (!renderer) return; - - renderer->setObserver(&observer_); -} - -void QMapboxGLRendererFrontend::render() { - if (!renderer || !updateParameters) return; - - // The OpenGL implementation automatically enables the OpenGL context for us. - mbgl::BackendScope scope { backend, mbgl::BackendScope::ScopeType::Implicit }; - - renderer->render(*updateParameters); -} diff --git a/platform/qt/src/qmapboxgl_renderer_frontend_p.hpp b/platform/qt/src/qmapboxgl_renderer_frontend_p.hpp deleted file mode 100644 index c5e2bacc34..0000000000 --- a/platform/qt/src/qmapboxgl_renderer_frontend_p.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include <mbgl/renderer/renderer_backend.hpp> -#include <mbgl/renderer/renderer_frontend.hpp> - -#include <QObject> - -namespace mbgl { - class Renderer; -} // namespace mbgl - -class QMapboxGLRendererFrontend : public QObject, public mbgl::RendererFrontend -{ - Q_OBJECT - -public: - explicit QMapboxGLRendererFrontend(std::unique_ptr<mbgl::Renderer>, mbgl::RendererBackend&); - ~QMapboxGLRendererFrontend() override; - - void reset() override; - void setObserver(mbgl::RendererObserver&) override; - - void update(std::shared_ptr<mbgl::UpdateParameters>) override; - -public slots: - void render(); - -signals: - void updated(); - -private: - std::unique_ptr<mbgl::Renderer> renderer; - mbgl::RendererBackend& backend; - std::shared_ptr<mbgl::UpdateParameters> updateParameters; -}; diff --git a/platform/qt/src/qmapboxgl_renderer_observer.hpp b/platform/qt/src/qmapboxgl_renderer_observer.hpp new file mode 100644 index 0000000000..ee340113ff --- /dev/null +++ b/platform/qt/src/qmapboxgl_renderer_observer.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include <mbgl/actor/actor.hpp> +#include <mbgl/actor/actor_ref.hpp> +#include <mbgl/actor/mailbox.hpp> +#include <mbgl/renderer/renderer_observer.hpp> +#include <mbgl/util/run_loop.hpp> + +#include <memory> + +// Forwards RendererObserver signals to the given +// Delegate RendererObserver on the given RunLoop +class QMapboxGLRendererObserver : public mbgl::RendererObserver { +public: + QMapboxGLRendererObserver(mbgl::util::RunLoop& mapRunLoop, mbgl::RendererObserver& delegate_) + : mailbox(std::make_shared<mbgl::Mailbox>(mapRunLoop)) + , delegate(delegate_, mailbox) { + } + + ~QMapboxGLRendererObserver() { + mailbox->close(); + } + + void onInvalidate() final { + delegate.invoke(&mbgl::RendererObserver::onInvalidate); + } + + void onResourceError(std::exception_ptr err) final { + delegate.invoke(&mbgl::RendererObserver::onResourceError, err); + } + + void onWillStartRenderingMap() final { + delegate.invoke(&mbgl::RendererObserver::onWillStartRenderingMap); + } + + void onWillStartRenderingFrame() final { + delegate.invoke(&mbgl::RendererObserver::onWillStartRenderingFrame); + } + + void onDidFinishRenderingFrame(RenderMode mode, bool repaintNeeded) final { + delegate.invoke(&mbgl::RendererObserver::onDidFinishRenderingFrame, mode, repaintNeeded); + } + + void onDidFinishRenderingMap() final { + delegate.invoke(&mbgl::RendererObserver::onDidFinishRenderingMap); + } + +private: + std::shared_ptr<mbgl::Mailbox> mailbox; + mbgl::ActorRef<mbgl::RendererObserver> delegate; +}; diff --git a/platform/qt/src/qt_logging.cpp b/platform/qt/src/qt_logging.cpp index acbe9562d0..acbe9562d0 100755..100644 --- a/platform/qt/src/qt_logging.cpp +++ b/platform/qt/src/qt_logging.cpp diff --git a/platform/qt/src/run_loop.cpp b/platform/qt/src/run_loop.cpp index af0c50ebb9..c25243c8e7 100644 --- a/platform/qt/src/run_loop.cpp +++ b/platform/qt/src/run_loop.cpp @@ -52,11 +52,8 @@ LOOP_HANDLE RunLoop::getLoopHandle() { return nullptr; } -void RunLoop::push(std::shared_ptr<WorkTask> task) { - withMutex([&] { - queue.push(std::move(task)); - impl->async->send(); - }); +void RunLoop::wake() { + impl->async->send(); } void RunLoop::run() { diff --git a/platform/qt/src/sqlite3.cpp b/platform/qt/src/sqlite3.cpp index 2f3db12f33..80efd6a326 100644 --- a/platform/qt/src/sqlite3.cpp +++ b/platform/qt/src/sqlite3.cpp @@ -354,7 +354,7 @@ template <> mbgl::Timestamp Statement::get(int offset) { QVariant value = impl->query.value(offset); checkQueryError(impl->query); return std::chrono::time_point_cast<std::chrono::seconds>( - std::chrono::system_clock::from_time_t(value.value<std::time_t>())); + std::chrono::system_clock::from_time_t(value.value<::time_t>())); } template <> optional<int64_t> Statement::get(int offset) { @@ -398,7 +398,7 @@ template <> optional<mbgl::Timestamp> Statement::get(int offset) { if (value.isNull()) return {}; return { std::chrono::time_point_cast<mbgl::Seconds>( - std::chrono::system_clock::from_time_t(value.value<std::time_t>())) }; + std::chrono::system_clock::from_time_t(value.value<::time_t>())) }; } void Statement::reset() { |