summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAsheem Mamoowala <asheem.mamoowala@mapbox.com>2018-11-12 14:58:13 -0800
committerAsheem Mamoowala <asheem.mamoowala@mapbox.com>2018-11-12 14:58:13 -0800
commitf2bc00267cd6430f85763beeb03b98109ff7b023 (patch)
treec589e1f6cc0759d5806af3b01a5c4d3773232deb
parent9f3cc7b7075b29595dec394733b10fbd26f274e4 (diff)
downloadqtlocation-mapboxgl-upstream/feature-state-changesets.tar.gz
Prototype ChangeSets based approach to feature state.upstream/feature-state-changesets
- A change set keeps track of all feature state changes for a source between two render. - The change set is applied to the TilePyramid to update the full feature state map, and generate the map of update features for the single frame. The Front end renderer may throttle updates. This results in some changesets not making it to the renderer, and data in that set being dropped entirely. To workaround this the front end renderers would need to accumulate the changes, or some other way to collect all change sets between throttled frames.
-rw-r--r--include/mbgl/style/sources/geojson_source.hpp5
-rw-r--r--include/mbgl/util/feature_state.hpp19
-rw-r--r--platform/glfw/glfw_view.cpp31
-rw-r--r--platform/glfw/glfw_view.hpp1
-rw-r--r--platform/glfw/main.cpp2
-rw-r--r--src/mbgl/map/map.cpp1
-rw-r--r--src/mbgl/renderer/render_source.hpp2
-rw-r--r--src/mbgl/renderer/renderer_impl.cpp22
-rw-r--r--src/mbgl/renderer/sources/render_geojson_source.cpp46
-rw-r--r--src/mbgl/renderer/sources/render_geojson_source.hpp7
-rw-r--r--src/mbgl/renderer/tile_pyramid.cpp22
-rw-r--r--src/mbgl/renderer/tile_pyramid.hpp2
-rw-r--r--src/mbgl/renderer/update_parameters.hpp3
-rw-r--r--src/mbgl/style/sources/geojson_source.cpp17
-rw-r--r--src/mbgl/style/style_impl.cpp16
-rw-r--r--src/mbgl/style/style_impl.hpp4
16 files changed, 175 insertions, 25 deletions
diff --git a/include/mbgl/style/sources/geojson_source.hpp b/include/mbgl/style/sources/geojson_source.hpp
index a03b910279..803588ac7e 100644
--- a/include/mbgl/style/sources/geojson_source.hpp
+++ b/include/mbgl/style/sources/geojson_source.hpp
@@ -2,8 +2,10 @@
#include <mbgl/style/source.hpp>
#include <mbgl/util/geojson.hpp>
+#include <mbgl/util/feature_state.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/util/constants.hpp>
+#include <mbgl/util/immutable.hpp>
namespace mbgl {
@@ -33,6 +35,7 @@ public:
void setURL(const std::string& url);
void setGeoJSON(const GeoJSON&);
+ void setFeatureState(const FeatureIdentifier&, const std::string&, const mbgl::Value&);
optional<std::string> getURL() const;
@@ -41,9 +44,11 @@ public:
void loadDescription(FileSource&) final;
+ Immutable<std::vector<FeatureStateChange>> collectFeatureStates();
private:
optional<std::string> url;
std::unique_ptr<AsyncRequest> req;
+ Mutable<std::vector<FeatureStateChange>> stateChanges;
};
template <>
diff --git a/include/mbgl/util/feature_state.hpp b/include/mbgl/util/feature_state.hpp
index e97926c6e1..f63f3dcbff 100644
--- a/include/mbgl/util/feature_state.hpp
+++ b/include/mbgl/util/feature_state.hpp
@@ -15,17 +15,32 @@ struct FeatureStateChange {
};
ChangeType type;
+ std::string sourceLayer;
FeatureIdentifier id;
std::string key;
optional<Value> value;
FeatureStateChange(ChangeType type_,
- FeatureIdentifier&& id_,
- std::string&& key_,
+ const std::string& sourceLayer_,
+ const FeatureIdentifier& id_,
+ const std::string& key_,
optional<Value> value_) :
type(type_),
+ sourceLayer(sourceLayer_),
id(std::move(id_)),
key(std::move(key_)),
value(std::move(value_)) {}
+
+ FeatureStateChange(ChangeType type_,
+ const FeatureIdentifier& id_,
+ const std::string& key_,
+ optional<Value> value_) :
+ type(type_),
+ id(std::move(id_)),
+ key(std::move(key_)),
+ value(std::move(value_)) {}
+
};
+using FeatureStateChangeSet = std::vector<FeatureStateChange>;
+
} // namespace mbgl
diff --git a/platform/glfw/glfw_view.cpp b/platform/glfw/glfw_view.cpp
index 9179113139..522a0c6f61 100644
--- a/platform/glfw/glfw_view.cpp
+++ b/platform/glfw/glfw_view.cpp
@@ -15,6 +15,7 @@
#include <mbgl/renderer/renderer.hpp>
#include <mbgl/renderer/backend_scope.hpp>
#include <mbgl/map/camera.hpp>
+#include <mbgl/style/sources/geojson_source.hpp>
#include <mapbox/cheap_ruler.hpp>
#include <mapbox/geometry.hpp>
@@ -518,6 +519,35 @@ void GLFWView::onMouseMove(GLFWwindow *window, double x, double y) {
}
view->lastX = x;
view->lastY = y;
+
+ if (view->tracking || view->rotating || view->pitching) return;
+
+ mbgl::ScreenCoordinate screenCoordinate = { x, y };
+
+ std::vector<mbgl::Feature> features = view->rendererFrontend->getRenderer()->queryRenderedFeatures(screenCoordinate,{ });
+
+ if (features.empty() && !view->hoveredId) return;
+ auto pointsSource = view->map->getStyle().getSource("points");
+ if (pointsSource && pointsSource->is<mbgl::style::GeoJSONSource>()) {
+ auto gj = pointsSource->as<mbgl::style::GeoJSONSource>();
+
+ if (features.size() >= 1 && features[0].id) {
+ const auto& fId = features[0].id;
+
+ if (view->hoveredId != fId) {
+ if (view->hoveredId) {
+ gj->setFeatureState(*(view->hoveredId), "hover", false);
+ }
+ gj->setFeatureState(*(features[0].id), "hover", true);
+ view->hoveredId = features[0].id;
+ view->invalidate();
+ }
+ } else if (view->hoveredId) {
+ gj->setFeatureState(*(view->hoveredId), "hover", false);
+ view->hoveredId = mbgl::nullopt;
+ view->invalidate();
+ }
+ }
}
void GLFWView::run() {
@@ -539,7 +569,6 @@ void GLFWView::run() {
updateAnimatedAnnotations();
activate();
-
rendererFrontend->render();
glfwSwapBuffers(window);
diff --git a/platform/glfw/glfw_view.hpp b/platform/glfw/glfw_view.hpp
index d5acf697f7..9a784660e3 100644
--- a/platform/glfw/glfw_view.hpp
+++ b/platform/glfw/glfw_view.hpp
@@ -125,6 +125,7 @@ private:
mbgl::util::RunLoop runLoop;
mbgl::util::Timer frameTick;
+ mbgl::optional<mbgl::FeatureIdentifier> hoveredId;
GLFWwindow *window = nullptr;
bool dirty = false;
diff --git a/platform/glfw/main.cpp b/platform/glfw/main.cpp
index 1bb2e13614..a0320d4052 100644
--- a/platform/glfw/main.cpp
+++ b/platform/glfw/main.cpp
@@ -107,7 +107,7 @@ int main(int argc, char *argv[]) {
fileSource.setAccessToken(std::string(token));
}
- mbgl::ThreadPool threadPool(4);
+ mbgl::ThreadPool threadPool(1);
GLFWRendererFrontend rendererFrontend { std::make_unique<mbgl::Renderer>(backend, view->getPixelRatio(), fileSource, threadPool), backend };
mbgl::Map map(rendererFrontend, backend, view->getSize(), view->getPixelRatio(), fileSource, threadPool);
diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp
index 9d886cb74c..273ed1bd75 100644
--- a/src/mbgl/map/map.cpp
+++ b/src/mbgl/map/map.cpp
@@ -787,6 +787,7 @@ void Map::Impl::onUpdate() {
style->impl->getImageImpls(),
style->impl->getSourceImpls(),
style->impl->getLayerImpls(),
+ style->impl->getFeatureStateChangeSets(),
annotationManager,
prefetchZoomDelta,
bool(stillImageRequest),
diff --git a/src/mbgl/renderer/render_source.hpp b/src/mbgl/renderer/render_source.hpp
index cffb482147..0445f88a17 100644
--- a/src/mbgl/renderer/render_source.hpp
+++ b/src/mbgl/renderer/render_source.hpp
@@ -50,7 +50,7 @@ public:
virtual void update(Immutable<style::Source::Impl>,
const std::vector<Immutable<style::Layer::Impl>>&,
- const FeatureStatesMap&,
+ Immutable<FeatureStateChangeSet>,
bool,
bool,
const TileParameters&) {}
diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp
index dc53f20110..4f9b6b248b 100644
--- a/src/mbgl/renderer/renderer_impl.cpp
+++ b/src/mbgl/renderer/renderer_impl.cpp
@@ -243,12 +243,22 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
filteredLayers.push_back(layer);
}
- //TODO: AHM: Send feature states
- renderSources.at(source->id)->update(source,
- filteredLayers,
- needsRendering,
- needsRelayout,
- tileParameters);
+ const auto changeSet = updateParameters.stateChanges->find(source->id);
+ if (changeSet != updateParameters.stateChanges->end()) {
+ renderSources.at(source->id)->update(source,
+ filteredLayers,
+ changeSet->second,
+ needsRendering,
+ needsRelayout,
+ tileParameters);
+ }
+ else {
+ renderSources.at(source->id)->update(source,
+ filteredLayers,
+ needsRendering,
+ needsRelayout,
+ tileParameters);
+ }
}
transformState = updateParameters.transformState;
diff --git a/src/mbgl/renderer/sources/render_geojson_source.cpp b/src/mbgl/renderer/sources/render_geojson_source.cpp
index 0e265efff4..bfbfe8d76d 100644
--- a/src/mbgl/renderer/sources/render_geojson_source.cpp
+++ b/src/mbgl/renderer/sources/render_geojson_source.cpp
@@ -26,6 +26,7 @@ bool RenderGeoJSONSource::isLoaded() const {
void RenderGeoJSONSource::update(Immutable<style::Source::Impl> baseImpl_,
const std::vector<Immutable<Layer::Impl>>& layers,
+ Immutable<FeatureStateChangeSet> statesChangeSet,
const bool needsRendering,
const bool needsRelayout,
const TileParameters& parameters) {
@@ -56,6 +57,7 @@ void RenderGeoJSONSource::update(Immutable<style::Source::Impl> baseImpl_,
}
tilePyramid.update(layers,
+ *statesChangeSet,
needsRendering,
needsRelayout,
parameters,
@@ -68,6 +70,50 @@ void RenderGeoJSONSource::update(Immutable<style::Source::Impl> baseImpl_,
});
}
+void RenderGeoJSONSource::update(Immutable<style::Source::Impl> baseImpl_,
+ const std::vector<Immutable<Layer::Impl>>& layers,
+ const bool needsRendering,
+ const bool needsRelayout,
+ const TileParameters& parameters) {
+ std::swap(baseImpl, baseImpl_);
+
+ enabled = needsRendering;
+
+ GeoJSONData* data_ = impl().getData();
+
+ if (data_ != data) {
+ data = data_;
+ tilePyramid.cache.clear();
+
+ if (data) {
+ const uint8_t maxZ = impl().getZoomRange().max;
+ for (const auto& pair : tilePyramid.tiles) {
+ if (pair.first.canonical.z <= maxZ) {
+ static_cast<GeoJSONTile*>(pair.second.get())->updateData(data->getTile(pair.first.canonical));
+ }
+ }
+ }
+ }
+
+ if (!data) {
+ tilePyramid.tiles.clear();
+ tilePyramid.renderTiles.clear();
+ return;
+ }
+
+ tilePyramid.update(layers,
+ {},
+ needsRendering,
+ needsRelayout,
+ parameters,
+ SourceType::GeoJSON,
+ util::tileSize,
+ impl().getZoomRange(),
+ optional<LatLngBounds>{},
+ [&] (const OverscaledTileID& tileID) {
+ return std::make_unique<GeoJSONTile>(tileID, impl().id, parameters, data->getTile(tileID.canonical));
+ });
+}
void RenderGeoJSONSource::startRender(PaintParameters& parameters) {
parameters.clipIDGenerator.update(tilePyramid.getRenderTiles());
tilePyramid.startRender(parameters);
diff --git a/src/mbgl/renderer/sources/render_geojson_source.hpp b/src/mbgl/renderer/sources/render_geojson_source.hpp
index 297fa09a29..ecba7298c1 100644
--- a/src/mbgl/renderer/sources/render_geojson_source.hpp
+++ b/src/mbgl/renderer/sources/render_geojson_source.hpp
@@ -18,6 +18,13 @@ public:
void update(Immutable<style::Source::Impl>,
const std::vector<Immutable<style::Layer::Impl>>&,
+ Immutable<FeatureStateChangeSet>,
+ bool needsRendering,
+ bool needsRelayout,
+ const TileParameters&) final;
+
+ void update(Immutable<style::Source::Impl>,
+ const std::vector<Immutable<style::Layer::Impl>>&,
bool needsRendering,
bool needsRelayout,
const TileParameters&) final;
diff --git a/src/mbgl/renderer/tile_pyramid.cpp b/src/mbgl/renderer/tile_pyramid.cpp
index b23adbec6e..a00617b321 100644
--- a/src/mbgl/renderer/tile_pyramid.cpp
+++ b/src/mbgl/renderer/tile_pyramid.cpp
@@ -71,7 +71,7 @@ void TilePyramid::update(const std::vector<Immutable<style::Layer::Impl>>& layer
const Range<uint8_t> zoomRange,
optional<LatLngBounds> bounds,
std::function<std::unique_ptr<Tile> (const OverscaledTileID&)> createTile) {
- FeatureStatesMap fsm;
+ FeatureStateChangeSet fsm;
update(layers,fsm, needsRendering, needsRelayout, parameters, type, tileSize, zoomRange, bounds, createTile);
}
@@ -87,7 +87,7 @@ void extend(PropertyMap& a, const PropertyMap& b) {
}
void TilePyramid::update(const std::vector<Immutable<style::Layer::Impl>>& layers,
- const FeatureStatesMap& newStates,
+ const FeatureStateChangeSet& statesChangeSet,
const bool needsRendering,
const bool needsRelayout,
const TileParameters& parameters,
@@ -151,19 +151,17 @@ void TilePyramid::update(const std::vector<Immutable<style::Layer::Impl>>& layer
idealTiles = util::tileCover(parameters.transformState, idealZoom);
}
+ FeatureStatesMap newStates = {};
//Coalesce changes to the feature state before applying to tiles.
std::shared_ptr<FeatureStatesMap> changedStates = std::make_shared<FeatureStatesMap>();
- for( const auto& sourceLayer: newStates) {
- auto& existing = (*featureStates)[sourceLayer.first];
- auto& changed = sourceLayer.second;
- FeatureStates newChanges;
- //for each feature id in this sourceLayer, get and merge the PropertyMap from newStates
- for (const auto& id: changed) {
- auto& e = existing[id.first];
- extend(e, id.second);
- newChanges[id.first] = e;
+// printf("TPU: %lu statechanges\n", statesChangeSet.size());
+ for( const auto& stateChange: statesChangeSet) {
+ auto& existing = (*featureStates)[stateChange.sourceLayer];
+ if (stateChange.type == FeatureStateChange::ChangeType::Insert) {
+
+ (existing[stateChange.id])[stateChange.key] = *(stateChange.value);
}
- changedStates->emplace(sourceLayer.first, newChanges);
+ (*changedStates)[stateChange.sourceLayer][stateChange.id] = existing[stateChange.id];
}
// Stores a list of all the tiles that we're definitely going to retain. There are two
diff --git a/src/mbgl/renderer/tile_pyramid.hpp b/src/mbgl/renderer/tile_pyramid.hpp
index c238e9f1bc..9f676b9ee8 100644
--- a/src/mbgl/renderer/tile_pyramid.hpp
+++ b/src/mbgl/renderer/tile_pyramid.hpp
@@ -44,7 +44,7 @@ public:
std::function<std::unique_ptr<Tile> (const OverscaledTileID&)> createTile);
void update(const std::vector<Immutable<style::Layer::Impl>>&,
- const FeatureStatesMap& newStates,
+ const FeatureStateChangeSet&,
bool needsRendering,
bool needsRelayout,
const TileParameters&,
diff --git a/src/mbgl/renderer/update_parameters.hpp b/src/mbgl/renderer/update_parameters.hpp
index a668c64f48..78dafd48e4 100644
--- a/src/mbgl/renderer/update_parameters.hpp
+++ b/src/mbgl/renderer/update_parameters.hpp
@@ -8,8 +8,10 @@
#include <mbgl/style/layer.hpp>
#include <mbgl/util/chrono.hpp>
#include <mbgl/util/immutable.hpp>
+#include <mbgl/util/feature_state.hpp>
#include <vector>
+#include <map>
namespace mbgl {
@@ -31,6 +33,7 @@ public:
const Immutable<std::vector<Immutable<style::Image::Impl>>> images;
const Immutable<std::vector<Immutable<style::Source::Impl>>> sources;
const Immutable<std::vector<Immutable<style::Layer::Impl>>> layers;
+ const Immutable<std::unordered_map<std::string, Immutable<std::vector<FeatureStateChange>>>> stateChanges;
AnnotationManager& annotationManager;
diff --git a/src/mbgl/style/sources/geojson_source.cpp b/src/mbgl/style/sources/geojson_source.cpp
index 4e3478322d..b626855d57 100644
--- a/src/mbgl/style/sources/geojson_source.cpp
+++ b/src/mbgl/style/sources/geojson_source.cpp
@@ -10,7 +10,8 @@ namespace mbgl {
namespace style {
GeoJSONSource::GeoJSONSource(const std::string& id, const GeoJSONOptions& options)
- : Source(makeMutable<Impl>(std::move(id), options)) {
+ : Source(makeMutable<Impl>(std::move(id), options)),
+ stateChanges(makeMutable<std::vector<FeatureStateChange>>()) {
}
GeoJSONSource::~GeoJSONSource() = default;
@@ -36,6 +37,20 @@ void GeoJSONSource::setGeoJSON(const mapbox::geojson::geojson& geoJSON) {
observer->onSourceChanged(*this);
}
+void GeoJSONSource::setFeatureState(const FeatureIdentifier& featureId, const std::string& key, const mbgl::Value& value) {
+ if ( featureId.valid() && !key.empty()) {
+ stateChanges->emplace_back(FeatureStateChange::ChangeType::Insert, featureId, key, value);
+// observer->onSourceChanged(*this);
+ }
+}
+
+Immutable<std::vector<FeatureStateChange>> GeoJSONSource::collectFeatureStates() {
+ Immutable<std::vector<FeatureStateChange>> immutable(std::move(stateChanges));
+ stateChanges = makeMutable<std::vector<FeatureStateChange>>();
+ printf("!)!)! Collecting feature state!@$!@$\n");
+ return immutable;
+}
+
optional<std::string> GeoJSONSource::getURL() const {
return url;
}
diff --git a/src/mbgl/style/style_impl.cpp b/src/mbgl/style/style_impl.cpp
index 5c9edc789f..236aa4d3aa 100644
--- a/src/mbgl/style/style_impl.cpp
+++ b/src/mbgl/style/style_impl.cpp
@@ -21,6 +21,8 @@
#include <mbgl/storage/file_source.hpp>
#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/response.hpp>
+#include <mbgl/util/feature_state.hpp>
+#include <mbgl/style/sources/geojson_source.hpp>
namespace mbgl {
namespace style {
@@ -357,5 +359,19 @@ Immutable<std::vector<Immutable<Layer::Impl>>> Style::Impl::getLayerImpls() cons
return layers.getImpls();
}
+Immutable<std::unordered_map<std::string, Immutable<std::vector<FeatureStateChange>>>> Style::Impl::getFeatureStateChangeSets() {
+ auto sources_ = getSources();
+ Mutable<std::unordered_map<std::string, Immutable<std::vector<FeatureStateChange>>>>
+ collectedStates(makeMutable<std::unordered_map<std::string, Immutable<std::vector<FeatureStateChange>>>>());
+
+ for (auto src: sources_) {
+ if (src->is<GeoJSONSource>()) {
+ GeoJSONSource * gjSrc = src->as<GeoJSONSource>();
+ collectedStates->insert({gjSrc->getID(), gjSrc->collectFeatureStates()});
+ }
+ }
+ return std::move(collectedStates);
+}
+
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/style_impl.hpp b/src/mbgl/style/style_impl.hpp
index 3dc222bfad..d34a69ea92 100644
--- a/src/mbgl/style/style_impl.hpp
+++ b/src/mbgl/style/style_impl.hpp
@@ -17,6 +17,7 @@
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/util/geo.hpp>
+#include <mbgl/util/feature_state.hpp>
#include <memory>
#include <string>
@@ -88,6 +89,9 @@ public:
Immutable<std::vector<Immutable<Image::Impl>>> getImageImpls() const;
Immutable<std::vector<Immutable<Source::Impl>>> getSourceImpls() const;
Immutable<std::vector<Immutable<Layer::Impl>>> getLayerImpls() const;
+ Immutable<std::unordered_map<std::string,
+ Immutable<std::vector<FeatureStateChange>>>>
+ getFeatureStateChangeSets();
void dumpDebugLogs() const;