From 55b392856442f957598a8e41b0a5b64dcdc12dd8 Mon Sep 17 00:00:00 2001 From: "Thiago Marcos P. Santos" Date: Tue, 6 Feb 2018 19:31:06 +0200 Subject: [qt] Add an interface for Static rendering --- platform/qt/include/qmapboxgl.hpp | 15 +++++ platform/qt/src/qmapboxgl.cpp | 99 ++++++++++++++++++++++++++++-- platform/qt/src/qmapboxgl_map_renderer.cpp | 4 ++ platform/qt/src/qmapboxgl_map_renderer.hpp | 7 ++- platform/qt/src/qmapboxgl_p.hpp | 3 + 5 files changed, 123 insertions(+), 5 deletions(-) diff --git a/platform/qt/include/qmapboxgl.hpp b/platform/qt/include/qmapboxgl.hpp index d3ba643248..bc18eaba59 100644 --- a/platform/qt/include/qmapboxgl.hpp +++ b/platform/qt/include/qmapboxgl.hpp @@ -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; @@ -235,11 +244,17 @@ 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/qmapboxgl.cpp b/platform/qt/src/qmapboxgl.cpp index fd12476a0f..414b65255c 100644 --- a/platform/qt/src/qmapboxgl.cpp +++ b/platform/qt/src/qmapboxgl.cpp @@ -64,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"); @@ -163,6 +167,27 @@ std::unique_ptr toStyleImage(const QString &id, const QImage \sa contextMode() */ +/*! + \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 @@ -199,6 +224,7 @@ std::unique_ptr 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) @@ -228,6 +254,31 @@ void QMapboxGLSettings::setContextMode(GLContextMode mode) m_contextMode = 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. @@ -1473,6 +1524,29 @@ 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 @@ -1520,6 +1594,16 @@ void QMapboxGL::connectionEstablished() \sa render() */ +/*! + \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) @@ -1573,7 +1657,7 @@ QMapboxGLPrivate::QMapboxGLPrivate(QMapboxGL *q, const QMapboxGLSettings &settin *m_mapObserver, sanitizedSize(size), m_pixelRatio, *m_fileSourceObj, *m_threadPool, - mbgl::MapMode::Continuous, + static_cast(settings.mapMode()), static_cast(settings.constrainMode()), static_cast(settings.viewportMode())); @@ -1595,9 +1679,7 @@ void QMapboxGLPrivate::update(std::shared_ptr parameters m_mapRenderer->updateParameters(std::move(parameters)); - if (!m_renderQueued.test_and_set()) { - emit needsRendering(); - } + requestRendering(); } void QMapboxGLPrivate::setObserver(mbgl::RendererObserver &observer) @@ -1627,6 +1709,8 @@ void QMapboxGLPrivate::createRenderer() m_mode ); + connect(m_mapRenderer.get(), SIGNAL(needsRendering()), this, SLOT(requestRendering())); + m_mapRenderer->setObserver(m_rendererObserver); } @@ -1667,3 +1751,10 @@ void QMapboxGLPrivate::setFramebufferObject(quint32 fbo, const QSize& size) m_mapRenderer->updateFramebuffer(fbo, sanitizedSize(size)); } + +void QMapboxGLPrivate::requestRendering() +{ + if (!m_renderQueued.test_and_set()) { + emit needsRendering(); + } +} diff --git a/platform/qt/src/qmapboxgl_map_renderer.cpp b/platform/qt/src/qmapboxgl_map_renderer.cpp index af6823acb8..7a9d1f6f78 100644 --- a/platform/qt/src/qmapboxgl_map_renderer.cpp +++ b/platform/qt/src/qmapboxgl_map_renderer.cpp @@ -18,6 +18,10 @@ void QMapboxGLMapRenderer::schedule(std::weak_ptr mailbox) { std::lock_guard 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 newParameters) diff --git a/platform/qt/src/qmapboxgl_map_renderer.hpp b/platform/qt/src/qmapboxgl_map_renderer.hpp index aed6434cb0..adba11de51 100644 --- a/platform/qt/src/qmapboxgl_map_renderer.hpp +++ b/platform/qt/src/qmapboxgl_map_renderer.hpp @@ -23,8 +23,10 @@ class UpdateParameters; class QMapboxGLRendererBackend; -class QMapboxGLMapRenderer : public mbgl::Scheduler +class QMapboxGLMapRenderer : public QObject, public mbgl::Scheduler { + Q_OBJECT + public: QMapboxGLMapRenderer(qreal pixelRatio, mbgl::DefaultFileSource &, mbgl::ThreadPool &, QMapboxGLSettings::GLContextMode); @@ -40,6 +42,9 @@ public: // Thread-safe, called by the Frontend void updateParameters(std::shared_ptr); +signals: + void needsRendering(); + private: MBGL_STORE_THREAD(tid) diff --git a/platform/qt/src/qmapboxgl_p.hpp b/platform/qt/src/qmapboxgl_p.hpp index 31fb5138bf..51c7cb8fc4 100644 --- a/platform/qt/src/qmapboxgl_p.hpp +++ b/platform/qt/src/qmapboxgl_p.hpp @@ -40,6 +40,9 @@ public: mbgl::EdgeInsets margins; std::unique_ptr mapObj; +public slots: + void requestRendering(); + signals: void needsRendering(); -- cgit v1.2.1