Fix laggy map when using synchronous GeoJSON source [Core fix] (#4092)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Bart Louwers <bart@emeel.net> Co-authored-by: Bart Louwers <bart.louwers@gmail.com>
This commit is contained in:
@@ -2,7 +2,21 @@
|
||||
|
||||
## 13.0.0
|
||||
|
||||
- Use Vulkan as rendering backend for the `org.maplibre.gl:android-sdk` package. You can still use OpenGL ES with the `org.maplibre.gl:android-sdk-opengl` package.
|
||||
### ✨ Features and improvements
|
||||
|
||||
- 💥 **Breaking:** Use Vulkan as rendering backend for the `org.maplibre.gl:android-sdk` package. You can still use OpenGL ES with the `org.maplibre.gl:android-sdk-opengl` package.
|
||||
|
||||
- core, android: add support for camera roll ([#3011](https://github.com/maplibre/maplibre-native/pull/3011)).
|
||||
- Add multithreaded upload to dynamic texture on Vulkan [Core feature] ([#4028](https://github.com/maplibre/maplibre-native/pull/4028)).
|
||||
- core: Avoid unnecessary raster buffer updates ([#4085](https://github.com/maplibre/maplibre-native/pull/4085)).
|
||||
|
||||
### 🐞 Bug fixes
|
||||
|
||||
- Fix laggy map when using synchronous GeoJSON source [#4092](https://github.com/maplibre/maplibre-native/pull/4092).
|
||||
This replaces the synchronous methods on `GeoJsonSource` introduced in [#3560](https://github.com/maplibre/maplibre-native/pull/3560). To migrate, pass `GeoJsonOptions` with `options.withSynchronousUpdate(true)` when constructing a `GeoJsonSource`.
|
||||
- Do not capture this in Android GeoJSONSource ([#3976](https://github.com/maplibre/maplibre-native/pull/3976)).
|
||||
- Fix Vulkan headless backend resize ([#4030](https://github.com/maplibre/maplibre-native/pull/4030)).
|
||||
- Disable scissor test when clearing on OpenGL ([#4029](https://github.com/maplibre/maplibre-native/pull/4029)).
|
||||
|
||||
## 12.3.1
|
||||
|
||||
|
||||
@@ -49,20 +49,24 @@ GeoJSONSource::GeoJSONSource(jni::JNIEnv& env, const jni::String& sourceId, cons
|
||||
: Source(env,
|
||||
std::make_unique<mbgl::style::GeoJSONSource>(jni::Make<std::string>(env, sourceId),
|
||||
convertGeoJSONOptions(env, options))),
|
||||
converter(std::make_unique<Actor<FeatureConverter>>(Scheduler::GetBackground(),
|
||||
source.as<style::GeoJSONSource>()->impl().getOptions())) {}
|
||||
converter(
|
||||
std::make_unique<OptionalActor<FeatureConverter>>(source.as<style::GeoJSONSource>()->isUpdateSynchronous(),
|
||||
Scheduler::GetBackground(),
|
||||
source.as<style::GeoJSONSource>()->impl().getOptions())) {}
|
||||
|
||||
GeoJSONSource::GeoJSONSource(jni::JNIEnv& env, mbgl::style::Source& coreSource, AndroidRendererFrontend* frontend)
|
||||
: Source(env, coreSource, createJavaPeer(env), frontend),
|
||||
converter(std::make_unique<Actor<FeatureConverter>>(Scheduler::GetBackground(),
|
||||
source.as<style::GeoJSONSource>()->impl().getOptions())) {}
|
||||
converter(
|
||||
std::make_unique<OptionalActor<FeatureConverter>>(source.as<style::GeoJSONSource>()->isUpdateSynchronous(),
|
||||
Scheduler::GetBackground(),
|
||||
source.as<style::GeoJSONSource>()->impl().getOptions())) {}
|
||||
|
||||
GeoJSONSource::~GeoJSONSource() = default;
|
||||
|
||||
void GeoJSONSource::setGeoJSONString(jni::JNIEnv& env, const jni::String& jString) {
|
||||
std::shared_ptr<std::string> json = std::make_shared<std::string>(jni::Make<std::string>(env, jString));
|
||||
|
||||
ActorRef<FeatureConverter> converterRef = converter->self();
|
||||
OptionalActorRef<FeatureConverter> converterRef = converter->self();
|
||||
Update::Converter converterFn = [converterRef, json](ActorRef<GeoJSONDataCallback> _callback) {
|
||||
converterRef.invoke(&FeatureConverter::convertJson, json, _callback);
|
||||
};
|
||||
@@ -70,17 +74,6 @@ void GeoJSONSource::setGeoJSONString(jni::JNIEnv& env, const jni::String& jStrin
|
||||
setAsync(converterFn);
|
||||
}
|
||||
|
||||
void GeoJSONSource::setGeoJSONStringSync(jni::JNIEnv& env, const jni::String& jString) {
|
||||
std::shared_ptr<std::string> json = std::make_shared<std::string>(jni::Make<std::string>(env, jString));
|
||||
|
||||
ActorRef<FeatureConverter> converterRef = converter->self();
|
||||
Update::Converter converterFn = [converterRef, json](ActorRef<GeoJSONDataCallback> _callback) {
|
||||
converterRef.ask(&FeatureConverter::convertJson, json, _callback).wait();
|
||||
};
|
||||
|
||||
setAsync(converterFn);
|
||||
}
|
||||
|
||||
void GeoJSONSource::setFeatureCollection(jni::JNIEnv& env, const jni::Object<geojson::FeatureCollection>& jFeatures) {
|
||||
setCollectionAsync(env, jFeatures);
|
||||
}
|
||||
@@ -93,19 +86,6 @@ void GeoJSONSource::setGeometry(jni::JNIEnv& env, const jni::Object<geojson::Geo
|
||||
setCollectionAsync(env, jGeometry);
|
||||
}
|
||||
|
||||
void GeoJSONSource::setFeatureCollectionSync(jni::JNIEnv& env,
|
||||
const jni::Object<geojson::FeatureCollection>& jFeatures) {
|
||||
setCollectionSync(env, jFeatures);
|
||||
}
|
||||
|
||||
void GeoJSONSource::setFeatureSync(jni::JNIEnv& env, const jni::Object<geojson::Feature>& jFeature) {
|
||||
setCollectionSync(env, jFeature);
|
||||
}
|
||||
|
||||
void GeoJSONSource::setGeometrySync(jni::JNIEnv& env, const jni::Object<geojson::Geometry>& jGeometry) {
|
||||
setCollectionSync(env, jGeometry);
|
||||
}
|
||||
|
||||
void GeoJSONSource::setURL(jni::JNIEnv& env, const jni::String& url) {
|
||||
// Update the core source
|
||||
source.as<style::GeoJSONSource>()->setURL(jni::Make<std::string>(env, url));
|
||||
@@ -195,7 +175,7 @@ void GeoJSONSource::setCollectionAsync(jni::JNIEnv& env, const jni::Object<JNITy
|
||||
auto global = jni::NewGlobal<jni::EnvAttachingDeleter>(env, jObject);
|
||||
auto object = std::make_shared<decltype(global)>(std::move(global));
|
||||
|
||||
ActorRef<FeatureConverter> converterRef = converter->self();
|
||||
OptionalActorRef<FeatureConverter> converterRef = converter->self();
|
||||
Update::Converter converterFn = [converterRef, object](ActorRef<GeoJSONDataCallback> _callback) {
|
||||
converterRef.invoke(&FeatureConverter::convertObject<JNIType>, object, _callback);
|
||||
};
|
||||
@@ -233,19 +213,6 @@ void GeoJSONSource::setAsync(Update::Converter converterFn) {
|
||||
update->converterFn(update->callback->self());
|
||||
}
|
||||
|
||||
template <class JNIType>
|
||||
void GeoJSONSource::setCollectionSync(jni::JNIEnv& env, const jni::Object<JNIType>& jObject) {
|
||||
auto global = jni::NewGlobal<jni::EnvAttachingDeleter>(env, jObject);
|
||||
auto object = std::make_shared<decltype(global)>(std::move(global));
|
||||
|
||||
ActorRef<FeatureConverter> converterRef = converter->self();
|
||||
Update::Converter converterFn = [converterRef, object](ActorRef<GeoJSONDataCallback> _callback) {
|
||||
converterRef.ask(&FeatureConverter::convertObject<JNIType>, object, _callback).wait();
|
||||
};
|
||||
|
||||
setAsync(converterFn);
|
||||
}
|
||||
|
||||
jboolean GeoJSONSource::isUpdateSynchronous(jni::JNIEnv&) {
|
||||
return source.as<style::GeoJSONSource>()->isUpdateSynchronous();
|
||||
}
|
||||
@@ -268,10 +235,6 @@ void GeoJSONSource::registerNative(jni::JNIEnv& env) {
|
||||
METHOD(&GeoJSONSource::setFeatureCollection, "nativeSetFeatureCollection"),
|
||||
METHOD(&GeoJSONSource::setFeature, "nativeSetFeature"),
|
||||
METHOD(&GeoJSONSource::setGeometry, "nativeSetGeometry"),
|
||||
METHOD(&GeoJSONSource::setGeoJSONStringSync, "nativeSetGeoJsonStringSync"),
|
||||
METHOD(&GeoJSONSource::setFeatureCollectionSync, "nativeSetFeatureCollectionSync"),
|
||||
METHOD(&GeoJSONSource::setFeatureSync, "nativeSetFeatureSync"),
|
||||
METHOD(&GeoJSONSource::setGeometrySync, "nativeSetGeometrySync"),
|
||||
METHOD(&GeoJSONSource::setURL, "nativeSetUrl"),
|
||||
METHOD(&GeoJSONSource::getURL, "nativeGetUrl"),
|
||||
METHOD(&GeoJSONSource::querySourceFeatures, "querySourceFeatures"),
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "source.hpp"
|
||||
#include <mbgl/style/sources/geojson_source.hpp>
|
||||
#include <mbgl/actor/optional_actor.hpp>
|
||||
#include "../../geojson/geometry.hpp"
|
||||
#include "../../geojson/feature.hpp"
|
||||
#include "../../geojson/feature_collection.hpp"
|
||||
@@ -55,11 +56,6 @@ private:
|
||||
void setFeature(jni::JNIEnv&, const jni::Object<geojson::Feature>&);
|
||||
void setGeometry(jni::JNIEnv&, const jni::Object<geojson::Geometry>&);
|
||||
|
||||
void setGeoJSONStringSync(jni::JNIEnv&, const jni::String&);
|
||||
void setFeatureCollectionSync(jni::JNIEnv&, const jni::Object<geojson::FeatureCollection>&);
|
||||
void setFeatureSync(jni::JNIEnv&, const jni::Object<geojson::Feature>&);
|
||||
void setGeometrySync(jni::JNIEnv&, const jni::Object<geojson::Geometry>&);
|
||||
|
||||
void setURL(jni::JNIEnv&, const jni::String&);
|
||||
|
||||
jni::Local<jni::Array<jni::Object<geojson::Feature>>> querySourceFeatures(jni::JNIEnv&,
|
||||
@@ -79,7 +75,7 @@ private:
|
||||
std::unique_ptr<Update> awaitingUpdate;
|
||||
std::unique_ptr<Update> update;
|
||||
std::shared_ptr<ThreadPool> threadPool;
|
||||
std::unique_ptr<Actor<FeatureConverter>> converter;
|
||||
std::unique_ptr<OptionalActor<FeatureConverter>> converter;
|
||||
|
||||
template <class JNIType>
|
||||
void setCollectionAsync(jni::JNIEnv&, const jni::Object<JNIType>&);
|
||||
|
||||
@@ -240,11 +240,7 @@ class GeoJsonSource : Source {
|
||||
return
|
||||
}
|
||||
checkThread()
|
||||
if (nativeIsUpdateSynchronous()) {
|
||||
nativeSetFeatureSync(feature)
|
||||
} else {
|
||||
nativeSetFeature(feature)
|
||||
}
|
||||
nativeSetFeature(feature)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -260,11 +256,7 @@ class GeoJsonSource : Source {
|
||||
return
|
||||
}
|
||||
checkThread()
|
||||
if (nativeIsUpdateSynchronous()) {
|
||||
nativeSetGeometrySync(geometry)
|
||||
} else {
|
||||
nativeSetGeometry(geometry)
|
||||
}
|
||||
nativeSetGeometry(geometry)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -285,11 +277,7 @@ class GeoJsonSource : Source {
|
||||
val featuresCopy: List<Feature> = ArrayList(features)
|
||||
featureCollection = FeatureCollection.fromFeatures(featuresCopy)
|
||||
}
|
||||
if (nativeIsUpdateSynchronous()) {
|
||||
nativeSetFeatureCollectionSync(featureCollection)
|
||||
} else {
|
||||
nativeSetFeatureCollection(featureCollection)
|
||||
}
|
||||
nativeSetFeatureCollection(featureCollection)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -304,77 +292,7 @@ class GeoJsonSource : Source {
|
||||
return
|
||||
}
|
||||
checkThread()
|
||||
if (nativeIsUpdateSynchronous()) {
|
||||
nativeSetGeoJsonStringSync(json)
|
||||
} else {
|
||||
nativeSetGeoJsonString(json)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the GeoJson with a single feature. The update is performed synchronously,
|
||||
* so the data will be immediately visible and available to query when this method returns.
|
||||
*
|
||||
* @param feature the GeoJSON [Feature] to set
|
||||
*/
|
||||
@Deprecated("use {@link GeoJsonOptions#withSynchronousUpdate(Boolean)} to enable synchronous updates on construction")
|
||||
fun setGeoJsonSync(feature: Feature?) {
|
||||
if (detached) {
|
||||
return
|
||||
}
|
||||
checkThread()
|
||||
nativeSetFeatureSync(feature)
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the GeoJson with a single geometry. The update is performed synchronously,
|
||||
* so the data will be immediately visible and available to query when this method returns.
|
||||
*
|
||||
* @param geometry the GeoJSON [Geometry] to set
|
||||
*/
|
||||
@Deprecated("use {@link GeoJsonOptions#withSynchronousUpdate(Boolean)} to enable synchronous updates on construction")
|
||||
fun setGeoJsonSync(geometry: Geometry?) {
|
||||
if (detached) {
|
||||
return
|
||||
}
|
||||
checkThread()
|
||||
nativeSetGeometrySync(geometry)
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the GeoJson. The update is performed synchronously,
|
||||
* so the data will be immediately visible and available to query when this method returns.
|
||||
*
|
||||
* @param featureCollection the GeoJSON FeatureCollection
|
||||
*/
|
||||
@Deprecated("use {@link GeoJsonOptions#withSynchronousUpdate(Boolean)} to enable synchronous updates on construction")
|
||||
fun setGeoJsonSync(featureCollection: FeatureCollection?) {
|
||||
if (detached) {
|
||||
return
|
||||
}
|
||||
checkThread()
|
||||
if (featureCollection != null && featureCollection.features() != null) {
|
||||
val features = featureCollection.features()
|
||||
val featuresCopy: List<Feature> = ArrayList(features)
|
||||
nativeSetFeatureCollectionSync(FeatureCollection.fromFeatures(featuresCopy))
|
||||
} else {
|
||||
nativeSetFeatureCollectionSync(featureCollection)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the GeoJson. The update is performed synchronously,
|
||||
* so the data will be immediately visible and available to query when this method returns.
|
||||
*
|
||||
* @param json the raw GeoJson FeatureCollection string
|
||||
*/
|
||||
@Deprecated("use {@link GeoJsonOptions#withSynchronousUpdate(Boolean)} to enable synchronous updates on construction")
|
||||
fun setGeoJsonSync(json: String) {
|
||||
if (detached) {
|
||||
return
|
||||
}
|
||||
checkThread()
|
||||
nativeSetGeoJsonStringSync(json)
|
||||
nativeSetGeoJsonString(json)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -568,18 +486,6 @@ class GeoJsonSource : Source {
|
||||
@Keep
|
||||
private external fun nativeSetGeometry(geometry: Geometry?)
|
||||
|
||||
@Keep
|
||||
private external fun nativeSetGeoJsonStringSync(geoJson: String)
|
||||
|
||||
@Keep
|
||||
private external fun nativeSetFeatureCollectionSync(geoJson: FeatureCollection?)
|
||||
|
||||
@Keep
|
||||
private external fun nativeSetFeatureSync(feature: Feature?)
|
||||
|
||||
@Keep
|
||||
private external fun nativeSetGeometrySync(geometry: Geometry?)
|
||||
|
||||
@Keep
|
||||
private external fun querySourceFeatures(filter: Array<Any>?): Array<Feature>
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
12.3.1
|
||||
13.0.0
|
||||
|
||||
Reference in New Issue
Block a user