Enable FastPFOR encodings in MLT (#4146)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Bart Louwers <bart@emeel.net>
This commit is contained in:
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -103,7 +103,7 @@
|
||||
[submodule "vendor/maplibre-tile-spec"]
|
||||
path = vendor/maplibre-tile-spec
|
||||
url = https://github.com/maplibre/maplibre-tile-spec.git
|
||||
branch = cpp
|
||||
branch = main
|
||||
[submodule "vendor/kdbush.hpp"]
|
||||
path = vendor/kdbush.hpp
|
||||
url = https://github.com/mourner/kdbush.hpp.git
|
||||
|
||||
@@ -154,7 +154,7 @@ cc_library(
|
||||
"//vendor:unordered_dense",
|
||||
"//vendor:vector-tile",
|
||||
"//vendor:wagyu",
|
||||
"//vendor/maplibre-tile-spec/cpp:mlt_cpp",
|
||||
"@maplibre_tile_spec//cpp:mlt_cpp",
|
||||
] + select({
|
||||
"@platforms//os:ios": [
|
||||
"//vendor:ghc_filesystem",
|
||||
|
||||
@@ -13,6 +13,12 @@ bazel_dep(name = "rules_cc", version = "0.2.14")
|
||||
bazel_dep(name = "rules_shell", version = "0.6.1")
|
||||
bazel_dep(name = "rules_swift_package_manager", version = "1.3.0")
|
||||
bazel_dep(name = "googletest", version = "1.17.0.bcr.2")
|
||||
bazel_dep(name = "maplibre-tile-spec", version = "0.0.0", repo_name = "maplibre_tile_spec")
|
||||
|
||||
local_path_override(
|
||||
module_name = "maplibre-tile-spec",
|
||||
path = "vendor/maplibre-tile-spec",
|
||||
)
|
||||
|
||||
# rules_xcodeproj accidentally includes a trailing comma in the generated
|
||||
# Testing.framework rsync exclusion, causing intermittent test-host build races.
|
||||
|
||||
@@ -133,6 +133,22 @@ public:
|
||||
*/
|
||||
float pixelRatio() const;
|
||||
|
||||
/**
|
||||
* @brief Sets whether to enable decoding of MapLibre Tile (MLT) tiles with FastPFOR integer encodings.
|
||||
* By default, it is set to false. Such tiles will fail if not explicitly enabled.
|
||||
*
|
||||
* @param enable true to enable, false to disable
|
||||
* @return MapOptions for chaining options together.
|
||||
*/
|
||||
MapOptions& withFastPFOREnabled(bool enable);
|
||||
|
||||
/**
|
||||
* @brief Gets the previously set (or default) value.
|
||||
*
|
||||
* @return true if enabled, alse otherwise.
|
||||
*/
|
||||
bool fastPFOREnabled() const;
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
std::unique_ptr<Impl> impl_;
|
||||
|
||||
@@ -47,5 +47,11 @@ bool NativeMapOptions::asyncRendererCleanup(jni::JNIEnv &env, const jni::Object<
|
||||
return obj.Get(env, asyncRendererCleanupField);
|
||||
}
|
||||
|
||||
bool NativeMapOptions::fastPFOREnabled(jni::JNIEnv &env, const jni::Object<NativeMapOptions> &obj) {
|
||||
auto &javaClass = jni::Class<NativeMapOptions>::Singleton(env);
|
||||
auto field = javaClass.GetField<jni::jboolean>(env, "fastPFOREnabled");
|
||||
return obj.Get(env, field);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -20,6 +20,7 @@ public:
|
||||
static float pixelRatio(jni::JNIEnv&, const jni::Object<NativeMapOptions>&);
|
||||
static bool crossSourceCollisions(jni::JNIEnv&, const jni::Object<NativeMapOptions>&);
|
||||
static bool asyncRendererCleanup(jni::JNIEnv&, const jni::Object<NativeMapOptions>&);
|
||||
static bool fastPFOREnabled(jni::JNIEnv&, const jni::Object<NativeMapOptions>&);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
@@ -87,7 +87,8 @@ NativeMapView::NativeMapView(jni::JNIEnv& _env,
|
||||
.withPixelRatio(pixelRatio)
|
||||
.withConstrainMode(ConstrainMode::HeightOnly)
|
||||
.withViewportMode(ViewportMode::Default)
|
||||
.withCrossSourceCollisions(NativeMapOptions::crossSourceCollisions(_env, jNativeMapOptions));
|
||||
.withCrossSourceCollisions(NativeMapOptions::crossSourceCollisions(_env, jNativeMapOptions))
|
||||
.withFastPFOREnabled(NativeMapOptions::fastPFOREnabled(_env, jNativeMapOptions));
|
||||
|
||||
// Create the core map
|
||||
map = std::make_unique<mbgl::Map>(
|
||||
|
||||
@@ -102,6 +102,8 @@ public class MapLibreMapOptions implements Parcelable {
|
||||
|
||||
private boolean asyncRendererCleanup = false;
|
||||
|
||||
private boolean fastPFOREnabled = false;
|
||||
|
||||
/**
|
||||
* Creates a new MapLibreMapOptions object.
|
||||
*
|
||||
@@ -167,6 +169,8 @@ public class MapLibreMapOptions implements Parcelable {
|
||||
actionJournalRenderingReportInterval = in.readInt();
|
||||
|
||||
asyncRendererCleanup = in.readByte() != 0;
|
||||
|
||||
fastPFOREnabled = in.readByte() != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -340,6 +344,10 @@ public class MapLibreMapOptions implements Parcelable {
|
||||
maplibreMapOptions.asyncRendererCleanup(
|
||||
typedArray.getBoolean(R.styleable.maplibre_MapView_maplibre_asyncRendererCleanup, false)
|
||||
);
|
||||
|
||||
maplibreMapOptions.fastPFOREnabled(
|
||||
typedArray.getBoolean(R.styleable.maplibre_MapView_maplibre_fastPFOREnabled, false)
|
||||
);
|
||||
} finally {
|
||||
typedArray.recycle();
|
||||
}
|
||||
@@ -852,6 +860,16 @@ public class MapLibreMapOptions implements Parcelable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable FastPFOR decompression for vector tiles, defaults to false.
|
||||
* @param enable true to enable, false to disable
|
||||
* @return This
|
||||
*/
|
||||
@NonNull public MapLibreMapOptions fastPFOREnabled(boolean enable) {
|
||||
this.fastPFOREnabled = enable;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable local ideograph font family, defaults to true.
|
||||
*
|
||||
@@ -999,6 +1017,15 @@ public class MapLibreMapOptions implements Parcelable {
|
||||
return asyncRendererCleanup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether FastPFOR decompression is enabled for vector tiles.
|
||||
*
|
||||
* @return true if enabled
|
||||
*/
|
||||
public boolean getFastPFOREnabled() {
|
||||
return fastPFOREnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the flag to render the map surface on top of another surface.
|
||||
*
|
||||
@@ -1391,6 +1418,8 @@ public class MapLibreMapOptions implements Parcelable {
|
||||
dest.writeInt(actionJournalRenderingReportInterval);
|
||||
|
||||
dest.writeByte((byte) (asyncRendererCleanup ? 1 : 0));
|
||||
|
||||
dest.writeByte((byte) (fastPFOREnabled ? 1 : 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1535,6 +1564,10 @@ public class MapLibreMapOptions implements Parcelable {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fastPFOREnabled != options.fastPFOREnabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1588,6 +1621,7 @@ public class MapLibreMapOptions implements Parcelable {
|
||||
result = 31 * result + (int) actionJournalLogFileCount;
|
||||
result = 31 * result + (int) actionJournalRenderingReportInterval;
|
||||
result = 31 * result + (asyncRendererCleanup ? 1 : 0);
|
||||
result = 31 * result + (fastPFOREnabled ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ public class NativeMapOptions {
|
||||
private final int actionJournalRenderingReportInterval;
|
||||
private final boolean asyncRendererCleanup;
|
||||
|
||||
private final boolean fastPFOREnabled;
|
||||
|
||||
public NativeMapOptions(MapLibreMapOptions options) {
|
||||
pixelRatio = options.getPixelRatio();
|
||||
crossSourceCollisions = options.getCrossSourceCollisions();
|
||||
@@ -22,6 +24,7 @@ public class NativeMapOptions {
|
||||
actionJournalLogFileCount = options.getActionJournalLogFileCount();
|
||||
actionJournalRenderingReportInterval = options.getActionJournalRenderingReportInterval();
|
||||
asyncRendererCleanup = options.getAsyncRendererCleanup();
|
||||
fastPFOREnabled = options.getFastPFOREnabled();
|
||||
}
|
||||
|
||||
public NativeMapOptions(float pixelRatio, boolean crossSourceCollisions) {
|
||||
@@ -35,6 +38,7 @@ public class NativeMapOptions {
|
||||
actionJournalRenderingReportInterval = 0;
|
||||
|
||||
asyncRendererCleanup = false;
|
||||
fastPFOREnabled = false;
|
||||
}
|
||||
|
||||
public float pixelRatio() {
|
||||
@@ -68,4 +72,8 @@ public class NativeMapOptions {
|
||||
public boolean asyncRendererCleanup() {
|
||||
return asyncRendererCleanup;
|
||||
}
|
||||
|
||||
public boolean fastPFOREnabled() {
|
||||
return fastPFOREnabled;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
<attr name="maplibre_localIdeographFontFamily" format="string"/>
|
||||
<attr name="maplibre_localIdeographFontFamilies" format="reference"/>
|
||||
<attr name="maplibre_cross_source_collisions" format="boolean"/>
|
||||
<attr name="maplibre_fastPFOREnabled" format="boolean"/>
|
||||
|
||||
<!--Action Journal-->
|
||||
<attr name="maplibre_actionJournalEnabled" format="boolean"/>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#Mon Jun 15 10:28:30 CDT 2026
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -21,7 +21,7 @@ dependencyResolutionManagement {
|
||||
}
|
||||
|
||||
plugins {
|
||||
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
|
||||
id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0"
|
||||
}
|
||||
|
||||
include(":MapLibreAndroid", ":MapLibreAndroidTestApp", ":MapLibreAndroidLint")
|
||||
|
||||
@@ -37,6 +37,11 @@ MLN_EXPORT
|
||||
*/
|
||||
@property NSArray *pluginLayers;
|
||||
|
||||
/**
|
||||
Enable FastPFOR decoding for vector tiles. Defaults to `NO`.
|
||||
*/
|
||||
@property bool fastPFOREnabled;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
_styleURL = nil;
|
||||
_styleJSON = nil;
|
||||
_pluginLayers = nil;
|
||||
|
||||
_actionJournalOptions = [[MLNActionJournalOptions alloc] init];
|
||||
_fastPFOREnabled = NO;
|
||||
}
|
||||
|
||||
return self;
|
||||
|
||||
@@ -710,7 +710,8 @@ public:
|
||||
.withPixelRatio(config.scaleFactor)
|
||||
.withConstrainMode(mbgl::ConstrainMode::None)
|
||||
.withViewportMode(mbgl::ViewportMode::Default)
|
||||
.withCrossSourceCollisions(enableCrossSourceCollisions);
|
||||
.withCrossSourceCollisions(enableCrossSourceCollisions)
|
||||
.withFastPFOREnabled(mlnMapoptions.fastPFOREnabled);
|
||||
|
||||
mbgl::TileServerOptions *tileServerOptions =
|
||||
[[MLNSettings sharedSettings] tileServerOptionsInternal];
|
||||
|
||||
@@ -54,6 +54,7 @@ Map::Impl::Impl(RendererFrontend& frontend_,
|
||||
mode(mapOptions.mapMode()),
|
||||
pixelRatio(mapOptions.pixelRatio()),
|
||||
crossSourceCollisions(mapOptions.crossSourceCollisions()),
|
||||
fastPFOREnabled(mapOptions.fastPFOREnabled()),
|
||||
fileSource(std::move(fileSource_)),
|
||||
style(std::make_unique<style::Style>(fileSource, pixelRatio, frontend_.getThreadPool())),
|
||||
annotationManager(*style) {
|
||||
@@ -132,6 +133,7 @@ void Map::Impl::onUpdate() {
|
||||
.prefetchZoomDelta = prefetchZoomDelta,
|
||||
.stillImageRequest = bool(stillImageRequest),
|
||||
.crossSourceCollisions = crossSourceCollisions,
|
||||
.fastPFOREnabled = fastPFOREnabled,
|
||||
.tileLodMinRadius = tileLodMinRadius,
|
||||
.tileLodScale = tileLodScale,
|
||||
.tileLodPitchThreshold = tileLodPitchThreshold,
|
||||
|
||||
@@ -91,6 +91,7 @@ public:
|
||||
const MapMode mode;
|
||||
const float pixelRatio;
|
||||
const bool crossSourceCollisions;
|
||||
const bool fastPFOREnabled;
|
||||
|
||||
MapDebugOptions debugOptions{MapDebugOptions::NoDebug};
|
||||
std::unique_ptr<gfx::RenderingStatsView> renderingStatsView;
|
||||
|
||||
@@ -11,6 +11,7 @@ public:
|
||||
bool crossSourceCollisions = true;
|
||||
Size size = {64, 64};
|
||||
float pixelRatio = 1.0;
|
||||
bool fastPFOREnabled = false;
|
||||
};
|
||||
|
||||
// These requires the complete type of Impl.
|
||||
@@ -82,4 +83,13 @@ float MapOptions::pixelRatio() const {
|
||||
return impl_->pixelRatio;
|
||||
}
|
||||
|
||||
MapOptions& MapOptions::withFastPFOREnabled(bool enable) {
|
||||
impl_->fastPFOREnabled = enable;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool MapOptions::fastPFOREnabled() const {
|
||||
return impl_->fastPFOREnabled;
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -339,6 +339,7 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(
|
||||
std::unique_ptr<RenderSource> renderSource = RenderSource::create(entry.second, threadPool);
|
||||
renderSource->setObserver(this);
|
||||
renderSource->setCacheEnabled(tileCacheEnabled);
|
||||
renderSource->setFastPFOREnabled(updateParameters->fastPFOREnabled);
|
||||
renderSources.emplace(entry.first, std::move(renderSource));
|
||||
}
|
||||
transformState = updateParameters->transformState;
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
#include <mbgl/annotation/render_annotation_source.hpp>
|
||||
#include <mbgl/layermanager/layer_manager.hpp>
|
||||
#include <mbgl/renderer/render_source_observer.hpp>
|
||||
#include <mbgl/renderer/sources/render_geojson_source.hpp>
|
||||
#include <mbgl/renderer/sources/render_raster_source.hpp>
|
||||
#include <mbgl/renderer/sources/render_raster_dem_source.hpp>
|
||||
#include <mbgl/renderer/sources/render_vector_source.hpp>
|
||||
#include <mbgl/renderer/sources/render_image_source.hpp>
|
||||
#include <mbgl/renderer/sources/render_custom_geometry_source.hpp>
|
||||
#include <mbgl/renderer/sources/render_geojson_source.hpp>
|
||||
#include <mbgl/renderer/sources/render_image_source.hpp>
|
||||
#include <mbgl/renderer/sources/render_raster_dem_source.hpp>
|
||||
#include <mbgl/renderer/sources/render_raster_source.hpp>
|
||||
#include <mbgl/renderer/sources/render_vector_source.hpp>
|
||||
#include <mbgl/renderer/tile_parameters.hpp>
|
||||
#include <mbgl/renderer/update_parameters.hpp>
|
||||
#include <mbgl/tile/tile.hpp>
|
||||
#include <mbgl/util/constants.hpp>
|
||||
|
||||
@@ -21,28 +22,24 @@ namespace mbgl {
|
||||
using namespace style;
|
||||
|
||||
std::unique_ptr<RenderSource> RenderSource::create(const Immutable<Source::Impl>& impl,
|
||||
const TaggedScheduler& threadPool_) {
|
||||
const TaggedScheduler& threadPool) {
|
||||
switch (impl->type) {
|
||||
case SourceType::Vector:
|
||||
// the TileSet isn't available yet, so we can't make different sources by format
|
||||
return std::make_unique<RenderVectorSource>(staticImmutableCast<TileSource::Impl>(impl),
|
||||
std::move(threadPool_));
|
||||
return std::make_unique<RenderVectorSource>(staticImmutableCast<TileSource::Impl>(impl), threadPool);
|
||||
case SourceType::Raster:
|
||||
return std::make_unique<RenderRasterSource>(staticImmutableCast<TileSource::Impl>(impl),
|
||||
std::move(threadPool_));
|
||||
return std::make_unique<RenderRasterSource>(staticImmutableCast<TileSource::Impl>(impl), threadPool);
|
||||
case SourceType::RasterDEM:
|
||||
return std::make_unique<RenderRasterDEMSource>(staticImmutableCast<TileSource::Impl>(impl),
|
||||
std::move(threadPool_));
|
||||
return std::make_unique<RenderRasterDEMSource>(staticImmutableCast<TileSource::Impl>(impl), threadPool);
|
||||
case SourceType::GeoJSON:
|
||||
return std::make_unique<RenderGeoJSONSource>(staticImmutableCast<GeoJSONSource::Impl>(impl),
|
||||
std::move(threadPool_));
|
||||
return std::make_unique<RenderGeoJSONSource>(staticImmutableCast<GeoJSONSource::Impl>(impl), threadPool);
|
||||
case SourceType::Video:
|
||||
assert(false);
|
||||
return nullptr;
|
||||
case SourceType::Annotations:
|
||||
if (LayerManager::annotationsEnabled) {
|
||||
return std::make_unique<RenderAnnotationSource>(staticImmutableCast<AnnotationSource::Impl>(impl),
|
||||
std::move(threadPool_));
|
||||
threadPool);
|
||||
} else {
|
||||
assert(false);
|
||||
return nullptr;
|
||||
@@ -51,7 +48,7 @@ std::unique_ptr<RenderSource> RenderSource::create(const Immutable<Source::Impl>
|
||||
return std::make_unique<RenderImageSource>(staticImmutableCast<ImageSource::Impl>(impl));
|
||||
case SourceType::CustomVector:
|
||||
return std::make_unique<RenderCustomGeometrySource>(staticImmutableCast<CustomGeometrySource::Impl>(impl),
|
||||
std::move(threadPool_));
|
||||
threadPool);
|
||||
}
|
||||
|
||||
// Not reachable, but placate GCC.
|
||||
|
||||
@@ -33,6 +33,7 @@ class Tile;
|
||||
class TileParameters;
|
||||
class TransformParameters;
|
||||
class TransformState;
|
||||
class UpdateParameters;
|
||||
|
||||
namespace gfx {
|
||||
class UploadPass;
|
||||
@@ -103,7 +104,9 @@ public:
|
||||
const std::optional<std::string>&,
|
||||
const std::optional<std::string>&) {}
|
||||
|
||||
virtual void setCacheEnabled(bool) {};
|
||||
virtual void setCacheEnabled(bool) {}
|
||||
|
||||
virtual void setFastPFOREnabled(bool) {}
|
||||
|
||||
virtual void reduceMemoryUse() = 0;
|
||||
|
||||
|
||||
@@ -22,29 +22,30 @@ void RenderVectorSource::updateInternal(const Tileset& tileset,
|
||||
const bool needsRendering,
|
||||
const bool needsRelayout,
|
||||
const TileParameters& parameters) {
|
||||
tilePyramid.update(
|
||||
layers,
|
||||
needsRendering,
|
||||
needsRelayout,
|
||||
parameters,
|
||||
*baseImpl,
|
||||
util::tileSize_I,
|
||||
tileset.zoomRange,
|
||||
tileset.bounds,
|
||||
[&](const OverscaledTileID& tileID, TileObserver* observer_) -> std::unique_ptr<VectorTile> {
|
||||
if (!isMLT.has_value()) {
|
||||
auto impl = staticImmutableCast<style::TileSource::Impl>(baseImpl);
|
||||
assert(impl->tileset); // we should have one by now
|
||||
if (impl->tileset) {
|
||||
isMLT = (impl->tileset->vectorEncoding == Tileset::VectorEncoding::MLT);
|
||||
}
|
||||
}
|
||||
if (isMLT && *isMLT) {
|
||||
return std::make_unique<VectorMLTTile>(tileID, baseImpl->id, parameters, tileset, observer_);
|
||||
} else {
|
||||
return std::make_unique<VectorMVTTile>(tileID, baseImpl->id, parameters, tileset, observer_);
|
||||
}
|
||||
});
|
||||
tilePyramid.update(layers,
|
||||
needsRendering,
|
||||
needsRelayout,
|
||||
parameters,
|
||||
*baseImpl,
|
||||
util::tileSize_I,
|
||||
tileset.zoomRange,
|
||||
tileset.bounds,
|
||||
[&](const OverscaledTileID& tileID, TileObserver* observer_) -> std::unique_ptr<VectorTile> {
|
||||
if (!isMLT.has_value()) {
|
||||
auto impl = staticImmutableCast<style::TileSource::Impl>(baseImpl);
|
||||
assert(impl->tileset); // we should have one by now
|
||||
if (impl->tileset) {
|
||||
isMLT = (impl->tileset->vectorEncoding == Tileset::VectorEncoding::MLT);
|
||||
}
|
||||
}
|
||||
if (isMLT && *isMLT) {
|
||||
return std::make_unique<VectorMLTTile>(
|
||||
tileID, baseImpl->id, parameters, tileset, observer_, fastPFOREnabled);
|
||||
} else {
|
||||
return std::make_unique<VectorMVTTile>(
|
||||
tileID, baseImpl->id, parameters, tileset, observer_);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -10,16 +10,22 @@ class RenderVectorSource final : public RenderTileSetSource {
|
||||
public:
|
||||
explicit RenderVectorSource(Immutable<style::TileSource::Impl>, const TaggedScheduler&);
|
||||
|
||||
private:
|
||||
/// Enable the decoding of MLT tiles with FastPFOR integer encodings.
|
||||
/// Default is false. Such tiles will fail if not explicitly enabled.
|
||||
void setFastPFOREnabled(bool enable) override { fastPFOREnabled = enable; }
|
||||
|
||||
protected:
|
||||
void updateInternal(const Tileset&,
|
||||
const std::vector<Immutable<style::LayerProperties>>&,
|
||||
bool needsRendering,
|
||||
bool needsRelayout,
|
||||
const TileParameters&) override;
|
||||
|
||||
const std::optional<Tileset>& getTileset() const override;
|
||||
|
||||
private:
|
||||
std::optional<bool> isMLT;
|
||||
bool fastPFOREnabled = false;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -48,6 +48,8 @@ public:
|
||||
|
||||
const bool crossSourceCollisions;
|
||||
|
||||
const bool fastPFOREnabled = false;
|
||||
|
||||
double tileLodMinRadius = 3;
|
||||
double tileLodScale = 1;
|
||||
double tileLodPitchThreshold = (60.0 / 180.0) * std::numbers::pi;
|
||||
|
||||
@@ -12,8 +12,10 @@ VectorMLTTile::VectorMLTTile(const OverscaledTileID& id_,
|
||||
std::string sourceID_,
|
||||
const TileParameters& parameters_,
|
||||
const Tileset& tileset_,
|
||||
TileObserver* observer_)
|
||||
: VectorTile(id_, std::move(sourceID_), parameters_, tileset_, observer_) {}
|
||||
TileObserver* observer_,
|
||||
bool fastPFOREnabled_)
|
||||
: VectorTile(id_, std::move(sourceID_), parameters_, tileset_, observer_),
|
||||
fastPFOREnabled(fastPFOREnabled_) {}
|
||||
|
||||
VectorMLTTile::~VectorMLTTile() {
|
||||
// this needs to be explicitly deleted in the most-derived destructor
|
||||
@@ -26,7 +28,7 @@ VectorMLTTile::~VectorMLTTile() {
|
||||
|
||||
void VectorMLTTile::setData(const std::shared_ptr<const std::string>& data_) {
|
||||
if (!obsolete) {
|
||||
GeometryTile::setData(data_ ? std::make_unique<VectorMLTTileData>(data_) : nullptr);
|
||||
GeometryTile::setData(data_ ? std::make_unique<VectorMLTTileData>(data_, fastPFOREnabled) : nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,11 +15,15 @@ public:
|
||||
std::string sourceID,
|
||||
const TileParameters&,
|
||||
const Tileset&,
|
||||
TileObserver* observer = nullptr);
|
||||
TileObserver* observer,
|
||||
bool fastPFOREnabled);
|
||||
|
||||
~VectorMLTTile() override;
|
||||
|
||||
void setData(const std::shared_ptr<const std::string>& data) override;
|
||||
|
||||
private:
|
||||
bool fastPFOREnabled;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -78,7 +78,7 @@ const PropertyMap& VectorMLTTileFeature::getProperties() const {
|
||||
}
|
||||
|
||||
FeatureIdentifier VectorMLTTileFeature::getID() const {
|
||||
return feature.getID();
|
||||
return feature.getID().has_value() ? mapbox::feature::identifier(*feature.getID()) : mapbox::feature::null_value;
|
||||
}
|
||||
|
||||
namespace {
|
||||
@@ -174,12 +174,14 @@ std::string VectorMLTTileLayer::getName() const {
|
||||
return layer.getName();
|
||||
}
|
||||
|
||||
VectorMLTTileData::VectorMLTTileData(std::shared_ptr<const std::string> data_)
|
||||
: data(std::move(data_)) {}
|
||||
VectorMLTTileData::VectorMLTTileData(std::shared_ptr<const std::string> data_, bool fastPFOREnabled_)
|
||||
: data(std::move(data_)),
|
||||
fastPFOREnabled(fastPFOREnabled_) {}
|
||||
|
||||
VectorMLTTileData::VectorMLTTileData(const VectorMLTTileData& other)
|
||||
: data(other.data),
|
||||
tile(other.tile) {}
|
||||
tile(other.tile),
|
||||
fastPFOREnabled(other.fastPFOREnabled) {}
|
||||
|
||||
std::unique_ptr<GeometryTileData> VectorMLTTileData::clone() const {
|
||||
return std::make_unique<VectorMLTTileData>(*this);
|
||||
@@ -191,7 +193,7 @@ std::unique_ptr<GeometryTileLayer> VectorMLTTileData::getLayer(const std::string
|
||||
if (data && !tile) {
|
||||
try {
|
||||
mlt::DataView tileData{data->data(), data->size()};
|
||||
tile = std::make_shared<MapLibreTile>(mlt::Decoder().decode(tileData));
|
||||
tile = std::make_shared<MapLibreTile>(mlt::Decoder(fastPFOREnabled).decode(tileData));
|
||||
} catch (const std::exception& ex) {
|
||||
Log::Warning(Event::ParseTile, "MLT parse failed: " + std::string(ex.what()));
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ private:
|
||||
|
||||
class VectorMLTTileData : public GeometryTileData {
|
||||
public:
|
||||
VectorMLTTileData(std::shared_ptr<const std::string> data);
|
||||
VectorMLTTileData(std::shared_ptr<const std::string> data, bool fastPFOREnabled);
|
||||
VectorMLTTileData(const VectorMLTTileData&);
|
||||
VectorMLTTileData(VectorMLTTileData&&) = default;
|
||||
|
||||
@@ -80,6 +80,7 @@ public:
|
||||
private:
|
||||
mutable std::shared_ptr<const std::string> data;
|
||||
mutable std::shared_ptr<const MapLibreTile> tile;
|
||||
bool fastPFOREnabled;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
BIN
test/fixtures/map/issue12432/0-0-0-fastpfor.mlt
vendored
Normal file
BIN
test/fixtures/map/issue12432/0-0-0-fastpfor.mlt
vendored
Normal file
Binary file not shown.
BIN
test/fixtures/map/issue12432/0-0-0.mlt
vendored
Normal file
BIN
test/fixtures/map/issue12432/0-0-0.mlt
vendored
Normal file
Binary file not shown.
@@ -21,11 +21,12 @@
|
||||
#include <mbgl/style/sources/vector_source.hpp>
|
||||
#include <mbgl/style/style.hpp>
|
||||
|
||||
#include <mbgl/renderer/sources/render_raster_source.hpp>
|
||||
#include <mbgl/renderer/sources/render_raster_dem_source.hpp>
|
||||
#include <mbgl/renderer/sources/render_vector_source.hpp>
|
||||
#include <mbgl/renderer/sources/render_geojson_source.hpp>
|
||||
#include <mbgl/renderer/sources/render_raster_dem_source.hpp>
|
||||
#include <mbgl/renderer/sources/render_raster_source.hpp>
|
||||
#include <mbgl/renderer/sources/render_vector_source.hpp>
|
||||
#include <mbgl/renderer/tile_parameters.hpp>
|
||||
#include <mbgl/renderer/update_parameters.hpp>
|
||||
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
#include <mbgl/util/string.hpp>
|
||||
@@ -46,10 +47,10 @@
|
||||
#include <mbgl/text/glyph_manager.hpp>
|
||||
#include <mbgl/gfx/dynamic_texture_atlas.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include <optional>
|
||||
|
||||
using namespace mbgl;
|
||||
using SourceType = mbgl::style::SourceType;
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <mbgl/text/glyph_manager.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include "mbgl/tile/vector_mlt_tile_data.hpp"
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
@@ -65,14 +66,7 @@ TEST(VectorTileData, ParseResults) {
|
||||
ASSERT_EQ(layer->getName(), "admin");
|
||||
ASSERT_EQ(layer->featureCount(), 17154u);
|
||||
|
||||
try {
|
||||
layer->getFeature(17154u);
|
||||
ASSERT_TRUE(false) << "should throw: feature index is out of range.";
|
||||
} catch (const std::out_of_range&) {
|
||||
ASSERT_TRUE(true);
|
||||
} catch (...) { // needed for iOS when MBGL_WITH_RTTI=OFF
|
||||
ASSERT_TRUE(true);
|
||||
}
|
||||
ASSERT_THROW(layer->getFeature(17154u), std::out_of_range);
|
||||
|
||||
std::unique_ptr<GeometryTileFeature> feature = layer->getFeature(0u);
|
||||
ASSERT_EQ(feature->getType(), mbgl::FeatureType::LineString);
|
||||
@@ -85,3 +79,50 @@ TEST(VectorTileData, ParseResults) {
|
||||
|
||||
ASSERT_EQ(feature->getValue("invalid"), std::nullopt);
|
||||
}
|
||||
|
||||
TEST(VectorTileData, MLTParseResults) {
|
||||
struct SubCase {
|
||||
bool useFastPFOR;
|
||||
bool fastPFOREnabled;
|
||||
};
|
||||
for (const auto& testCase : std::vector{
|
||||
SubCase{.useFastPFOR = false, .fastPFOREnabled = false},
|
||||
SubCase{.useFastPFOR = false, .fastPFOREnabled = true},
|
||||
SubCase{.useFastPFOR = true, .fastPFOREnabled = true},
|
||||
SubCase{.useFastPFOR = true, .fastPFOREnabled = false},
|
||||
}) {
|
||||
const auto path = "test/fixtures/map/issue12432/0-0-0" +
|
||||
std::string(testCase.useFastPFOR ? "-fastpfor.mlt" : ".mlt");
|
||||
VectorMLTTileData data(std::make_shared<std::string>(util::read_file(path)), testCase.fastPFOREnabled);
|
||||
|
||||
std::vector<std::string> layerNames = data.layerNames();
|
||||
|
||||
if (!testCase.fastPFOREnabled && testCase.useFastPFOR) {
|
||||
// If fast PFOR is not enabled, the fast PFOR tile should fail to parse
|
||||
ASSERT_EQ(layerNames.size(), 0u);
|
||||
continue;
|
||||
}
|
||||
|
||||
// MLT layers are presented in the order they're encountered, not sorted alphabetically like MVT layers
|
||||
ASSERT_EQ(layerNames.size(), 2u);
|
||||
ASSERT_EQ(layerNames.at(0), "water");
|
||||
ASSERT_EQ(layerNames.at(1), "admin");
|
||||
|
||||
ASSERT_FALSE(data.getLayer("invalid"));
|
||||
|
||||
std::unique_ptr<GeometryTileLayer> layer = data.getLayer("admin");
|
||||
ASSERT_EQ(layer->getName(), "admin");
|
||||
ASSERT_EQ(layer->featureCount(), 17154u);
|
||||
|
||||
std::unique_ptr<GeometryTileFeature> feature = layer->getFeature(0u);
|
||||
ASSERT_EQ(feature->getType(), mbgl::FeatureType::LineString);
|
||||
ASSERT_TRUE(feature->getID().is<uint64_t>());
|
||||
ASSERT_EQ(feature->getID().get<uint64_t>(), 1u);
|
||||
|
||||
const std::unordered_map<std::string, Value>& properties = feature->getProperties();
|
||||
ASSERT_EQ(properties.size(), 3u);
|
||||
ASSERT_EQ(properties.at("disputed"), *feature->getValue("disputed"));
|
||||
|
||||
ASSERT_EQ(feature->getValue("invalid"), std::nullopt);
|
||||
}
|
||||
}
|
||||
|
||||
2
vendor/maplibre-tile-spec
vendored
2
vendor/maplibre-tile-spec
vendored
Submodule vendor/maplibre-tile-spec updated: f493beb627...d457bf2b01
7
vendor/maplibre-tile-spec.cmake
vendored
7
vendor/maplibre-tile-spec.cmake
vendored
@@ -1,6 +1,5 @@
|
||||
set(MLT_WITH_JSON OFF CACHE BOOL "No JSON support" FORCE)
|
||||
set(MLT_WITH_PROTOZERO OFF CACHE BOOL "No protozero" FORCE)
|
||||
set(MLT_WITH_FASTPFOR OFF CACHE BOOL "disabled for lack of support for ARMv7 in SIMDE and requirement for SSE on x86" FORCE)
|
||||
set(MLT_WITH_TESTS OFF CACHE BOOL "Google Test conflicts with Dawn")
|
||||
set(MLT_WITH_TOOLS OFF CACHE BOOL "Not used")
|
||||
|
||||
@@ -8,8 +7,4 @@ set(MLT_WITH_TOOLS OFF CACHE BOOL "Not used")
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 14.3)
|
||||
set(MLT_OSX_DEPLOYMENT_TARGET ${CMAKE_OSX_DEPLOYMENT_TARGET} CACHE STRING "Inherited MacOS/iOS target" FORCE)
|
||||
|
||||
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.25")
|
||||
add_subdirectory(${PROJECT_SOURCE_DIR}/vendor/maplibre-tile-spec/cpp SYSTEM)
|
||||
else()
|
||||
add_subdirectory(${PROJECT_SOURCE_DIR}/vendor/maplibre-tile-spec/cpp)
|
||||
endif()
|
||||
add_subdirectory(${PROJECT_SOURCE_DIR}/vendor/maplibre-tile-spec/cpp SYSTEM)
|
||||
|
||||
Reference in New Issue
Block a user