drive Android rendering from the main thread via invalidate() calls
This commit is contained in:
committed by
John Firebaugh
parent
84e2ea886d
commit
dca42018d2
@@ -30,6 +30,7 @@ std::string dataPath;
|
||||
std::string apkPath;
|
||||
std::string androidRelease;
|
||||
|
||||
jmethodID onInvalidateId = nullptr;
|
||||
jmethodID onMapChangedId = nullptr;
|
||||
jmethodID onFpsChangedId = nullptr;
|
||||
|
||||
@@ -277,6 +278,13 @@ void JNICALL nativeUpdate(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
|
||||
nativeMapView->getMap().update();
|
||||
}
|
||||
|
||||
void JNICALL nativeOnInvalidate(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) {
|
||||
mbgl::Log::Debug(mbgl::Event::JNI, "nativeOnInvalidate");
|
||||
assert(nativeMapViewPtr != 0);
|
||||
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
|
||||
nativeMapView->onInvalidate();
|
||||
}
|
||||
|
||||
void JNICALL nativeResize(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jint width, jint height,
|
||||
jfloat ratio, jint fbWidth, jint fbHeight) {
|
||||
mbgl::Log::Debug(mbgl::Event::JNI, "nativeResize");
|
||||
@@ -805,6 +813,12 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
onInvalidateId = env->GetMethodID(nativeMapViewClass, "onInvalidate", "()V");
|
||||
if (onInvalidateId == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
onMapChangedId = env->GetMethodID(nativeMapViewClass, "onMapChanged", "()V");
|
||||
if (onMapChangedId == nullptr) {
|
||||
env->ExceptionDescribe();
|
||||
@@ -921,6 +935,7 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
|
||||
{"nativePause", "(J)V", reinterpret_cast<void *>(&nativePause)},
|
||||
{"nativeResume", "(J)V", reinterpret_cast<void *>(&nativeResume)},
|
||||
{"nativeUpdate", "(J)V", reinterpret_cast<void *>(&nativeUpdate)},
|
||||
{"nativeOnInvalidate", "(J)V", reinterpret_cast<void *>(&nativeOnInvalidate)},
|
||||
{"nativeResize", "(JIIFII)V",
|
||||
reinterpret_cast<void *>(static_cast<void JNICALL (
|
||||
*)(JNIEnv *, jobject, jlong, jint, jint, jfloat, jint, jint)>(&nativeResize))},
|
||||
@@ -1092,6 +1107,7 @@ extern "C" JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) {
|
||||
latLngZoomLatitudeId = nullptr;
|
||||
latLngZoomZoomId = nullptr;
|
||||
|
||||
onInvalidateId = nullptr;
|
||||
onMapChangedId = nullptr;
|
||||
onFpsChangedId = nullptr;
|
||||
|
||||
|
||||
@@ -125,13 +125,49 @@ void NativeMapView::deactivate() {
|
||||
}
|
||||
|
||||
void NativeMapView::invalidate() {
|
||||
mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::invalidate");
|
||||
mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::invalidate()");
|
||||
|
||||
// TODO: inform the main thread that it must call map->renderSync();
|
||||
clean.clear();
|
||||
|
||||
assert(vm != nullptr);
|
||||
assert(obj != nullptr);
|
||||
|
||||
JavaVMAttachArgs args = {JNI_VERSION_1_2, "NativeMapView::invalidate()", NULL};
|
||||
|
||||
jint ret;
|
||||
JNIEnv *env = nullptr;
|
||||
bool detach = false;
|
||||
ret = vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6);
|
||||
if (ret != JNI_OK) {
|
||||
if (ret != JNI_EDETACHED) {
|
||||
mbgl::Log::Error(mbgl::Event::JNI, "GetEnv() failed with %i", ret);
|
||||
throw new std::runtime_error("GetEnv() failed");
|
||||
} else {
|
||||
ret = vm->AttachCurrentThread(&env, &args);
|
||||
if (ret != JNI_OK) {
|
||||
mbgl::Log::Error(mbgl::Event::JNI, "AttachCurrentThread() failed with %i", ret);
|
||||
throw new std::runtime_error("AttachCurrentThread() failed");
|
||||
}
|
||||
detach = true;
|
||||
}
|
||||
}
|
||||
|
||||
env->CallVoidMethod(obj, onInvalidateId);
|
||||
if (env->ExceptionCheck()) {
|
||||
env->ExceptionDescribe();
|
||||
}
|
||||
|
||||
if (detach) {
|
||||
if ((ret = vm->DetachCurrentThread()) != JNI_OK) {
|
||||
mbgl::Log::Error(mbgl::Event::JNI, "DetachCurrentThread() failed with %i", ret);
|
||||
throw new std::runtime_error("DetachCurrentThread() failed");
|
||||
}
|
||||
}
|
||||
env = nullptr;
|
||||
}
|
||||
|
||||
void NativeMapView::swap() {
|
||||
mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::invalidate");
|
||||
mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::swap");
|
||||
|
||||
if ((display != EGL_NO_DISPLAY) && (surface != EGL_NO_SURFACE)) {
|
||||
if (!eglSwapBuffers(display, surface)) {
|
||||
@@ -709,5 +745,14 @@ void NativeMapView::updateFps() {
|
||||
env = nullptr;
|
||||
}
|
||||
|
||||
void NativeMapView::onInvalidate() {
|
||||
mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::onInvalidate()");
|
||||
|
||||
const bool dirty = !clean.test_and_set();
|
||||
if (dirty) {
|
||||
map.renderSync();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.view.SurfaceView;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.widget.ZoomButtonsController;
|
||||
import android.util.Log;
|
||||
|
||||
import com.almeros.android.multitouch.gesturedetectors.RotateGestureDetector;
|
||||
import com.almeros.android.multitouch.gesturedetectors.TwoFingerGestureDetector;
|
||||
@@ -1168,6 +1169,18 @@ public class MapView extends SurfaceView {
|
||||
// Map events
|
||||
//
|
||||
|
||||
// Called when the map needs to be rerendered
|
||||
// Called via JNI from NativeMapView
|
||||
protected void onInvalidate() {
|
||||
post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mNativeMapView.invalidate();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public interface OnMapChangedListener {
|
||||
void onMapChanged();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.mapbox.mapboxgl.views;
|
||||
|
||||
import android.graphics.PointF;
|
||||
import android.view.Surface;
|
||||
import android.util.Log;
|
||||
|
||||
import com.mapbox.mapboxgl.geometry.LatLng;
|
||||
import com.mapbox.mapboxgl.geometry.LatLngZoom;
|
||||
@@ -85,6 +86,10 @@ class NativeMapView {
|
||||
nativeUpdate(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
nativeOnInvalidate(mNativeMapViewPtr);
|
||||
}
|
||||
|
||||
public void resize(int width, int height, float ratio, int fbWidth,
|
||||
int fbHeight) {
|
||||
if (width < 0) {
|
||||
@@ -342,6 +347,10 @@ class NativeMapView {
|
||||
// Callbacks
|
||||
//
|
||||
|
||||
protected void onInvalidate() {
|
||||
mMapView.onInvalidate();
|
||||
}
|
||||
|
||||
protected void onMapChanged() {
|
||||
mMapView.onMapChanged();
|
||||
}
|
||||
@@ -384,6 +393,8 @@ class NativeMapView {
|
||||
|
||||
private native void nativeUpdate(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeOnInvalidate(long nativeMapViewPtr);
|
||||
|
||||
private native void nativeResize(long nativeMapViewPtr, int width,
|
||||
int height, float ratio, int fbWidth, int fbHeight);
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ extern std::string dataPath;
|
||||
extern std::string apkPath;
|
||||
extern std::string androidRelease;
|
||||
|
||||
extern jmethodID onInvalidateId;
|
||||
extern jmethodID onMapChangedId;
|
||||
extern jmethodID onFpsChangedId;
|
||||
|
||||
|
||||
@@ -46,6 +46,8 @@ public:
|
||||
void enableFps(bool enable);
|
||||
void updateFps();
|
||||
|
||||
void onInvalidate();
|
||||
|
||||
private:
|
||||
EGLConfig chooseConfig(const EGLConfig configs[], EGLint numConfigs);
|
||||
|
||||
@@ -76,6 +78,7 @@ private:
|
||||
mbgl::DefaultFileSource fileSource;
|
||||
mbgl::Map map;
|
||||
|
||||
std::atomic_flag clean = ATOMIC_FLAG_INIT;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user