summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com>2019-10-30 12:04:01 +0200
committerMikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com>2019-10-31 10:24:55 +0200
commit4afb4438ebf0c8e7d4b4ae5fcfd10d363be6c3c7 (patch)
tree8ddf07a7a05a0514df2fe1a9c90b31e37fa9fafd
parent8c498cd36c07b1019e5ddb60d5f9f8872f036e25 (diff)
downloadqtlocation-mapboxgl-4afb4438ebf0c8e7d4b4ae5fcfd10d363be6c3c7.tar.gz
[android] Convert GeoJSON features to tiles in background
Composing tiles from the GeoJSON features is an expensive operation that might block UI thread on updating the `GeoJsonSource` with the new data. This change moves tile composing to the background thread and thus unblocks the UI thread.
-rw-r--r--include/mbgl/style/sources/geojson_source.hpp1
-rw-r--r--platform/android/src/style/sources/geojson_source.cpp82
-rw-r--r--platform/android/src/style/sources/geojson_source.hpp20
-rw-r--r--src/mbgl/style/sources/geojson_source.cpp4
4 files changed, 56 insertions, 51 deletions
diff --git a/include/mbgl/style/sources/geojson_source.hpp b/include/mbgl/style/sources/geojson_source.hpp
index c8dc65b912..549393e9b2 100644
--- a/include/mbgl/style/sources/geojson_source.hpp
+++ b/include/mbgl/style/sources/geojson_source.hpp
@@ -60,6 +60,7 @@ public:
void setGeoJSONData(std::shared_ptr<GeoJSONData>);
optional<std::string> getURL() const;
+ const GeoJSONOptions& getOptions() const;
class Impl;
const Impl& impl() const;
diff --git a/platform/android/src/style/sources/geojson_source.cpp b/platform/android/src/style/sources/geojson_source.cpp
index 5ff4864275..0eece4b1ad 100644
--- a/platform/android/src/style/sources/geojson_source.cpp
+++ b/platform/android/src/style/sources/geojson_source.cpp
@@ -44,18 +44,16 @@ namespace android {
}
GeoJSONSource::GeoJSONSource(jni::JNIEnv& env, const jni::String& sourceId, const jni::Object<>& options)
- : 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(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>()->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())) {
- }
+ 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>()->getOptions())) {}
GeoJSONSource::~GeoJSONSource() = default;
@@ -63,7 +61,7 @@ namespace android {
std::shared_ptr<std::string> json = std::make_shared<std::string>(jni::Make<std::string>(env, jString));
- Update::Converter converterFn = [this, json](ActorRef<Callback> _callback) {
+ Update::Converter converterFn = [this, json](ActorRef<GeoJSONDataCallback> _callback) {
converter->self().invoke(&FeatureConverter::convertJson, json, _callback);
};
@@ -84,11 +82,11 @@ namespace android {
void GeoJSONSource::setURL(jni::JNIEnv& env, const jni::String& url) {
// Update the core source
- source.as<mbgl::style::GeoJSONSource>()->GeoJSONSource::setURL(jni::Make<std::string>(env, url));
+ source.as<style::GeoJSONSource>()->setURL(jni::Make<std::string>(env, url));
}
jni::Local<jni::String> GeoJSONSource::getURL(jni::JNIEnv& env) {
- optional<std::string> url = source.as<mbgl::style::GeoJSONSource>()->GeoJSONSource::getURL();
+ optional<std::string> url = source.as<style::GeoJSONSource>()->getURL();
return url ? jni::Make<jni::String>(env, *url) : jni::Local<jni::String>();
}
@@ -166,7 +164,7 @@ namespace android {
auto global = jni::NewGlobal<jni::EnvAttachingDeleter>(env, jObject);
auto object = std::make_shared<decltype(global)>(std::move(global));
- Update::Converter converterFn = [this, object](ActorRef<Callback> _callback) {
+ Update::Converter converterFn = [this, object](ActorRef<GeoJSONDataCallback> _callback) {
converter->self().invoke(&FeatureConverter::convertObject<JNIType>, object, _callback);
};
@@ -175,25 +173,23 @@ namespace android {
void GeoJSONSource::setAsync(Update::Converter converterFn) {
awaitingUpdate = std::make_unique<Update>(
- std::move(converterFn),
- std::make_unique<Actor<Callback>>(
- *Scheduler::GetCurrent(),
- [this](GeoJSON geoJSON) {
- // conversion from Java features to core ones finished
- android::UniqueEnv _env = android::AttachEnv();
-
- // Update the core source
- source.as<mbgl::style::GeoJSONSource>()->GeoJSONSource::setGeoJSON(geoJSON);
-
- // if there is an awaiting update, execute it, otherwise, release resources
- if (awaitingUpdate) {
- update = std::move(awaitingUpdate);
- update->converterFn(update->callback->self());
- } else {
- update.reset();
- }
- })
- );
+ std::move(converterFn),
+ std::make_unique<Actor<GeoJSONDataCallback>>(
+ *Scheduler::GetCurrent(), [this](std::shared_ptr<style::GeoJSONData> geoJSONData) {
+ // conversion from Java features to core ones finished
+ android::UniqueEnv _env = android::AttachEnv();
+
+ // Update the core source
+ source.as<mbgl::style::GeoJSONSource>()->setGeoJSONData(std::move(geoJSONData));
+
+ // if there is an awaiting update, execute it, otherwise, release resources
+ if (awaitingUpdate) {
+ update = std::move(awaitingUpdate);
+ update->converterFn(update->callback->self());
+ } else {
+ update.reset();
+ }
+ }));
// If another update is running, wait
if (update) {
@@ -230,12 +226,10 @@ namespace android {
);
}
- void FeatureConverter::convertJson(std::shared_ptr<std::string> json,
- ActorRef<Callback> callback) {
+ void FeatureConverter::convertJson(std::shared_ptr<std::string> json, ActorRef<GeoJSONDataCallback> callback) {
using namespace mbgl::style::conversion;
android::UniqueEnv _env = android::AttachEnv();
-
// Convert the jni object
Error error;
optional<GeoJSON> converted = parseGeoJSON(*json, error);
@@ -243,23 +237,23 @@ namespace android {
mbgl::Log::Error(mbgl::Event::JNI, "Error setting geo json: " + error.message);
return;
}
-
- callback.invoke(&Callback::operator(), *converted);
+ callback.invoke(&GeoJSONDataCallback::operator(), style::GeoJSONData::create(*converted, options));
}
template <class JNIType>
- void FeatureConverter::convertObject(std::shared_ptr<jni::Global<jni::Object<JNIType>, jni::EnvAttachingDeleter>> jObject, ActorRef<Callback> callback) {
+ void FeatureConverter::convertObject(
+ std::shared_ptr<jni::Global<jni::Object<JNIType>, jni::EnvAttachingDeleter>> jObject,
+ ActorRef<GeoJSONDataCallback> callback) {
using namespace mbgl::android::geojson;
android::UniqueEnv _env = android::AttachEnv();
// Convert the jni object
auto geometry = JNIType::convert(*_env, *jObject);
- callback.invoke(&Callback::operator(), GeoJSON(geometry));
+ callback.invoke(&GeoJSONDataCallback::operator(), style::GeoJSONData::create(geometry, options));
}
- Update::Update(Converter _converterFn, std::unique_ptr<Actor<Callback>> _callback)
- : converterFn(std::move(_converterFn))
- , callback(std::move(_callback)) {}
+ Update::Update(Converter _converterFn, std::unique_ptr<Actor<GeoJSONDataCallback>> _callback)
+ : converterFn(std::move(_converterFn)), callback(std::move(_callback)) {}
} // namespace android
} // namespace mbgl
diff --git a/platform/android/src/style/sources/geojson_source.hpp b/platform/android/src/style/sources/geojson_source.hpp
index e737e41924..e506191ceb 100644
--- a/platform/android/src/style/sources/geojson_source.hpp
+++ b/platform/android/src/style/sources/geojson_source.hpp
@@ -11,22 +11,28 @@
namespace mbgl {
namespace android {
-using Callback = std::function<void (GeoJSON)>;
+using GeoJSONDataCallback = std::function<void(std::shared_ptr<style::GeoJSONData>)>;
-struct FeatureConverter {
- void convertJson(std::shared_ptr<std::string>, ActorRef<Callback>);
+class FeatureConverter {
+public:
+ explicit FeatureConverter(style::GeoJSONOptions options_) : options(std::move(options_)) {}
+ void convertJson(std::shared_ptr<std::string>, ActorRef<GeoJSONDataCallback>);
template <class JNIType>
- void convertObject(std::shared_ptr<jni::Global<jni::Object<JNIType>, jni::EnvAttachingDeleter>>, ActorRef<Callback>);
+ void convertObject(std::shared_ptr<jni::Global<jni::Object<JNIType>, jni::EnvAttachingDeleter>>,
+ ActorRef<GeoJSONDataCallback>);
+
+private:
+ style::GeoJSONOptions options;
};
struct Update {
- using Converter = std::function<void (ActorRef<Callback>)>;
+ using Converter = std::function<void(ActorRef<GeoJSONDataCallback>)>;
Converter converterFn;
- std::unique_ptr<Actor<Callback>> callback;
+ std::unique_ptr<Actor<GeoJSONDataCallback>> callback;
- Update(Converter, std::unique_ptr<Actor<Callback>>);
+ Update(Converter, std::unique_ptr<Actor<GeoJSONDataCallback>>);
};
class GeoJSONSource : public Source {
diff --git a/src/mbgl/style/sources/geojson_source.cpp b/src/mbgl/style/sources/geojson_source.cpp
index 79e7c23459..3832977cd4 100644
--- a/src/mbgl/style/sources/geojson_source.cpp
+++ b/src/mbgl/style/sources/geojson_source.cpp
@@ -45,6 +45,10 @@ optional<std::string> GeoJSONSource::getURL() const {
return url;
}
+const GeoJSONOptions& GeoJSONSource::getOptions() const {
+ return impl().getOptions();
+}
+
void GeoJSONSource::loadDescription(FileSource& fileSource) {
if (!url) {
loaded = true;