diff options
author | Ivo van Dongen <info@ivovandongen.nl> | 2017-09-13 14:34:05 +0300 |
---|---|---|
committer | Ivo van Dongen <info@ivovandongen.nl> | 2017-09-13 14:37:11 +0300 |
commit | 8d5fef5f9941c62ac49cd01af18e47e85927d8e9 (patch) | |
tree | 5f2dcae3d3458ca0932f99547467dd6fd5f54076 | |
parent | e76d7df35a26c8e6274d5386463145506a3cf160 (diff) | |
download | qtlocation-mapboxgl-upstream/ivd-android-glsurfaceview-3tier.tar.gz |
[android] Re-initialise renderer, backend and context when the android system destroyed the underlying gl resourcesupstream/ivd-android-glsurfaceview-3tier
6 files changed, 80 insertions, 19 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java index d1faa910bb..dece1a1dce 100755 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java @@ -903,6 +903,8 @@ final class NativeMapView implements GLSurfaceView.Renderer { float pixelRatio, String programCacheDir); + private native void nativeOnSurfaceCreated(); + private native void nativeDestroy(); private native void nativeInitializeDisplay(); @@ -1142,6 +1144,7 @@ final class NativeMapView implements GLSurfaceView.Renderer { @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { Timber.i("[%s] onSurfaceCreated", Thread.currentThread().getName()); + nativeOnSurfaceCreated(); //TODO: callback to map to re-create renderer? } diff --git a/platform/android/src/android_renderer_backend.cpp b/platform/android/src/android_renderer_backend.cpp index eac12177a5..536090ddec 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,12 @@ void AndroidRendererBackend::updateAssumedState() { assumeViewport(0, 0, getFramebufferSize()); } + +void AndroidRendererBackend::abandonContext() { + 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 0cc9d1b682..16cc782132 100755 --- a/platform/android/src/android_renderer_backend.hpp +++ b/platform/android/src/android_renderer_backend.hpp @@ -12,6 +12,10 @@ public: void bind() override; void updateAssumedState() override; + // Ensures the current context is not + // cleaned up when destroyed + void abandonContext(); + 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 6ad7872f89..11bb9ab3fc 100644 --- a/platform/android/src/android_renderer_frontend.cpp +++ b/platform/android/src/android_renderer_frontend.cpp @@ -62,22 +62,16 @@ private: RendererObserver& delegate; }; -AndroidRendererFrontend::AndroidRendererFrontend(float pixelRatio, - FileSource& fileSource, - Scheduler& scheduler, - std::string programCacheDir, - InvalidateCallback invalidate) - : backend(std::make_unique<AndroidRendererBackend>()) - , renderer(std::make_unique<util::Thread<Renderer>>( - "Orchestration Thread", - *backend, - pixelRatio, - fileSource, - scheduler, - GLContextMode::Unique, - programCacheDir - )) - , asyncInvalidate([=, invalidate=std::move(invalidate)]() { +AndroidRendererFrontend::AndroidRendererFrontend(float pixelRatio_, + FileSource& fileSource_, + Scheduler& scheduler_, + std::string programCacheDir_, + InvalidateCallback invalidate_) + : pixelRatio(pixelRatio_) + , fileSource(fileSource_) + , scheduler(scheduler_) + , programCacheDir(programCacheDir_) + , asyncInvalidate([=, invalidate=std::move(invalidate_)]() { invalidate(); }) , mapRunLoop(util::RunLoop::Get()) { @@ -90,11 +84,50 @@ void AndroidRendererFrontend::reset() { renderer.reset(); } +void AndroidRendererFrontend::initialise() { + // Lock as the initialization can come from the main thread or the GL thread first + std::lock_guard<std::mutex> lock(intitialisationMutex); + + if (backend) { + // The android system will have already destroyed the underlying + // GL resources and an attempt to clean them up will fail + backend->abandonContext(); + } + + // Destroy in reverse order + renderer.reset(); + backend.reset(); + + // Re-create + backend = std::make_unique<AndroidRendererBackend>(); + renderer = std::make_unique<util::Thread<Renderer>>( + "Orchestration Thread", + *backend, + pixelRatio, + fileSource, + scheduler, + GLContextMode::Unique, + programCacheDir + ); + + // Set the observer on the new Renderer implementation + if (rendererObserver) { + renderer->actor().invoke(&Renderer::setObserver, rendererObserver.get()); + } +} + void AndroidRendererFrontend::setObserver(RendererObserver& observer) { - assert (renderer); assert (util::RunLoop::Get()); + + // Lock as the initialization can come from the main thread or the GL thread first + std::lock_guard<std::mutex> lock(intitialisationMutex); + rendererObserver = std::make_unique<ForwardingRendererObserver>(*mapRunLoop, observer); - renderer->actor().invoke(&Renderer::setObserver, rendererObserver.get()); + + // Set the new observer on the Renderer implementation + if (renderer) { + renderer->actor().invoke(&Renderer::setObserver, rendererObserver.get()); + } } 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 36db705f2e..9c90e63c83 100644 --- a/platform/android/src/android_renderer_frontend.hpp +++ b/platform/android/src/android_renderer_frontend.hpp @@ -42,6 +42,7 @@ public: InvalidateCallback); ~AndroidRendererFrontend() override; + void initialise(); void reset() override; void setObserver(RendererObserver&) override; @@ -67,6 +68,11 @@ public: void requestSnapshot(SnapshotCallback); private: + float pixelRatio; + FileSource& fileSource; + Scheduler& scheduler; + std::string programCacheDir; + std::unique_ptr<AndroidRendererBackend> backend; std::unique_ptr<util::Thread<Renderer>> renderer; std::unique_ptr<RendererObserver> rendererObserver; @@ -74,6 +80,7 @@ private: std::mutex updateMutex; std::shared_ptr<UpdateParameters> updateParameters; + std::mutex intitialisationMutex; util::AsyncTask asyncInvalidate; diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp index 1a0dc34bbc..e55628b202 100755 --- a/platform/android/src/native_map_view.cpp +++ b/platform/android/src/native_map_view.cpp @@ -187,6 +187,10 @@ void NativeMapView::onSourceChanged(mbgl::style::Source&) { // JNI Methods // +void NativeMapView::onSurfaceCreated(jni::JNIEnv&) { + rendererFrontend->initialise(); +} + // Called from the OpenGL renderer thread void NativeMapView::render(jni::JNIEnv& ) { rendererFrontend->render(); @@ -1003,6 +1007,7 @@ void NativeMapView::registerNative(jni::JNIEnv& env) { std::make_unique<NativeMapView, JNIEnv&, jni::Object<NativeMapView>, jni::Object<FileSource>, jni::jfloat, jni::String>, "nativeInitialize", "nativeDestroy", + METHOD(&NativeMapView::onSurfaceCreated, "nativeOnSurfaceCreated"), METHOD(&NativeMapView::render, "nativeRender"), METHOD(&NativeMapView::update, "nativeUpdate"), METHOD(&NativeMapView::resizeView, "nativeResizeView"), |