summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvo van Dongen <info@ivovandongen.nl>2017-09-13 14:34:05 +0300
committerIvo van Dongen <ivovandongen@users.noreply.github.com>2017-09-22 23:33:56 +0300
commit67285f3a95f74966324fc59f271ba8b6b763b2b5 (patch)
tree444065837cebe710f54429cbfc61180c1e6f8ae8
parent6211db69680e08a1f463ec098ed843ca49a859b2 (diff)
downloadqtlocation-mapboxgl-67285f3a95f74966324fc59f271ba8b6b763b2b5.tar.gz
[android] Re-initialise renderer, backend and context when the android system destroyed the underlying gl resources
-rwxr-xr-xplatform/android/src/android_renderer_backend.cpp10
-rwxr-xr-xplatform/android/src/android_renderer_backend.hpp4
-rw-r--r--platform/android/src/android_renderer_frontend.cpp7
-rw-r--r--platform/android/src/android_renderer_frontend.hpp7
-rw-r--r--platform/android/src/map_renderer.cpp89
-rw-r--r--platform/android/src/map_renderer.hpp26
-rwxr-xr-xplatform/android/src/native_map_view.cpp1
7 files changed, 99 insertions, 45 deletions
diff --git a/platform/android/src/android_renderer_backend.cpp b/platform/android/src/android_renderer_backend.cpp
index 558395d296..9e49915650 100755
--- a/platform/android/src/android_renderer_backend.cpp
+++ b/platform/android/src/android_renderer_backend.cpp
@@ -1,5 +1,7 @@
#include "android_renderer_backend.hpp"
+#include <mbgl/gl/context.hpp>
+
#include <EGL/egl.h>
#include <cassert>
@@ -51,5 +53,11 @@ void AndroidRendererBackend::updateAssumedState() {
assumeViewport(0, 0, getFramebufferSize());
}
+void AndroidRendererBackend::markContextLost() {
+ if (context) {
+ context->setCleanupOnDestruction(false);
+ }
}
-}
+
+} // namespace android
+} // namspace mbgl
diff --git a/platform/android/src/android_renderer_backend.hpp b/platform/android/src/android_renderer_backend.hpp
index 8dbc1f2be8..c5c552459f 100755
--- a/platform/android/src/android_renderer_backend.hpp
+++ b/platform/android/src/android_renderer_backend.hpp
@@ -13,6 +13,10 @@ public:
void updateAssumedState() override;
mbgl::Size getFramebufferSize() const override;
+ // Ensures the current context is not
+ // cleaned up when destroyed
+ void markContextLost();
+
void updateViewPort();
void resizeFramebuffer(int width, int height);
diff --git a/platform/android/src/android_renderer_frontend.cpp b/platform/android/src/android_renderer_frontend.cpp
index 38b1ff252b..ac29639bd4 100644
--- a/platform/android/src/android_renderer_frontend.cpp
+++ b/platform/android/src/android_renderer_frontend.cpp
@@ -1,6 +1,7 @@
#include "android_renderer_frontend.hpp"
#include <mbgl/actor/scheduler.hpp>
+#include <mbgl/renderer/renderer.hpp>
#include <mbgl/renderer/renderer_observer.hpp>
#include <mbgl/storage/file_source.hpp>
#include <mbgl/util/thread.hpp>
@@ -63,13 +64,13 @@ AndroidRendererFrontend::~AndroidRendererFrontend() = default;
void AndroidRendererFrontend::reset() {
mapRenderer.reset();
- rendererObserver.reset();
}
void AndroidRendererFrontend::setObserver(RendererObserver& observer) {
assert (util::RunLoop::Get());
- rendererObserver = std::make_unique<ForwardingRendererObserver>(*mapRunLoop, observer);
- mapRenderer.actor().invoke(&Renderer::setObserver, rendererObserver.get());
+ // Don't call the Renderer directly, but use MapRenderer#setObserver to make sure
+ // the Renderer may be re-initialised without losing the RendererObserver reference.
+ mapRenderer.setObserver(std::make_unique<ForwardingRendererObserver>(*mapRunLoop, observer));
}
void AndroidRendererFrontend::update(std::shared_ptr<UpdateParameters> params) {
diff --git a/platform/android/src/android_renderer_frontend.hpp b/platform/android/src/android_renderer_frontend.hpp
index 598327838e..bb8323b390 100644
--- a/platform/android/src/android_renderer_frontend.hpp
+++ b/platform/android/src/android_renderer_frontend.hpp
@@ -2,7 +2,6 @@
#include <mbgl/actor/actor.hpp>
#include <mbgl/annotation/annotation.hpp>
-#include <mbgl/renderer/renderer_backend.hpp>
#include <mbgl/renderer/renderer_frontend.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/image.hpp>
@@ -17,15 +16,11 @@
namespace mbgl {
-class FileSource;
-class Scheduler;
class RenderedQueryOptions;
class SourceQueryOptions;
namespace android {
-class AndroidRendererBackend;
-
class AndroidRendererFrontend : public RendererFrontend {
public:
@@ -51,9 +46,7 @@ public:
void requestSnapshot(SnapshotCallback);
private:
- std::unique_ptr<RendererObserver> rendererObserver;
MapRenderer& mapRenderer;
-
util::RunLoop* mapRunLoop;
// TODO
diff --git a/platform/android/src/map_renderer.cpp b/platform/android/src/map_renderer.cpp
index 8346d2f139..b2186e6272 100644
--- a/platform/android/src/map_renderer.cpp
+++ b/platform/android/src/map_renderer.cpp
@@ -13,29 +13,29 @@
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(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()))), pixelRatio(pixelRatio_)
+ , fileSource(FileSource::getDefaultFileSource(_env, _fileSource))
+ , programCacheDir(jni::Make<std::string>(_env, programCacheDir_))
+ , threadPool(sharedThreadPool())
+ , mailbox(std::make_shared<Mailbox>(*this)) {
}
MapRenderer::~MapRenderer() = default;
-void MapRenderer::reset() {
+void MapRenderer::reset() {
assert (renderer);
renderer.reset();
+
+ // Lock to make sure there is no concurrent initialisation on the gl thread
+ std::lock_guard<std::mutex> lock(initialisationMutex);
+ rendererObserver.reset();
}
ActorRef<Renderer> MapRenderer::actor() const {
- return rendererRef;
+ return *rendererRef;
}
void MapRenderer::schedule(std::weak_ptr<Mailbox> scheduled) {
@@ -43,7 +43,8 @@ void MapRenderer::schedule(std::weak_ptr<Mailbox> scheduled) {
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");
+ 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
@@ -52,7 +53,7 @@ void MapRenderer::schedule(std::weak_ptr<Mailbox> scheduled) {
void MapRenderer::requestRender() {
android::UniqueEnv _env = android::AttachEnv();
- static auto onInvalidate = javaClass.GetMethod<void ()>(*_env, "requestRender");
+ static auto onInvalidate = javaClass.GetMethod<void()>(*_env, "requestRender");
javaPeer->Call(*_env, onInvalidate);
}
@@ -62,6 +63,18 @@ void MapRenderer::update(std::shared_ptr<UpdateParameters> params) {
updateParameters = std::move(params);
}
+void MapRenderer::setObserver(std::shared_ptr<RendererObserver> _rendererObserver) {
+ // Lock as the initialization can come from the main thread or the GL thread first
+ std::lock_guard<std::mutex> lock(initialisationMutex);
+
+ rendererObserver = std::move(_rendererObserver);
+
+ // Set the new observer on the Renderer implementation
+ if (renderer) {
+ renderer->setObserver(rendererObserver.get());
+ }
+}
+
// Called on OpenGL thread //
void MapRenderer::render(JNIEnv&) {
@@ -93,7 +106,28 @@ void MapRenderer::render(JNIEnv&) {
}
void MapRenderer::onSurfaceCreated(JNIEnv&) {
- // TODO (re-)create Context, Backend and Renderer
+ // Lock as the initialization can come from the main thread or the GL thread first
+ std::lock_guard<std::mutex> lock(initialisationMutex);
+
+ // The android system will have already destroyed the underlying
+ // GL resources if this is not the first intialization and an
+ // attempt to clean them up will fail
+ if (backend) backend->markContextLost();
+
+ // Reset in opposite order
+ renderer.reset();
+ backend.reset();
+
+ // Create the new backend and renderer
+ backend = std::make_unique<AndroidRendererBackend>();
+ renderer = std::make_unique<Renderer>(*backend, pixelRatio, fileSource, *threadPool,
+ GLContextMode::Unique, programCacheDir);
+ rendererRef = std::make_unique<ActorRef<Renderer>>(*renderer, mailbox);
+
+ // Set the observer on the new Renderer implementation
+ if (rendererObserver) {
+ renderer->setObserver(rendererObserver.get());
+ }
}
void MapRenderer::onSurfaceChanged(JNIEnv&, jint width, jint height) {
@@ -113,22 +147,19 @@ void MapRenderer::registerNative(jni::JNIEnv& env) {
#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")
- );
+ 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));
+ MapRenderer* mapRenderer = reinterpret_cast<MapRenderer*>(jObject.Get(env, field));
assert(mapRenderer != nullptr);
return *mapRenderer;
}
diff --git a/platform/android/src/map_renderer.hpp b/platform/android/src/map_renderer.hpp
index 51fca48ee6..ca216fc240 100644
--- a/platform/android/src/map_renderer.hpp
+++ b/platform/android/src/map_renderer.hpp
@@ -1,21 +1,23 @@
#pragma once
-#include <mbgl/actor/actor_ref.hpp>
-#include <mbgl/actor/mailbox.hpp>
#include <mbgl/actor/scheduler.hpp>
-#include <mbgl/renderer/renderer.hpp>
#include <memory>
#include <utility>
#include <jni/jni.hpp>
+#include <mbgl/storage/default_file_source.hpp>
#include "jni/generic_global_ref_deleter.hpp"
namespace mbgl {
+template <class>
+class ActorRef;
+class Mailbox;
class Renderer;
class RendererBackend;
+class RendererObserver;
class ThreadPool;
class UpdateParameters;
@@ -52,6 +54,11 @@ public:
// Resets the renderer to clean up on the calling thread
void reset();
+ // Takes the RendererObserver by shared_ptr so we
+ // don't have to make the header public. Use
+ // this instead of Renderer#setObserver directly
+ void setObserver(std::shared_ptr<RendererObserver>);
+
// Sets the new update parameters to use on subsequent
// renders. Be sure to trigger a render with
// requestRender().
@@ -79,11 +86,20 @@ private:
private:
GenericUniqueWeakObject<MapRenderer> javaPeer;
+
+ float pixelRatio;
+ DefaultFileSource& fileSource;
+ std::string programCacheDir;
+
std::shared_ptr<ThreadPool> threadPool;
+ std::shared_ptr<Mailbox> mailbox;
+
+ std::mutex initialisationMutex;
+ std::shared_ptr<RendererObserver> rendererObserver;
+
std::unique_ptr<AndroidRendererBackend> backend;
std::unique_ptr<Renderer> renderer;
- std::shared_ptr<Mailbox> mailbox;
- ActorRef<Renderer> rendererRef;
+ std::unique_ptr<ActorRef<Renderer>> rendererRef;
std::shared_ptr<UpdateParameters> updateParameters;
std::mutex updateMutex;
diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp
index f7f487f227..e44bd023c5 100755
--- a/platform/android/src/native_map_view.cpp
+++ b/platform/android/src/native_map_view.cpp
@@ -26,6 +26,7 @@
#include <mbgl/style/style.hpp>
#include <mbgl/style/image.hpp>
#include <mbgl/style/filter.hpp>
+#include <mbgl/renderer/query.hpp>
// Java -> C++ conversion
#include "style/android_conversion.hpp"