diff options
author | Ivo van Dongen <info@ivovandongen.nl> | 2017-09-04 14:48:06 +0300 |
---|---|---|
committer | Ivo van Dongen <info@ivovandongen.nl> | 2017-09-18 10:07:04 +0300 |
commit | 29fa5bbefeeff508cdbb3923b1f5a7625e4d4c79 (patch) | |
tree | f71c2077e8489236ab25a5b3c04356808c72d675 | |
parent | f083240c53c7ff7c7124e55a15636bc294cda9ff (diff) | |
download | qtlocation-mapboxgl-29fa5bbefeeff508cdbb3923b1f5a7625e4d4c79.tar.gz |
[android] use only two threads
-rw-r--r-- | platform/android/src/android_gl_thread.hpp | 75 | ||||
-rw-r--r-- | platform/android/src/android_renderer_frontend.cpp | 54 | ||||
-rw-r--r-- | platform/android/src/android_renderer_frontend.hpp | 12 |
3 files changed, 111 insertions, 30 deletions
diff --git a/platform/android/src/android_gl_thread.hpp b/platform/android/src/android_gl_thread.hpp new file mode 100644 index 0000000000..06bfce1444 --- /dev/null +++ b/platform/android/src/android_gl_thread.hpp @@ -0,0 +1,75 @@ +#pragma once + +#include <mbgl/actor/actor.hpp> +#include <mbgl/actor/mailbox.hpp> +#include <mbgl/actor/scheduler.hpp> +#include <mbgl/renderer/renderer.hpp> + +#include <functional> +#include <memory> +#include <mutex> +#include <queue> +#include <utility> + +namespace mbgl { +namespace android { + +class AndroidGLThread : public Scheduler { +public: + using InvalidateCallback = std::function<void ()>; + + template <class... Args> + AndroidGLThread(ActorRef<InvalidateCallback> callback_, Args&&... args) + : renderer(std::make_unique<Renderer>(std::forward<Args>(args)...)) + , mailbox(std::make_shared<Mailbox>(*this)) + , callback(callback_) + , rendererRef(*renderer, mailbox) { + } + + ~AndroidGLThread() override = default; + + ActorRef<Renderer> actor() const { + return rendererRef; + } + + void schedule(std::weak_ptr<Mailbox> scheduled) override { + { + std::lock_guard<std::mutex> lock(mutex); + queue.push(scheduled); + } + + callback.invoke(&InvalidateCallback::operator()); + } + + // Only safe on the GL Thread + void process() { + while (true) { + std::unique_lock<std::mutex> lock(mutex); + + if (queue.empty()) { + return; + } + + auto scheduled = queue.front(); + queue.pop(); + + lock.unlock(); + + Mailbox::maybeReceive(scheduled); + } + } + + // Only safe to access on the GL Thread + std::unique_ptr<Renderer> renderer; + +private: + std::mutex mutex; + std::queue<std::weak_ptr<Mailbox>> queue; + + std::shared_ptr<Mailbox> mailbox; + ActorRef<InvalidateCallback> callback; + ActorRef<Renderer> rendererRef; +}; + +} // namespace android +} // namespace mbgl diff --git a/platform/android/src/android_renderer_frontend.cpp b/platform/android/src/android_renderer_frontend.cpp index 73cb0a817e..b010022d94 100644 --- a/platform/android/src/android_renderer_frontend.cpp +++ b/platform/android/src/android_renderer_frontend.cpp @@ -7,6 +7,7 @@ #include <mbgl/storage/file_source.hpp> #include <mbgl/util/thread.hpp> #include <mbgl/util/run_loop.hpp> +#include <mbgl/util/logging.hpp> #include "android_renderer_backend.hpp" @@ -68,8 +69,16 @@ AndroidRendererFrontend::AndroidRendererFrontend(float pixelRatio, std::string programCacheDir, InvalidateCallback invalidate) : backend(std::make_unique<AndroidRendererBackend>()) - , renderer(std::make_unique<util::Thread<Renderer>>( - "Orchestration Thread", + , glThreadCallback(std::make_unique<Actor<AndroidGLThread::InvalidateCallback>>( + *Scheduler::GetCurrent(), + [&]() { + Log::Info(Event::JNI, "GL Thread invalidate callback"); + // TODO: replace the whole thing with rendererOberver.invalidate()? + asyncInvalidate.send(); + } + )) + , glThread(std::make_unique<AndroidGLThread>( + glThreadCallback->self(), *backend, pixelRatio, fileSource, @@ -86,15 +95,15 @@ AndroidRendererFrontend::AndroidRendererFrontend(float pixelRatio, AndroidRendererFrontend::~AndroidRendererFrontend() = default; void AndroidRendererFrontend::reset() { - assert(renderer); - renderer.reset(); + assert(glThread); + glThread.reset(); } void AndroidRendererFrontend::setObserver(RendererObserver& observer) { - assert (renderer); + assert (glThread); assert (util::RunLoop::Get()); rendererObserver = std::make_unique<ForwardingRendererObserver>(*mapRunLoop, observer); - renderer->actor().invoke(&Renderer::setObserver, rendererObserver.get()); + glThread->actor().invoke(&Renderer::setObserver, rendererObserver.get()); } void AndroidRendererFrontend::update(std::shared_ptr<UpdateParameters> params) { @@ -104,66 +113,66 @@ void AndroidRendererFrontend::update(std::shared_ptr<UpdateParameters> params) { // Called on OpenGL thread void AndroidRendererFrontend::render() { - assert (renderer); + assert (glThread); if (!updateParameters) return; + // Process the gl thread mailbox + glThread->process(); + // Activate the backend BackendScope backendGuard { *backend }; - // Block the orchestration thread during render - util::BlockingThreadGuard<Renderer> rendererGuard { *renderer }; - // Ensure that the "current" scheduler on the render thread is // actually the scheduler from the orchestration thread - Scheduler::SetCurrent(renderer.get()); + Scheduler::SetCurrent(glThread.get()); if (framebufferSizeChanged) { backend->updateViewPort(); framebufferSizeChanged = false; } - rendererGuard.object().render(*updateParameters); + glThread->renderer->render(*updateParameters); } void AndroidRendererFrontend::onLowMemory() { - assert (renderer); - renderer->actor().invoke(&Renderer::onLowMemory); + assert (glThread); + glThread->actor().invoke(&Renderer::onLowMemory); } std::vector<Feature> AndroidRendererFrontend::querySourceFeatures(const std::string& sourceID, const SourceQueryOptions& options) const { - assert (renderer); + assert (glThread); // Waits for the result from the orchestration thread and returns - return renderer->actor().ask(&Renderer::querySourceFeatures, sourceID, options).get(); + return glThread->actor().ask(&Renderer::querySourceFeatures, sourceID, options).get(); } std::vector<Feature> AndroidRendererFrontend::queryRenderedFeatures(const ScreenBox& box, const RenderedQueryOptions& options) const { - assert (renderer); + assert (glThread); // Select the right overloaded method std::vector<Feature> (Renderer::*fn)(const ScreenBox&, const RenderedQueryOptions&) const = &Renderer::queryRenderedFeatures; // Waits for the result from the orchestration thread and returns - return renderer->actor().ask(fn, box, options).get(); + return glThread->actor().ask(fn, box, options).get(); } std::vector<Feature> AndroidRendererFrontend::queryRenderedFeatures(const ScreenCoordinate& point, const RenderedQueryOptions& options) const { - assert (renderer); + assert (glThread); // Select the right overloaded method std::vector<Feature> (Renderer::*fn)(const ScreenCoordinate&, const RenderedQueryOptions&) const = &Renderer::queryRenderedFeatures; // Waits for the result from the orchestration thread and returns - return renderer->actor().ask(fn, point, options).get(); + return glThread->actor().ask(fn, point, options).get(); } AnnotationIDs AndroidRendererFrontend::queryPointAnnotations(const ScreenBox& box) const { - assert (renderer); + assert (glThread); // Waits for the result from the orchestration thread and returns - return renderer->actor().ask(&Renderer::queryPointAnnotations, box).get(); + return glThread->actor().ask(&Renderer::queryPointAnnotations, box).get(); } void AndroidRendererFrontend::requestSnapshot(SnapshotCallback callback_) { @@ -175,7 +184,6 @@ void AndroidRendererFrontend::requestSnapshot(SnapshotCallback callback_) { } void AndroidRendererFrontend::resizeFramebuffer(int width, int height) { - util::BlockingThreadGuard<Renderer> guard { *renderer }; backend->resizeFramebuffer(width, height); framebufferSizeChanged = true; // TODO: thread safe? diff --git a/platform/android/src/android_renderer_frontend.hpp b/platform/android/src/android_renderer_frontend.hpp index ca7c27b196..4e57f80d53 100644 --- a/platform/android/src/android_renderer_frontend.hpp +++ b/platform/android/src/android_renderer_frontend.hpp @@ -1,6 +1,9 @@ #pragma once +#include "android_gl_thread.hpp" + +#include <mbgl/actor/actor.hpp> #include <mbgl/annotation/annotation.hpp> #include <mbgl/renderer/renderer_backend.hpp> #include <mbgl/renderer/renderer_frontend.hpp> @@ -16,17 +19,11 @@ namespace mbgl { -class Renderer; - class FileSource; class Scheduler; class RenderedQueryOptions; class SourceQueryOptions; -namespace util { -template <class> class Thread; -} // namespace util - namespace android { class AndroidRendererBackend; @@ -68,7 +65,8 @@ public: private: std::unique_ptr<AndroidRendererBackend> backend; - std::unique_ptr<util::Thread<Renderer>> renderer; + std::unique_ptr<Actor<AndroidGLThread::InvalidateCallback>> glThreadCallback; + std::unique_ptr<AndroidGLThread> glThread; std::unique_ptr<RendererObserver> rendererObserver; std::shared_ptr<UpdateParameters> updateParameters; util::AsyncTask asyncInvalidate; |