summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThiago Marcos P. Santos <tmpsantos@gmail.com>2018-06-06 14:15:15 +0300
committerThiago Marcos P. Santos <tmpsantos@gmail.com>2018-06-06 15:28:53 +0300
commit00ef3ae720efe1436d555f3a18968a93708ef57b (patch)
tree4cc56cdb3f4921e477ea86e5a20556047c339e49
parent6eee8729554ed778491c52bda46cdcbec61b9c95 (diff)
downloadqtlocation-mapboxgl-00ef3ae720efe1436d555f3a18968a93708ef57b.tar.gz
Use a shared scheduler on threads without a default schedulerupstream/tmpsantos-qt_renderer_scheduler
Render threads won't have a scheduler, so we create one that is shared by all the maps rendering at this thread. The bad side effect of this is that we need to wake up the render thread to process events. Mapbox GL should get rid of processing events on the render thread. This solution is a workaround.
-rw-r--r--platform/qt/qt.cmake4
-rw-r--r--platform/qt/src/qmapboxgl_map_renderer.cpp67
-rw-r--r--platform/qt/src/qmapboxgl_map_renderer.hpp11
-rw-r--r--platform/qt/src/qmapboxgl_scheduler.cpp36
-rw-r--r--platform/qt/src/qmapboxgl_scheduler.hpp31
5 files changed, 110 insertions, 39 deletions
diff --git a/platform/qt/qt.cmake b/platform/qt/qt.cmake
index 989618a59a..dda15174fb 100644
--- a/platform/qt/qt.cmake
+++ b/platform/qt/qt.cmake
@@ -65,8 +65,10 @@ add_library(qmapboxgl SHARED
platform/qt/src/qmapboxgl_map_observer.hpp
platform/qt/src/qmapboxgl_map_renderer.cpp
platform/qt/src/qmapboxgl_map_renderer.hpp
- platform/qt/src/qmapboxgl_renderer_backend.hpp
platform/qt/src/qmapboxgl_renderer_backend.cpp
+ platform/qt/src/qmapboxgl_renderer_backend.hpp
+ platform/qt/src/qmapboxgl_scheduler.cpp
+ platform/qt/src/qmapboxgl_scheduler.hpp
platform/default/mbgl/util/default_styles.hpp
)
diff --git a/platform/qt/src/qmapboxgl_map_renderer.cpp b/platform/qt/src/qmapboxgl_map_renderer.cpp
index 7a9d1f6f78..acc4194498 100644
--- a/platform/qt/src/qmapboxgl_map_renderer.cpp
+++ b/platform/qt/src/qmapboxgl_map_renderer.cpp
@@ -1,12 +1,47 @@
#include "qmapboxgl_map_renderer.hpp"
+#include "qmapboxgl_scheduler.hpp"
+#include <QThreadStorage>
#include <QtGlobal>
+static bool needsToForceScheduler() {
+ static QThreadStorage<bool> force;
+
+ if (!force.hasLocalData()) {
+ force.setLocalData(mbgl::Scheduler::GetCurrent() == nullptr);
+ }
+
+ return force.localData();
+};
+
+static auto *getScheduler() {
+ static QThreadStorage<std::shared_ptr<QMapboxGLScheduler>> scheduler;
+
+ if (!scheduler.hasLocalData()) {
+ scheduler.setLocalData(std::make_shared<QMapboxGLScheduler>());
+ }
+
+ return scheduler.localData().get();
+};
+
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)
+ , m_forceScheduler(needsToForceScheduler())
{
+ // If we don't have a Scheduler on this thread, which
+ // is usually the case for render threads, use a shared
+ // dummy scheduler that needs to be explicitly forced to
+ // process events.
+ if (m_forceScheduler) {
+ auto scheduler = getScheduler();
+
+ if (mbgl::Scheduler::GetCurrent() == nullptr) {
+ mbgl::Scheduler::SetCurrent(scheduler);
+ }
+
+ connect(scheduler, SIGNAL(needsProcessing()), this, SIGNAL(needsRendering()));
+ }
}
QMapboxGLMapRenderer::~QMapboxGLMapRenderer()
@@ -14,16 +49,6 @@ 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);
@@ -57,26 +82,10 @@ void QMapboxGLMapRenderer::render()
// 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();
- }
+ if (m_forceScheduler) {
+ getScheduler()->processEvents();
}
}
diff --git a/platform/qt/src/qmapboxgl_map_renderer.hpp b/platform/qt/src/qmapboxgl_map_renderer.hpp
index adba11de51..0b17542e2f 100644
--- a/platform/qt/src/qmapboxgl_map_renderer.hpp
+++ b/platform/qt/src/qmapboxgl_map_renderer.hpp
@@ -14,7 +14,6 @@
#include <memory>
#include <mutex>
-#include <queue>
namespace mbgl {
class Renderer;
@@ -23,7 +22,7 @@ class UpdateParameters;
class QMapboxGLRendererBackend;
-class QMapboxGLMapRenderer : public QObject, public mbgl::Scheduler
+class QMapboxGLMapRenderer : public QObject
{
Q_OBJECT
@@ -32,9 +31,6 @@ public:
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>);
@@ -56,8 +52,5 @@ private:
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;
+ bool m_forceScheduler;
};
diff --git a/platform/qt/src/qmapboxgl_scheduler.cpp b/platform/qt/src/qmapboxgl_scheduler.cpp
new file mode 100644
index 0000000000..7c64336d5b
--- /dev/null
+++ b/platform/qt/src/qmapboxgl_scheduler.cpp
@@ -0,0 +1,36 @@
+#include "qmapboxgl_scheduler.hpp"
+
+#include <mbgl/util/util.hpp>
+
+QMapboxGLScheduler::QMapboxGLScheduler()
+{
+}
+
+QMapboxGLScheduler::~QMapboxGLScheduler()
+{
+ MBGL_VERIFY_THREAD(tid);
+}
+
+void QMapboxGLScheduler::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 needsProcessing();
+}
+
+void QMapboxGLScheduler::processEvents()
+{
+ 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();
+ }
+}
diff --git a/platform/qt/src/qmapboxgl_scheduler.hpp b/platform/qt/src/qmapboxgl_scheduler.hpp
new file mode 100644
index 0000000000..c23abf816d
--- /dev/null
+++ b/platform/qt/src/qmapboxgl_scheduler.hpp
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <mbgl/actor/mailbox.hpp>
+#include <mbgl/actor/scheduler.hpp>
+
+#include <QObject>
+
+#include <memory>
+#include <mutex>
+#include <queue>
+
+class QMapboxGLScheduler : public QObject, public mbgl::Scheduler
+{
+ Q_OBJECT
+
+public:
+ QMapboxGLScheduler();
+ virtual ~QMapboxGLScheduler();
+
+ // mbgl::Scheduler implementation.
+ void schedule(std::weak_ptr<mbgl::Mailbox> scheduled) final;
+
+ void processEvents();
+
+signals:
+ void needsProcessing();
+
+private:
+ std::mutex m_taskQueueMutex;
+ std::queue<std::weak_ptr<mbgl::Mailbox>> m_taskQueue;
+};