summaryrefslogtreecommitdiff
path: root/src/mbgl/tile
diff options
context:
space:
mode:
authorThiago Marcos P. Santos <tmpsantos@gmail.com>2017-08-07 19:19:32 +0300
committerThiago Marcos P. Santos <tmpsantos@gmail.com>2017-08-09 18:02:46 +0300
commitc53896caefc96a8c18ab746026330ddc4fc0338e (patch)
tree8f562b0c416d6c99f7b565e58b758701f6081677 /src/mbgl/tile
parent9ecbe3642fb4a53b558598239b59bf1d0224c25b (diff)
downloadqtlocation-mapboxgl-c53896caefc96a8c18ab746026330ddc4fc0338e.tar.gz
Bump Mapbox GL Nativeqt-v1.1.0
mapbox-gl-native @ edd7948893fcd40a24d96b790e21d3dd028cecbe
Diffstat (limited to 'src/mbgl/tile')
-rw-r--r--src/mbgl/tile/geojson_tile.cpp83
-rw-r--r--src/mbgl/tile/geojson_tile.hpp15
-rw-r--r--src/mbgl/tile/geometry_tile.cpp202
-rw-r--r--src/mbgl/tile/geometry_tile.hpp93
-rw-r--r--src/mbgl/tile/geometry_tile_data.cpp71
-rw-r--r--src/mbgl/tile/geometry_tile_data.hpp16
-rw-r--r--src/mbgl/tile/geometry_tile_worker.cpp189
-rw-r--r--src/mbgl/tile/geometry_tile_worker.hpp33
-rw-r--r--src/mbgl/tile/raster_tile.cpp30
-rw-r--r--src/mbgl/tile/raster_tile.hpp15
-rw-r--r--src/mbgl/tile/raster_tile_worker.cpp4
-rw-r--r--src/mbgl/tile/tile.cpp10
-rw-r--r--src/mbgl/tile/tile.hpp61
-rw-r--r--src/mbgl/tile/tile_id.hpp37
-rw-r--r--src/mbgl/tile/tile_id_io.cpp5
-rw-r--r--src/mbgl/tile/tile_loader.hpp7
-rw-r--r--src/mbgl/tile/tile_loader_impl.hpp4
-rw-r--r--src/mbgl/tile/vector_tile.cpp284
-rw-r--r--src/mbgl/tile/vector_tile.hpp7
-rw-r--r--src/mbgl/tile/vector_tile_data.cpp89
-rw-r--r--src/mbgl/tile/vector_tile_data.hpp54
21 files changed, 761 insertions, 548 deletions
diff --git a/src/mbgl/tile/geojson_tile.cpp b/src/mbgl/tile/geojson_tile.cpp
index a2f453f03d..5d8339d775 100644
--- a/src/mbgl/tile/geojson_tile.cpp
+++ b/src/mbgl/tile/geojson_tile.cpp
@@ -1,7 +1,10 @@
#include <mbgl/tile/geojson_tile.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
-
+#include <mbgl/renderer/query.hpp>
+#include <mbgl/renderer/tile_parameters.hpp>
+#include <mbgl/style/filter_evaluator.hpp>
#include <mbgl/util/string.hpp>
+
#include <mapbox/geojsonvt.hpp>
#include <supercluster.hpp>
@@ -26,6 +29,10 @@ public:
return feature.properties;
}
+ optional<FeatureIdentifier> getID() const override {
+ return feature.id;
+ }
+
GeometryCollection getGeometries() const override {
GeometryCollection geometry = apply_visitor(ToGeometryCollection(), feature.geometry);
@@ -46,46 +53,86 @@ public:
}
};
-class GeoJSONTileData : public GeometryTileData,
- public GeometryTileLayer {
+class GeoJSONTileLayer : public GeometryTileLayer {
public:
- mapbox::geometry::feature_collection<int16_t> features;
-
- GeoJSONTileData(mapbox::geometry::feature_collection<int16_t> features_)
+ GeoJSONTileLayer(std::shared_ptr<const mapbox::geometry::feature_collection<int16_t>> features_)
: features(std::move(features_)) {
}
- std::unique_ptr<GeometryTileData> clone() const override {
- return std::make_unique<GeoJSONTileData>(*this);
+ std::size_t featureCount() const override {
+ return features->size();
}
- const GeometryTileLayer* getLayer(const std::string&) const override {
- return this;
+ std::unique_ptr<GeometryTileFeature> getFeature(std::size_t i) const override {
+ return std::make_unique<GeoJSONTileFeature>((*features)[i]);
}
std::string getName() const override {
return "";
}
- std::size_t featureCount() const override {
- return features.size();
+private:
+ std::shared_ptr<const mapbox::geometry::feature_collection<int16_t>> features;
+};
+
+class GeoJSONTileData : public GeometryTileData {
+public:
+ GeoJSONTileData(mapbox::geometry::feature_collection<int16_t> features_)
+ : features(std::make_shared<mapbox::geometry::feature_collection<int16_t>>(
+ std::move(features_))) {
}
- std::unique_ptr<GeometryTileFeature> getFeature(std::size_t i) const override {
- return std::make_unique<GeoJSONTileFeature>(features[i]);
+ GeoJSONTileData(std::shared_ptr<const mapbox::geometry::feature_collection<int16_t>> features_)
+ : features(std::move(features_)) {
}
+
+ std::unique_ptr<GeometryTileData> clone() const override {
+ return std::make_unique<GeoJSONTileData>(features);
+ }
+
+ std::unique_ptr<GeometryTileLayer> getLayer(const std::string&) const override {
+ return std::make_unique<GeoJSONTileLayer>(features);
+ }
+
+
+private:
+ std::shared_ptr<const mapbox::geometry::feature_collection<int16_t>> features;
};
GeoJSONTile::GeoJSONTile(const OverscaledTileID& overscaledTileID,
std::string sourceID_,
- const style::UpdateParameters& parameters)
+ const TileParameters& parameters,
+ mapbox::geometry::feature_collection<int16_t> features)
: GeometryTile(overscaledTileID, sourceID_, parameters) {
+ updateData(std::move(features));
}
-
-void GeoJSONTile::updateData(const mapbox::geometry::feature_collection<int16_t>& features) {
- setData(std::make_unique<GeoJSONTileData>(features));
+
+void GeoJSONTile::updateData(mapbox::geometry::feature_collection<int16_t> features) {
+ setData(std::make_unique<GeoJSONTileData>(std::move(features)));
}
void GeoJSONTile::setNecessity(Necessity) {}
+
+void GeoJSONTile::querySourceFeatures(
+ std::vector<Feature>& result,
+ const SourceQueryOptions& options) {
+
+ // Ignore the sourceLayer, there is only one
+ auto layer = getData()->getLayer({});
+
+ if (layer) {
+ auto featureCount = layer->featureCount();
+ for (std::size_t i = 0; i < featureCount; i++) {
+ auto feature = layer->getFeature(i);
+
+ // Apply filter, if any
+ if (options.filter && !(*options.filter)(*feature)) {
+ continue;
+ }
+
+ result.push_back(convertFeature(*feature, id.canonical));
+ }
+ }
+}
} // namespace mbgl
diff --git a/src/mbgl/tile/geojson_tile.hpp b/src/mbgl/tile/geojson_tile.hpp
index 2880408736..d8a0a379d7 100644
--- a/src/mbgl/tile/geojson_tile.hpp
+++ b/src/mbgl/tile/geojson_tile.hpp
@@ -5,19 +5,22 @@
namespace mbgl {
-namespace style {
-class UpdateParameters;
-} // namespace style
+class TileParameters;
class GeoJSONTile : public GeometryTile {
public:
GeoJSONTile(const OverscaledTileID&,
std::string sourceID,
- const style::UpdateParameters&);
+ const TileParameters&,
+ mapbox::geometry::feature_collection<int16_t>);
+
+ void updateData(mapbox::geometry::feature_collection<int16_t>);
- void updateData(const mapbox::geometry::feature_collection<int16_t>&);
-
void setNecessity(Necessity) final;
+
+ void querySourceFeatures(
+ std::vector<Feature>& result,
+ const SourceQueryOptions&) override;
};
} // namespace mbgl
diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp
index 9aeb35c821..33911df9ed 100644
--- a/src/mbgl/tile/geometry_tile.cpp
+++ b/src/mbgl/tile/geometry_tile.cpp
@@ -2,17 +2,27 @@
#include <mbgl/tile/geometry_tile_worker.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/tile/tile_observer.hpp>
-#include <mbgl/style/update_parameters.hpp>
#include <mbgl/style/layer_impl.hpp>
#include <mbgl/style/layers/background_layer.hpp>
#include <mbgl/style/layers/custom_layer.hpp>
-#include <mbgl/style/layers/symbol_layer.hpp>
-#include <mbgl/style/style.hpp>
+#include <mbgl/renderer/tile_parameters.hpp>
+#include <mbgl/renderer/layers/render_background_layer.hpp>
+#include <mbgl/renderer/layers/render_custom_layer.hpp>
+#include <mbgl/renderer/layers/render_symbol_layer.hpp>
+#include <mbgl/renderer/buckets/symbol_bucket.hpp>
+#include <mbgl/renderer/query.hpp>
+#include <mbgl/text/glyph_atlas.hpp>
+#include <mbgl/renderer/image_atlas.hpp>
#include <mbgl/storage/file_source.hpp>
#include <mbgl/geometry/feature_index.hpp>
#include <mbgl/text/collision_tile.hpp>
#include <mbgl/map/transform_state.hpp>
#include <mbgl/util/run_loop.hpp>
+#include <mbgl/style/filter_evaluator.hpp>
+#include <mbgl/util/chrono.hpp>
+#include <mbgl/util/logging.hpp>
+
+#include <iostream>
namespace mbgl {
@@ -20,41 +30,49 @@ using namespace style;
GeometryTile::GeometryTile(const OverscaledTileID& id_,
std::string sourceID_,
- const style::UpdateParameters& parameters)
+ const TileParameters& parameters)
: Tile(id_),
sourceID(std::move(sourceID_)),
- style(parameters.style),
mailbox(std::make_shared<Mailbox>(*util::RunLoop::Get())),
worker(parameters.workerScheduler,
ActorRef<GeometryTile>(*this, mailbox),
id_,
- *parameters.style.glyphAtlas,
obsolete,
- parameters.mode) {
+ parameters.mode,
+ parameters.pixelRatio),
+ glyphManager(parameters.glyphManager),
+ imageManager(parameters.imageManager),
+ placementThrottler(Milliseconds(300), [this] { invokePlacement(); }),
+ lastYStretch(1.0f) {
}
GeometryTile::~GeometryTile() {
- cancel();
+ glyphManager.removeRequestor(*this);
+ imageManager.removeRequestor(*this);
+ markObsolete();
}
void GeometryTile::cancel() {
+ markObsolete();
+}
+
+void GeometryTile::markObsolete() {
obsolete = true;
}
void GeometryTile::setError(std::exception_ptr err) {
+ loaded = true;
+ renderable = false;
observer->onTileError(*this, err);
}
void GeometryTile::setData(std::unique_ptr<const GeometryTileData> data_) {
// Mark the tile as pending again if it was complete before to prevent signaling a complete
// state despite pending parse operations.
- if (availableData == DataAvailability::All) {
- availableData = DataAvailability::Some;
- }
+ pending = true;
++correlationID;
worker.invoke(&GeometryTileWorker::setData, std::move(data_), correlationID);
- redoLayout();
}
void GeometryTile::setPlacementConfig(const PlacementConfig& desiredConfig) {
@@ -64,71 +82,126 @@ void GeometryTile::setPlacementConfig(const PlacementConfig& desiredConfig) {
// Mark the tile as pending again if it was complete before to prevent signaling a complete
// state despite pending parse operations.
- if (availableData == DataAvailability::All) {
- availableData = DataAvailability::Some;
- }
+ pending = true;
++correlationID;
requestedConfig = desiredConfig;
- worker.invoke(&GeometryTileWorker::setPlacementConfig, desiredConfig, correlationID);
+ placementThrottler.invoke();
}
-void GeometryTile::symbolDependenciesChanged() {
- worker.invoke(&GeometryTileWorker::symbolDependenciesChanged);
+void GeometryTile::invokePlacement() {
+ if (requestedConfig) {
+ worker.invoke(&GeometryTileWorker::setPlacementConfig, *requestedConfig, correlationID);
+ }
}
-void GeometryTile::redoLayout() {
+void GeometryTile::setLayers(const std::vector<Immutable<Layer::Impl>>& layers) {
// Mark the tile as pending again if it was complete before to prevent signaling a complete
// state despite pending parse operations.
- if (availableData == DataAvailability::All) {
- availableData = DataAvailability::Some;
- }
+ pending = true;
- std::vector<std::unique_ptr<Layer>> copy;
+ std::vector<Immutable<Layer::Impl>> impls;
- for (const Layer* layer : style.getLayers()) {
- // Avoid cloning and including irrelevant layers.
- if (layer->is<BackgroundLayer>() ||
- layer->is<CustomLayer>() ||
- layer->baseImpl->source != sourceID ||
- id.overscaledZ < std::floor(layer->baseImpl->minZoom) ||
- id.overscaledZ >= std::ceil(layer->baseImpl->maxZoom) ||
- layer->baseImpl->visibility == VisibilityType::None) {
+ for (const auto& layer : layers) {
+ // Skip irrelevant layers.
+ if (layer->type == LayerType::Background ||
+ layer->type == LayerType::Custom ||
+ layer->source != sourceID ||
+ id.overscaledZ < std::floor(layer->minZoom) ||
+ id.overscaledZ >= std::ceil(layer->maxZoom) ||
+ layer->visibility == VisibilityType::None) {
continue;
}
- copy.push_back(layer->baseImpl->clone());
+ impls.push_back(layer);
}
++correlationID;
- worker.invoke(&GeometryTileWorker::setLayers, std::move(copy), correlationID);
+ worker.invoke(&GeometryTileWorker::setLayers, std::move(impls), correlationID);
}
void GeometryTile::onLayout(LayoutResult result) {
- availableData = DataAvailability::Some;
+ loaded = true;
+ renderable = true;
nonSymbolBuckets = std::move(result.nonSymbolBuckets);
featureIndex = std::move(result.featureIndex);
data = std::move(result.tileData);
+ collisionTile.reset();
observer->onTileChanged(*this);
}
void GeometryTile::onPlacement(PlacementResult result) {
+ loaded = true;
+ renderable = true;
if (result.correlationID == correlationID) {
- availableData = DataAvailability::All;
+ pending = false;
}
symbolBuckets = std::move(result.symbolBuckets);
collisionTile = std::move(result.collisionTile);
+ if (result.glyphAtlasImage) {
+ glyphAtlasImage = std::move(*result.glyphAtlasImage);
+ }
+ if (result.iconAtlasImage) {
+ iconAtlasImage = std::move(*result.iconAtlasImage);
+ }
+ if (collisionTile.get()) {
+ lastYStretch = collisionTile->yStretch;
+ }
observer->onTileChanged(*this);
}
void GeometryTile::onError(std::exception_ptr err) {
- availableData = DataAvailability::All;
+ loaded = true;
+ pending = false;
+ renderable = false;
observer->onTileError(*this, err);
}
+
+void GeometryTile::onGlyphsAvailable(GlyphMap glyphs) {
+ worker.invoke(&GeometryTileWorker::onGlyphsAvailable, std::move(glyphs));
+}
+
+void GeometryTile::getGlyphs(GlyphDependencies glyphDependencies) {
+ glyphManager.getGlyphs(*this, std::move(glyphDependencies));
+}
+
+void GeometryTile::onImagesAvailable(ImageMap images) {
+ worker.invoke(&GeometryTileWorker::onImagesAvailable, std::move(images));
+}
+
+void GeometryTile::getImages(ImageDependencies imageDependencies) {
+ imageManager.getImages(*this, std::move(imageDependencies));
+}
+
+void GeometryTile::upload(gl::Context& context) {
+ auto uploadFn = [&] (Bucket& bucket) {
+ if (bucket.needsUpload()) {
+ bucket.upload(context);
+ }
+ };
+
+ for (auto& entry : nonSymbolBuckets) {
+ uploadFn(*entry.second);
+ }
+
+ for (auto& entry : symbolBuckets) {
+ uploadFn(*entry.second);
+ }
+
+ if (glyphAtlasImage) {
+ glyphAtlasTexture = context.createTexture(*glyphAtlasImage, 0);
+ glyphAtlasImage = {};
+ }
+
+ if (iconAtlasImage) {
+ iconAtlasTexture = context.createTexture(*iconAtlasImage, 0);
+ iconAtlasImage = {};
+ }
+}
-Bucket* GeometryTile::getBucket(const Layer& layer) {
- const auto& buckets = layer.is<SymbolLayer>() ? symbolBuckets : nonSymbolBuckets;
- const auto it = buckets.find(layer.baseImpl->id);
+Bucket* GeometryTile::getBucket(const Layer::Impl& layer) const {
+ const auto& buckets = layer.type == LayerType::Symbol ? symbolBuckets : nonSymbolBuckets;
+ const auto it = buckets.find(layer.id);
if (it == buckets.end()) {
return nullptr;
}
@@ -141,7 +214,8 @@ void GeometryTile::queryRenderedFeatures(
std::unordered_map<std::string, std::vector<Feature>>& result,
const GeometryCoordinates& queryGeometry,
const TransformState& transformState,
- const optional<std::vector<std::string>>& layerIDs) {
+ const RenderStyle& style,
+ const RenderedQueryOptions& options) {
if (!featureIndex || !data) return;
@@ -150,11 +224,55 @@ void GeometryTile::queryRenderedFeatures(
transformState.getAngle(),
util::tileSize * id.overscaleFactor(),
std::pow(2, transformState.getZoom() - id.overscaledZ),
- layerIDs,
+ options,
*data,
id.canonical,
style,
- collisionTile.get());
+ collisionTile.get(),
+ *this);
+}
+
+void GeometryTile::querySourceFeatures(
+ std::vector<Feature>& result,
+ const SourceQueryOptions& options) {
+
+ // Data not yet available
+ if (!data) {
+ return;
+ }
+
+ // No source layers, specified, nothing to do
+ if (!options.sourceLayers) {
+ Log::Warning(Event::General, "At least one sourceLayer required");
+ return;
+ }
+
+ for (auto sourceLayer : *options.sourceLayers) {
+ // Go throught all sourceLayers, if any
+ // to gather all the features
+ auto layer = data->getLayer(sourceLayer);
+
+ if (layer) {
+ auto featureCount = layer->featureCount();
+ for (std::size_t i = 0; i < featureCount; i++) {
+ auto feature = layer->getFeature(i);
+
+ // Apply filter, if any
+ if (options.filter && !(*options.filter)(*feature)) {
+ continue;
+ }
+
+ result.push_back(convertFeature(*feature, id.canonical));
+ }
+ }
+ }
+}
+
+float GeometryTile::yStretch() const {
+ // collisionTile gets reset in onLayout but we don't clear the symbolBuckets
+ // until a new placement result comes along, so keep the yStretch value in
+ // case we need to render them.
+ return lastYStretch;
}
} // namespace mbgl
diff --git a/src/mbgl/tile/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp
index c61a510311..c45762742b 100644
--- a/src/mbgl/tile/geometry_tile.hpp
+++ b/src/mbgl/tile/geometry_tile.hpp
@@ -2,9 +2,14 @@
#include <mbgl/tile/tile.hpp>
#include <mbgl/tile/geometry_tile_worker.hpp>
+#include <mbgl/renderer/image_manager.hpp>
+#include <mbgl/text/glyph_manager.hpp>
#include <mbgl/text/placement_config.hpp>
+#include <mbgl/text/collision_tile.hpp>
#include <mbgl/util/feature.hpp>
+#include <mbgl/util/throttler.hpp>
#include <mbgl/actor/actor.hpp>
+#include <mbgl/geometry/feature_index.hpp>
#include <atomic>
#include <memory>
@@ -14,20 +19,18 @@
namespace mbgl {
class GeometryTileData;
-class FeatureIndex;
-class CollisionTile;
-
-namespace style {
-class Style;
-class Layer;
-class UpdateParameters;
-} // namespace style
-
-class GeometryTile : public Tile {
+class RenderStyle;
+class RenderLayer;
+class SourceQueryOptions;
+class TileParameters;
+class GlyphAtlas;
+class ImageAtlas;
+
+class GeometryTile : public Tile, public GlyphRequestor, ImageRequestor {
public:
GeometryTile(const OverscaledTileID&,
std::string sourceID,
- const style::UpdateParameters&);
+ const TileParameters&);
~GeometryTile() override;
@@ -35,16 +38,30 @@ public:
void setData(std::unique_ptr<const GeometryTileData>);
void setPlacementConfig(const PlacementConfig&) override;
- void symbolDependenciesChanged() override;
- void redoLayout() override;
+ void setLayers(const std::vector<Immutable<style::Layer::Impl>>&) override;
+
+ void onGlyphsAvailable(GlyphMap) override;
+ void onImagesAvailable(ImageMap) override;
+
+ void getGlyphs(GlyphDependencies);
+ void getImages(ImageDependencies);
+
+ void upload(gl::Context&) override;
+ Bucket* getBucket(const style::Layer::Impl&) const override;
- Bucket* getBucket(const style::Layer&) override;
+ Size bindGlyphAtlas(gl::Context&);
+ Size bindIconAtlas(gl::Context&);
void queryRenderedFeatures(
std::unordered_map<std::string, std::vector<Feature>>& result,
const GeometryCoordinates& queryGeometry,
const TransformState&,
- const optional<std::vector<std::string>>& layerIDs) override;
+ const RenderStyle&,
+ const RenderedQueryOptions& options) override;
+
+ void querySourceFeatures(
+ std::vector<Feature>& result,
+ const SourceQueryOptions&) override;
void cancel() override;
@@ -54,6 +71,15 @@ public:
std::unique_ptr<FeatureIndex> featureIndex;
std::unique_ptr<GeometryTileData> tileData;
uint64_t correlationID;
+
+ LayoutResult(std::unordered_map<std::string, std::shared_ptr<Bucket>> nonSymbolBuckets_,
+ std::unique_ptr<FeatureIndex> featureIndex_,
+ std::unique_ptr<GeometryTileData> tileData_,
+ uint64_t correlationID_)
+ : nonSymbolBuckets(std::move(nonSymbolBuckets_)),
+ featureIndex(std::move(featureIndex_)),
+ tileData(std::move(tileData_)),
+ correlationID(correlationID_) {}
};
void onLayout(LayoutResult);
@@ -61,15 +87,37 @@ public:
public:
std::unordered_map<std::string, std::shared_ptr<Bucket>> symbolBuckets;
std::unique_ptr<CollisionTile> collisionTile;
+ optional<AlphaImage> glyphAtlasImage;
+ optional<PremultipliedImage> iconAtlasImage;
uint64_t correlationID;
+
+ PlacementResult(std::unordered_map<std::string, std::shared_ptr<Bucket>> symbolBuckets_,
+ std::unique_ptr<CollisionTile> collisionTile_,
+ optional<AlphaImage> glyphAtlasImage_,
+ optional<PremultipliedImage> iconAtlasImage_,
+ uint64_t correlationID_)
+ : symbolBuckets(std::move(symbolBuckets_)),
+ collisionTile(std::move(collisionTile_)),
+ glyphAtlasImage(std::move(glyphAtlasImage_)),
+ iconAtlasImage(std::move(iconAtlasImage_)),
+ correlationID(correlationID_) {}
};
void onPlacement(PlacementResult);
void onError(std::exception_ptr);
+
+ float yStretch() const override;
+
+protected:
+ const GeometryTileData* getData() {
+ return data.get();
+ }
private:
+ void markObsolete();
+ void invokePlacement();
+
const std::string sourceID;
- style::Style& style;
// Used to signal the worker that it should abandon parsing this tile as soon as possible.
std::atomic<bool> obsolete { false };
@@ -77,6 +125,9 @@ private:
std::shared_ptr<Mailbox> mailbox;
Actor<GeometryTileWorker> worker;
+ GlyphManager& glyphManager;
+ ImageManager& imageManager;
+
uint64_t correlationID = 0;
optional<PlacementConfig> requestedConfig;
@@ -84,8 +135,18 @@ private:
std::unique_ptr<FeatureIndex> featureIndex;
std::unique_ptr<const GeometryTileData> data;
+ optional<AlphaImage> glyphAtlasImage;
+ optional<PremultipliedImage> iconAtlasImage;
+
std::unordered_map<std::string, std::shared_ptr<Bucket>> symbolBuckets;
std::unique_ptr<CollisionTile> collisionTile;
+
+ util::Throttler placementThrottler;
+ float lastYStretch;
+
+public:
+ optional<gl::Texture> glyphAtlasTexture;
+ optional<gl::Texture> iconAtlasTexture;
};
} // namespace mbgl
diff --git a/src/mbgl/tile/geometry_tile_data.cpp b/src/mbgl/tile/geometry_tile_data.cpp
index ccc91b027a..680f8d1497 100644
--- a/src/mbgl/tile/geometry_tile_data.cpp
+++ b/src/mbgl/tile/geometry_tile_data.cpp
@@ -1,7 +1,7 @@
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/tile/tile_id.hpp>
-#include <clipper/clipper.hpp>
+#include <mapbox/geometry/wagyu/wagyu.hpp>
namespace mbgl {
@@ -17,8 +17,8 @@ static double signedArea(const GeometryCoordinates& ring) {
return sum;
}
-static ClipperLib::Path toClipperPath(const GeometryCoordinates& ring) {
- ClipperLib::Path result;
+static LinearRing<int32_t> toWagyuPath(const GeometryCoordinates& ring) {
+ LinearRing<int32_t> result;
result.reserve(ring.size());
for (const auto& p : ring) {
result.emplace_back(p.x, p.y);
@@ -26,63 +26,29 @@ static ClipperLib::Path toClipperPath(const GeometryCoordinates& ring) {
return result;
}
-static GeometryCoordinates fromClipperPath(const ClipperLib::Path& path) {
- GeometryCoordinates result;
- result.reserve(path.size() + 1);
-
- for (const auto& p : path) {
- using Coordinate = GeometryCoordinates::coordinate_type;
- assert(p.x >= std::numeric_limits<Coordinate>::min());
- assert(p.x <= std::numeric_limits<Coordinate>::max());
- assert(p.y >= std::numeric_limits<Coordinate>::min());
- assert(p.y <= std::numeric_limits<Coordinate>::max());
- result.emplace_back(Coordinate(p.x), Coordinate(p.y));
- }
-
- // Clipper does not repeat initial point, but our geometry model requires it.
- if (!result.empty()) {
- result.push_back(result.front());
- }
-
- return result;
-}
-
-static void processPolynodeBranch(ClipperLib::PolyNode* polynode, GeometryCollection& rings) {
- // Exterior ring.
- rings.push_back(fromClipperPath(polynode->Contour));
- assert(signedArea(rings.back()) > 0);
-
- // Interior rings.
- for (auto * ring : polynode->Childs) {
- rings.push_back(fromClipperPath(ring->Contour));
- assert(signedArea(rings.back()) < 0);
- }
-
- // PolyNodes may be nested in the case of a polygon inside a hole.
- for (auto * ring : polynode->Childs) {
- for (auto * subRing : ring->Childs) {
- processPolynodeBranch(subRing, rings);
+static GeometryCollection toGeometryCollection(MultiPolygon<int16_t>&& multipolygon) {
+ GeometryCollection result;
+ for (auto& polygon : multipolygon) {
+ for (auto& ring : polygon) {
+ result.emplace_back(std::move(ring));
}
}
+ return result;
}
GeometryCollection fixupPolygons(const GeometryCollection& rings) {
- ClipperLib::Clipper clipper;
- clipper.StrictlySimple(true);
+ using namespace mapbox::geometry::wagyu;
+
+ wagyu<int32_t> clipper;
for (const auto& ring : rings) {
- clipper.AddPath(toClipperPath(ring), ClipperLib::ptSubject, true);
+ clipper.add_ring(toWagyuPath(ring));
}
- ClipperLib::PolyTree polygons;
- clipper.Execute(ClipperLib::ctUnion, polygons, ClipperLib::pftEvenOdd, ClipperLib::pftEvenOdd);
- clipper.Clear();
+ MultiPolygon<int16_t> multipolygon;
+ clipper.execute(clip_type_union, multipolygon, fill_type_even_odd, fill_type_even_odd);
- GeometryCollection result;
- for (auto * polynode : polygons.Childs) {
- processPolynodeBranch(polynode, result);
- }
- return result;
+ return toGeometryCollection(std::move(multipolygon));
}
std::vector<GeometryCollection> classifyRings(const GeometryCollection& rings) {
@@ -208,12 +174,7 @@ static Feature::geometry_type convertGeometry(const GeometryTileFeature& geometr
}
Feature convertFeature(const GeometryTileFeature& geometryTileFeature, const CanonicalTileID& tileID) {
-#if !defined(__GNUC__) || __GNUC__ >= 5
Feature feature { convertGeometry(geometryTileFeature, tileID) };
-#else
- Feature feature;
- feature.geometry = convertGeometry(geometryTileFeature, tileID);
-#endif
feature.properties = geometryTileFeature.getProperties();
feature.id = geometryTileFeature.getID();
return feature;
diff --git a/src/mbgl/tile/geometry_tile_data.hpp b/src/mbgl/tile/geometry_tile_data.hpp
index 8a10ec058a..449d8cab28 100644
--- a/src/mbgl/tile/geometry_tile_data.hpp
+++ b/src/mbgl/tile/geometry_tile_data.hpp
@@ -21,6 +21,13 @@ using GeometryCoordinate = Point<int16_t>;
class GeometryCoordinates : public std::vector<GeometryCoordinate> {
public:
using coordinate_type = int16_t;
+
+ GeometryCoordinates() = default;
+ GeometryCoordinates(const std::vector<GeometryCoordinate>& v)
+ : std::vector<GeometryCoordinate>(v) {}
+ GeometryCoordinates(std::vector<GeometryCoordinate>&& v)
+ : std::vector<GeometryCoordinate>(std::move(v)) {}
+
using std::vector<GeometryCoordinate>::vector;
};
@@ -44,7 +51,11 @@ class GeometryTileLayer {
public:
virtual ~GeometryTileLayer() = default;
virtual std::size_t featureCount() const = 0;
+
+ // Returns the feature object at the given position within the layer. The returned feature
+ // object may *not* outlive the layer object.
virtual std::unique_ptr<GeometryTileFeature> getFeature(std::size_t) const = 0;
+
virtual std::string getName() const = 0;
};
@@ -52,7 +63,10 @@ class GeometryTileData {
public:
virtual ~GeometryTileData() = default;
virtual std::unique_ptr<GeometryTileData> clone() const = 0;
- virtual const GeometryTileLayer* getLayer(const std::string&) const = 0;
+
+ // Returns the layer with the given name. The returned layer object *may* outlive the data
+ // object.
+ virtual std::unique_ptr<GeometryTileLayer> getLayer(const std::string&) const = 0;
};
// classifies an array of rings into polygons with outer rings and holes
diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp
index 2a86b7feda..c622d82e31 100644
--- a/src/mbgl/tile/geometry_tile_worker.cpp
+++ b/src/mbgl/tile/geometry_tile_worker.cpp
@@ -2,13 +2,14 @@
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/tile/geometry_tile.hpp>
#include <mbgl/text/collision_tile.hpp>
-#include <mbgl/text/glyph_atlas.hpp>
#include <mbgl/layout/symbol_layout.hpp>
-#include <mbgl/style/bucket_parameters.hpp>
-#include <mbgl/style/group_by_layout.hpp>
-#include <mbgl/style/layers/symbol_layer.hpp>
+#include <mbgl/renderer/bucket_parameters.hpp>
+#include <mbgl/renderer/group_by_layout.hpp>
+#include <mbgl/style/filter.hpp>
+#include <mbgl/style/filter_evaluator.hpp>
#include <mbgl/style/layers/symbol_layer_impl.hpp>
-#include <mbgl/renderer/symbol_bucket.hpp>
+#include <mbgl/renderer/layers/render_symbol_layer.hpp>
+#include <mbgl/renderer/buckets/symbol_bucket.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/string.hpp>
@@ -23,20 +24,18 @@ using namespace style;
GeometryTileWorker::GeometryTileWorker(ActorRef<GeometryTileWorker> self_,
ActorRef<GeometryTile> parent_,
OverscaledTileID id_,
- GlyphAtlas& glyphAtlas_,
const std::atomic<bool>& obsolete_,
- const MapMode mode_)
+ const MapMode mode_,
+ const float pixelRatio_)
: self(std::move(self_)),
parent(std::move(parent_)),
id(std::move(id_)),
- glyphAtlas(glyphAtlas_),
obsolete(obsolete_),
- mode(mode_) {
+ mode(mode_),
+ pixelRatio(pixelRatio_) {
}
-GeometryTileWorker::~GeometryTileWorker() {
- glyphAtlas.removeGlyphs(reinterpret_cast<uintptr_t>(this));
-}
+GeometryTileWorker::~GeometryTileWorker() = default;
/*
GeometryTileWorker is a state machine. This is its transition diagram.
@@ -93,7 +92,7 @@ void GeometryTileWorker::setData(std::unique_ptr<const GeometryTileData> data_,
}
}
-void GeometryTileWorker::setLayers(std::vector<std::unique_ptr<Layer>> layers_, uint64_t correlationID_) {
+void GeometryTileWorker::setLayers(std::vector<Immutable<Layer::Impl>> layers_, uint64_t correlationID_) {
try {
layers = std::move(layers_);
correlationID = correlationID_;
@@ -145,14 +144,14 @@ void GeometryTileWorker::symbolDependenciesChanged() {
try {
switch (state) {
case Idle:
- if (hasPendingSymbolDependencies()) {
+ if (symbolLayoutsNeedPreparation) {
attemptPlacement();
coalesce();
}
break;
case Coalescing:
- if (hasPendingSymbolDependencies()) {
+ if (symbolLayoutsNeedPreparation) {
state = NeedPlacement;
}
break;
@@ -197,6 +196,71 @@ void GeometryTileWorker::coalesce() {
self.invoke(&GeometryTileWorker::coalesced);
}
+void GeometryTileWorker::onGlyphsAvailable(GlyphMap newGlyphMap) {
+ for (auto& newFontGlyphs : newGlyphMap) {
+ const FontStack& fontStack = newFontGlyphs.first;
+ Glyphs& newGlyphs = newFontGlyphs.second;
+
+ Glyphs& glyphs = glyphMap[fontStack];
+ GlyphIDs& pendingGlyphIDs = pendingGlyphDependencies[fontStack];
+
+ for (auto& newGlyph : newGlyphs) {
+ const GlyphID& glyphID = newGlyph.first;
+ optional<Immutable<Glyph>>& glyph = newGlyph.second;
+
+ if (pendingGlyphIDs.erase(glyphID)) {
+ glyphs.emplace(glyphID, std::move(glyph));
+ }
+ }
+ }
+ symbolDependenciesChanged();
+}
+
+void GeometryTileWorker::onImagesAvailable(ImageMap newImageMap) {
+ imageMap = std::move(newImageMap);
+ pendingImageDependencies.clear();
+ symbolDependenciesChanged();
+}
+
+void GeometryTileWorker::requestNewGlyphs(const GlyphDependencies& glyphDependencies) {
+ for (auto& fontDependencies : glyphDependencies) {
+ auto fontGlyphs = glyphMap.find(fontDependencies.first);
+ for (auto glyphID : fontDependencies.second) {
+ if (fontGlyphs == glyphMap.end() || fontGlyphs->second.find(glyphID) == fontGlyphs->second.end()) {
+ pendingGlyphDependencies[fontDependencies.first].insert(glyphID);
+ }
+ }
+ }
+ if (!pendingGlyphDependencies.empty()) {
+ parent.invoke(&GeometryTile::getGlyphs, pendingGlyphDependencies);
+ }
+}
+
+void GeometryTileWorker::requestNewImages(const ImageDependencies& imageDependencies) {
+ pendingImageDependencies = imageDependencies;
+ if (!pendingImageDependencies.empty()) {
+ parent.invoke(&GeometryTile::getImages, pendingImageDependencies);
+ }
+}
+
+static std::vector<std::unique_ptr<RenderLayer>> toRenderLayers(const std::vector<Immutable<style::Layer::Impl>>& layers, float zoom) {
+ std::vector<std::unique_ptr<RenderLayer>> renderLayers;
+ renderLayers.reserve(layers.size());
+ for (auto& layer : layers) {
+ renderLayers.push_back(RenderLayer::create(layer));
+
+ renderLayers.back()->transition(TransitionParameters {
+ Clock::time_point::max(),
+ TransitionOptions()
+ });
+
+ renderLayers.back()->evaluate(PropertyEvaluationParameters {
+ zoom
+ });
+ }
+ return renderLayers;
+}
+
void GeometryTileWorker::redoLayout() {
if (!data || !layers) {
return;
@@ -204,17 +268,23 @@ void GeometryTileWorker::redoLayout() {
std::vector<std::string> symbolOrder;
for (auto it = layers->rbegin(); it != layers->rend(); it++) {
- if ((*it)->is<SymbolLayer>()) {
- symbolOrder.push_back((*it)->getID());
+ if ((*it)->type == LayerType::Symbol) {
+ symbolOrder.push_back((*it)->id);
}
}
std::unordered_map<std::string, std::unique_ptr<SymbolLayout>> symbolLayoutMap;
std::unordered_map<std::string, std::shared_ptr<Bucket>> buckets;
auto featureIndex = std::make_unique<FeatureIndex>();
- BucketParameters parameters { id, obsolete, *featureIndex, mode };
+ BucketParameters parameters { id, mode, pixelRatio };
+
+ GlyphDependencies glyphDependencies;
+ ImageDependencies imageDependencies;
+
+ // Create render layers and group by layout
+ std::vector<std::unique_ptr<RenderLayer>> renderLayers = toRenderLayers(*layers, id.overscaledZ);
+ std::vector<std::vector<const RenderLayer*>> groups = groupByLayout(renderLayers);
- std::vector<std::vector<const Layer*>> groups = groupByLayout(*layers);
for (auto& group : groups) {
if (obsolete) {
return;
@@ -224,7 +294,7 @@ void GeometryTileWorker::redoLayout() {
continue; // Tile has no data.
}
- const Layer& leader = *group.at(0);
+ const RenderLayer& leader = *group.at(0);
auto geometryLayer = (*data)->getLayer(leader.baseImpl->sourceLayer);
if (!geometryLayer) {
@@ -238,14 +308,31 @@ void GeometryTileWorker::redoLayout() {
featureIndex->setBucketLayerIDs(leader.getID(), layerIDs);
- if (leader.is<SymbolLayer>()) {
- symbolLayoutMap.emplace(leader.getID(),
- leader.as<SymbolLayer>()->impl->createLayout(parameters, *geometryLayer, layerIDs));
+ if (leader.is<RenderSymbolLayer>()) {
+ auto layout = leader.as<RenderSymbolLayer>()->createLayout(
+ parameters, group, std::move(geometryLayer), glyphDependencies, imageDependencies);
+ symbolLayoutMap.emplace(leader.getID(), std::move(layout));
+ symbolLayoutsNeedPreparation = true;
} else {
- std::shared_ptr<Bucket> bucket = leader.baseImpl->createBucket(parameters, *geometryLayer);
+ const Filter& filter = leader.baseImpl->filter;
+ const std::string& sourceLayerID = leader.baseImpl->sourceLayer;
+ std::shared_ptr<Bucket> bucket = leader.createBucket(parameters, group);
+
+ for (std::size_t i = 0; !obsolete && i < geometryLayer->featureCount(); i++) {
+ std::unique_ptr<GeometryTileFeature> feature = geometryLayer->getFeature(i);
+
+ if (!filter(feature->getType(), feature->getID(), [&] (const auto& key) { return feature->getValue(key); }))
+ continue;
+
+ GeometryCollection geometries = feature->getGeometries();
+ bucket->addFeature(*feature, geometries);
+ featureIndex->insert(geometries, i, sourceLayerID, leader.getID());
+ }
+
if (!bucket->hasData()) {
continue;
}
+
for (const auto& layer : group) {
buckets.emplace(layer->getID(), bucket);
}
@@ -260,6 +347,9 @@ void GeometryTileWorker::redoLayout() {
}
}
+ requestNewGlyphs(glyphDependencies);
+ requestNewImages(imageDependencies);
+
parent.invoke(&GeometryTile::onLayout, GeometryTile::LayoutResult {
std::move(buckets),
std::move(featureIndex),
@@ -271,43 +361,39 @@ void GeometryTileWorker::redoLayout() {
}
bool GeometryTileWorker::hasPendingSymbolDependencies() const {
- bool result = false;
-
- for (const auto& symbolLayout : symbolLayouts) {
- if (symbolLayout->state == SymbolLayout::Pending) {
- result = true;
+ for (auto& glyphDependency : pendingGlyphDependencies) {
+ if (!glyphDependency.second.empty()) {
+ return true;
}
}
-
- return result;
+ return !pendingImageDependencies.empty();
}
void GeometryTileWorker::attemptPlacement() {
- if (!data || !layers || !placementConfig) {
+ if (!data || !layers || !placementConfig || hasPendingSymbolDependencies()) {
return;
}
+
+ optional<AlphaImage> glyphAtlasImage;
+ optional<PremultipliedImage> iconAtlasImage;
- bool canPlace = true;
+ if (symbolLayoutsNeedPreparation) {
+ GlyphAtlas glyphAtlas = makeGlyphAtlas(glyphMap);
+ ImageAtlas imageAtlas = makeImageAtlas(imageMap);
- // Prepare as many SymbolLayouts as possible.
- for (auto& symbolLayout : symbolLayouts) {
- if (obsolete) {
- return;
- }
+ glyphAtlasImage = std::move(glyphAtlas.image);
+ iconAtlasImage = std::move(imageAtlas.image);
- if (symbolLayout->state == SymbolLayout::Pending) {
- if (symbolLayout->canPrepare(glyphAtlas)) {
- symbolLayout->state = SymbolLayout::Prepared;
- symbolLayout->prepare(reinterpret_cast<uintptr_t>(this),
- glyphAtlas);
- } else {
- canPlace = false;
+ for (auto& symbolLayout : symbolLayouts) {
+ if (obsolete) {
+ return;
}
+
+ symbolLayout->prepare(glyphMap, glyphAtlas.positions,
+ imageMap, imageAtlas.positions);
}
- }
- if (!canPlace) {
- return; // We'll be notified (via `setPlacementConfig`) when it's time to try again.
+ symbolLayoutsNeedPreparation = false;
}
auto collisionTile = std::make_unique<CollisionTile>(*placementConfig);
@@ -318,20 +404,21 @@ void GeometryTileWorker::attemptPlacement() {
return;
}
- symbolLayout->state = SymbolLayout::Placed;
if (!symbolLayout->hasSymbolInstances()) {
continue;
}
std::shared_ptr<Bucket> bucket = symbolLayout->place(*collisionTile);
- for (const auto& layerID : symbolLayout->layerIDs) {
- buckets.emplace(layerID, bucket);
+ for (const auto& pair : symbolLayout->layerPaintProperties) {
+ buckets.emplace(pair.first, bucket);
}
}
parent.invoke(&GeometryTile::onPlacement, GeometryTile::PlacementResult {
std::move(buckets),
std::move(collisionTile),
+ std::move(glyphAtlasImage),
+ std::move(iconAtlasImage),
correlationID
});
}
diff --git a/src/mbgl/tile/geometry_tile_worker.hpp b/src/mbgl/tile/geometry_tile_worker.hpp
index 58b5e23cfd..7f80c3b4f7 100644
--- a/src/mbgl/tile/geometry_tile_worker.hpp
+++ b/src/mbgl/tile/geometry_tile_worker.hpp
@@ -2,19 +2,21 @@
#include <mbgl/map/mode.hpp>
#include <mbgl/tile/tile_id.hpp>
+#include <mbgl/style/image_impl.hpp>
+#include <mbgl/text/glyph.hpp>
#include <mbgl/text/placement_config.hpp>
#include <mbgl/actor/actor_ref.hpp>
#include <mbgl/util/optional.hpp>
+#include <mbgl/util/immutable.hpp>
+#include <mbgl/style/layer_impl.hpp>
#include <atomic>
#include <memory>
-#include <unordered_map>
namespace mbgl {
class GeometryTile;
class GeometryTileData;
-class GlyphAtlas;
class SymbolLayout;
namespace style {
@@ -26,30 +28,38 @@ public:
GeometryTileWorker(ActorRef<GeometryTileWorker> self,
ActorRef<GeometryTile> parent,
OverscaledTileID,
- GlyphAtlas&,
const std::atomic<bool>&,
- const MapMode);
+ const MapMode,
+ const float pixelRatio);
~GeometryTileWorker();
- void setLayers(std::vector<std::unique_ptr<style::Layer>>, uint64_t correlationID);
+ void setLayers(std::vector<Immutable<style::Layer::Impl>>, uint64_t correlationID);
void setData(std::unique_ptr<const GeometryTileData>, uint64_t correlationID);
void setPlacementConfig(PlacementConfig, uint64_t correlationID);
- void symbolDependenciesChanged();
+
+ void onGlyphsAvailable(GlyphMap glyphs);
+ void onImagesAvailable(ImageMap images);
private:
- void coalesce();
void coalesced();
void redoLayout();
void attemptPlacement();
+
+ void coalesce();
+
+ void requestNewGlyphs(const GlyphDependencies&);
+ void requestNewImages(const ImageDependencies&);
+
+ void symbolDependenciesChanged();
bool hasPendingSymbolDependencies() const;
ActorRef<GeometryTileWorker> self;
ActorRef<GeometryTile> parent;
const OverscaledTileID id;
- GlyphAtlas& glyphAtlas;
const std::atomic<bool>& obsolete;
const MapMode mode;
+ const float pixelRatio;
enum State {
Idle,
@@ -62,11 +72,16 @@ private:
uint64_t correlationID = 0;
// Outer optional indicates whether we've received it or not.
- optional<std::vector<std::unique_ptr<style::Layer>>> layers;
+ optional<std::vector<Immutable<style::Layer::Impl>>> layers;
optional<std::unique_ptr<const GeometryTileData>> data;
optional<PlacementConfig> placementConfig;
+ bool symbolLayoutsNeedPreparation = false;
std::vector<std::unique_ptr<SymbolLayout>> symbolLayouts;
+ GlyphDependencies pendingGlyphDependencies;
+ ImageDependencies pendingImageDependencies;
+ GlyphMap glyphMap;
+ ImageMap imageMap;
};
} // namespace mbgl
diff --git a/src/mbgl/tile/raster_tile.cpp b/src/mbgl/tile/raster_tile.cpp
index c7a051f841..1260fd1edd 100644
--- a/src/mbgl/tile/raster_tile.cpp
+++ b/src/mbgl/tile/raster_tile.cpp
@@ -3,17 +3,17 @@
#include <mbgl/tile/tile_observer.hpp>
#include <mbgl/tile/tile_loader_impl.hpp>
#include <mbgl/style/source.hpp>
-#include <mbgl/style/update_parameters.hpp>
#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/response.hpp>
#include <mbgl/storage/file_source.hpp>
-#include <mbgl/renderer/raster_bucket.hpp>
+#include <mbgl/renderer/tile_parameters.hpp>
+#include <mbgl/renderer/buckets/raster_bucket.hpp>
#include <mbgl/util/run_loop.hpp>
namespace mbgl {
RasterTile::RasterTile(const OverscaledTileID& id_,
- const style::UpdateParameters& parameters,
+ const TileParameters& parameters,
const Tileset& tileset)
: Tile(id_),
loader(*this, id_, parameters, tileset),
@@ -28,6 +28,8 @@ void RasterTile::cancel() {
}
void RasterTile::setError(std::exception_ptr err) {
+ loaded = true;
+ renderable = false;
observer->onTileError(*this, err);
}
@@ -39,22 +41,36 @@ void RasterTile::setData(std::shared_ptr<const std::string> data,
worker.invoke(&RasterTileWorker::parse, data);
}
-void RasterTile::onParsed(std::unique_ptr<Bucket> result) {
+void RasterTile::onParsed(std::unique_ptr<RasterBucket> result) {
bucket = std::move(result);
- availableData = DataAvailability::All;
+ loaded = true;
+ renderable = bucket ? true : false;
observer->onTileChanged(*this);
}
void RasterTile::onError(std::exception_ptr err) {
bucket.reset();
- availableData = DataAvailability::All;
+ loaded = true;
+ renderable = false;
observer->onTileError(*this, err);
}
-Bucket* RasterTile::getBucket(const style::Layer&) {
+void RasterTile::upload(gl::Context& context) {
+ if (bucket) {
+ bucket->upload(context);
+ }
+}
+
+Bucket* RasterTile::getBucket(const style::Layer::Impl&) const {
return bucket.get();
}
+void RasterTile::setMask(TileMask&& mask) {
+ if (bucket) {
+ bucket->setMask(std::move(mask));
+ }
+}
+
void RasterTile::setNecessity(Necessity necessity) {
loader.setNecessity(necessity);
}
diff --git a/src/mbgl/tile/raster_tile.hpp b/src/mbgl/tile/raster_tile.hpp
index 1f6ceef0db..28a27b2b37 100644
--- a/src/mbgl/tile/raster_tile.hpp
+++ b/src/mbgl/tile/raster_tile.hpp
@@ -8,16 +8,17 @@
namespace mbgl {
class Tileset;
+class TileParameters;
+class RasterBucket;
namespace style {
class Layer;
-class UpdateParameters;
} // namespace style
class RasterTile : public Tile {
public:
RasterTile(const OverscaledTileID&,
- const style::UpdateParameters&,
+ const TileParameters&,
const Tileset&);
~RasterTile() final;
@@ -29,9 +30,13 @@ public:
optional<Timestamp> expires_);
void cancel() override;
- Bucket* getBucket(const style::Layer&) override;
- void onParsed(std::unique_ptr<Bucket> result);
+ void upload(gl::Context&) override;
+ Bucket* getBucket(const style::Layer::Impl&) const override;
+
+ void setMask(TileMask&&) override;
+
+ void onParsed(std::unique_ptr<RasterBucket> result);
void onError(std::exception_ptr);
private:
@@ -42,7 +47,7 @@ private:
// Contains the Bucket object for the tile. Buckets are render
// objects and they get added by tile parsing operations.
- std::unique_ptr<Bucket> bucket;
+ std::unique_ptr<RasterBucket> bucket;
};
} // namespace mbgl
diff --git a/src/mbgl/tile/raster_tile_worker.cpp b/src/mbgl/tile/raster_tile_worker.cpp
index 219e9a2e41..3c8af97b40 100644
--- a/src/mbgl/tile/raster_tile_worker.cpp
+++ b/src/mbgl/tile/raster_tile_worker.cpp
@@ -1,6 +1,6 @@
#include <mbgl/tile/raster_tile_worker.hpp>
#include <mbgl/tile/raster_tile.hpp>
-#include <mbgl/renderer/raster_bucket.cpp>
+#include <mbgl/renderer/buckets/raster_bucket.hpp>
#include <mbgl/actor/actor.hpp>
#include <mbgl/util/premultiply.hpp>
@@ -17,7 +17,7 @@ void RasterTileWorker::parse(std::shared_ptr<const std::string> data) {
}
try {
- auto bucket = std::make_unique<RasterBucket>(util::unpremultiply(decodeImage(*data)));
+ auto bucket = std::make_unique<RasterBucket>(decodeImage(*data));
parent.invoke(&RasterTile::onParsed, std::move(bucket));
} catch (...) {
parent.invoke(&RasterTile::onError, std::current_exception());
diff --git a/src/mbgl/tile/tile.cpp b/src/mbgl/tile/tile.cpp
index e84eaaf780..35fc31dae1 100644
--- a/src/mbgl/tile/tile.cpp
+++ b/src/mbgl/tile/tile.cpp
@@ -1,6 +1,7 @@
#include <mbgl/tile/tile.hpp>
#include <mbgl/tile/tile_observer.hpp>
-#include <mbgl/renderer/debug_bucket.hpp>
+#include <mbgl/renderer/buckets/debug_bucket.hpp>
+#include <mbgl/renderer/query.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/logging.hpp>
@@ -32,6 +33,11 @@ void Tile::queryRenderedFeatures(
std::unordered_map<std::string, std::vector<Feature>>&,
const GeometryCoordinates&,
const TransformState&,
- const optional<std::vector<std::string>>&) {}
+ const RenderStyle&,
+ const RenderedQueryOptions&) {}
+
+void Tile::querySourceFeatures(
+ std::vector<Feature>&,
+ const SourceQueryOptions&) {}
} // namespace mbgl
diff --git a/src/mbgl/tile/tile.hpp b/src/mbgl/tile/tile.hpp
index cebf913f56..a1ab6a84b7 100644
--- a/src/mbgl/tile/tile.hpp
+++ b/src/mbgl/tile/tile.hpp
@@ -6,9 +6,11 @@
#include <mbgl/util/feature.hpp>
#include <mbgl/util/tile_coordinate.hpp>
#include <mbgl/tile/tile_id.hpp>
+#include <mbgl/renderer/tile_mask.hpp>
#include <mbgl/renderer/bucket.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/storage/resource.hpp>
+#include <mbgl/style/layer_impl.hpp>
#include <string>
#include <memory>
@@ -21,10 +23,13 @@ class DebugBucket;
class TransformState;
class TileObserver;
class PlacementConfig;
+class RenderStyle;
+class RenderedQueryOptions;
+class SourceQueryOptions;
-namespace style {
-class Layer;
-} // namespace style
+namespace gl {
+class Context;
+} // namespace gl
class Tile : private util::noncopyable {
public:
@@ -45,17 +50,23 @@ public:
// Mark this tile as no longer needed and cancel any pending work.
virtual void cancel() = 0;
- virtual Bucket* getBucket(const style::Layer&) = 0;
+ virtual void upload(gl::Context&) = 0;
+ virtual Bucket* getBucket(const style::Layer::Impl&) const = 0;
virtual void setPlacementConfig(const PlacementConfig&) {}
- virtual void symbolDependenciesChanged() {};
- virtual void redoLayout() {}
+ virtual void setLayers(const std::vector<Immutable<style::Layer::Impl>>&) {}
+ virtual void setMask(TileMask&&) {}
virtual void queryRenderedFeatures(
std::unordered_map<std::string, std::vector<Feature>>& result,
const GeometryCoordinates& queryGeometry,
const TransformState&,
- const optional<std::vector<std::string>>& layerIDs);
+ const RenderStyle&,
+ const RenderedQueryOptions& options);
+
+ virtual void querySourceFeatures(
+ std::vector<Feature>& result,
+ const SourceQueryOptions&);
void setTriedOptional();
@@ -69,11 +80,23 @@ public:
// partial state is still waiting for network resources but can also
// be rendered, although layers will be missing.
bool isRenderable() const {
- return availableData != DataAvailability::None;
+ return renderable;
+ }
+
+ // A tile is "Loaded" when we have received a response from a FileSource, and have attempted to
+ // parse the tile (if applicable). Tile implementations should set this to true when a load
+ // error occurred, or after the tile was parsed successfully.
+ bool isLoaded() const {
+ return loaded;
}
+ // "Completion" of a tile means that we have attempted to load it, and parsed it completely,
+ // i.e. no parsing or placement operations are pending for that tile.
+ // Completeness doesn't mean that the tile can be rendered, but merely that we have exhausted
+ // all options to get this tile to a renderable state. Some tiles may not be renderable, but
+ // complete, e.g. when a raster tile couldn't be loaded, or parsing failed.
bool isComplete() const {
- return availableData == DataAvailability::All;
+ return loaded && !pending;
}
void dumpDebugLogs() const;
@@ -84,24 +107,14 @@ public:
// Contains the tile ID string for painting debug information.
std::unique_ptr<DebugBucket> debugBucket;
+
+ virtual float yStretch() const { return 1.0f; }
protected:
bool triedOptional = false;
-
- enum class DataAvailability : uint8_t {
- // Still waiting for data to load or parse.
- None,
-
- // Tile is partially parsed, some buckets are still waiting for dependencies
- // to arrive, but it is good for rendering. Partial tiles can also be re-parsed,
- // but might remain in the same state if dependencies are still missing.
- Some,
-
- // Tile is fully parsed, and all buckets are available if they exist.
- All,
- };
-
- DataAvailability availableData = DataAvailability::None;
+ bool renderable = false;
+ bool pending = false;
+ bool loaded = false;
TileObserver* observer = nullptr;
};
diff --git a/src/mbgl/tile/tile_id.hpp b/src/mbgl/tile/tile_id.hpp
index 6415debfdc..811158e9b9 100644
--- a/src/mbgl/tile/tile_id.hpp
+++ b/src/mbgl/tile/tile_id.hpp
@@ -46,8 +46,8 @@ std::string toString(const CanonicalTileID&);
// z/x/y describe the
class OverscaledTileID {
public:
- OverscaledTileID(uint8_t overscaledZ, CanonicalTileID);
- OverscaledTileID(uint8_t overscaledZ, uint8_t z, uint32_t x, uint32_t y);
+ OverscaledTileID(uint8_t overscaledZ, int16_t wrap, CanonicalTileID);
+ OverscaledTileID(uint8_t overscaledZ, int16_t wrap, uint8_t z, uint32_t x, uint32_t y);
OverscaledTileID(uint8_t z, uint32_t x, uint32_t y);
explicit OverscaledTileID(const CanonicalTileID&);
explicit OverscaledTileID(CanonicalTileID&&);
@@ -57,9 +57,10 @@ public:
bool isChildOf(const OverscaledTileID&) const;
uint32_t overscaleFactor() const;
OverscaledTileID scaledTo(uint8_t z) const;
- UnwrappedTileID unwrapTo(int16_t wrap) const;
+ UnwrappedTileID toUnwrapped() const;
const uint8_t overscaledZ;
+ const int16_t wrap;
const CanonicalTileID canonical;
};
@@ -137,40 +138,40 @@ inline std::array<CanonicalTileID, 4> CanonicalTileID::children() const {
} };
}
-inline OverscaledTileID::OverscaledTileID(uint8_t overscaledZ_, CanonicalTileID canonical_)
- : overscaledZ(overscaledZ_), canonical(std::move(canonical_)) {
+inline OverscaledTileID::OverscaledTileID(uint8_t overscaledZ_, int16_t wrap_, CanonicalTileID canonical_)
+ : overscaledZ(overscaledZ_), wrap(wrap_), canonical(std::move(canonical_)) {
assert(overscaledZ >= canonical.z);
}
-inline OverscaledTileID::OverscaledTileID(uint8_t overscaledZ_, uint8_t z, uint32_t x, uint32_t y)
- : overscaledZ(overscaledZ_), canonical(z, x, y) {
+inline OverscaledTileID::OverscaledTileID(uint8_t overscaledZ_, int16_t wrap_, uint8_t z, uint32_t x, uint32_t y)
+ : overscaledZ(overscaledZ_), wrap(wrap_), canonical(z, x, y) {
assert(overscaledZ >= canonical.z);
}
inline OverscaledTileID::OverscaledTileID(uint8_t z, uint32_t x, uint32_t y)
- : overscaledZ(z), canonical(z, x, y) {
+ : overscaledZ(z), wrap(0), canonical(z, x, y) {
}
inline OverscaledTileID::OverscaledTileID(const CanonicalTileID& canonical_)
- : overscaledZ(canonical_.z), canonical(canonical_) {
+ : overscaledZ(canonical_.z), wrap(0), canonical(canonical_) {
assert(overscaledZ >= canonical.z);
}
inline OverscaledTileID::OverscaledTileID(CanonicalTileID&& canonical_)
- : overscaledZ(canonical_.z), canonical(std::forward<CanonicalTileID>(canonical_)) {
+ : overscaledZ(canonical_.z), wrap(0), canonical(std::forward<CanonicalTileID>(canonical_)) {
assert(overscaledZ >= canonical.z);
}
inline bool OverscaledTileID::operator==(const OverscaledTileID& rhs) const {
- return overscaledZ == rhs.overscaledZ && canonical == rhs.canonical;
+ return overscaledZ == rhs.overscaledZ && wrap == rhs.wrap &&canonical == rhs.canonical;
}
inline bool OverscaledTileID::operator!=(const OverscaledTileID& rhs) const {
- return overscaledZ != rhs.overscaledZ || canonical != rhs.canonical;
+ return overscaledZ != rhs.overscaledZ || wrap != rhs.wrap || canonical != rhs.canonical;
}
inline bool OverscaledTileID::operator<(const OverscaledTileID& rhs) const {
- return std::tie(overscaledZ, canonical) < std::tie(rhs.overscaledZ, rhs.canonical);
+ return std::tie(overscaledZ, wrap, canonical) < std::tie(rhs.overscaledZ, rhs.wrap, rhs.canonical);
}
inline uint32_t OverscaledTileID::overscaleFactor() const {
@@ -183,10 +184,10 @@ inline bool OverscaledTileID::isChildOf(const OverscaledTileID& rhs) const {
}
inline OverscaledTileID OverscaledTileID::scaledTo(uint8_t z) const {
- return { z, z >= canonical.z ? canonical : canonical.scaledTo(z) };
+ return { z, wrap, z >= canonical.z ? canonical : canonical.scaledTo(z) };
}
-inline UnwrappedTileID OverscaledTileID::unwrapTo(int16_t wrap) const {
+inline UnwrappedTileID OverscaledTileID::toUnwrapped() const {
return { wrap, canonical };
}
@@ -232,7 +233,7 @@ inline std::array<UnwrappedTileID, 4> UnwrappedTileID::children() const {
inline OverscaledTileID UnwrappedTileID::overscaleTo(const uint8_t overscaledZ) const {
assert(overscaledZ >= canonical.z);
- return { overscaledZ, canonical };
+ return { overscaledZ, wrap, canonical };
}
inline float UnwrappedTileID::pixelsToTileUnits(const float pixelValue, const float zoom) const {
@@ -252,7 +253,7 @@ template <> struct hash<mbgl::CanonicalTileID> {
return seed;
}
};
-
+
template <> struct hash<mbgl::UnwrappedTileID> {
size_t operator()(const mbgl::UnwrappedTileID &id) const {
std::size_t seed = 0;
@@ -261,7 +262,7 @@ template <> struct hash<mbgl::UnwrappedTileID> {
return seed;
}
};
-
+
template <> struct hash<mbgl::OverscaledTileID> {
size_t operator()(const mbgl::OverscaledTileID &id) const {
std::size_t seed = 0;
diff --git a/src/mbgl/tile/tile_id_io.cpp b/src/mbgl/tile/tile_id_io.cpp
index f6adbf183f..d8be6b93d6 100644
--- a/src/mbgl/tile/tile_id_io.cpp
+++ b/src/mbgl/tile/tile_id_io.cpp
@@ -6,6 +6,8 @@
namespace mbgl {
::std::ostream& operator<<(::std::ostream& os, const CanonicalTileID& rhs) {
+ // Uncomment this to create code instead of shorthands.
+ // return os << "CanonicalTileID{ " << uint32_t(rhs.z) << ", " << rhs.x << ", " << rhs.y << " }";
return os << uint32_t(rhs.z) << "/" << rhs.x << "/" << rhs.y;
}
@@ -26,6 +28,9 @@ std::string toString(const OverscaledTileID& rhs) {
} // namespace util
::std::ostream& operator<<(::std::ostream& os, const UnwrappedTileID& rhs) {
+ // Uncomment this to create code instead of shorthands.
+ // return os << "UnwrappedTileID{ " << uint32_t(rhs.wrap) << ", { " << uint32_t(rhs.canonical.z)
+ // << ", " << rhs.canonical.x << ", " << rhs.canonical.y << " } }";
return os << rhs.canonical << (rhs.wrap >= 0 ? "+" : "") << rhs.wrap;
}
diff --git a/src/mbgl/tile/tile_loader.hpp b/src/mbgl/tile/tile_loader.hpp
index 0d64f647d7..bc408ebaf6 100644
--- a/src/mbgl/tile/tile_loader.hpp
+++ b/src/mbgl/tile/tile_loader.hpp
@@ -10,17 +10,14 @@ class FileSource;
class AsyncRequest;
class Response;
class Tileset;
-
-namespace style {
-class UpdateParameters;
-} // namespace style
+class TileParameters;
template <typename T>
class TileLoader : private util::noncopyable {
public:
TileLoader(T&,
const OverscaledTileID&,
- const style::UpdateParameters&,
+ const TileParameters&,
const Tileset&);
~TileLoader();
diff --git a/src/mbgl/tile/tile_loader_impl.hpp b/src/mbgl/tile/tile_loader_impl.hpp
index 9a5b35a7af..899cbaf9b0 100644
--- a/src/mbgl/tile/tile_loader_impl.hpp
+++ b/src/mbgl/tile/tile_loader_impl.hpp
@@ -2,7 +2,7 @@
#include <mbgl/tile/tile_loader.hpp>
#include <mbgl/storage/file_source.hpp>
-#include <mbgl/style/update_parameters.hpp>
+#include <mbgl/renderer/tile_parameters.hpp>
#include <mbgl/util/tileset.hpp>
#include <cassert>
@@ -12,7 +12,7 @@ namespace mbgl {
template <typename T>
TileLoader<T>::TileLoader(T& tile_,
const OverscaledTileID& id,
- const style::UpdateParameters& parameters,
+ const TileParameters& parameters,
const Tileset& tileset)
: tile(tile_),
necessity(Necessity::Optional),
diff --git a/src/mbgl/tile/vector_tile.cpp b/src/mbgl/tile/vector_tile.cpp
index a195885415..e2e700b7b7 100644
--- a/src/mbgl/tile/vector_tile.cpp
+++ b/src/mbgl/tile/vector_tile.cpp
@@ -1,81 +1,15 @@
#include <mbgl/tile/vector_tile.hpp>
+#include <mbgl/tile/vector_tile_data.hpp>
#include <mbgl/tile/tile_loader_impl.hpp>
-#include <mbgl/tile/geometry_tile_data.hpp>
-
-#include <protozero/pbf_reader.hpp>
-
-#include <unordered_map>
-#include <unordered_map>
-#include <functional>
-#include <utility>
+#include <mbgl/renderer/tile_parameters.hpp>
namespace mbgl {
-class VectorTileLayer;
-
-using packed_iter_type = protozero::iterator_range<protozero::pbf_reader::const_uint32_iterator>;
-
-class VectorTileFeature : public GeometryTileFeature {
-public:
- VectorTileFeature(protozero::pbf_reader, const VectorTileLayer&);
-
- FeatureType getType() const override { return type; }
- optional<Value> getValue(const std::string&) const override;
- std::unordered_map<std::string,Value> getProperties() const override;
- optional<FeatureIdentifier> getID() const override;
- GeometryCollection getGeometries() const override;
-
-private:
- const VectorTileLayer& layer;
- optional<FeatureIdentifier> id;
- FeatureType type = FeatureType::Unknown;
- packed_iter_type tags_iter;
- packed_iter_type geometry_iter;
-};
-
-class VectorTileLayer : public GeometryTileLayer {
-public:
- VectorTileLayer(protozero::pbf_reader);
-
- std::size_t featureCount() const override { return features.size(); }
- std::unique_ptr<GeometryTileFeature> getFeature(std::size_t) const override;
- std::string getName() const override;
-
-private:
- friend class VectorTileData;
- friend class VectorTileFeature;
-
- std::string name;
- uint32_t version = 1;
- uint32_t extent = 4096;
- std::unordered_map<std::string, uint32_t> keysMap;
- std::vector<std::reference_wrapper<const std::string>> keys;
- std::vector<Value> values;
- std::vector<protozero::pbf_reader> features;
-};
-
-class VectorTileData : public GeometryTileData {
-public:
- VectorTileData(std::shared_ptr<const std::string> data);
-
- std::unique_ptr<GeometryTileData> clone() const override {
- return std::make_unique<VectorTileData>(*this);
- }
-
- const GeometryTileLayer* getLayer(const std::string&) const override;
-
-private:
- std::shared_ptr<const std::string> data;
- mutable bool parsed = false;
- mutable std::unordered_map<std::string, VectorTileLayer> layers;
-};
-
VectorTile::VectorTile(const OverscaledTileID& id_,
std::string sourceID_,
- const style::UpdateParameters& parameters,
+ const TileParameters& parameters,
const Tileset& tileset)
- : GeometryTile(id_, sourceID_, parameters),
- loader(*this, id_, parameters, tileset) {
+ : GeometryTile(id_, sourceID_, parameters), loader(*this, id_, parameters, tileset) {
}
void VectorTile::setNecessity(Necessity necessity) {
@@ -91,214 +25,4 @@ void VectorTile::setData(std::shared_ptr<const std::string> data_,
GeometryTile::setData(data_ ? std::make_unique<VectorTileData>(data_) : nullptr);
}
-Value parseValue(protozero::pbf_reader data) {
- while (data.next())
- {
- switch (data.tag()) {
- case 1: // string_value
- return data.get_string();
- case 2: // float_value
- return static_cast<double>(data.get_float());
- case 3: // double_value
- return data.get_double();
- case 4: // int_value
- return data.get_int64();
- case 5: // uint_value
- return data.get_uint64();
- case 6: // sint_value
- return data.get_sint64();
- case 7: // bool_value
- return data.get_bool();
- default:
- data.skip();
- break;
- }
- }
- return false;
-}
-
-VectorTileFeature::VectorTileFeature(protozero::pbf_reader feature_pbf, const VectorTileLayer& layer_)
- : layer(layer_) {
- while (feature_pbf.next()) {
- switch (feature_pbf.tag()) {
- case 1: // id
- id = { feature_pbf.get_uint64() };
- break;
- case 2: // tags
- tags_iter = feature_pbf.get_packed_uint32();
- break;
- case 3: // type
- type = static_cast<FeatureType>(feature_pbf.get_enum());
- break;
- case 4: // geometry
- geometry_iter = feature_pbf.get_packed_uint32();
- break;
- default:
- feature_pbf.skip();
- break;
- }
- }
-}
-
-optional<Value> VectorTileFeature::getValue(const std::string& key) const {
- auto keyIter = layer.keysMap.find(key);
- if (keyIter == layer.keysMap.end()) {
- return optional<Value>();
- }
-
- auto start_itr = tags_iter.begin();
- const auto & end_itr = tags_iter.end();
- while (start_itr != end_itr) {
- uint32_t tag_key = static_cast<uint32_t>(*start_itr++);
-
- if (layer.keysMap.size() <= tag_key) {
- throw std::runtime_error("feature referenced out of range key");
- }
-
- if (start_itr == end_itr) {
- throw std::runtime_error("uneven number of feature tag ids");
- }
-
- uint32_t tag_val = static_cast<uint32_t>(*start_itr++);;
- if (layer.values.size() <= tag_val) {
- throw std::runtime_error("feature referenced out of range value");
- }
-
- if (tag_key == keyIter->second) {
- return layer.values[tag_val];
- }
- }
-
- return optional<Value>();
-}
-
-std::unordered_map<std::string,Value> VectorTileFeature::getProperties() const {
- std::unordered_map<std::string,Value> properties;
- auto start_itr = tags_iter.begin();
- const auto & end_itr = tags_iter.end();
- while (start_itr != end_itr) {
- uint32_t tag_key = static_cast<uint32_t>(*start_itr++);
- if (start_itr == end_itr) {
- throw std::runtime_error("uneven number of feature tag ids");
- }
- uint32_t tag_val = static_cast<uint32_t>(*start_itr++);
- properties[layer.keys.at(tag_key)] = layer.values.at(tag_val);
- }
- return properties;
-}
-
-optional<FeatureIdentifier> VectorTileFeature::getID() const {
- return id;
-}
-
-GeometryCollection VectorTileFeature::getGeometries() const {
- uint8_t cmd = 1;
- uint32_t length = 0;
- int32_t x = 0;
- int32_t y = 0;
- const float scale = float(util::EXTENT) / layer.extent;
-
- GeometryCollection lines;
-
- lines.emplace_back();
- GeometryCoordinates* line = &lines.back();
-
- auto g_itr = geometry_iter.begin();
- while (g_itr != geometry_iter.end()) {
- if (length == 0) {
- uint32_t cmd_length = static_cast<uint32_t>(*g_itr++);
- cmd = cmd_length & 0x7;
- length = cmd_length >> 3;
- }
-
- --length;
-
- if (cmd == 1 || cmd == 2) {
- x += protozero::decode_zigzag32(static_cast<uint32_t>(*g_itr++));
- y += protozero::decode_zigzag32(static_cast<uint32_t>(*g_itr++));
-
- if (cmd == 1 && !line->empty()) { // moveTo
- lines.emplace_back();
- line = &lines.back();
- }
-
- line->emplace_back(::round(x * scale), ::round(y * scale));
-
- } else if (cmd == 7) { // closePolygon
- if (!line->empty()) {
- line->push_back((*line)[0]);
- }
-
- } else {
- throw std::runtime_error("unknown command");
- }
- }
-
- if (layer.version >= 2 || type != FeatureType::Polygon) {
- return lines;
- }
-
- return fixupPolygons(lines);
-}
-
-VectorTileData::VectorTileData(std::shared_ptr<const std::string> data_)
- : data(std::move(data_)) {
-}
-
-const GeometryTileLayer* VectorTileData::getLayer(const std::string& name) const {
- if (!parsed) {
- parsed = true;
- protozero::pbf_reader tile_pbf(*data);
- while (tile_pbf.next(3)) {
- VectorTileLayer layer(tile_pbf.get_message());
- layers.emplace(layer.name, std::move(layer));
- }
- }
-
- auto it = layers.find(name);
- if (it != layers.end()) {
- return &it->second;
- }
- return nullptr;
-}
-
-VectorTileLayer::VectorTileLayer(protozero::pbf_reader layer_pbf) {
- while (layer_pbf.next()) {
- switch (layer_pbf.tag()) {
- case 1: // name
- name = layer_pbf.get_string();
- break;
- case 2: // feature
- features.push_back(layer_pbf.get_message());
- break;
- case 3: // keys
- {
- auto iter = keysMap.emplace(layer_pbf.get_string(), keysMap.size());
- keys.emplace_back(std::reference_wrapper<const std::string>(iter.first->first));
- }
- break;
- case 4: // values
- values.emplace_back(parseValue(layer_pbf.get_message()));
- break;
- case 5: // extent
- extent = layer_pbf.get_uint32();
- break;
- case 15: // version
- version = layer_pbf.get_uint32();
- break;
- default:
- layer_pbf.skip();
- break;
- }
- }
-}
-
-std::unique_ptr<GeometryTileFeature> VectorTileLayer::getFeature(std::size_t i) const {
- return std::make_unique<VectorTileFeature>(features.at(i), *this);
-}
-
-std::string VectorTileLayer::getName() const {
- return name;
-}
-
} // namespace mbgl
diff --git a/src/mbgl/tile/vector_tile.hpp b/src/mbgl/tile/vector_tile.hpp
index 2568a277e6..566cde4f37 100644
--- a/src/mbgl/tile/vector_tile.hpp
+++ b/src/mbgl/tile/vector_tile.hpp
@@ -6,16 +6,13 @@
namespace mbgl {
class Tileset;
-
-namespace style {
-class UpdateParameters;
-} // namespace style
+class TileParameters;
class VectorTile : public GeometryTile {
public:
VectorTile(const OverscaledTileID&,
std::string sourceID,
- const style::UpdateParameters&,
+ const TileParameters&,
const Tileset&);
void setNecessity(Necessity) final;
diff --git a/src/mbgl/tile/vector_tile_data.cpp b/src/mbgl/tile/vector_tile_data.cpp
new file mode 100644
index 0000000000..2d4a01bda3
--- /dev/null
+++ b/src/mbgl/tile/vector_tile_data.cpp
@@ -0,0 +1,89 @@
+#include <mbgl/tile/vector_tile_data.hpp>
+#include <mbgl/util/constants.hpp>
+
+namespace mbgl {
+
+VectorTileFeature::VectorTileFeature(const mapbox::vector_tile::layer& layer,
+ const protozero::data_view& view)
+ : feature(view, layer) {
+}
+
+FeatureType VectorTileFeature::getType() const {
+ switch (feature.getType()) {
+ case mapbox::vector_tile::GeomType::POINT:
+ return FeatureType::Point;
+ case mapbox::vector_tile::GeomType::LINESTRING:
+ return FeatureType::LineString;
+ case mapbox::vector_tile::GeomType::POLYGON:
+ return FeatureType::Polygon;
+ default:
+ return FeatureType::Unknown;
+ }
+}
+
+optional<Value> VectorTileFeature::getValue(const std::string& key) const {
+ return feature.getValue(key);
+}
+
+std::unordered_map<std::string, Value> VectorTileFeature::getProperties() const {
+ return feature.getProperties();
+}
+
+optional<FeatureIdentifier> VectorTileFeature::getID() const {
+ return feature.getID();
+}
+
+GeometryCollection VectorTileFeature::getGeometries() const {
+ const float scale = float(util::EXTENT) / feature.getExtent();
+ auto lines = feature.getGeometries<GeometryCollection>(scale);
+ if (feature.getVersion() >= 2 || feature.getType() != mapbox::vector_tile::GeomType::POLYGON) {
+ return lines;
+ } else {
+ return fixupPolygons(lines);
+ }
+}
+
+VectorTileLayer::VectorTileLayer(std::shared_ptr<const std::string> data_,
+ const protozero::data_view& view)
+ : data(std::move(data_)), layer(view) {
+}
+
+std::size_t VectorTileLayer::featureCount() const {
+ return layer.featureCount();
+}
+
+std::unique_ptr<GeometryTileFeature> VectorTileLayer::getFeature(std::size_t i) const {
+ return std::make_unique<VectorTileFeature>(layer, layer.getFeature(i));
+}
+
+std::string VectorTileLayer::getName() const {
+ return layer.getName();
+}
+
+VectorTileData::VectorTileData(std::shared_ptr<const std::string> data_) : data(std::move(data_)) {
+}
+
+std::unique_ptr<GeometryTileData> VectorTileData::clone() const {
+ return std::make_unique<VectorTileData>(data);
+}
+
+std::unique_ptr<GeometryTileLayer> VectorTileData::getLayer(const std::string& name) const {
+ if (!parsed) {
+ // We're parsing this lazily so that we can construct VectorTileData objects on the main
+ // thread without incurring the overhead of parsing immediately.
+ layers = mapbox::vector_tile::buffer(*data).getLayers();
+ parsed = true;
+ }
+
+ auto it = layers.find(name);
+ if (it != layers.end()) {
+ return std::make_unique<VectorTileLayer>(data, it->second);
+ }
+ return nullptr;
+}
+
+std::vector<std::string> VectorTileData::layerNames() const {
+ return mapbox::vector_tile::buffer(*data).layerNames();
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/tile/vector_tile_data.hpp b/src/mbgl/tile/vector_tile_data.hpp
new file mode 100644
index 0000000000..48beaf9d07
--- /dev/null
+++ b/src/mbgl/tile/vector_tile_data.hpp
@@ -0,0 +1,54 @@
+#include <mbgl/tile/geometry_tile_data.hpp>
+
+#include <mapbox/vector_tile.hpp>
+#include <protozero/pbf_reader.hpp>
+
+#include <unordered_map>
+#include <functional>
+#include <utility>
+
+namespace mbgl {
+
+class VectorTileFeature : public GeometryTileFeature {
+public:
+ VectorTileFeature(const mapbox::vector_tile::layer&, const protozero::data_view&);
+
+ FeatureType getType() const override;
+ optional<Value> getValue(const std::string& key) const override;
+ std::unordered_map<std::string, Value> getProperties() const override;
+ optional<FeatureIdentifier> getID() const override;
+ GeometryCollection getGeometries() const override;
+
+private:
+ mapbox::vector_tile::feature feature;
+};
+
+class VectorTileLayer : public GeometryTileLayer {
+public:
+ VectorTileLayer(std::shared_ptr<const std::string> data, const protozero::data_view&);
+
+ std::size_t featureCount() const override;
+ std::unique_ptr<GeometryTileFeature> getFeature(std::size_t i) const override;
+ std::string getName() const override;
+
+private:
+ std::shared_ptr<const std::string> data;
+ mapbox::vector_tile::layer layer;
+};
+
+class VectorTileData : public GeometryTileData {
+public:
+ VectorTileData(std::shared_ptr<const std::string> data);
+
+ std::unique_ptr<GeometryTileData> clone() const override;
+ std::unique_ptr<GeometryTileLayer> getLayer(const std::string& name) const override;
+
+ std::vector<std::string> layerNames() const;
+
+private:
+ std::shared_ptr<const std::string> data;
+ mutable bool parsed = false;
+ mutable std::map<std::string, const protozero::data_view> layers;
+};
+
+} // namespace mbgl