summaryrefslogtreecommitdiff
path: root/src/mbgl/renderer
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/renderer')
-rw-r--r--src/mbgl/renderer/bucket.hpp8
-rw-r--r--src/mbgl/renderer/buckets/circle_bucket.cpp23
-rw-r--r--src/mbgl/renderer/buckets/circle_bucket.hpp8
-rw-r--r--src/mbgl/renderer/buckets/fill_bucket.cpp29
-rw-r--r--src/mbgl/renderer/buckets/fill_bucket.hpp8
-rw-r--r--src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp26
-rw-r--r--src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp8
-rw-r--r--src/mbgl/renderer/buckets/heatmap_bucket.cpp8
-rw-r--r--src/mbgl/renderer/buckets/heatmap_bucket.hpp6
-rw-r--r--src/mbgl/renderer/buckets/line_bucket.cpp27
-rw-r--r--src/mbgl/renderer/buckets/line_bucket.hpp8
-rw-r--r--src/mbgl/renderer/layers/render_circle_layer.cpp15
-rw-r--r--src/mbgl/renderer/layers/render_circle_layer.hpp9
-rw-r--r--src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp12
-rw-r--r--src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp9
-rw-r--r--src/mbgl/renderer/layers/render_fill_layer.cpp12
-rw-r--r--src/mbgl/renderer/layers/render_fill_layer.hpp9
-rw-r--r--src/mbgl/renderer/layers/render_heatmap_layer.cpp11
-rw-r--r--src/mbgl/renderer/layers/render_heatmap_layer.hpp9
-rw-r--r--src/mbgl/renderer/layers/render_line_layer.cpp29
-rw-r--r--src/mbgl/renderer/layers/render_line_layer.hpp11
-rw-r--r--src/mbgl/renderer/paint_property_binder.hpp137
-rw-r--r--src/mbgl/renderer/possibly_evaluated_property_value.hpp8
-rw-r--r--src/mbgl/renderer/render_layer.hpp11
-rw-r--r--src/mbgl/renderer/render_orchestrator.cpp23
-rw-r--r--src/mbgl/renderer/render_orchestrator.hpp9
-rw-r--r--src/mbgl/renderer/render_source.hpp7
-rw-r--r--src/mbgl/renderer/render_tile.cpp4
-rw-r--r--src/mbgl/renderer/render_tile.hpp3
-rw-r--r--src/mbgl/renderer/renderer.cpp15
-rw-r--r--src/mbgl/renderer/source_state.cpp132
-rw-r--r--src/mbgl/renderer/source_state.hpp29
-rw-r--r--src/mbgl/renderer/sources/render_tile_source.cpp19
-rw-r--r--src/mbgl/renderer/sources/render_tile_source.hpp13
-rw-r--r--src/mbgl/renderer/tile_pyramid.cpp18
-rw-r--r--src/mbgl/renderer/tile_pyramid.hpp10
36 files changed, 537 insertions, 186 deletions
diff --git a/src/mbgl/renderer/bucket.hpp b/src/mbgl/renderer/bucket.hpp
index a978c06d6b..6c74b8309f 100644
--- a/src/mbgl/renderer/bucket.hpp
+++ b/src/mbgl/renderer/bucket.hpp
@@ -32,10 +32,10 @@ public:
// Feature geometries are also used to populate the feature index.
// Obtaining these is a costly operation, so we do it only once, and
// pass-by-const-ref the geometries as a second parameter.
- virtual void addFeature(const GeometryTileFeature&,
- const GeometryCollection&,
- const ImagePositions&,
- const PatternLayerMap&) {};
+ virtual void addFeature(const GeometryTileFeature&, const GeometryCollection&, const ImagePositions&,
+ 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..560a74781a 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);
@@ -39,10 +41,8 @@ bool CircleBucket::hasData() const {
return !segments.empty();
}
-void CircleBucket::addFeature(const GeometryTileFeature& feature,
- const GeometryCollection& geometry,
- const ImagePositions&,
- const PatternLayerMap&) {
+void CircleBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometry,
+ const ImagePositions&, const PatternLayerMap&, std::size_t featureIndex) {
constexpr const uint16_t vertexLength = 4;
for (auto& circle : geometry) {
@@ -90,7 +90,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 +112,13 @@ 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..e514f8a5f2 100644
--- a/src/mbgl/renderer/buckets/circle_bucket.hpp
+++ b/src/mbgl/renderer/buckets/circle_bucket.hpp
@@ -18,10 +18,8 @@ public:
CircleBucket(const BucketParameters&, const std::vector<Immutable<style::LayerProperties>>&);
~CircleBucket() override;
- void addFeature(const GeometryTileFeature&,
- const GeometryCollection&,
- const ImagePositions&,
- const PatternLayerMap&) override;
+ void addFeature(const GeometryTileFeature&, const GeometryCollection&, const ImagePositions&,
+ const PatternLayerMap&, std::size_t) override;
bool hasData() const override;
@@ -29,6 +27,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..6660934f8d 100644
--- a/src/mbgl/renderer/buckets/fill_bucket.cpp
+++ b/src/mbgl/renderer/buckets/fill_bucket.cpp
@@ -44,10 +44,9 @@ FillBucket::FillBucket(const FillBucket::PossiblyEvaluatedLayoutProperties,
FillBucket::~FillBucket() = default;
-void FillBucket::addFeature(const GeometryTileFeature& feature,
- const GeometryCollection& geometry,
- const ImagePositions& patternPositions,
- const PatternLayerMap& patternDependencies) {
+void FillBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometry,
+ const ImagePositions& patternPositions, 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 +113,20 @@ 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 +145,13 @@ 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..9f65e774ca 100644
--- a/src/mbgl/renderer/buckets/fill_bucket.hpp
+++ b/src/mbgl/renderer/buckets/fill_bucket.hpp
@@ -26,10 +26,8 @@ public:
const float zoom,
const uint32_t overscaling);
- void addFeature(const GeometryTileFeature&,
- const GeometryCollection&,
- const mbgl::ImagePositions&,
- const PatternLayerMap&) override;
+ void addFeature(const GeometryTileFeature&, const GeometryCollection&, const mbgl::ImagePositions&,
+ const PatternLayerMap&, std::size_t) override;
bool hasData() const override;
@@ -37,6 +35,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..698895fdcf 100644
--- a/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp
+++ b/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp
@@ -50,10 +50,9 @@ FillExtrusionBucket::FillExtrusionBucket(const FillExtrusionBucket::PossiblyEval
FillExtrusionBucket::~FillExtrusionBucket() = default;
-void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature,
- const GeometryCollection& geometry,
- const ImagePositions& patternPositions,
- const PatternLayerMap& patternDependencies) {
+void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometry,
+ const ImagePositions& patternPositions, 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 +157,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 +187,13 @@ 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..8535f99b70 100644
--- a/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp
+++ b/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp
@@ -24,10 +24,8 @@ public:
const float,
const uint32_t);
- void addFeature(const GeometryTileFeature&,
- const GeometryCollection&,
- const mbgl::ImagePositions&,
- const PatternLayerMap&) override;
+ void addFeature(const GeometryTileFeature&, const GeometryCollection&, const mbgl::ImagePositions&,
+ const PatternLayerMap&, std::size_t) override;
bool hasData() const override;
@@ -35,6 +33,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..78c4fb7507 100644
--- a/src/mbgl/renderer/buckets/heatmap_bucket.cpp
+++ b/src/mbgl/renderer/buckets/heatmap_bucket.cpp
@@ -39,10 +39,8 @@ bool HeatmapBucket::hasData() const {
return !segments.empty();
}
-void HeatmapBucket::addFeature(const GeometryTileFeature& feature,
- const GeometryCollection& geometry,
- const ImagePositions&,
- const PatternLayerMap&) {
+void HeatmapBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometry,
+ const ImagePositions&, const PatternLayerMap&, std::size_t featureIndex) {
constexpr const uint16_t vertexLength = 4;
for (auto& points : geometry) {
@@ -89,7 +87,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..04d4170b50 100644
--- a/src/mbgl/renderer/buckets/heatmap_bucket.hpp
+++ b/src/mbgl/renderer/buckets/heatmap_bucket.hpp
@@ -18,10 +18,8 @@ public:
HeatmapBucket(const BucketParameters&, const std::vector<Immutable<style::LayerProperties>>&);
~HeatmapBucket() override;
- void addFeature(const GeometryTileFeature&,
- const GeometryCollection&,
- const ImagePositions&,
- const PatternLayerMap&) override;
+ void addFeature(const GeometryTileFeature&, const GeometryCollection&, const ImagePositions&,
+ 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..f65c239968 100644
--- a/src/mbgl/renderer/buckets/line_bucket.cpp
+++ b/src/mbgl/renderer/buckets/line_bucket.cpp
@@ -30,10 +30,9 @@ LineBucket::LineBucket(const style::LineLayoutProperties::PossiblyEvaluated layo
LineBucket::~LineBucket() = default;
-void LineBucket::addFeature(const GeometryTileFeature& feature,
- const GeometryCollection& geometryCollection,
- const ImagePositions& patternPositions,
- const PatternLayerMap& patternDependencies) {
+void LineBucket::addFeature(const GeometryTileFeature& feature, const GeometryCollection& geometryCollection,
+ const ImagePositions& patternPositions, const PatternLayerMap& patternDependencies,
+ std::size_t index) {
for (auto& line : geometryCollection) {
addGeometry(line, feature);
}
@@ -41,14 +40,13 @@ 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, {});
}
}
}
-
/*
* Sharp corners cause dashed lines to tilt because the distance along the line
* is the same at both the inner and outer corners. To improve the appearance of
@@ -517,8 +515,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 +554,13 @@ 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..6343aab2be 100644
--- a/src/mbgl/renderer/buckets/line_bucket.hpp
+++ b/src/mbgl/renderer/buckets/line_bucket.hpp
@@ -26,10 +26,8 @@ public:
const uint32_t overscaling);
~LineBucket() override;
- void addFeature(const GeometryTileFeature&,
- const GeometryCollection&,
- const mbgl::ImagePositions& patternPositions,
- const PatternLayerMap&) override;
+ void addFeature(const GeometryTileFeature&, const GeometryCollection&, const mbgl::ImagePositions& patternPositions,
+ const PatternLayerMap&, std::size_t) override;
bool hasData() const override;
@@ -37,6 +35,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/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp
index ea0c20f124..b88a026e11 100644
--- a/src/mbgl/renderer/layers/render_circle_layer.cpp
+++ b/src/mbgl/renderer/layers/render_circle_layer.cpp
@@ -141,13 +141,10 @@ GeometryCoordinates projectQueryGeometry(const GeometryCoordinates& queryGeometr
return projectedGeometry;
}
-bool RenderCircleLayer::queryIntersectsFeature(
- const GeometryCoordinates& queryGeometry,
- const GeometryTileFeature& feature,
- const float zoom,
- const TransformState& transformState,
- const float pixelsToTileUnits,
- const mat4& posMatrix) const {
+bool RenderCircleLayer::queryIntersectsFeature(const GeometryCoordinates& queryGeometry,
+ const GeometryTileFeature& feature, const float zoom,
+ const TransformState& transformState, const float pixelsToTileUnits,
+ const mat4& posMatrix, const FeatureState& featureState) const {
const auto& evaluated = static_cast<const CircleLayerProperties&>(*evaluatedProperties).evaluated;
// Translate query geometry
const GeometryCoordinates& translatedQueryGeometry = FeatureIndex::translateQueryGeometry(
@@ -158,8 +155,8 @@ bool RenderCircleLayer::queryIntersectsFeature(
pixelsToTileUnits).value_or(queryGeometry);
// Evaluate functions
- auto radius = evaluated.evaluate<style::CircleRadius>(zoom, feature);
- auto stroke = evaluated.evaluate<style::CircleStrokeWidth>(zoom, feature);
+ auto radius = evaluated.evaluate<style::CircleRadius>(zoom, feature, featureState);
+ auto stroke = evaluated.evaluate<style::CircleStrokeWidth>(zoom, feature, featureState);
auto size = radius + stroke;
// For pitch-alignment: map, compare feature geometry to query geometry in the plane of the tile
diff --git a/src/mbgl/renderer/layers/render_circle_layer.hpp b/src/mbgl/renderer/layers/render_circle_layer.hpp
index 9348e48929..70af20f0cf 100644
--- a/src/mbgl/renderer/layers/render_circle_layer.hpp
+++ b/src/mbgl/renderer/layers/render_circle_layer.hpp
@@ -18,13 +18,8 @@ private:
bool hasCrossfade() const override;
void render(PaintParameters&) override;
- bool queryIntersectsFeature(
- const GeometryCoordinates&,
- const GeometryTileFeature&,
- const float,
- const TransformState&,
- const float,
- const mat4&) const override;
+ bool queryIntersectsFeature(const GeometryCoordinates&, const GeometryTileFeature&, const float,
+ const TransformState&, const float, const mat4&, const FeatureState&) const override;
// Paint properties
style::CirclePaintProperties::Unevaluated unevaluated;
diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp
index 835e8c8ee5..fc830e462c 100644
--- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp
+++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp
@@ -224,13 +224,11 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters) {
}
}
-bool RenderFillExtrusionLayer::queryIntersectsFeature(
- const GeometryCoordinates& queryGeometry,
- const GeometryTileFeature& feature,
- const float,
- const TransformState& transformState,
- const float pixelsToTileUnits,
- const mat4&) const {
+bool RenderFillExtrusionLayer::queryIntersectsFeature(const GeometryCoordinates& queryGeometry,
+ const GeometryTileFeature& feature, const float,
+ const TransformState& transformState,
+ const float pixelsToTileUnits, const mat4&,
+ const FeatureState&) const {
const auto& evaluated = static_cast<const FillExtrusionLayerProperties&>(*evaluatedProperties).evaluated;
auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry(
queryGeometry,
diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp
index 8bd1f52adf..0e6a747c71 100644
--- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp
+++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp
@@ -20,13 +20,8 @@ private:
bool is3D() const override;
void render(PaintParameters&) override;
- bool queryIntersectsFeature(
- const GeometryCoordinates&,
- const GeometryTileFeature&,
- const float,
- const TransformState&,
- const float,
- const mat4&) const override;
+ bool queryIntersectsFeature(const GeometryCoordinates&, const GeometryTileFeature&, const float,
+ const TransformState&, const float, const mat4&, const FeatureState&) const override;
// Paint properties
style::FillExtrusionPaintProperties::Unevaluated unevaluated;
diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp
index 27cb76fede..e855866eea 100644
--- a/src/mbgl/renderer/layers/render_fill_layer.cpp
+++ b/src/mbgl/renderer/layers/render_fill_layer.cpp
@@ -249,13 +249,10 @@ void RenderFillLayer::render(PaintParameters& parameters) {
}
}
-bool RenderFillLayer::queryIntersectsFeature(
- const GeometryCoordinates& queryGeometry,
- const GeometryTileFeature& feature,
- const float,
- const TransformState& transformState,
- const float pixelsToTileUnits,
- const mat4&) const {
+bool RenderFillLayer::queryIntersectsFeature(const GeometryCoordinates& queryGeometry,
+ const GeometryTileFeature& feature, const float,
+ const TransformState& transformState, const float pixelsToTileUnits,
+ const mat4&, const FeatureState&) const {
const auto& evaluated = getEvaluated<FillLayerProperties>(evaluatedProperties);
auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry(
queryGeometry,
@@ -267,5 +264,4 @@ bool RenderFillLayer::queryIntersectsFeature(
return util::polygonIntersectsMultiPolygon(translatedQueryGeometry.value_or(queryGeometry), feature.getGeometries());
}
-
} // namespace mbgl
diff --git a/src/mbgl/renderer/layers/render_fill_layer.hpp b/src/mbgl/renderer/layers/render_fill_layer.hpp
index 79adc9dab4..12484dbfb1 100644
--- a/src/mbgl/renderer/layers/render_fill_layer.hpp
+++ b/src/mbgl/renderer/layers/render_fill_layer.hpp
@@ -21,13 +21,8 @@ private:
bool hasCrossfade() const override;
void render(PaintParameters&) override;
- bool queryIntersectsFeature(
- const GeometryCoordinates&,
- const GeometryTileFeature&,
- const float,
- const TransformState&,
- const float,
- const mat4&) const override;
+ bool queryIntersectsFeature(const GeometryCoordinates&, const GeometryTileFeature&, const float,
+ const TransformState&, const float, const mat4&, const FeatureState&) const override;
// Paint properties
style::FillPaintProperties::Unevaluated unevaluated;
diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.cpp b/src/mbgl/renderer/layers/render_heatmap_layer.cpp
index 4fa20ffd13..797aedd297 100644
--- a/src/mbgl/renderer/layers/render_heatmap_layer.cpp
+++ b/src/mbgl/renderer/layers/render_heatmap_layer.cpp
@@ -219,13 +219,10 @@ void RenderHeatmapLayer::updateColorRamp() {
}
}
-bool RenderHeatmapLayer::queryIntersectsFeature(
- const GeometryCoordinates& queryGeometry,
- const GeometryTileFeature& feature,
- const float zoom,
- const TransformState&,
- const float pixelsToTileUnits,
- const mat4&) const {
+bool RenderHeatmapLayer::queryIntersectsFeature(const GeometryCoordinates& queryGeometry,
+ const GeometryTileFeature& feature, const float zoom,
+ const TransformState&, const float pixelsToTileUnits, const mat4&,
+ const FeatureState&) const {
(void) queryGeometry;
(void) feature;
(void) zoom;
diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.hpp b/src/mbgl/renderer/layers/render_heatmap_layer.hpp
index 27e27adb28..1e9b1063ae 100644
--- a/src/mbgl/renderer/layers/render_heatmap_layer.hpp
+++ b/src/mbgl/renderer/layers/render_heatmap_layer.hpp
@@ -22,13 +22,8 @@ private:
void upload(gfx::UploadPass&) override;
void render(PaintParameters&) override;
- bool queryIntersectsFeature(
- const GeometryCoordinates&,
- const GeometryTileFeature&,
- const float,
- const TransformState&,
- const float,
- const mat4&) const override;
+ bool queryIntersectsFeature(const GeometryCoordinates&, const GeometryTileFeature&, const float,
+ const TransformState&, const float, const mat4&, const FeatureState&) const override;
// Paint properties
style::HeatmapPaintProperties::Unevaluated unevaluated;
diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp
index 6d635f65e7..36665c1db4 100644
--- a/src/mbgl/renderer/layers/render_line_layer.cpp
+++ b/src/mbgl/renderer/layers/render_line_layer.cpp
@@ -257,13 +257,10 @@ GeometryCollection offsetLine(const GeometryCollection& rings, double offset) {
} // namespace
-bool RenderLineLayer::queryIntersectsFeature(
- const GeometryCoordinates& queryGeometry,
- const GeometryTileFeature& feature,
- const float zoom,
- const TransformState& transformState,
- const float pixelsToTileUnits,
- const mat4&) const {
+bool RenderLineLayer::queryIntersectsFeature(const GeometryCoordinates& queryGeometry,
+ const GeometryTileFeature& feature, const float zoom,
+ const TransformState& transformState, const float pixelsToTileUnits,
+ const mat4&, const FeatureState& featureState) const {
const auto& evaluated = static_cast<const LineLayerProperties&>(*evaluatedProperties).evaluated;
// Translate query geometry
auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry(
@@ -274,10 +271,11 @@ bool RenderLineLayer::queryIntersectsFeature(
pixelsToTileUnits);
// Evaluate function
- auto offset = evaluated.get<style::LineOffset>()
- .evaluate(feature, zoom, style::LineOffset::defaultValue()) * pixelsToTileUnits;
+ auto offset =
+ evaluated.get<style::LineOffset>().evaluate(feature, zoom, featureState, style::LineOffset::defaultValue()) *
+ pixelsToTileUnits;
// Test intersection
- const float halfWidth = getLineWidth(feature, zoom) / 2.0 * pixelsToTileUnits;
+ const auto halfWidth = static_cast<float>(getLineWidth(feature, zoom, featureState) / 2.0 * pixelsToTileUnits);
// Apply offset to geometry
if (offset != 0.0f && !feature.getGeometries().empty()) {
@@ -314,12 +312,13 @@ void RenderLineLayer::updateColorRamp() {
}
}
-float RenderLineLayer::getLineWidth(const GeometryTileFeature& feature, const float zoom) const {
+float RenderLineLayer::getLineWidth(const GeometryTileFeature& feature, const float zoom,
+ const FeatureState& featureState) const {
const auto& evaluated = static_cast<const LineLayerProperties&>(*evaluatedProperties).evaluated;
- float lineWidth = evaluated.get<style::LineWidth>()
- .evaluate(feature, zoom, style::LineWidth::defaultValue());
- float gapWidth = evaluated.get<style::LineGapWidth>()
- .evaluate(feature, zoom, style::LineGapWidth::defaultValue());
+ float lineWidth =
+ evaluated.get<style::LineWidth>().evaluate(feature, zoom, featureState, style::LineWidth::defaultValue());
+ float gapWidth =
+ evaluated.get<style::LineGapWidth>().evaluate(feature, zoom, featureState, style::LineGapWidth::defaultValue());
if (gapWidth) {
return gapWidth + 2 * lineWidth;
} else {
diff --git a/src/mbgl/renderer/layers/render_line_layer.hpp b/src/mbgl/renderer/layers/render_line_layer.hpp
index 4454d215d9..1914a82b77 100644
--- a/src/mbgl/renderer/layers/render_line_layer.hpp
+++ b/src/mbgl/renderer/layers/render_line_layer.hpp
@@ -24,18 +24,13 @@ private:
void upload(gfx::UploadPass&) override;
void render(PaintParameters&) override;
- bool queryIntersectsFeature(
- const GeometryCoordinates&,
- const GeometryTileFeature&,
- const float,
- const TransformState&,
- const float,
- const mat4&) const override;
+ bool queryIntersectsFeature(const GeometryCoordinates&, const GeometryTileFeature&, const float,
+ const TransformState&, const float, const mat4&, const FeatureState&) const override;
// Paint properties
style::LinePaintProperties::Unevaluated unevaluated;
- float getLineWidth(const GeometryTileFeature&, const float) const;
+ float getLineWidth(const GeometryTileFeature&, const float, const FeatureState&) const;
void updateColorRamp();
PremultipliedImage colorRamp;
diff --git a/src/mbgl/renderer/paint_property_binder.hpp b/src/mbgl/renderer/paint_property_binder.hpp
index cd6b259e88..1a36f8a2e5 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
@@ -96,10 +105,14 @@ public:
virtual ~PaintPropertyBinder() = default;
- virtual void populateVertexVector(const GeometryTileFeature& feature,
- std::size_t length, const ImagePositions&,
- const optional<PatternDependency>&,
+ virtual void populateVertexVector(const GeometryTileFeature& feature, 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 +131,9 @@ 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 +160,9 @@ 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 +204,50 @@ 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 +282,7 @@ private:
T defaultValue;
gfx::VertexVector<BaseVertex> vertexVector;
optional<gfx::VertexBuffer<BaseVertex>> vertexBuffer;
+ FeatureVertexRangeMap featureMap;
};
template <class T, class A>
@@ -245,7 +299,9 @@ 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 +312,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 +392,7 @@ private:
Range<float> zoomRange;
gfx::VertexVector<Vertex> vertexVector;
optional<gfx::VertexBuffer<Vertex>> vertexBuffer;
+ FeatureVertexRangeMap featureMap;
};
template <class T, class A1, class A2>
@@ -322,8 +417,10 @@ 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
// string and will not have a valid entry in patternPositions. We still need to populate the attribute buffers to avoid crashes
@@ -353,6 +450,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,10 +590,18 @@ 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 = {}) {
- util::ignore({
- (binders.template get<Ps>()->populateVertexVector(feature, length, patternPositions, patternDependencies, formattedSection), 0)...
- });
+ 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>()->updateVertexVectors(states, layer, imagePositions), 0)...});
}
void setPatternParameters(const optional<ImagePosition>& posA, const optional<ImagePosition>& posB, const CrossfadeParameters& crossfade) const {
diff --git a/src/mbgl/renderer/possibly_evaluated_property_value.hpp b/src/mbgl/renderer/possibly_evaluated_property_value.hpp
index 625235011c..1198e43aae 100644
--- a/src/mbgl/renderer/possibly_evaluated_property_value.hpp
+++ b/src/mbgl/renderer/possibly_evaluated_property_value.hpp
@@ -49,6 +49,14 @@ public:
}
);
}
+
+ template <class Feature>
+ T evaluate(const Feature& feature, float zoom, const FeatureState& featureState, T defaultValue) const {
+ return this->match([&](const T& constant_) { return constant_; },
+ [&](const style::PropertyExpression<T>& expression) {
+ return expression.evaluate(zoom, feature, featureState, defaultValue);
+ });
+ }
};
template <class T>
diff --git a/src/mbgl/renderer/render_layer.hpp b/src/mbgl/renderer/render_layer.hpp
index 75c729444b..ba3c638f88 100644
--- a/src/mbgl/renderer/render_layer.hpp
+++ b/src/mbgl/renderer/render_layer.hpp
@@ -88,13 +88,10 @@ public:
// Check wether the given geometry intersects
// with the feature
- virtual bool queryIntersectsFeature(
- const GeometryCoordinates&,
- const GeometryTileFeature&,
- const float,
- const TransformState&,
- const float,
- const mat4&) const { return false; };
+ virtual bool queryIntersectsFeature(const GeometryCoordinates&, const GeometryTileFeature&, const float,
+ const TransformState&, const float, const mat4&, const FeatureState&) const {
+ return false;
+ };
virtual void prepare(const LayerPrepareParameters&);
diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp
index a62ccb0a0a..a1280331b1 100644
--- a/src/mbgl/renderer/render_orchestrator.cpp
+++ b/src/mbgl/renderer/render_orchestrator.cpp
@@ -562,6 +562,29 @@ FeatureExtensionValue RenderOrchestrator::queryFeatureExtensions(const std::stri
return {};
}
+void RenderOrchestrator::setFeatureState(const std::string& sourceID, const optional<std::string>& sourceLayerID,
+ const std::string& featureID, const FeatureState& state) {
+ if (RenderSource* renderSource = getRenderSource(sourceID)) {
+ renderSource->setFeatureState(sourceLayerID, featureID, state);
+ }
+}
+
+void RenderOrchestrator::getFeatureState(FeatureState& state, const std::string& sourceID,
+ const optional<std::string>& sourceLayerID,
+ const std::string& featureID) const {
+ if (RenderSource* renderSource = getRenderSource(sourceID)) {
+ renderSource->getFeatureState(state, sourceLayerID, featureID);
+ }
+}
+
+void RenderOrchestrator::removeFeatureState(const std::string& sourceID, const optional<std::string>& sourceLayerID,
+ const optional<std::string>& featureID,
+ const optional<std::string>& stateKey) {
+ if (RenderSource* renderSource = getRenderSource(sourceID)) {
+ renderSource->removeFeatureState(sourceLayerID, featureID, stateKey);
+ }
+}
+
void RenderOrchestrator::reduceMemoryUse() {
filteredLayersForSource.shrink_to_fit();
for (const auto& entry : renderSources) {
diff --git a/src/mbgl/renderer/render_orchestrator.hpp b/src/mbgl/renderer/render_orchestrator.hpp
index 884bd21b7b..34b623348f 100644
--- a/src/mbgl/renderer/render_orchestrator.hpp
+++ b/src/mbgl/renderer/render_orchestrator.hpp
@@ -64,6 +64,15 @@ public:
const std::string& extensionField,
const optional<std::map<std::string, Value>>& args) const;
+ void setFeatureState(const std::string& sourceID, const optional<std::string>& layerID,
+ const std::string& featureID, const FeatureState& state);
+
+ void getFeatureState(FeatureState& state, const std::string& sourceID, const optional<std::string>& layerID,
+ const std::string& featureID) const;
+
+ void removeFeatureState(const std::string& sourceID, const optional<std::string>& sourceLayerID,
+ const optional<std::string>& featureID, const optional<std::string>& stateKey);
+
void reduceMemoryUse();
void dumpDebugLogs();
diff --git a/src/mbgl/renderer/render_source.hpp b/src/mbgl/renderer/render_source.hpp
index cd471223a8..ee90e1c4d0 100644
--- a/src/mbgl/renderer/render_source.hpp
+++ b/src/mbgl/renderer/render_source.hpp
@@ -93,6 +93,13 @@ public:
return {};
}
+ virtual void setFeatureState(const optional<std::string>&, const std::string&, const FeatureState&) {}
+
+ virtual void getFeatureState(FeatureState&, const optional<std::string>&, const std::string&) const {}
+
+ virtual void removeFeatureState(const optional<std::string>&, const optional<std::string>&,
+ const optional<std::string>&) {}
+
virtual void reduceMemoryUse() = 0;
virtual void dumpDebugLogs() const = 0;
diff --git a/src/mbgl/renderer/render_tile.cpp b/src/mbgl/renderer/render_tile.cpp
index 65a6cb9f30..0d63e5b265 100644
--- a/src/mbgl/renderer/render_tile.cpp
+++ b/src/mbgl/renderer/render_tile.cpp
@@ -227,4 +227,8 @@ void RenderTile::finishRender(PaintParameters& parameters) const {
}
}
+void RenderTile::setFeatureState(const LayerFeatureStates& states) {
+ tile.setFeatureState(states);
+}
+
} // namespace mbgl
diff --git a/src/mbgl/renderer/render_tile.hpp b/src/mbgl/renderer/render_tile.hpp
index 34d027cae5..483dbf7413 100644
--- a/src/mbgl/renderer/render_tile.hpp
+++ b/src/mbgl/renderer/render_tile.hpp
@@ -68,6 +68,9 @@ public:
style::TranslateAnchorType anchor,
const TransformState& state,
const bool inViewportPixelUnits) const;
+
+ void setFeatureState(const LayerFeatureStates&);
+
private:
Tile& tile;
// The following members are reset at placement stage.
diff --git a/src/mbgl/renderer/renderer.cpp b/src/mbgl/renderer/renderer.cpp
index 52cd7a4351..cf4072036c 100644
--- a/src/mbgl/renderer/renderer.cpp
+++ b/src/mbgl/renderer/renderer.cpp
@@ -109,6 +109,21 @@ FeatureExtensionValue Renderer::queryFeatureExtensions(const std::string& source
return impl->orchestrator.queryFeatureExtensions(sourceID, feature, extension, extensionField, args);
}
+void Renderer::setFeatureState(const std::string& sourceID, const optional<std::string>& sourceLayerID,
+ const std::string& featureID, const FeatureState& state) {
+ impl->orchestrator.setFeatureState(sourceID, sourceLayerID, featureID, state);
+}
+
+void Renderer::getFeatureState(FeatureState& state, const std::string& sourceID,
+ const optional<std::string>& sourceLayerID, const std::string& featureID) const {
+ impl->orchestrator.getFeatureState(state, sourceID, sourceLayerID, featureID);
+}
+
+void Renderer::removeFeatureState(const std::string& sourceID, const optional<std::string>& sourceLayerID,
+ const optional<std::string>& featureID, const optional<std::string>& stateKey) {
+ impl->orchestrator.removeFeatureState(sourceID, sourceLayerID, featureID, stateKey);
+}
+
void Renderer::dumpDebugLogs() {
impl->orchestrator.dumpDebugLogs();
}
diff --git a/src/mbgl/renderer/source_state.cpp b/src/mbgl/renderer/source_state.cpp
new file mode 100644
index 0000000000..d057c211b5
--- /dev/null
+++ b/src/mbgl/renderer/source_state.cpp
@@ -0,0 +1,132 @@
+#include <mbgl/renderer/render_tile.hpp>
+#include <mbgl/renderer/source_state.hpp>
+#include <mbgl/style/conversion_impl.hpp>
+#include <mbgl/util/logging.hpp>
+
+namespace mbgl {
+
+void SourceFeatureState::updateState(const optional<std::string>& sourceLayerID, const std::string& featureID,
+ const FeatureState& newState) {
+ std::string sourceLayer = sourceLayerID.value_or(std::string());
+ for (const auto& state : newState) {
+ auto& layerStates = stateChanges[sourceLayer];
+ auto& featureStates = layerStates[featureID];
+ featureStates[state.first] = state.second;
+ }
+}
+
+void SourceFeatureState::getState(FeatureState& result, const optional<std::string>& sourceLayerID,
+ const std::string& featureID) const {
+ std::string sourceLayer = sourceLayerID.value_or(std::string());
+ FeatureState current;
+ FeatureState changes;
+ auto layerStates = currentStates.find(sourceLayer);
+ if (layerStates != currentStates.end()) {
+ const auto currentStateEntry = layerStates->second.find(featureID);
+ if (currentStateEntry != layerStates->second.end()) {
+ current = currentStateEntry->second;
+ }
+ }
+
+ layerStates = stateChanges.find(sourceLayer);
+ if (layerStates != stateChanges.end()) {
+ const auto stateChangesEntry = layerStates->second.find(featureID);
+ if (stateChangesEntry != layerStates->second.end()) {
+ changes = stateChangesEntry->second;
+ }
+ }
+ result = std::move(changes);
+ result.insert(current.begin(), current.end());
+}
+
+void SourceFeatureState::coalesceChanges(std::vector<RenderTile>& tiles) {
+ LayerFeatureStates changes;
+ for (const auto& layerStatesEntry : stateChanges) {
+ const auto& sourceLayer = layerStatesEntry.first;
+ FeatureStates layerStates;
+ for (const auto& featureStatesEntry : stateChanges[sourceLayer]) {
+ const auto& featureID = featureStatesEntry.first;
+ for (const auto& stateEntry : stateChanges[sourceLayer][featureID]) {
+ const auto& stateKey = stateEntry.first;
+ const auto& stateVal = stateEntry.second;
+
+ auto currentState = currentStates[sourceLayer][featureID].find(stateKey);
+ if (currentState != currentStates[sourceLayer][featureID].end()) {
+ currentState->second = stateVal;
+ } else {
+ currentStates[sourceLayer][featureID].insert(std::make_pair(stateKey, stateVal));
+ }
+ }
+ layerStates[featureID] = currentStates[sourceLayer][featureID];
+ }
+ changes[sourceLayer] = std::move(layerStates);
+ }
+
+ for (const auto& layerStatesEntry : deletedStates) {
+ const auto& sourceLayer = layerStatesEntry.first;
+ FeatureStates layerStates = {{}, {}};
+
+ if (deletedStates[sourceLayer].empty()) {
+ for (const auto& featureStatesEntry : currentStates[sourceLayer]) {
+ const auto& featureID = featureStatesEntry.first;
+ layerStates[featureID] = {};
+ currentStates[sourceLayer][featureID] = {};
+ }
+ } else {
+ for (const auto& feature : deletedStates[sourceLayer]) {
+ const auto& featureID = feature.first;
+ bool deleteWholeFeatureState = deletedStates[sourceLayer][featureID].empty();
+ if (deleteWholeFeatureState) {
+ currentStates[sourceLayer][featureID] = {};
+ } else {
+ for (const auto& stateEntry : deletedStates[sourceLayer][featureID]) {
+ currentStates[sourceLayer][featureID].erase(stateEntry.first);
+ }
+ }
+ layerStates[featureID] = currentStates[sourceLayer][featureID];
+ }
+ }
+ changes[sourceLayer] = std::move(layerStates);
+ }
+
+ stateChanges.clear();
+ deletedStates.clear();
+
+ if (changes.empty()) {
+ return;
+ }
+
+ for (auto& tile : tiles) {
+ tile.setFeatureState(changes);
+ }
+}
+
+void SourceFeatureState::removeState(const optional<std::string>& sourceLayerID, const optional<std::string>& featureID,
+ const optional<std::string>& stateKey) {
+ std::string sourceLayer = sourceLayerID.value_or(std::string());
+
+ bool sourceLayerDeleted = (deletedStates.count(sourceLayer) > 0) && deletedStates[sourceLayer].empty();
+ if (sourceLayerDeleted) {
+ return;
+ }
+
+ if (stateKey && featureID) {
+ if ((deletedStates.count(sourceLayer) == 0) && (deletedStates[sourceLayer].count(*featureID)) == 0) {
+ deletedStates[sourceLayer][*featureID][*stateKey] = {};
+ }
+ } else if (featureID) {
+ bool updateInQueue =
+ (stateChanges.count(sourceLayer) != 0U) && (stateChanges[sourceLayer].count(*featureID) != 0U);
+ if (updateInQueue) {
+ for (const auto& changeEntry : stateChanges[sourceLayer][*featureID]) {
+ deletedStates[sourceLayer][*featureID][changeEntry.first] = {};
+ }
+ } else {
+ deletedStates[sourceLayer][*featureID] = {};
+ }
+ } else {
+ deletedStates[sourceLayer] = {};
+ }
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/source_state.hpp b/src/mbgl/renderer/source_state.hpp
new file mode 100644
index 0000000000..7217302630
--- /dev/null
+++ b/src/mbgl/renderer/source_state.hpp
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/util/feature.hpp>
+
+namespace mbgl {
+
+class RenderTile;
+
+class SourceFeatureState {
+public:
+ SourceFeatureState() = default;
+ ~SourceFeatureState() = default;
+
+ void updateState(const optional<std::string>& sourceLayerID, const std::string& featureID,
+ const FeatureState& newState);
+ void getState(FeatureState& result, const optional<std::string>& sourceLayerID, const std::string& featureID) const;
+ void removeState(const optional<std::string>& sourceLayerID, const optional<std::string>& featureID,
+ const optional<std::string>& stateKey);
+
+ void coalesceChanges(std::vector<RenderTile>& tiles);
+
+private:
+ LayerFeatureStates currentStates;
+ LayerFeatureStates stateChanges;
+ LayerFeatureStates deletedStates;
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/sources/render_tile_source.cpp b/src/mbgl/renderer/sources/render_tile_source.cpp
index c5afb38435..221f976c50 100644
--- a/src/mbgl/renderer/sources/render_tile_source.cpp
+++ b/src/mbgl/renderer/sources/render_tile_source.cpp
@@ -68,6 +68,7 @@ void RenderTileSource::prepare(const SourcePrepareParameters& parameters) {
tiles->emplace_back(entry.first, entry.second);
tiles->back().prepare(parameters);
}
+ featureState.coalesceChanges(*tiles);
renderTiles = std::move(tiles);
}
@@ -126,13 +127,29 @@ RenderTileSource::queryRenderedFeatures(const ScreenLineString& geometry,
const std::unordered_map<std::string, const RenderLayer*>& layers,
const RenderedQueryOptions& options,
const mat4& projMatrix) const {
- return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options, projMatrix);
+ return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options, projMatrix, featureState);
}
std::vector<Feature> RenderTileSource::querySourceFeatures(const SourceQueryOptions& options) const {
return tilePyramid.querySourceFeatures(options);
}
+void RenderTileSource::setFeatureState(const optional<std::string>& sourceLayerID, const std::string& featureID,
+ const FeatureState& state) {
+ featureState.updateState(sourceLayerID, featureID, state);
+}
+
+void RenderTileSource::getFeatureState(FeatureState& state, const optional<std::string>& sourceLayerID,
+ const std::string& featureID) const {
+ featureState.getState(state, sourceLayerID, featureID);
+}
+
+void RenderTileSource::removeFeatureState(const optional<std::string>& sourceLayerID,
+ const optional<std::string>& featureID,
+ const optional<std::string>& stateKey) {
+ featureState.removeState(sourceLayerID, featureID, stateKey);
+}
+
void RenderTileSource::reduceMemoryUse() {
tilePyramid.reduceMemoryUse();
}
diff --git a/src/mbgl/renderer/sources/render_tile_source.hpp b/src/mbgl/renderer/sources/render_tile_source.hpp
index 7edff726d5..7756bd8ed0 100644
--- a/src/mbgl/renderer/sources/render_tile_source.hpp
+++ b/src/mbgl/renderer/sources/render_tile_source.hpp
@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/renderer/render_source.hpp>
+#include <mbgl/renderer/source_state.hpp>
#include <mbgl/renderer/tile_pyramid.hpp>
#include <mbgl/style/sources/vector_source_impl.hpp>
@@ -34,6 +35,13 @@ public:
std::vector<Feature>
querySourceFeatures(const SourceQueryOptions&) const override;
+ void setFeatureState(const optional<std::string>&, const std::string&, const FeatureState&) override;
+
+ void getFeatureState(FeatureState& state, const optional<std::string>&, const std::string&) const override;
+
+ void removeFeatureState(const optional<std::string>&, const optional<std::string>&,
+ const optional<std::string>&) override;
+
void reduceMemoryUse() override;
void dumpDebugLogs() const override;
@@ -43,7 +51,10 @@ protected:
Immutable<std::vector<RenderTile>> renderTiles;
mutable RenderTiles filteredRenderTiles;
mutable RenderTiles renderTilesSortedByY;
- float bearing = 0.0f;
+
+private:
+ float bearing = 0.0F;
+ SourceFeatureState featureState;
};
/**
diff --git a/src/mbgl/renderer/tile_pyramid.cpp b/src/mbgl/renderer/tile_pyramid.cpp
index 7f0fad1500..2bf6e2e1a9 100644
--- a/src/mbgl/renderer/tile_pyramid.cpp
+++ b/src/mbgl/renderer/tile_pyramid.cpp
@@ -278,12 +278,10 @@ void TilePyramid::handleWrapJump(float lng) {
}
}
-
-std::unordered_map<std::string, std::vector<Feature>> TilePyramid::queryRenderedFeatures(const ScreenLineString& geometry,
- const TransformState& transformState,
- const std::unordered_map<std::string, const RenderLayer*>& layers,
- const RenderedQueryOptions& options,
- const mat4& projMatrix) const {
+std::unordered_map<std::string, std::vector<Feature>> TilePyramid::queryRenderedFeatures(
+ const ScreenLineString& geometry, const TransformState& transformState,
+ const std::unordered_map<std::string, const RenderLayer*>& layers, const RenderedQueryOptions& options,
+ const mat4& projMatrix, const SourceFeatureState& featureState) const {
std::unordered_map<std::string, std::vector<Feature>> result;
if (renderedTiles.empty() || geometry.empty()) {
return result;
@@ -331,12 +329,8 @@ std::unordered_map<std::string, std::vector<Feature>> TilePyramid::queryRendered
tileSpaceQueryGeometry.push_back(TileCoordinate::toGeometryCoordinate(id, c));
}
- tile.queryRenderedFeatures(result,
- tileSpaceQueryGeometry,
- transformState,
- layers,
- options,
- projMatrix);
+ tile.queryRenderedFeatures(result, tileSpaceQueryGeometry, transformState, layers, options, projMatrix,
+ featureState);
}
return result;
diff --git a/src/mbgl/renderer/tile_pyramid.hpp b/src/mbgl/renderer/tile_pyramid.hpp
index f80eb0db78..3b5cab5d6c 100644
--- a/src/mbgl/renderer/tile_pyramid.hpp
+++ b/src/mbgl/renderer/tile_pyramid.hpp
@@ -49,12 +49,10 @@ public:
void handleWrapJump(float lng);
- std::unordered_map<std::string, std::vector<Feature>>
- queryRenderedFeatures(const ScreenLineString& geometry,
- const TransformState& transformState,
- const std::unordered_map<std::string, const RenderLayer*>&,
- const RenderedQueryOptions& options,
- const mat4& projMatrix) const;
+ std::unordered_map<std::string, std::vector<Feature>> queryRenderedFeatures(
+ const ScreenLineString& geometry, const TransformState& transformState,
+ const std::unordered_map<std::string, const RenderLayer*>&, const RenderedQueryOptions& options,
+ const mat4& projMatrix, const mbgl::SourceFeatureState& featureState) const;
std::vector<Feature> querySourceFeatures(const SourceQueryOptions&) const;