summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuha Alanen <juha.alanen@mapbox.com>2019-08-21 16:03:36 +0300
committerJuha Alanen <19551460+jmalanen@users.noreply.github.com>2019-09-18 14:29:15 +0300
commit413278ca20de77f7025b5304493dca6d1863fbb3 (patch)
tree194c238e77795c3421fc0f849406340fd8e4ad77
parent91171bc1a98acf3d21704fa86ad7ada5d1ac762e (diff)
downloadqtlocation-mapboxgl-413278ca20de77f7025b5304493dca6d1863fbb3.tar.gz
[core] Add feature state support to bucket classes
-rw-r--r--include/mbgl/util/feature.hpp24
-rw-r--r--src/mbgl/gfx/vertex_vector.hpp5
-rw-r--r--src/mbgl/layout/pattern_layout.hpp2
-rw-r--r--src/mbgl/layout/symbol_layout.cpp4
-rw-r--r--src/mbgl/renderer/bucket.hpp6
-rw-r--r--src/mbgl/renderer/buckets/circle_bucket.cpp19
-rw-r--r--src/mbgl/renderer/buckets/circle_bucket.hpp5
-rw-r--r--src/mbgl/renderer/buckets/fill_bucket.cpp23
-rw-r--r--src/mbgl/renderer/buckets/fill_bucket.hpp5
-rw-r--r--src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp21
-rw-r--r--src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp5
-rw-r--r--src/mbgl/renderer/buckets/heatmap_bucket.cpp5
-rw-r--r--src/mbgl/renderer/buckets/heatmap_bucket.hpp3
-rw-r--r--src/mbgl/renderer/buckets/line_bucket.cpp21
-rw-r--r--src/mbgl/renderer/buckets/line_bucket.hpp5
-rw-r--r--src/mbgl/renderer/paint_property_binder.hpp119
-rw-r--r--src/mbgl/tile/geometry_tile_worker.cpp2
17 files changed, 232 insertions, 42 deletions
diff --git a/include/mbgl/util/feature.hpp b/include/mbgl/util/feature.hpp
index 56db250de0..d2a23cc5b0 100644
--- a/include/mbgl/util/feature.hpp
+++ b/include/mbgl/util/feature.hpp
@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/util/optional.hpp>
+#include <mbgl/util/string.hpp>
#include <mapbox/feature.hpp>
@@ -32,4 +33,27 @@ optional<T> numericValue(const Value& value) {
});
}
+inline optional<std::string> featureIDtoString(const FeatureIdentifier& id) {
+ if (id.is<NullValue>()) {
+ return nullopt;
+ }
+
+ return id.match(
+ [] (const std::string& value_) {
+ return value_;
+ },
+ [] (uint64_t value_) {
+ return util::toString(value_);
+ },
+ [] (int64_t value_) {
+ return util::toString(value_);
+ },
+ [] (double value_) {
+ return util::toString(value_);
+ },
+ [] (const auto&) -> optional<std::string> {
+ return nullopt;
+ });
+}
+
} // namespace mbgl
diff --git a/src/mbgl/gfx/vertex_vector.hpp b/src/mbgl/gfx/vertex_vector.hpp
index 59fe67586b..091ecb912e 100644
--- a/src/mbgl/gfx/vertex_vector.hpp
+++ b/src/mbgl/gfx/vertex_vector.hpp
@@ -20,6 +20,11 @@ public:
v.resize(v.size() + n, val);
}
+ Vertex& at(std::size_t n) {
+ assert(n < v.size());
+ return v.at(n);
+ }
+
std::size_t elements() const {
return v.size();
}
diff --git a/src/mbgl/layout/pattern_layout.hpp b/src/mbgl/layout/pattern_layout.hpp
index 858d515347..d6d878955f 100644
--- a/src/mbgl/layout/pattern_layout.hpp
+++ b/src/mbgl/layout/pattern_layout.hpp
@@ -108,7 +108,7 @@ public:
const PatternLayerMap& patterns = patternFeature.patterns;
const GeometryCollection& geometries = feature->getGeometries();
- bucket->addFeature(*feature, geometries, patternPositions, patterns);
+ bucket->addFeature(*feature, geometries, patternPositions, patterns, i);
featureIndex->insert(geometries, i, sourceLayerID, bucketLeaderID);
}
if (bucket->hasData()) {
diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp
index 1dbb5d91dc..71724cad5f 100644
--- a/src/mbgl/layout/symbol_layout.cpp
+++ b/src/mbgl/layout/symbol_layout.cpp
@@ -713,7 +713,7 @@ void SymbolLayout::createBucket(const ImagePositions&, std::unique_ptr<FeatureIn
}
for (auto& pair : bucket->paintProperties) {
- pair.second.iconBinders.populateVertexVectors(feature, iconBuffer.vertices.elements(), {}, {});
+ pair.second.iconBinders.populateVertexVectors(feature, iconBuffer.vertices.elements(), symbolInstance.dataFeatureIndex, {}, {});
}
}
@@ -765,7 +765,7 @@ void SymbolLayout::updatePaintPropertiesForSection(SymbolBucket& bucket,
std::size_t sectionIndex) {
const auto& formattedSection = sectionOptionsToValue((*feature.formattedText).sectionAt(sectionIndex));
for (auto& pair : bucket.paintProperties) {
- pair.second.textBinders.populateVertexVectors(feature, bucket.text.vertices.elements(), {}, {}, formattedSection);
+ pair.second.textBinders.populateVertexVectors(feature, bucket.text.vertices.elements(), feature.index, {}, {}, formattedSection);
}
}
diff --git a/src/mbgl/renderer/bucket.hpp b/src/mbgl/renderer/bucket.hpp
index a978c06d6b..98c2200ce9 100644
--- a/src/mbgl/renderer/bucket.hpp
+++ b/src/mbgl/renderer/bucket.hpp
@@ -35,7 +35,11 @@ public:
virtual void addFeature(const GeometryTileFeature&,
const GeometryCollection&,
const ImagePositions&,
- const PatternLayerMap&) {};
+ const PatternLayerMap&,
+ std::size_t) {};
+
+ virtual void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) {}
+
// As long as this bucket has a Prepare render pass, this function is getting called. Typically,
// this only happens once when the bucket is being rendered for the first time.
diff --git a/src/mbgl/renderer/buckets/circle_bucket.cpp b/src/mbgl/renderer/buckets/circle_bucket.cpp
index 7ba130da64..ffa6f59128 100644
--- a/src/mbgl/renderer/buckets/circle_bucket.cpp
+++ b/src/mbgl/renderer/buckets/circle_bucket.cpp
@@ -25,8 +25,10 @@ CircleBucket::CircleBucket(const BucketParameters& parameters, const std::vector
CircleBucket::~CircleBucket() = default;
void CircleBucket::upload(gfx::UploadPass& uploadPass) {
- vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices));
- indexBuffer = uploadPass.createIndexBuffer(std::move(triangles));
+ if (!uploaded) {
+ vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices));
+ indexBuffer = uploadPass.createIndexBuffer(std::move(triangles));
+ }
for (auto& pair : paintPropertyBinders) {
pair.second.upload(uploadPass);
@@ -42,7 +44,8 @@ bool CircleBucket::hasData() const {
void CircleBucket::addFeature(const GeometryTileFeature& feature,
const GeometryCollection& geometry,
const ImagePositions&,
- const PatternLayerMap&) {
+ const PatternLayerMap&,
+ std::size_t featureIndex) {
constexpr const uint16_t vertexLength = 4;
for (auto& circle : geometry) {
@@ -90,7 +93,7 @@ void CircleBucket::addFeature(const GeometryTileFeature& feature,
}
for (auto& pair : paintPropertyBinders) {
- pair.second.populateVertexVectors(feature, vertices.elements(), {}, {});
+ pair.second.populateVertexVectors(feature, vertices.elements(), featureIndex, {}, {});
}
}
@@ -112,4 +115,12 @@ float CircleBucket::getQueryRadius(const RenderLayer& layer) const {
return radius + stroke + util::length(translate[0], translate[1]);
}
+void CircleBucket::update(const FeatureStates& states, const GeometryTileLayer& layer, const std::string& layerID, const ImagePositions& imagePositions) {
+ auto it = paintPropertyBinders.find(layerID);
+ if (it != paintPropertyBinders.end()) {
+ it->second.updateVertexVectors(states, layer, imagePositions);
+ uploaded = false;
+ }
+}
+
} // namespace mbgl
diff --git a/src/mbgl/renderer/buckets/circle_bucket.hpp b/src/mbgl/renderer/buckets/circle_bucket.hpp
index 27423bc568..9fee45ad79 100644
--- a/src/mbgl/renderer/buckets/circle_bucket.hpp
+++ b/src/mbgl/renderer/buckets/circle_bucket.hpp
@@ -21,7 +21,8 @@ public:
void addFeature(const GeometryTileFeature&,
const GeometryCollection&,
const ImagePositions&,
- const PatternLayerMap&) override;
+ const PatternLayerMap&,
+ std::size_t) override;
bool hasData() const override;
@@ -29,6 +30,8 @@ public:
float getQueryRadius(const RenderLayer&) const override;
+ void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) override;
+
gfx::VertexVector<CircleLayoutVertex> vertices;
gfx::IndexVector<gfx::Triangles> triangles;
SegmentVector<CircleAttributes> segments;
diff --git a/src/mbgl/renderer/buckets/fill_bucket.cpp b/src/mbgl/renderer/buckets/fill_bucket.cpp
index 8a089c679e..ea79a1e687 100644
--- a/src/mbgl/renderer/buckets/fill_bucket.cpp
+++ b/src/mbgl/renderer/buckets/fill_bucket.cpp
@@ -47,7 +47,8 @@ FillBucket::~FillBucket() = default;
void FillBucket::addFeature(const GeometryTileFeature& feature,
const GeometryCollection& geometry,
const ImagePositions& patternPositions,
- const PatternLayerMap& patternDependencies) {
+ const PatternLayerMap& patternDependencies,
+ std::size_t index) {
for (auto& polygon : classifyRings(geometry)) {
// Optimize polygons with many interior rings for earcut tesselation.
limitHoles(polygon, 500);
@@ -114,17 +115,19 @@ void FillBucket::addFeature(const GeometryTileFeature& feature,
for (auto& pair : paintPropertyBinders) {
const auto it = patternDependencies.find(pair.first);
if (it != patternDependencies.end()){
- pair.second.populateVertexVectors(feature, vertices.elements(), patternPositions, it->second);
+ pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, it->second);
} else {
- pair.second.populateVertexVectors(feature, vertices.elements(), patternPositions, {});
+ pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, {});
}
}
}
void FillBucket::upload(gfx::UploadPass& uploadPass) {
- vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices));
- lineIndexBuffer = uploadPass.createIndexBuffer(std::move(lines));
- triangleIndexBuffer = triangles.empty() ? optional<gfx::IndexBuffer> {} : uploadPass.createIndexBuffer(std::move(triangles));
+ if (!uploaded) {
+ vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices));
+ lineIndexBuffer = uploadPass.createIndexBuffer(std::move(lines));
+ triangleIndexBuffer = triangles.empty() ? optional<gfx::IndexBuffer> {} : uploadPass.createIndexBuffer(std::move(triangles));
+ }
for (auto& pair : paintPropertyBinders) {
pair.second.upload(uploadPass);
@@ -143,4 +146,12 @@ float FillBucket::getQueryRadius(const RenderLayer& layer) const {
return util::length(translate[0], translate[1]);
}
+void FillBucket::update(const FeatureStates& states, const GeometryTileLayer& layer, const std::string& layerID, const ImagePositions& imagePositions) {
+ auto it = paintPropertyBinders.find(layerID);
+ if (it != paintPropertyBinders.end()) {
+ it->second.updateVertexVectors(states, layer, imagePositions);
+ uploaded = false;
+ }
+}
+
} // namespace mbgl
diff --git a/src/mbgl/renderer/buckets/fill_bucket.hpp b/src/mbgl/renderer/buckets/fill_bucket.hpp
index 6747c1083f..eee421f938 100644
--- a/src/mbgl/renderer/buckets/fill_bucket.hpp
+++ b/src/mbgl/renderer/buckets/fill_bucket.hpp
@@ -29,7 +29,8 @@ public:
void addFeature(const GeometryTileFeature&,
const GeometryCollection&,
const mbgl::ImagePositions&,
- const PatternLayerMap&) override;
+ const PatternLayerMap&,
+ std::size_t) override;
bool hasData() const override;
@@ -37,6 +38,8 @@ public:
float getQueryRadius(const RenderLayer&) const override;
+ void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) override;
+
gfx::VertexVector<FillLayoutVertex> vertices;
gfx::IndexVector<gfx::Lines> lines;
gfx::IndexVector<gfx::Triangles> triangles;
diff --git a/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp b/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp
index be13850e55..6a25349c22 100644
--- a/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp
+++ b/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp
@@ -53,7 +53,8 @@ FillExtrusionBucket::~FillExtrusionBucket() = default;
void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature,
const GeometryCollection& geometry,
const ImagePositions& patternPositions,
- const PatternLayerMap& patternDependencies) {
+ const PatternLayerMap& patternDependencies,
+ std::size_t index) {
for (auto& polygon : classifyRings(geometry)) {
// Optimize polygons with many interior rings for earcut tesselation.
limitHoles(polygon, 500);
@@ -158,16 +159,18 @@ void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature,
for (auto& pair : paintPropertyBinders) {
const auto it = patternDependencies.find(pair.first);
if (it != patternDependencies.end()){
- pair.second.populateVertexVectors(feature, vertices.elements(), patternPositions, it->second);
+ pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, it->second);
} else {
- pair.second.populateVertexVectors(feature, vertices.elements(), patternPositions, {});
+ pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, {});
}
}
}
void FillExtrusionBucket::upload(gfx::UploadPass& uploadPass) {
- vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices));
- indexBuffer = uploadPass.createIndexBuffer(std::move(triangles));
+ if (!uploaded) {
+ vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices));
+ indexBuffer = uploadPass.createIndexBuffer(std::move(triangles));
+ }
for (auto& pair : paintPropertyBinders) {
pair.second.upload(uploadPass);
@@ -186,4 +189,12 @@ float FillExtrusionBucket::getQueryRadius(const RenderLayer& layer) const {
return util::length(translate[0], translate[1]);
}
+void FillExtrusionBucket::update(const FeatureStates& states, const GeometryTileLayer& layer, const std::string& layerID, const ImagePositions& imagePositions) {
+ auto it = paintPropertyBinders.find(layerID);
+ if (it != paintPropertyBinders.end()) {
+ it->second.updateVertexVectors(states, layer, imagePositions);
+ uploaded = false;
+ }
+}
+
} // namespace mbgl
diff --git a/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp b/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp
index 4c97618a77..582480bf41 100644
--- a/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp
+++ b/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp
@@ -27,7 +27,8 @@ public:
void addFeature(const GeometryTileFeature&,
const GeometryCollection&,
const mbgl::ImagePositions&,
- const PatternLayerMap&) override;
+ const PatternLayerMap&,
+ std::size_t) override;
bool hasData() const override;
@@ -35,6 +36,8 @@ public:
float getQueryRadius(const RenderLayer&) const override;
+ void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) override;
+
gfx::VertexVector<FillExtrusionLayoutVertex> vertices;
gfx::IndexVector<gfx::Triangles> triangles;
SegmentVector<FillExtrusionAttributes> triangleSegments;
diff --git a/src/mbgl/renderer/buckets/heatmap_bucket.cpp b/src/mbgl/renderer/buckets/heatmap_bucket.cpp
index fad78f6cec..0ea645a9a0 100644
--- a/src/mbgl/renderer/buckets/heatmap_bucket.cpp
+++ b/src/mbgl/renderer/buckets/heatmap_bucket.cpp
@@ -42,7 +42,8 @@ bool HeatmapBucket::hasData() const {
void HeatmapBucket::addFeature(const GeometryTileFeature& feature,
const GeometryCollection& geometry,
const ImagePositions&,
- const PatternLayerMap&) {
+ const PatternLayerMap&,
+ std::size_t featureIndex) {
constexpr const uint16_t vertexLength = 4;
for (auto& points : geometry) {
@@ -89,7 +90,7 @@ void HeatmapBucket::addFeature(const GeometryTileFeature& feature,
}
for (auto& pair : paintPropertyBinders) {
- pair.second.populateVertexVectors(feature, vertices.elements(), {}, {});
+ pair.second.populateVertexVectors(feature, vertices.elements(), featureIndex, {}, {});
}
}
diff --git a/src/mbgl/renderer/buckets/heatmap_bucket.hpp b/src/mbgl/renderer/buckets/heatmap_bucket.hpp
index 68790bf5bf..3f9d1cb5c3 100644
--- a/src/mbgl/renderer/buckets/heatmap_bucket.hpp
+++ b/src/mbgl/renderer/buckets/heatmap_bucket.hpp
@@ -21,7 +21,8 @@ public:
void addFeature(const GeometryTileFeature&,
const GeometryCollection&,
const ImagePositions&,
- const PatternLayerMap&) override;
+ const PatternLayerMap&,
+ std::size_t) override;
bool hasData() const override;
void upload(gfx::UploadPass&) override;
diff --git a/src/mbgl/renderer/buckets/line_bucket.cpp b/src/mbgl/renderer/buckets/line_bucket.cpp
index 9019e76d3b..318af99b0f 100644
--- a/src/mbgl/renderer/buckets/line_bucket.cpp
+++ b/src/mbgl/renderer/buckets/line_bucket.cpp
@@ -33,7 +33,8 @@ LineBucket::~LineBucket() = default;
void LineBucket::addFeature(const GeometryTileFeature& feature,
const GeometryCollection& geometryCollection,
const ImagePositions& patternPositions,
- const PatternLayerMap& patternDependencies) {
+ const PatternLayerMap& patternDependencies,
+ std::size_t index) {
for (auto& line : geometryCollection) {
addGeometry(line, feature);
}
@@ -41,9 +42,9 @@ void LineBucket::addFeature(const GeometryTileFeature& feature,
for (auto& pair : paintPropertyBinders) {
const auto it = patternDependencies.find(pair.first);
if (it != patternDependencies.end()){
- pair.second.populateVertexVectors(feature, vertices.elements(), patternPositions, it->second);
+ pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, it->second);
} else {
- pair.second.populateVertexVectors(feature, vertices.elements(), patternPositions, {});
+ pair.second.populateVertexVectors(feature, vertices.elements(), index, patternPositions, {});
}
}
}
@@ -517,8 +518,10 @@ void LineBucket::addPieSliceVertex(const GeometryCoordinate& currentVertex,
}
void LineBucket::upload(gfx::UploadPass& uploadPass) {
- vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices));
- indexBuffer = uploadPass.createIndexBuffer(std::move(triangles));
+ if (!uploaded) {
+ vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices));
+ indexBuffer = uploadPass.createIndexBuffer(std::move(triangles));
+ }
for (auto& pair : paintPropertyBinders) {
pair.second.upload(uploadPass);
@@ -554,4 +557,12 @@ float LineBucket::getQueryRadius(const RenderLayer& layer) const {
return lineWidth / 2.0f + std::abs(offset) + util::length(translate[0], translate[1]);
}
+void LineBucket::update(const FeatureStates& states, const GeometryTileLayer& layer, const std::string& layerID, const ImagePositions& imagePositions) {
+ auto it = paintPropertyBinders.find(layerID);
+ if (it != paintPropertyBinders.end()) {
+ it->second.updateVertexVectors(states, layer, imagePositions);
+ uploaded = false;
+ }
+}
+
} // namespace mbgl
diff --git a/src/mbgl/renderer/buckets/line_bucket.hpp b/src/mbgl/renderer/buckets/line_bucket.hpp
index eac9e14e4c..6be35593d9 100644
--- a/src/mbgl/renderer/buckets/line_bucket.hpp
+++ b/src/mbgl/renderer/buckets/line_bucket.hpp
@@ -29,7 +29,8 @@ public:
void addFeature(const GeometryTileFeature&,
const GeometryCollection&,
const mbgl::ImagePositions& patternPositions,
- const PatternLayerMap&) override;
+ const PatternLayerMap&,
+ std::size_t) override;
bool hasData() const override;
@@ -37,6 +38,8 @@ public:
float getQueryRadius(const RenderLayer&) const override;
+ void update(const FeatureStates&, const GeometryTileLayer&, const std::string&, const ImagePositions&) override;
+
PossiblyEvaluatedLayoutProperties layout;
gfx::VertexVector<LineLayoutVertex> vertices;
diff --git a/src/mbgl/renderer/paint_property_binder.hpp b/src/mbgl/renderer/paint_property_binder.hpp
index cd6b259e88..fdfbc99642 100644
--- a/src/mbgl/renderer/paint_property_binder.hpp
+++ b/src/mbgl/renderer/paint_property_binder.hpp
@@ -19,6 +19,15 @@
namespace mbgl {
+// Maps vertex range to feature index
+struct FeatureVertexRange {
+ std::size_t featureIndex;
+ std::size_t start;
+ std::size_t end;
+};
+
+using FeatureVertexRangeMap = std::map<std::string, std::vector<FeatureVertexRange>>;
+
/*
ZoomInterpolatedAttribute<Attr> is a 'compound' attribute, representing two values of the
the base attribute Attr. These two values are provided to the shader to allow interpolation
@@ -97,9 +106,17 @@ public:
virtual ~PaintPropertyBinder() = default;
virtual void populateVertexVector(const GeometryTileFeature& feature,
- std::size_t length, const ImagePositions&,
+ std::size_t length, std::size_t index,
+ const ImagePositions&,
const optional<PatternDependency>&,
const style::expression::Value&) = 0;
+
+ virtual void updateVertexVectors(const FeatureStates&,
+ const GeometryTileLayer&,
+ const ImagePositions&) {}
+
+ virtual void updateVertexVector(std::size_t, std::size_t, const GeometryTileFeature&, const FeatureState&) = 0;
+
virtual void upload(gfx::UploadPass&) = 0;
virtual void setPatternParameters(const optional<ImagePosition>&, const optional<ImagePosition>&, const CrossfadeParameters&) = 0;
virtual std::tuple<ExpandToType<As, optional<gfx::AttributeBinding>>...> attributeBinding(const PossiblyEvaluatedType& currentValue) const = 0;
@@ -118,7 +135,8 @@ public:
: constant(std::move(constant_)) {
}
- void populateVertexVector(const GeometryTileFeature&, std::size_t, const ImagePositions&, const optional<PatternDependency>&, const style::expression::Value&) override {}
+ void populateVertexVector(const GeometryTileFeature&, std::size_t, std::size_t, const ImagePositions&, const optional<PatternDependency>&, const style::expression::Value&) override {}
+ void updateVertexVector(std::size_t, std::size_t, const GeometryTileFeature&, const FeatureState&) override {}
void upload(gfx::UploadPass&) override {}
void setPatternParameters(const optional<ImagePosition>&, const optional<ImagePosition>&, const CrossfadeParameters&) override {};
@@ -145,7 +163,8 @@ public:
: constant(std::move(constant_)), constantPatternPositions({}) {
}
- void populateVertexVector(const GeometryTileFeature&, std::size_t, const ImagePositions&, const optional<PatternDependency>&, const style::expression::Value&) override {}
+ void populateVertexVector(const GeometryTileFeature&, std::size_t, std::size_t, const ImagePositions&, const optional<PatternDependency>&, const style::expression::Value&) override {}
+ void updateVertexVector(std::size_t, std::size_t, const GeometryTileFeature&, const FeatureState&) override {}
void upload(gfx::UploadPass&) override {}
void setPatternParameters(const optional<ImagePosition>& posA, const optional<ImagePosition>& posB, const CrossfadeParameters&) override {
@@ -187,14 +206,46 @@ public:
defaultValue(std::move(defaultValue_)) {
}
void setPatternParameters(const optional<ImagePosition>&, const optional<ImagePosition>&, const CrossfadeParameters&) override {};
- void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, const ImagePositions&, const optional<PatternDependency>&, const style::expression::Value& formattedSection) override {
+ void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, std::size_t index, const ImagePositions&, const optional<PatternDependency>&, const style::expression::Value& formattedSection) override {
using style::expression::EvaluationContext;
auto evaluated = expression.evaluate(EvaluationContext(&feature).withFormattedSection(&formattedSection), defaultValue);
this->statistics.add(evaluated);
auto value = attributeValue(evaluated);
- for (std::size_t i = vertexVector.elements(); i < length; ++i) {
+ auto elements = vertexVector.elements();
+ for (std::size_t i = elements; i < length; ++i) {
vertexVector.emplace_back(BaseVertex { value });
}
+ optional<std::string> idStr = featureIDtoString(feature.getID());
+ if (idStr) {
+ featureMap[*idStr].emplace_back(FeatureVertexRange { index, elements, length });
+ }
+ }
+
+ void updateVertexVectors(const FeatureStates& states, const GeometryTileLayer& layer, const ImagePositions&) override {
+ for (const auto& it : states) {
+ const auto positions = featureMap.find(it.first);
+ if (positions == featureMap.end()) {
+ continue;
+ }
+
+ for (const auto& pos : positions->second) {
+ std::unique_ptr<GeometryTileFeature> feature = layer.getFeature(pos.featureIndex);
+ if (feature) {
+ updateVertexVector(pos.start, pos.end, *feature, it.second);
+ }
+ }
+ }
+ }
+
+ void updateVertexVector(std::size_t start, std::size_t end, const GeometryTileFeature& feature, const FeatureState& state) override {
+ using style::expression::EvaluationContext;
+
+ auto evaluated = expression.evaluate(EvaluationContext(&feature).withFeatureState(&state), defaultValue);
+ this->statistics.add(evaluated);
+ auto value = attributeValue(evaluated);
+ for (std::size_t i = start; i < end; ++i) {
+ vertexVector.at(i) = BaseVertex { value };
+ }
}
void upload(gfx::UploadPass& uploadPass) override {
@@ -229,6 +280,7 @@ private:
T defaultValue;
gfx::VertexVector<BaseVertex> vertexVector;
optional<gfx::VertexBuffer<BaseVertex>> vertexBuffer;
+ FeatureVertexRangeMap featureMap;
};
template <class T, class A>
@@ -245,7 +297,7 @@ public:
zoomRange({zoom, zoom + 1}) {
}
void setPatternParameters(const optional<ImagePosition>&, const optional<ImagePosition>&, const CrossfadeParameters&) override {};
- void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, const ImagePositions&, const optional<PatternDependency>&, const style::expression::Value& formattedSection) override {
+ void populateVertexVector(const GeometryTileFeature& feature, std::size_t length, std::size_t index, const ImagePositions&, const optional<PatternDependency>&, const style::expression::Value& formattedSection) override {
using style::expression::EvaluationContext;
Range<T> range = {
expression.evaluate(EvaluationContext(zoomRange.min, &feature).withFormattedSection(&formattedSection), defaultValue),
@@ -256,9 +308,47 @@ public:
AttributeValue value = zoomInterpolatedAttributeValue(
attributeValue(range.min),
attributeValue(range.max));
- for (std::size_t i = vertexVector.elements(); i < length; ++i) {
+ auto elements = vertexVector.elements();
+ for (std::size_t i = elements; i < length; ++i) {
vertexVector.emplace_back(Vertex { value });
}
+ optional<std::string> idStr = featureIDtoString(feature.getID());
+ if (idStr) {
+ featureMap[*idStr].emplace_back(FeatureVertexRange { index, elements, length });
+ }
+ }
+
+ void updateVertexVectors(const FeatureStates& states, const GeometryTileLayer& layer, const ImagePositions&) override {
+ for (const auto& it : states) {
+ const auto positions = featureMap.find(it.first);
+ if (positions == featureMap.end()) {
+ continue;
+ }
+
+ for (const auto& pos : positions->second) {
+ std::unique_ptr<GeometryTileFeature> feature = layer.getFeature(pos.featureIndex);
+ if (feature) {
+ updateVertexVector(pos.start, pos.end, *feature, it.second);
+ }
+ }
+ }
+ }
+
+ void updateVertexVector(std::size_t start, std::size_t end, const GeometryTileFeature& feature, const FeatureState& state) override {
+ using style::expression::EvaluationContext;
+ Range<T> range = {
+ expression.evaluate(EvaluationContext(zoomRange.min, &feature, &state), defaultValue),
+ expression.evaluate(EvaluationContext(zoomRange.max, &feature, &state), defaultValue),
+ };
+ this->statistics.add(range.min);
+ this->statistics.add(range.max);
+ AttributeValue value = zoomInterpolatedAttributeValue(
+ attributeValue(range.min),
+ attributeValue(range.max));
+
+ for (std::size_t i = start; i < end; ++i) {
+ vertexVector.at(i) = Vertex { value };
+ }
}
void upload(gfx::UploadPass& uploadPass) override {
@@ -298,6 +388,7 @@ private:
Range<float> zoomRange;
gfx::VertexVector<Vertex> vertexVector;
optional<gfx::VertexBuffer<Vertex>> vertexBuffer;
+ FeatureVertexRangeMap featureMap;
};
template <class T, class A1, class A2>
@@ -322,7 +413,7 @@ public:
crossfade = crossfade_;
};
- void populateVertexVector(const GeometryTileFeature&, std::size_t length, const ImagePositions& patternPositions, const optional<PatternDependency>& patternDependencies, const style::expression::Value&) override {
+ void populateVertexVector(const GeometryTileFeature&, std::size_t length, std::size_t /* index */, const ImagePositions& patternPositions, const optional<PatternDependency>& patternDependencies, const style::expression::Value&) override {
if (!patternDependencies || patternDependencies->mid.empty()) {
// Unlike other propperties with expressions that evaluate to null, the default value for `*-pattern` properties is an empty
@@ -353,6 +444,8 @@ public:
}
}
+ void updateVertexVector(std::size_t, std::size_t, const GeometryTileFeature&, const FeatureState&) override {}
+
void upload(gfx::UploadPass& uploadPass) override {
if (!patternToVertexVector.empty()) {
assert(!zoomInVertexVector.empty());
@@ -491,9 +584,15 @@ public:
PaintPropertyBinders(PaintPropertyBinders&&) = default;
PaintPropertyBinders(const PaintPropertyBinders&) = delete;
- void populateVertexVectors(const GeometryTileFeature& feature, std::size_t length, const ImagePositions& patternPositions, const optional<PatternDependency>& patternDependencies, const style::expression::Value& formattedSection = {}) {
+ void populateVertexVectors(const GeometryTileFeature& feature, std::size_t length, std::size_t index, const ImagePositions& patternPositions, const optional<PatternDependency>& patternDependencies, const style::expression::Value& formattedSection = {}) {
+ util::ignore({
+ (binders.template get<Ps>()->populateVertexVector(feature, length, index, patternPositions, patternDependencies, formattedSection), 0)...
+ });
+ }
+
+ void updateVertexVectors(const FeatureStates& states, const GeometryTileLayer& layer, const ImagePositions& imagePositions) {
util::ignore({
- (binders.template get<Ps>()->populateVertexVector(feature, length, patternPositions, patternDependencies, formattedSection), 0)...
+ (binders.template get<Ps>()->updateVertexVectors(states, layer, imagePositions), 0)...
});
}
diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp
index 428a5b0d5e..ce883ad93f 100644
--- a/src/mbgl/tile/geometry_tile_worker.cpp
+++ b/src/mbgl/tile/geometry_tile_worker.cpp
@@ -384,7 +384,7 @@ void GeometryTileWorker::parse() {
continue;
const GeometryCollection& geometries = feature->getGeometries();
- bucket->addFeature(*feature, geometries, {}, PatternLayerMap ());
+ bucket->addFeature(*feature, geometries, {}, PatternLayerMap (), i);
featureIndex->insert(geometries, i, sourceLayerID, leaderImpl.id);
}