From a11571ce21c451d06b888bf4cbd0fa8b5e7314c3 Mon Sep 17 00:00:00 2001 From: Alex Cristici Date: Tue, 3 Mar 2026 19:28:45 +0200 Subject: [PATCH] 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 Co-authored-by: Bart Louwers --- platform/android/CHANGELOG.md | 16 ++- .../src/cpp/style/sources/geojson_source.cpp | 57 ++-------- .../src/cpp/style/sources/geojson_source.hpp | 8 +- .../android/style/sources/GeoJsonSource.kt | 102 +----------------- platform/android/VERSION | 2 +- 5 files changed, 32 insertions(+), 153 deletions(-) diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index be344fb12..9b5e2a091 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -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 diff --git a/platform/android/MapLibreAndroid/src/cpp/style/sources/geojson_source.cpp b/platform/android/MapLibreAndroid/src/cpp/style/sources/geojson_source.cpp index 4ccfc7690..926664fac 100644 --- a/platform/android/MapLibreAndroid/src/cpp/style/sources/geojson_source.cpp +++ b/platform/android/MapLibreAndroid/src/cpp/style/sources/geojson_source.cpp @@ -49,20 +49,24 @@ GeoJSONSource::GeoJSONSource(jni::JNIEnv& env, const jni::String& sourceId, cons : Source(env, std::make_unique(jni::Make(env, sourceId), convertGeoJSONOptions(env, options))), - converter(std::make_unique>(Scheduler::GetBackground(), - source.as()->impl().getOptions())) {} + converter( + std::make_unique>(source.as()->isUpdateSynchronous(), + Scheduler::GetBackground(), + source.as()->impl().getOptions())) {} GeoJSONSource::GeoJSONSource(jni::JNIEnv& env, mbgl::style::Source& coreSource, AndroidRendererFrontend* frontend) : Source(env, coreSource, createJavaPeer(env), frontend), - converter(std::make_unique>(Scheduler::GetBackground(), - source.as()->impl().getOptions())) {} + converter( + std::make_unique>(source.as()->isUpdateSynchronous(), + Scheduler::GetBackground(), + source.as()->impl().getOptions())) {} GeoJSONSource::~GeoJSONSource() = default; void GeoJSONSource::setGeoJSONString(jni::JNIEnv& env, const jni::String& jString) { std::shared_ptr json = std::make_shared(jni::Make(env, jString)); - ActorRef converterRef = converter->self(); + OptionalActorRef converterRef = converter->self(); Update::Converter converterFn = [converterRef, json](ActorRef _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 json = std::make_shared(jni::Make(env, jString)); - - ActorRef converterRef = converter->self(); - Update::Converter converterFn = [converterRef, json](ActorRef _callback) { - converterRef.ask(&FeatureConverter::convertJson, json, _callback).wait(); - }; - - setAsync(converterFn); -} - void GeoJSONSource::setFeatureCollection(jni::JNIEnv& env, const jni::Object& jFeatures) { setCollectionAsync(env, jFeatures); } @@ -93,19 +86,6 @@ void GeoJSONSource::setGeometry(jni::JNIEnv& env, const jni::Object& jFeatures) { - setCollectionSync(env, jFeatures); -} - -void GeoJSONSource::setFeatureSync(jni::JNIEnv& env, const jni::Object& jFeature) { - setCollectionSync(env, jFeature); -} - -void GeoJSONSource::setGeometrySync(jni::JNIEnv& env, const jni::Object& jGeometry) { - setCollectionSync(env, jGeometry); -} - void GeoJSONSource::setURL(jni::JNIEnv& env, const jni::String& url) { // Update the core source source.as()->setURL(jni::Make(env, url)); @@ -195,7 +175,7 @@ void GeoJSONSource::setCollectionAsync(jni::JNIEnv& env, const jni::Object(env, jObject); auto object = std::make_shared(std::move(global)); - ActorRef converterRef = converter->self(); + OptionalActorRef converterRef = converter->self(); Update::Converter converterFn = [converterRef, object](ActorRef _callback) { converterRef.invoke(&FeatureConverter::convertObject, object, _callback); }; @@ -233,19 +213,6 @@ void GeoJSONSource::setAsync(Update::Converter converterFn) { update->converterFn(update->callback->self()); } -template -void GeoJSONSource::setCollectionSync(jni::JNIEnv& env, const jni::Object& jObject) { - auto global = jni::NewGlobal(env, jObject); - auto object = std::make_shared(std::move(global)); - - ActorRef converterRef = converter->self(); - Update::Converter converterFn = [converterRef, object](ActorRef _callback) { - converterRef.ask(&FeatureConverter::convertObject, object, _callback).wait(); - }; - - setAsync(converterFn); -} - jboolean GeoJSONSource::isUpdateSynchronous(jni::JNIEnv&) { return source.as()->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"), diff --git a/platform/android/MapLibreAndroid/src/cpp/style/sources/geojson_source.hpp b/platform/android/MapLibreAndroid/src/cpp/style/sources/geojson_source.hpp index 49591e3a3..4e308b1dd 100644 --- a/platform/android/MapLibreAndroid/src/cpp/style/sources/geojson_source.hpp +++ b/platform/android/MapLibreAndroid/src/cpp/style/sources/geojson_source.hpp @@ -2,6 +2,7 @@ #include "source.hpp" #include +#include #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&); void setGeometry(jni::JNIEnv&, const jni::Object&); - void setGeoJSONStringSync(jni::JNIEnv&, const jni::String&); - void setFeatureCollectionSync(jni::JNIEnv&, const jni::Object&); - void setFeatureSync(jni::JNIEnv&, const jni::Object&); - void setGeometrySync(jni::JNIEnv&, const jni::Object&); - void setURL(jni::JNIEnv&, const jni::String&); jni::Local>> querySourceFeatures(jni::JNIEnv&, @@ -79,7 +75,7 @@ private: std::unique_ptr awaitingUpdate; std::unique_ptr update; std::shared_ptr threadPool; - std::unique_ptr> converter; + std::unique_ptr> converter; template void setCollectionAsync(jni::JNIEnv&, const jni::Object&); diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/style/sources/GeoJsonSource.kt b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/style/sources/GeoJsonSource.kt index 7919bfebf..9a1dc5fa6 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/style/sources/GeoJsonSource.kt +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/style/sources/GeoJsonSource.kt @@ -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 = 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 = 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?): Array diff --git a/platform/android/VERSION b/platform/android/VERSION index 9c028e25d..02161ca86 100644 --- a/platform/android/VERSION +++ b/platform/android/VERSION @@ -1 +1 @@ -12.3.1 +13.0.0