diff options
author | Ivo van Dongen <info@ivovandongen.nl> | 2017-09-14 21:23:07 +0300 |
---|---|---|
committer | Ivo van Dongen <ivovandongen@users.noreply.github.com> | 2017-09-22 23:33:56 +0300 |
commit | 5d12503302dff168137d6f3b1444e4dc32ad44dd (patch) | |
tree | 98128bdddb287c30b2c1445eb88d44e9a97d57ab /platform/android/src/map_renderer.cpp | |
parent | 15a47d116a0fc15d249b37574fcd932ce88909df (diff) | |
download | qtlocation-mapboxgl-5d12503302dff168137d6f3b1444e4dc32ad44dd.tar.gz |
[android] self-contained map renderer
- Isolates the GL thread in a MapRenderer class with a native peer
Diffstat (limited to 'platform/android/src/map_renderer.cpp')
-rw-r--r-- | platform/android/src/map_renderer.cpp | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/platform/android/src/map_renderer.cpp b/platform/android/src/map_renderer.cpp new file mode 100644 index 0000000000..8346d2f139 --- /dev/null +++ b/platform/android/src/map_renderer.cpp @@ -0,0 +1,137 @@ +#include "map_renderer.hpp" + +#include <mbgl/renderer/renderer.hpp> +#include <mbgl/util/shared_thread_pool.hpp> + +#include <string> + +#include "attach_env.hpp" +#include "android_renderer_backend.hpp" +#include "map_renderer_runnable.hpp" +#include "file_source.hpp" + +namespace mbgl { +namespace android { + +MapRenderer::MapRenderer(jni::JNIEnv& _env, + jni::Object<MapRenderer> obj, + jni::Object<FileSource> fileSource, + jni::jfloat pixelRatio, + jni::String programCacheDir) + : javaPeer(SeizeGenericWeakRef(_env, jni::Object<MapRenderer>(jni::NewWeakGlobalRef(_env, obj.Get()).release()))) + , threadPool(sharedThreadPool()) + , backend(std::make_unique<AndroidRendererBackend>()) + , renderer(std::make_unique<Renderer>(*backend, pixelRatio, FileSource::getDefaultFileSource(_env, fileSource), + *threadPool, GLContextMode::Unique, jni::Make<std::string>(_env, programCacheDir))) + , mailbox(std::make_shared<Mailbox>(*this)) + , rendererRef(*renderer, mailbox) { +} + +MapRenderer::~MapRenderer() = default; + +void MapRenderer::reset() { + assert (renderer); + renderer.reset(); +} + +ActorRef<Renderer> MapRenderer::actor() const { + return rendererRef; +} + +void MapRenderer::schedule(std::weak_ptr<Mailbox> scheduled) { + // Create a runnable and schedule it on the gl thread + android::UniqueEnv _env = android::AttachEnv(); + auto runnable = std::make_unique<MapRendererRunnable>(*_env, std::move(scheduled)); + + static auto queueEvent = javaClass.GetMethod<void (jni::Object<MapRendererRunnable>)>(*_env, "queueEvent"); + javaPeer->Call(*_env, queueEvent, runnable->getPeer()); + + // Release the object as it will be destroyed on GC of the Java Peer + runnable.release(); +} + +void MapRenderer::requestRender() { + android::UniqueEnv _env = android::AttachEnv(); + static auto onInvalidate = javaClass.GetMethod<void ()>(*_env, "requestRender"); + javaPeer->Call(*_env, onInvalidate); +} + +void MapRenderer::update(std::shared_ptr<UpdateParameters> params) { + // Lock on the parameters + std::lock_guard<std::mutex> lock(updateMutex); + updateParameters = std::move(params); +} + +// Called on OpenGL thread // + +void MapRenderer::render(JNIEnv&) { + assert (renderer); + + std::shared_ptr<UpdateParameters> params; + { + // Lock on the parameters + std::unique_lock<std::mutex> lock(updateMutex); + if (!updateParameters) return; + + // Hold on to the update parameters during render + params = updateParameters; + } + + // Activate the backend + BackendScope backendGuard { *backend }; + + // Ensure that the "current" scheduler on the render thread is + // this scheduler. + Scheduler::SetCurrent(this); + + if (framebufferSizeChanged) { + backend->updateViewPort(); + framebufferSizeChanged = false; + } + + renderer->render(*params); +} + +void MapRenderer::onSurfaceCreated(JNIEnv&) { + // TODO (re-)create Context, Backend and Renderer +} + +void MapRenderer::onSurfaceChanged(JNIEnv&, jint width, jint height) { + backend->resizeFramebuffer(width, height); + framebufferSizeChanged = true; + requestRender(); +} + +// Static methods // + +jni::Class<MapRenderer> MapRenderer::javaClass; + +void MapRenderer::registerNative(jni::JNIEnv& env) { + // Lookup the class + MapRenderer::javaClass = *jni::Class<MapRenderer>::Find(env).NewGlobalRef(env).release(); + +#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) + + // Register the peer + jni::RegisterNativePeer<MapRenderer>( + env, + MapRenderer::javaClass, + "nativePtr", + std::make_unique<MapRenderer, JNIEnv&, jni::Object<MapRenderer>, jni::Object<FileSource>, jni::jfloat, jni::String>, + "nativeInitialize", + "finalize", + METHOD(&MapRenderer::render, "nativeRender"), + METHOD(&MapRenderer::onSurfaceCreated, "nativeOnSurfaceCreated"), + METHOD(&MapRenderer::onSurfaceChanged, "nativeOnSurfaceChanged") + ); +} + +MapRenderer& MapRenderer::getNativePeer(JNIEnv& env, jni::Object<MapRenderer> jObject) { + static auto field = MapRenderer::javaClass.GetField<jlong>(env, "nativePtr"); + MapRenderer* mapRenderer = reinterpret_cast<MapRenderer *>(jObject.Get(env, field)); + assert(mapRenderer != nullptr); + return *mapRenderer; +} + +} // namespace android +} // namespace mbgl |