summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2017-04-20 17:11:50 -0700
committerJohn Firebaugh <john.firebaugh@gmail.com>2017-05-02 08:45:09 -0700
commit3f0c89d633a5056006557ad5f4b9e446807d00ee (patch)
tree5405c50dd26a5a393a982e8e0f76b764dbbccf48
parent197751bace6181f2c2dbe4c890f277a0dc7e58b1 (diff)
downloadqtlocation-mapboxgl-3f0c89d633a5056006557ad5f4b9e446807d00ee.tar.gz
[core] Refactor Source::*Impls into RenderSources and TilePyramid
-rw-r--r--cmake/core-files.cmake15
-rw-r--r--include/mbgl/style/source.hpp1
-rw-r--r--include/mbgl/style/sources/geojson_source.hpp19
-rw-r--r--platform/default/mbgl/storage/offline_download.cpp4
-rw-r--r--src/mbgl/annotation/annotation_source.cpp11
-rw-r--r--src/mbgl/annotation/annotation_source.hpp8
-rw-r--r--src/mbgl/annotation/render_annotation_source.cpp79
-rw-r--r--src/mbgl/annotation/render_annotation_source.hpp53
-rw-r--r--src/mbgl/map/map.cpp7
-rw-r--r--src/mbgl/renderer/painter.cpp8
-rw-r--r--src/mbgl/renderer/painter.hpp1
-rw-r--r--src/mbgl/renderer/render_item.hpp4
-rw-r--r--src/mbgl/renderer/render_source.cpp26
-rw-r--r--src/mbgl/renderer/render_source.hpp87
-rw-r--r--src/mbgl/renderer/render_source_observer.hpp18
-rw-r--r--src/mbgl/renderer/sources/render_geojson_source.cpp95
-rw-r--r--src/mbgl/renderer/sources/render_geojson_source.hpp59
-rw-r--r--src/mbgl/renderer/sources/render_raster_source.cpp87
-rw-r--r--src/mbgl/renderer/sources/render_raster_source.hpp55
-rw-r--r--src/mbgl/renderer/sources/render_vector_source.cpp91
-rw-r--r--src/mbgl/renderer/sources/render_vector_source.hpp55
-rw-r--r--src/mbgl/renderer/tile_pyramid.cpp263
-rw-r--r--src/mbgl/renderer/tile_pyramid.hpp87
-rw-r--r--src/mbgl/style/source.cpp4
-rw-r--r--src/mbgl/style/source_impl.cpp281
-rw-r--r--src/mbgl/style/source_impl.hpp96
-rw-r--r--src/mbgl/style/source_observer.hpp8
-rw-r--r--src/mbgl/style/sources/geojson_source.cpp2
-rw-r--r--src/mbgl/style/sources/geojson_source_impl.cpp89
-rw-r--r--src/mbgl/style/sources/geojson_source_impl.hpp21
-rw-r--r--src/mbgl/style/sources/raster_source_impl.cpp7
-rw-r--r--src/mbgl/style/sources/raster_source_impl.hpp3
-rw-r--r--src/mbgl/style/sources/vector_source_impl.cpp8
-rw-r--r--src/mbgl/style/sources/vector_source_impl.hpp3
-rw-r--r--src/mbgl/style/style.cpp127
-rw-r--r--src/mbgl/style/style.hpp11
-rw-r--r--src/mbgl/style/tile_source_impl.cpp25
-rw-r--r--src/mbgl/style/tile_source_impl.hpp4
-rw-r--r--src/mbgl/tile/geojson_tile.cpp8
-rw-r--r--src/mbgl/tile/geojson_tile.hpp5
-rw-r--r--test/src/mbgl/test/stub_render_source_observer.hpp23
-rw-r--r--test/src/mbgl/test/stub_style_observer.hpp11
-rw-r--r--test/style/source.test.cpp226
-rw-r--r--test/tile/geojson_tile.test.cpp16
44 files changed, 1401 insertions, 710 deletions
diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake
index d5f7ee0cc2..3594b55be6 100644
--- a/cmake/core-files.cmake
+++ b/cmake/core-files.cmake
@@ -28,6 +28,8 @@ set(MBGL_CORE_FILES
src/mbgl/annotation/fill_annotation_impl.hpp
src/mbgl/annotation/line_annotation_impl.cpp
src/mbgl/annotation/line_annotation_impl.hpp
+ src/mbgl/annotation/render_annotation_source.cpp
+ src/mbgl/annotation/render_annotation_source.hpp
src/mbgl/annotation/shape_annotation_impl.cpp
src/mbgl/annotation/shape_annotation_impl.hpp
src/mbgl/annotation/style_sourced_annotation_impl.cpp
@@ -208,10 +210,23 @@ set(MBGL_CORE_FILES
src/mbgl/renderer/render_raster_layer.hpp
src/mbgl/renderer/render_symbol_layer.cpp
src/mbgl/renderer/render_symbol_layer.hpp
+ src/mbgl/renderer/render_source.cpp
+ src/mbgl/renderer/render_source.hpp
+ src/mbgl/renderer/render_source_observer.hpp
src/mbgl/renderer/render_tile.cpp
src/mbgl/renderer/render_tile.hpp
src/mbgl/renderer/symbol_bucket.cpp
src/mbgl/renderer/symbol_bucket.hpp
+ src/mbgl/renderer/tile_pyramid.cpp
+ src/mbgl/renderer/tile_pyramid.hpp
+
+ # renderer/sources
+ src/mbgl/renderer/sources/render_geojson_source.cpp
+ src/mbgl/renderer/sources/render_geojson_source.hpp
+ src/mbgl/renderer/sources/render_raster_source.cpp
+ src/mbgl/renderer/sources/render_raster_source.hpp
+ src/mbgl/renderer/sources/render_vector_source.cpp
+ src/mbgl/renderer/sources/render_vector_source.hpp
# shaders
src/mbgl/shaders/circle.cpp
diff --git a/include/mbgl/style/source.hpp b/include/mbgl/style/source.hpp
index e49f1fc273..66fc2afd25 100644
--- a/include/mbgl/style/source.hpp
+++ b/include/mbgl/style/source.hpp
@@ -56,7 +56,6 @@ public:
std::unique_ptr<Source> copy(const std::string& id) const;
optional<std::string> getAttribution() const;
- optional<Range<uint8_t>> getZoomRange() const;
// Private implementation
class Impl;
diff --git a/include/mbgl/style/sources/geojson_source.hpp b/include/mbgl/style/sources/geojson_source.hpp
index ede0301725..5b39d7821b 100644
--- a/include/mbgl/style/sources/geojson_source.hpp
+++ b/include/mbgl/style/sources/geojson_source.hpp
@@ -4,26 +4,9 @@
#include <mbgl/util/geojson.hpp>
#include <mbgl/util/optional.hpp>
-#include <mapbox/geojson.hpp>
-
-namespace mapbox {
-
-namespace geojsonvt {
-class GeoJSONVT;
-} // namespace geojsonvt
-
-namespace supercluster {
-class Supercluster;
-} // namespace supercluster
-
-} // namespace mapbox
-
namespace mbgl {
namespace style {
-using GeoJSONVTPointer = std::unique_ptr<mapbox::geojsonvt::GeoJSONVT>;
-using SuperclusterPointer = std::unique_ptr<mapbox::supercluster::Supercluster>;
-
struct GeoJSONOptions {
// GeoJSON-VT options
uint8_t maxzoom = 18;
@@ -38,7 +21,7 @@ struct GeoJSONOptions {
class GeoJSONSource : public Source {
public:
- GeoJSONSource(const std::string& id, const GeoJSONOptions options_ = GeoJSONOptions());
+ GeoJSONSource(const std::string& id, const GeoJSONOptions& = {});
void setURL(const std::string& url);
void setGeoJSON(const GeoJSON&);
diff --git a/platform/default/mbgl/storage/offline_download.cpp b/platform/default/mbgl/storage/offline_download.cpp
index c8aa98d874..cba2f70df8 100644
--- a/platform/default/mbgl/storage/offline_download.cpp
+++ b/platform/default/mbgl/storage/offline_download.cpp
@@ -98,9 +98,7 @@ OfflineRegionStatus OfflineDownload::getStatus() const {
}
case SourceType::GeoJSON: {
- style::GeoJSONSource::Impl* geojsonSource =
- static_cast<style::GeoJSONSource::Impl*>(source->baseImpl.get());
-
+ style::GeoJSONSource* geojsonSource = source->as<style::GeoJSONSource>();
if (geojsonSource->getURL()) {
result.requiredResourceCount += 1;
}
diff --git a/src/mbgl/annotation/annotation_source.cpp b/src/mbgl/annotation/annotation_source.cpp
index c52836c500..9956140179 100644
--- a/src/mbgl/annotation/annotation_source.cpp
+++ b/src/mbgl/annotation/annotation_source.cpp
@@ -1,6 +1,6 @@
#include <mbgl/annotation/annotation_source.hpp>
#include <mbgl/annotation/annotation_manager.hpp>
-#include <mbgl/annotation/annotation_tile.hpp>
+#include <mbgl/annotation/render_annotation_source.hpp>
namespace mbgl {
@@ -14,17 +14,12 @@ AnnotationSource::Impl::Impl(Source& base_)
: Source::Impl(SourceType::Annotations, AnnotationManager::SourceID, base_) {
}
-optional<Range<uint8_t>> AnnotationSource::Impl::getZoomRange() const {
- return { { 0, 22 } };
-}
-
void AnnotationSource::Impl::loadDescription(FileSource&) {
loaded = true;
}
-std::unique_ptr<Tile> AnnotationSource::Impl::createTile(const OverscaledTileID& tileID,
- const style::UpdateParameters& parameters) {
- return std::make_unique<AnnotationTile>(tileID, parameters);
+std::unique_ptr<RenderSource> AnnotationSource::Impl::createRenderSource() const {
+ return std::make_unique<RenderAnnotationSource>(*this);
}
} // namespace mbgl
diff --git a/src/mbgl/annotation/annotation_source.hpp b/src/mbgl/annotation/annotation_source.hpp
index 07e00dc52d..46c9564443 100644
--- a/src/mbgl/annotation/annotation_source.hpp
+++ b/src/mbgl/annotation/annotation_source.hpp
@@ -17,13 +17,7 @@ public:
Impl(Source&);
void loadDescription(FileSource&) final;
-
- optional<Range<uint8_t>> getZoomRange() const final;
-
-private:
- uint16_t getTileSize() const final { return util::tileSize; }
-
- std::unique_ptr<Tile> createTile(const OverscaledTileID&, const style::UpdateParameters&) final;
+ std::unique_ptr<RenderSource> createRenderSource() const final;
};
} // namespace mbgl
diff --git a/src/mbgl/annotation/render_annotation_source.cpp b/src/mbgl/annotation/render_annotation_source.cpp
new file mode 100644
index 0000000000..f926b6ce9a
--- /dev/null
+++ b/src/mbgl/annotation/render_annotation_source.cpp
@@ -0,0 +1,79 @@
+#include <mbgl/annotation/render_annotation_source.hpp>
+#include <mbgl/annotation/annotation_tile.hpp>
+#include <mbgl/renderer/render_tile.hpp>
+
+#include <mbgl/algorithm/generate_clip_ids.hpp>
+#include <mbgl/algorithm/generate_clip_ids_impl.hpp>
+
+namespace mbgl {
+
+using namespace style;
+
+RenderAnnotationSource::RenderAnnotationSource(const AnnotationSource::Impl& impl_)
+ : RenderSource(impl_) {
+ tilePyramid.setObserver(this);
+}
+
+bool RenderAnnotationSource::isLoaded() const {
+ return tilePyramid.isLoaded();
+}
+
+void RenderAnnotationSource::invalidateTiles() {
+ tilePyramid.invalidateTiles();
+}
+
+void RenderAnnotationSource::startRender(algorithm::ClipIDGenerator& generator, const mat4& projMatrix, const mat4& clipMatrix, const TransformState& transform) {
+ generator.update(tilePyramid.getRenderTiles());
+ tilePyramid.startRender(projMatrix, clipMatrix, transform);
+}
+
+void RenderAnnotationSource::finishRender(Painter& painter) {
+ tilePyramid.finishRender(painter);
+}
+
+std::map<UnwrappedTileID, RenderTile>& RenderAnnotationSource::getRenderTiles() {
+ return tilePyramid.getRenderTiles();
+}
+
+void RenderAnnotationSource::updateTiles(const UpdateParameters& parameters) {
+ tilePyramid.updateTiles(parameters,
+ SourceType::Annotations,
+ util::tileSize,
+ { 0, 22 },
+ [&] (const OverscaledTileID& tileID) {
+ return std::make_unique<AnnotationTile>(tileID, parameters);
+ });
+}
+
+void RenderAnnotationSource::removeTiles() {
+ tilePyramid.removeTiles();
+}
+
+void RenderAnnotationSource::reloadTiles() {
+ tilePyramid.reloadTiles();
+}
+
+std::unordered_map<std::string, std::vector<Feature>>
+RenderAnnotationSource::queryRenderedFeatures(const ScreenLineString& geometry,
+ const TransformState& transformState,
+ const RenderedQueryOptions& options) const {
+ return tilePyramid.queryRenderedFeatures(geometry, transformState, options);
+}
+
+std::vector<Feature> RenderAnnotationSource::querySourceFeatures(const SourceQueryOptions&) const {
+ return {};
+}
+
+void RenderAnnotationSource::setCacheSize(size_t size) {
+ tilePyramid.setCacheSize(size);
+}
+
+void RenderAnnotationSource::onLowMemory() {
+ tilePyramid.onLowMemory();
+}
+
+void RenderAnnotationSource::dumpDebugLogs() const {
+ tilePyramid.dumpDebugLogs();
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/annotation/render_annotation_source.hpp b/src/mbgl/annotation/render_annotation_source.hpp
new file mode 100644
index 0000000000..394acc5108
--- /dev/null
+++ b/src/mbgl/annotation/render_annotation_source.hpp
@@ -0,0 +1,53 @@
+#pragma once
+
+#include <mbgl/renderer/render_source.hpp>
+#include <mbgl/renderer/tile_pyramid.hpp>
+#include <mbgl/annotation/annotation_source.hpp>
+
+namespace mbgl {
+
+class RenderAnnotationSource : public RenderSource {
+public:
+ RenderAnnotationSource(const AnnotationSource::Impl&);
+
+ bool isLoaded() const final;
+
+ // Called when the camera has changed. May load new tiles, unload obsolete tiles, or
+ // trigger re-placement of existing complete tiles.
+ void updateTiles(const style::UpdateParameters&) final;
+
+ // Removes all tiles (by putting them into the cache).
+ void removeTiles() final;
+
+ // Remove all tiles and clear the cache.
+ void invalidateTiles() final;
+
+ // Request that all loaded tiles re-run the layout operation on the existing source
+ // data with fresh style information.
+ void reloadTiles() final;
+
+ void startRender(algorithm::ClipIDGenerator&,
+ const mat4& projMatrix,
+ const mat4& clipMatrix,
+ const TransformState&) final;
+ void finishRender(Painter&) final;
+
+ std::map<UnwrappedTileID, RenderTile>& getRenderTiles() final;
+
+ std::unordered_map<std::string, std::vector<Feature>>
+ queryRenderedFeatures(const ScreenLineString& geometry,
+ const TransformState& transformState,
+ const RenderedQueryOptions& options) const final;
+
+ std::vector<Feature>
+ querySourceFeatures(const SourceQueryOptions&) const final;
+
+ void setCacheSize(size_t) final;
+ void onLowMemory() final;
+ void dumpDebugLogs() const final;
+
+private:
+ TilePyramid tilePyramid;
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp
index 696dca1872..a1f3bdbbde 100644
--- a/src/mbgl/map/map.cpp
+++ b/src/mbgl/map/map.cpp
@@ -7,13 +7,14 @@
#include <mbgl/map/transform_state.hpp>
#include <mbgl/annotation/annotation_manager.hpp>
#include <mbgl/style/style.hpp>
-#include <mbgl/style/source_impl.hpp>
+#include <mbgl/style/source.hpp>
#include <mbgl/style/layer.hpp>
#include <mbgl/style/light.hpp>
#include <mbgl/style/observer.hpp>
#include <mbgl/style/transition_options.hpp>
#include <mbgl/style/update_parameters.hpp>
#include <mbgl/renderer/painter.hpp>
+#include <mbgl/renderer/render_source.hpp>
#include <mbgl/storage/file_source.hpp>
#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/response.hpp>
@@ -871,10 +872,10 @@ std::vector<Feature> Map::queryRenderedFeatures(const ScreenBox& box, const Rend
std::vector<Feature> Map::querySourceFeatures(const std::string& sourceID, const SourceQueryOptions& options) {
if (!impl->style) return {};
- const style::Source* source = impl->style->getSource(sourceID);
+ const RenderSource* source = impl->style->getRenderSource(sourceID);
if (!source) return {};
- return source->baseImpl->querySourceFeatures(options);
+ return source->querySourceFeatures(options);
}
AnnotationIDs Map::queryPointAnnotations(const ScreenBox& box) {
diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp
index 36dd4a793f..01df326d95 100644
--- a/src/mbgl/renderer/painter.cpp
+++ b/src/mbgl/renderer/painter.cpp
@@ -1,6 +1,7 @@
#include <mbgl/renderer/painter.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/render_tile.hpp>
+#include <mbgl/renderer/render_source.hpp>
#include <mbgl/style/source.hpp>
#include <mbgl/style/source_impl.hpp>
@@ -13,6 +14,7 @@
#include <mbgl/style/style.hpp>
#include <mbgl/style/layer_impl.hpp>
+#include <mbgl/tile/tile.hpp>
#include <mbgl/renderer/render_background_layer.hpp>
#include <mbgl/renderer/render_custom_layer.hpp>
#include <mbgl/style/layers/custom_layer_impl.hpp>
@@ -148,7 +150,7 @@ void Painter::render(const Style& style, const FrameData& frame_, View& view, Sp
RenderData renderData = style.getRenderData(frame.debugOptions, state.getAngle());
const std::vector<RenderItem>& order = renderData.order;
- const std::unordered_set<Source*>& sources = renderData.sources;
+ const std::unordered_set<RenderSource*>& sources = renderData.sources;
// Update the default matrices to the current viewport dimensions.
state.getProjMatrix(projMatrix);
@@ -209,7 +211,7 @@ void Painter::render(const Style& style, const FrameData& frame_, View& view, Sp
// Update all clipping IDs.
algorithm::ClipIDGenerator generator;
for (const auto& source : sources) {
- source->baseImpl->startRender(generator, projMatrix, nearClippedProjMatrix, state);
+ source->startRender(generator, projMatrix, nearClippedProjMatrix, state);
}
MBGL_DEBUG_GROUP(context, "clipping masks");
@@ -258,7 +260,7 @@ void Painter::render(const Style& style, const FrameData& frame_, View& view, Sp
// When only rendering layers via the stylesheet, it's possible that we don't
// ever visit a tile during rendering.
for (const auto& source : sources) {
- source->baseImpl->finishRender(*this);
+ source->finishRender(*this);
}
}
diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp
index 7706d2d451..c7c8173d0d 100644
--- a/src/mbgl/renderer/painter.hpp
+++ b/src/mbgl/renderer/painter.hpp
@@ -54,6 +54,7 @@ class RenderBackgroundLayer;
class Programs;
class PaintParameters;
+class TilePyramid;
struct ClipID;
diff --git a/src/mbgl/renderer/render_item.hpp b/src/mbgl/renderer/render_item.hpp
index 01bb263d1e..787211c30a 100644
--- a/src/mbgl/renderer/render_item.hpp
+++ b/src/mbgl/renderer/render_item.hpp
@@ -8,11 +8,11 @@
namespace mbgl {
class RenderLayer;
+class RenderSource;
class RenderTile;
class Bucket;
namespace style {
-class Source;
} // namespace style
class RenderItem {
@@ -29,7 +29,7 @@ public:
class RenderData {
public:
Color backgroundColor;
- std::unordered_set<style::Source*> sources;
+ std::unordered_set<RenderSource*> sources;
std::vector<RenderItem> order;
};
diff --git a/src/mbgl/renderer/render_source.cpp b/src/mbgl/renderer/render_source.cpp
new file mode 100644
index 0000000000..643d92fe81
--- /dev/null
+++ b/src/mbgl/renderer/render_source.cpp
@@ -0,0 +1,26 @@
+#include <mbgl/renderer/render_source.hpp>
+#include <mbgl/renderer/render_source_observer.hpp>
+#include <mbgl/tile/tile.hpp>
+
+namespace mbgl {
+
+static RenderSourceObserver nullObserver;
+
+RenderSource::RenderSource(const style::Source::Impl& impl)
+ : baseImpl(impl),
+ observer(&nullObserver) {
+}
+
+void RenderSource::setObserver(RenderSourceObserver* observer_) {
+ observer = observer_;
+}
+
+void RenderSource::onTileChanged(Tile& tile) {
+ observer->onTileChanged(*this, tile.id);
+}
+
+void RenderSource::onTileError(Tile& tile, std::exception_ptr error) {
+ observer->onTileError(*this, tile.id, error);
+}
+
+}
diff --git a/src/mbgl/renderer/render_source.hpp b/src/mbgl/renderer/render_source.hpp
new file mode 100644
index 0000000000..5d93ae49d6
--- /dev/null
+++ b/src/mbgl/renderer/render_source.hpp
@@ -0,0 +1,87 @@
+#pragma once
+
+#include <mbgl/tile/tile_id.hpp>
+#include <mbgl/tile/tile_observer.hpp>
+#include <mbgl/util/mat4.hpp>
+#include <mbgl/util/geo.hpp>
+#include <mbgl/util/feature.hpp>
+#include <mbgl/style/source_impl.hpp>
+
+#include <unordered_map>
+#include <vector>
+#include <map>
+#include <memory>
+
+namespace mbgl {
+
+class Painter;
+class TransformState;
+class RenderTile;
+class RenderedQueryOptions;
+class SourceQueryOptions;
+class Tile;
+class RenderSourceObserver;
+
+namespace algorithm {
+class ClipIDGenerator;
+} // namespace algorithm
+
+namespace style {
+class UpdateParameters;
+} // namespace style
+
+class RenderSource : protected TileObserver {
+public:
+ RenderSource(const style::Source::Impl&);
+ virtual ~RenderSource() = default;
+
+ virtual bool isLoaded() const = 0;
+
+ // Called when the camera has changed. May load new tiles, unload obsolete tiles, or
+ // trigger re-placement of existing complete tiles.
+ virtual void updateTiles(const style::UpdateParameters&) = 0;
+
+ // Removes all tiles (by putting them into the cache).
+ virtual void removeTiles() = 0;
+
+ // Remove all tiles and clear the cache.
+ virtual void invalidateTiles() = 0;
+
+ // Request that all loaded tiles re-run the layout operation on the existing source
+ // data with fresh style information.
+ virtual void reloadTiles() = 0;
+
+ virtual void startRender(algorithm::ClipIDGenerator&,
+ const mat4& projMatrix,
+ const mat4& clipMatrix,
+ const TransformState&) = 0;
+ virtual void finishRender(Painter&) = 0;
+
+ virtual std::map<UnwrappedTileID, RenderTile>& getRenderTiles() = 0;
+
+ virtual std::unordered_map<std::string, std::vector<Feature>>
+ queryRenderedFeatures(const ScreenLineString& geometry,
+ const TransformState& transformState,
+ const RenderedQueryOptions& options) const = 0;
+
+ virtual std::vector<Feature>
+ querySourceFeatures(const SourceQueryOptions&) const = 0;
+
+ virtual void setCacheSize(size_t) = 0;
+ virtual void onLowMemory() = 0;
+
+ virtual void dumpDebugLogs() const = 0;
+
+ void setObserver(RenderSourceObserver*);
+
+ const style::Source::Impl& baseImpl;
+ bool enabled = false;
+
+protected:
+ RenderSourceObserver* observer;
+
+ void onTileChanged(Tile&) final;
+ void onTileError(Tile&, std::exception_ptr) final;
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/render_source_observer.hpp b/src/mbgl/renderer/render_source_observer.hpp
new file mode 100644
index 0000000000..792a18db2b
--- /dev/null
+++ b/src/mbgl/renderer/render_source_observer.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <exception>
+
+namespace mbgl {
+
+class RenderSource;
+class OverscaledTileID;
+
+class RenderSourceObserver {
+public:
+ virtual ~RenderSourceObserver() = default;
+
+ virtual void onTileChanged(RenderSource&, const OverscaledTileID&) {}
+ virtual void onTileError(RenderSource&, const OverscaledTileID&, std::exception_ptr) {}
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/sources/render_geojson_source.cpp b/src/mbgl/renderer/sources/render_geojson_source.cpp
new file mode 100644
index 0000000000..7e36b44ea4
--- /dev/null
+++ b/src/mbgl/renderer/sources/render_geojson_source.cpp
@@ -0,0 +1,95 @@
+#include <mbgl/renderer/sources/render_geojson_source.hpp>
+#include <mbgl/renderer/render_tile.hpp>
+#include <mbgl/tile/geojson_tile.hpp>
+
+#include <mbgl/algorithm/generate_clip_ids.hpp>
+#include <mbgl/algorithm/generate_clip_ids_impl.hpp>
+
+namespace mbgl {
+
+using namespace style;
+
+RenderGeoJSONSource::RenderGeoJSONSource(const style::GeoJSONSource::Impl& impl_)
+ : RenderSource(impl_),
+ impl(impl_) {
+ tilePyramid.setObserver(this);
+}
+
+bool RenderGeoJSONSource::isLoaded() const {
+ return tilePyramid.isLoaded();
+}
+
+void RenderGeoJSONSource::invalidateTiles() {
+ tilePyramid.invalidateTiles();
+}
+
+void RenderGeoJSONSource::startRender(algorithm::ClipIDGenerator& generator, const mat4& projMatrix, const mat4& clipMatrix, const TransformState& transform) {
+ generator.update(tilePyramid.getRenderTiles());
+ tilePyramid.startRender(projMatrix, clipMatrix, transform);
+}
+
+void RenderGeoJSONSource::finishRender(Painter& painter) {
+ tilePyramid.finishRender(painter);
+}
+
+std::map<UnwrappedTileID, RenderTile>& RenderGeoJSONSource::getRenderTiles() {
+ return tilePyramid.getRenderTiles();
+}
+
+void RenderGeoJSONSource::updateTiles(const UpdateParameters& parameters) {
+ GeoJSONData* data_ = impl.getData();
+
+ if (!data_) {
+ return;
+ }
+
+ if (data_ != data) {
+ data = data_;
+ tilePyramid.cache.clear();
+
+ for (auto const& item : tilePyramid.tiles) {
+ static_cast<GeoJSONTile*>(item.second.get())->updateData(data->getTile(item.first.canonical));
+ }
+ }
+
+ tilePyramid.updateTiles(parameters,
+ SourceType::GeoJSON,
+ util::tileSize,
+ impl.getZoomRange(),
+ [&] (const OverscaledTileID& tileID) {
+ return std::make_unique<GeoJSONTile>(tileID, impl.id, parameters, data->getTile(tileID.canonical));
+ });
+}
+
+void RenderGeoJSONSource::removeTiles() {
+ tilePyramid.removeTiles();
+}
+
+void RenderGeoJSONSource::reloadTiles() {
+ tilePyramid.reloadTiles();
+}
+
+std::unordered_map<std::string, std::vector<Feature>>
+RenderGeoJSONSource::queryRenderedFeatures(const ScreenLineString& geometry,
+ const TransformState& transformState,
+ const RenderedQueryOptions& options) const {
+ return tilePyramid.queryRenderedFeatures(geometry, transformState, options);
+}
+
+std::vector<Feature> RenderGeoJSONSource::querySourceFeatures(const SourceQueryOptions& options) const {
+ return tilePyramid.querySourceFeatures(options);
+}
+
+void RenderGeoJSONSource::setCacheSize(size_t size) {
+ tilePyramid.setCacheSize(size);
+}
+
+void RenderGeoJSONSource::onLowMemory() {
+ tilePyramid.onLowMemory();
+}
+
+void RenderGeoJSONSource::dumpDebugLogs() const {
+ tilePyramid.dumpDebugLogs();
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/sources/render_geojson_source.hpp b/src/mbgl/renderer/sources/render_geojson_source.hpp
new file mode 100644
index 0000000000..3476b63afd
--- /dev/null
+++ b/src/mbgl/renderer/sources/render_geojson_source.hpp
@@ -0,0 +1,59 @@
+#pragma once
+
+#include <mbgl/renderer/render_source.hpp>
+#include <mbgl/renderer/tile_pyramid.hpp>
+#include <mbgl/style/sources/geojson_source_impl.hpp>
+
+namespace mbgl {
+
+namespace style {
+class GeoJSONData;
+} // namespace style
+
+class RenderGeoJSONSource : public RenderSource {
+public:
+ RenderGeoJSONSource(const style::GeoJSONSource::Impl&);
+
+ bool isLoaded() const final;
+
+ // Called when the camera has changed. May load new tiles, unload obsolete tiles, or
+ // trigger re-placement of existing complete tiles.
+ void updateTiles(const style::UpdateParameters&) final;
+
+ // Removes all tiles (by putting them into the cache).
+ void removeTiles() final;
+
+ // Remove all tiles and clear the cache.
+ void invalidateTiles() final;
+
+ // Request that all loaded tiles re-run the layout operation on the existing source
+ // data with fresh style information.
+ void reloadTiles() final;
+
+ void startRender(algorithm::ClipIDGenerator&,
+ const mat4& projMatrix,
+ const mat4& clipMatrix,
+ const TransformState&) final;
+ void finishRender(Painter&) final;
+
+ std::map<UnwrappedTileID, RenderTile>& getRenderTiles() final;
+
+ std::unordered_map<std::string, std::vector<Feature>>
+ queryRenderedFeatures(const ScreenLineString& geometry,
+ const TransformState& transformState,
+ const RenderedQueryOptions& options) const final;
+
+ std::vector<Feature>
+ querySourceFeatures(const SourceQueryOptions&) const final;
+
+ void setCacheSize(size_t) final;
+ void onLowMemory() final;
+ void dumpDebugLogs() const final;
+
+private:
+ const style::GeoJSONSource::Impl& impl;
+ TilePyramid tilePyramid;
+ style::GeoJSONData* data;
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/sources/render_raster_source.cpp b/src/mbgl/renderer/sources/render_raster_source.cpp
new file mode 100644
index 0000000000..75a2189053
--- /dev/null
+++ b/src/mbgl/renderer/sources/render_raster_source.cpp
@@ -0,0 +1,87 @@
+#include <mbgl/renderer/sources/render_raster_source.hpp>
+#include <mbgl/renderer/render_tile.hpp>
+#include <mbgl/tile/raster_tile.hpp>
+
+namespace mbgl {
+
+using namespace style;
+
+RenderRasterSource::RenderRasterSource(const style::RasterSource::Impl& impl_)
+ : RenderSource(impl_),
+ impl(impl_) {
+ tilePyramid.setObserver(this);
+}
+
+bool RenderRasterSource::isLoaded() const {
+ return tilePyramid.isLoaded();
+}
+
+void RenderRasterSource::invalidateTiles() {
+ tilePyramid.invalidateTiles();
+}
+
+void RenderRasterSource::startRender(algorithm::ClipIDGenerator&, const mat4& projMatrix, const mat4& clipMatrix, const TransformState& transform) {
+ tilePyramid.startRender(projMatrix, clipMatrix, transform);
+}
+
+void RenderRasterSource::finishRender(Painter& painter) {
+ tilePyramid.finishRender(painter);
+}
+
+std::map<UnwrappedTileID, RenderTile>& RenderRasterSource::getRenderTiles() {
+ return tilePyramid.getRenderTiles();
+}
+
+void RenderRasterSource::updateTiles(const UpdateParameters& parameters) {
+ optional<Tileset> tileset = impl.getTileset();
+
+ if (!tileset) {
+ return;
+ }
+
+ if (tileURLTemplates != tileset->tiles) {
+ tileURLTemplates = tileset->tiles;
+ tilePyramid.invalidateTiles();
+ }
+
+ tilePyramid.updateTiles(parameters,
+ SourceType::Raster,
+ impl.getTileSize(),
+ tileset->zoomRange,
+ [&] (const OverscaledTileID& tileID) {
+ return std::make_unique<RasterTile>(tileID, parameters, *tileset);
+ });
+}
+
+void RenderRasterSource::removeTiles() {
+ tilePyramid.removeTiles();
+}
+
+void RenderRasterSource::reloadTiles() {
+ tilePyramid.reloadTiles();
+}
+
+std::unordered_map<std::string, std::vector<Feature>>
+RenderRasterSource::queryRenderedFeatures(const ScreenLineString&,
+ const TransformState&,
+ const RenderedQueryOptions&) const {
+ return {};
+}
+
+std::vector<Feature> RenderRasterSource::querySourceFeatures(const SourceQueryOptions&) const {
+ return {};
+}
+
+void RenderRasterSource::setCacheSize(size_t size) {
+ tilePyramid.setCacheSize(size);
+}
+
+void RenderRasterSource::onLowMemory() {
+ tilePyramid.onLowMemory();
+}
+
+void RenderRasterSource::dumpDebugLogs() const {
+ tilePyramid.dumpDebugLogs();
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/sources/render_raster_source.hpp b/src/mbgl/renderer/sources/render_raster_source.hpp
new file mode 100644
index 0000000000..6b95be363f
--- /dev/null
+++ b/src/mbgl/renderer/sources/render_raster_source.hpp
@@ -0,0 +1,55 @@
+#pragma once
+
+#include <mbgl/renderer/render_source.hpp>
+#include <mbgl/renderer/tile_pyramid.hpp>
+#include <mbgl/style/sources/raster_source_impl.hpp>
+
+namespace mbgl {
+
+class RenderRasterSource : public RenderSource {
+public:
+ RenderRasterSource(const style::RasterSource::Impl&);
+
+ bool isLoaded() const final;
+
+ // Called when the camera has changed. May load new tiles, unload obsolete tiles, or
+ // trigger re-placement of existing complete tiles.
+ void updateTiles(const style::UpdateParameters&) final;
+
+ // Removes all tiles (by putting them into the cache).
+ void removeTiles() final;
+
+ // Remove all tiles and clear the cache.
+ void invalidateTiles() final;
+
+ // Request that all loaded tiles re-run the layout operation on the existing source
+ // data with fresh style information.
+ void reloadTiles() final;
+
+ void startRender(algorithm::ClipIDGenerator&,
+ const mat4& projMatrix,
+ const mat4& clipMatrix,
+ const TransformState&) final;
+ void finishRender(Painter&) final;
+
+ std::map<UnwrappedTileID, RenderTile>& getRenderTiles() final;
+
+ std::unordered_map<std::string, std::vector<Feature>>
+ queryRenderedFeatures(const ScreenLineString& geometry,
+ const TransformState& transformState,
+ const RenderedQueryOptions& options) const final;
+
+ std::vector<Feature>
+ querySourceFeatures(const SourceQueryOptions&) const final;
+
+ void setCacheSize(size_t) final;
+ void onLowMemory() final;
+ void dumpDebugLogs() const final;
+
+private:
+ const style::RasterSource::Impl& impl;
+ TilePyramid tilePyramid;
+ optional<std::vector<std::string>> tileURLTemplates;
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/sources/render_vector_source.cpp b/src/mbgl/renderer/sources/render_vector_source.cpp
new file mode 100644
index 0000000000..3d7e09fd2a
--- /dev/null
+++ b/src/mbgl/renderer/sources/render_vector_source.cpp
@@ -0,0 +1,91 @@
+#include <mbgl/renderer/sources/render_vector_source.hpp>
+#include <mbgl/renderer/render_tile.hpp>
+#include <mbgl/tile/vector_tile.hpp>
+
+#include <mbgl/algorithm/generate_clip_ids.hpp>
+#include <mbgl/algorithm/generate_clip_ids_impl.hpp>
+
+namespace mbgl {
+
+using namespace style;
+
+RenderVectorSource::RenderVectorSource(const style::VectorSource::Impl& impl_)
+ : RenderSource(impl_),
+ impl(impl_) {
+ tilePyramid.setObserver(this);
+}
+
+bool RenderVectorSource::isLoaded() const {
+ return tilePyramid.isLoaded();
+}
+
+void RenderVectorSource::invalidateTiles() {
+ tilePyramid.invalidateTiles();
+}
+
+void RenderVectorSource::startRender(algorithm::ClipIDGenerator& generator, const mat4& projMatrix, const mat4& clipMatrix, const TransformState& transform) {
+ generator.update(tilePyramid.getRenderTiles());
+ tilePyramid.startRender(projMatrix, clipMatrix, transform);
+}
+
+void RenderVectorSource::finishRender(Painter& painter) {
+ tilePyramid.finishRender(painter);
+}
+
+std::map<UnwrappedTileID, RenderTile>& RenderVectorSource::getRenderTiles() {
+ return tilePyramid.getRenderTiles();
+}
+
+void RenderVectorSource::updateTiles(const UpdateParameters& parameters) {
+ optional<Tileset> tileset = impl.getTileset();
+
+ if (!tileset) {
+ return;
+ }
+
+ if (tileURLTemplates != tileset->tiles) {
+ tileURLTemplates = tileset->tiles;
+ tilePyramid.invalidateTiles();
+ }
+
+ tilePyramid.updateTiles(parameters,
+ SourceType::Vector,
+ util::tileSize,
+ tileset->zoomRange,
+ [&] (const OverscaledTileID& tileID) {
+ return std::make_unique<VectorTile>(tileID, impl.id, parameters, *tileset);
+ });
+}
+
+void RenderVectorSource::removeTiles() {
+ tilePyramid.removeTiles();
+}
+
+void RenderVectorSource::reloadTiles() {
+ tilePyramid.reloadTiles();
+}
+
+std::unordered_map<std::string, std::vector<Feature>>
+RenderVectorSource::queryRenderedFeatures(const ScreenLineString& geometry,
+ const TransformState& transformState,
+ const RenderedQueryOptions& options) const {
+ return tilePyramid.queryRenderedFeatures(geometry, transformState, options);
+}
+
+std::vector<Feature> RenderVectorSource::querySourceFeatures(const SourceQueryOptions& options) const {
+ return tilePyramid.querySourceFeatures(options);
+}
+
+void RenderVectorSource::setCacheSize(size_t size) {
+ tilePyramid.setCacheSize(size);
+}
+
+void RenderVectorSource::onLowMemory() {
+ tilePyramid.onLowMemory();
+}
+
+void RenderVectorSource::dumpDebugLogs() const {
+ tilePyramid.dumpDebugLogs();
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/sources/render_vector_source.hpp b/src/mbgl/renderer/sources/render_vector_source.hpp
new file mode 100644
index 0000000000..0f40c14cf5
--- /dev/null
+++ b/src/mbgl/renderer/sources/render_vector_source.hpp
@@ -0,0 +1,55 @@
+#pragma once
+
+#include <mbgl/renderer/render_source.hpp>
+#include <mbgl/renderer/tile_pyramid.hpp>
+#include <mbgl/style/sources/vector_source_impl.hpp>
+
+namespace mbgl {
+
+class RenderVectorSource : public RenderSource {
+public:
+ RenderVectorSource(const style::VectorSource::Impl&);
+
+ bool isLoaded() const final;
+
+ // Called when the camera has changed. May load new tiles, unload obsolete tiles, or
+ // trigger re-placement of existing complete tiles.
+ void updateTiles(const style::UpdateParameters&) final;
+
+ // Removes all tiles (by putting them into the cache).
+ void removeTiles() final;
+
+ // Remove all tiles and clear the cache.
+ void invalidateTiles() final;
+
+ // Request that all loaded tiles re-run the layout operation on the existing source
+ // data with fresh style information.
+ void reloadTiles() final;
+
+ void startRender(algorithm::ClipIDGenerator&,
+ const mat4& projMatrix,
+ const mat4& clipMatrix,
+ const TransformState&) final;
+ void finishRender(Painter&) final;
+
+ std::map<UnwrappedTileID, RenderTile>& getRenderTiles() final;
+
+ std::unordered_map<std::string, std::vector<Feature>>
+ queryRenderedFeatures(const ScreenLineString& geometry,
+ const TransformState& transformState,
+ const RenderedQueryOptions& options) const final;
+
+ std::vector<Feature>
+ querySourceFeatures(const SourceQueryOptions&) const final;
+
+ void setCacheSize(size_t) final;
+ void onLowMemory() final;
+ void dumpDebugLogs() const final;
+
+private:
+ const style::VectorSource::Impl& impl;
+ TilePyramid tilePyramid;
+ optional<std::vector<std::string>> tileURLTemplates;
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/tile_pyramid.cpp b/src/mbgl/renderer/tile_pyramid.cpp
new file mode 100644
index 0000000000..130b9dc5b6
--- /dev/null
+++ b/src/mbgl/renderer/tile_pyramid.cpp
@@ -0,0 +1,263 @@
+#include <mbgl/renderer/tile_pyramid.hpp>
+#include <mbgl/renderer/render_tile.hpp>
+#include <mbgl/renderer/painter.hpp>
+#include <mbgl/renderer/render_source.hpp>
+#include <mbgl/style/update_parameters.hpp>
+#include <mbgl/map/transform.hpp>
+#include <mbgl/map/query.hpp>
+#include <mbgl/text/placement_config.hpp>
+#include <mbgl/math/clamp.hpp>
+#include <mbgl/util/tile_cover.hpp>
+#include <mbgl/util/enum.hpp>
+#include <mbgl/util/logging.hpp>
+
+#include <mbgl/algorithm/update_renderables.hpp>
+
+#include <mapbox/geometry/envelope.hpp>
+
+#include <algorithm>
+
+namespace mbgl {
+
+using namespace style;
+
+static TileObserver nullObserver;
+
+TilePyramid::TilePyramid()
+ : observer(&nullObserver) {
+}
+
+TilePyramid::~TilePyramid() = default;
+
+bool TilePyramid::isLoaded() const {
+ for (const auto& pair : tiles) {
+ if (!pair.second->isComplete()) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void TilePyramid::invalidateTiles() {
+ tiles.clear();
+ renderTiles.clear();
+ cache.clear();
+}
+
+void TilePyramid::startRender(const mat4& projMatrix,
+ const mat4& clipMatrix,
+ const TransformState& transform) {
+ for (auto& pair : renderTiles) {
+ auto& tile = pair.second;
+ tile.calculateMatrices(projMatrix, clipMatrix, transform);
+ }
+}
+
+void TilePyramid::finishRender(Painter& painter) {
+ for (auto& pair : renderTiles) {
+ auto& tile = pair.second;
+ if (tile.used) {
+ painter.renderTileDebug(tile);
+ }
+ }
+}
+
+std::map<UnwrappedTileID, RenderTile>& TilePyramid::getRenderTiles() {
+ return renderTiles;
+}
+
+void TilePyramid::updateTiles(const UpdateParameters& parameters,
+ const SourceType type,
+ const uint16_t tileSize,
+ const Range<uint8_t> zoomRange,
+ std::function<std::unique_ptr<Tile> (const OverscaledTileID&)> createTile) {
+ // Determine the overzooming/underzooming amounts and required tiles.
+ int32_t overscaledZoom = util::coveringZoomLevel(parameters.transformState.getZoom(), type, tileSize);
+ int32_t tileZoom = overscaledZoom;
+
+ std::vector<UnwrappedTileID> idealTiles;
+ if (overscaledZoom >= zoomRange.min) {
+ int32_t idealZoom = std::min<int32_t>(zoomRange.max, overscaledZoom);
+
+ // Make sure we're not reparsing overzoomed raster tiles.
+ if (type == SourceType::Raster) {
+ tileZoom = idealZoom;
+ }
+
+ idealTiles = util::tileCover(parameters.transformState, idealZoom);
+ }
+
+ // Stores a list of all the tiles that we're definitely going to retain. There are two
+ // kinds of tiles we need: the ideal tiles determined by the tile cover. They may not yet be in
+ // use because they're still loading. In addition to that, we also need to retain all tiles that
+ // we're actively using, e.g. as a replacement for tile that aren't loaded yet.
+ std::set<OverscaledTileID> retain;
+
+ auto retainTileFn = [&](Tile& tile, Resource::Necessity necessity) -> void {
+ retain.emplace(tile.id);
+ tile.setNecessity(necessity);
+ };
+ auto getTileFn = [&](const OverscaledTileID& tileID) -> Tile* {
+ auto it = tiles.find(tileID);
+ return it == tiles.end() ? nullptr : it->second.get();
+ };
+ auto createTileFn = [&](const OverscaledTileID& tileID) -> Tile* {
+ std::unique_ptr<Tile> tile = cache.get(tileID);
+ if (!tile) {
+ tile = createTile(tileID);
+ if (tile) {
+ tile->setObserver(observer);
+ }
+ }
+ if (!tile) {
+ return nullptr;
+ }
+ return tiles.emplace(tileID, std::move(tile)).first->second.get();
+ };
+ auto renderTileFn = [&](const UnwrappedTileID& tileID, Tile& tile) {
+ renderTiles.emplace(tileID, RenderTile{ tileID, tile });
+ };
+
+ renderTiles.clear();
+ algorithm::updateRenderables(getTileFn, createTileFn, retainTileFn, renderTileFn,
+ idealTiles, zoomRange, tileZoom);
+
+ if (type != SourceType::Annotations) {
+ size_t conservativeCacheSize =
+ std::max((float)parameters.transformState.getSize().width / tileSize, 1.0f) *
+ std::max((float)parameters.transformState.getSize().height / tileSize, 1.0f) *
+ (parameters.transformState.getMaxZoom() - parameters.transformState.getMinZoom() + 1) *
+ 0.5;
+ cache.setSize(conservativeCacheSize);
+ }
+
+ removeStaleTiles(retain);
+
+ const PlacementConfig config { parameters.transformState.getAngle(),
+ parameters.transformState.getPitch(),
+ parameters.debugOptions & MapDebugOptions::Collision };
+
+ for (auto& pair : tiles) {
+ pair.second->setPlacementConfig(config);
+ }
+}
+
+// Moves all tiles to the cache except for those specified in the retain set.
+void TilePyramid::removeStaleTiles(const std::set<OverscaledTileID>& retain) {
+ // Remove stale tiles. This goes through the (sorted!) tiles map and retain set in lockstep
+ // and removes items from tiles that don't have the corresponding key in the retain set.
+ auto tilesIt = tiles.begin();
+ auto retainIt = retain.begin();
+ while (tilesIt != tiles.end()) {
+ if (retainIt == retain.end() || tilesIt->first < *retainIt) {
+ tilesIt->second->setNecessity(Tile::Necessity::Optional);
+ cache.add(tilesIt->first, std::move(tilesIt->second));
+ tiles.erase(tilesIt++);
+ } else {
+ if (!(*retainIt < tilesIt->first)) {
+ ++tilesIt;
+ }
+ ++retainIt;
+ }
+ }
+}
+
+void TilePyramid::removeTiles() {
+ renderTiles.clear();
+ if (!tiles.empty()) {
+ removeStaleTiles({});
+ }
+}
+
+void TilePyramid::reloadTiles() {
+ cache.clear();
+
+ for (auto& pair : tiles) {
+ pair.second->redoLayout();
+ }
+}
+
+std::unordered_map<std::string, std::vector<Feature>> TilePyramid::queryRenderedFeatures(const ScreenLineString& geometry,
+ const TransformState& transformState,
+ const RenderedQueryOptions& options) const {
+ std::unordered_map<std::string, std::vector<Feature>> result;
+ if (renderTiles.empty() || geometry.empty()) {
+ return result;
+ }
+
+ LineString<double> queryGeometry;
+
+ for (const auto& p : geometry) {
+ queryGeometry.push_back(TileCoordinate::fromScreenCoordinate(
+ transformState, 0, { p.x, transformState.getSize().height - p.y }).p);
+ }
+
+ mapbox::geometry::box<double> box = mapbox::geometry::envelope(queryGeometry);
+
+
+ auto sortRenderTiles = [](const RenderTile& a, const RenderTile& b) {
+ return std::tie(a.id.canonical.z, a.id.canonical.y, a.id.wrap, a.id.canonical.x) <
+ std::tie(b.id.canonical.z, b.id.canonical.y, b.id.wrap, b.id.canonical.x);
+ };
+ std::vector<std::reference_wrapper<const RenderTile>> sortedTiles;
+ std::transform(renderTiles.cbegin(), renderTiles.cend(), std::back_inserter(sortedTiles),
+ [](const auto& pair) { return std::ref(pair.second); });
+ std::sort(sortedTiles.begin(), sortedTiles.end(), sortRenderTiles);
+
+ for (const auto& renderTileRef : sortedTiles) {
+ const RenderTile& renderTile = renderTileRef.get();
+ GeometryCoordinate tileSpaceBoundsMin = TileCoordinate::toGeometryCoordinate(renderTile.id, box.min);
+ if (tileSpaceBoundsMin.x >= util::EXTENT || tileSpaceBoundsMin.y >= util::EXTENT) {
+ continue;
+ }
+
+ GeometryCoordinate tileSpaceBoundsMax = TileCoordinate::toGeometryCoordinate(renderTile.id, box.max);
+ if (tileSpaceBoundsMax.x < 0 || tileSpaceBoundsMax.y < 0) {
+ continue;
+ }
+
+ GeometryCoordinates tileSpaceQueryGeometry;
+ tileSpaceQueryGeometry.reserve(queryGeometry.size());
+ for (const auto& c : queryGeometry) {
+ tileSpaceQueryGeometry.push_back(TileCoordinate::toGeometryCoordinate(renderTile.id, c));
+ }
+
+ renderTile.tile.queryRenderedFeatures(result,
+ tileSpaceQueryGeometry,
+ transformState,
+ options);
+ }
+
+ return result;
+}
+
+std::vector<Feature> TilePyramid::querySourceFeatures(const SourceQueryOptions& options) const {
+ std::vector<Feature> result;
+
+ for (const auto& pair : tiles) {
+ pair.second->querySourceFeatures(result, options);
+ }
+
+ return result;
+}
+
+void TilePyramid::setCacheSize(size_t size) {
+ cache.setSize(size);
+}
+
+void TilePyramid::onLowMemory() {
+ cache.clear();
+}
+
+void TilePyramid::setObserver(TileObserver* observer_) {
+ observer = observer_;
+}
+
+void TilePyramid::dumpDebugLogs() const {
+ for (const auto& pair : tiles) {
+ pair.second->dumpDebugLogs();
+ }
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/tile_pyramid.hpp b/src/mbgl/renderer/tile_pyramid.hpp
new file mode 100644
index 0000000000..a38a21dd88
--- /dev/null
+++ b/src/mbgl/renderer/tile_pyramid.hpp
@@ -0,0 +1,87 @@
+#pragma once
+
+#include <mbgl/tile/tile_id.hpp>
+#include <mbgl/tile/tile_observer.hpp>
+#include <mbgl/tile/tile.hpp>
+#include <mbgl/tile/tile_cache.hpp>
+#include <mbgl/style/types.hpp>
+
+#include <mbgl/util/mat4.hpp>
+#include <mbgl/util/feature.hpp>
+#include <mbgl/util/range.hpp>
+
+#include <memory>
+#include <unordered_map>
+#include <vector>
+#include <map>
+
+namespace mbgl {
+
+class Painter;
+class TransformState;
+class RenderTile;
+class RenderedQueryOptions;
+class SourceQueryOptions;
+
+namespace style {
+class UpdateParameters;
+} // namespace style
+
+class TilePyramid {
+public:
+ TilePyramid();
+ ~TilePyramid();
+
+ bool isLoaded() const;
+
+ // Called when the camera has changed. May load new tiles, unload obsolete tiles, or
+ // trigger re-placement of existing complete tiles.
+ void updateTiles(const style::UpdateParameters&,
+ SourceType type,
+ uint16_t tileSize,
+ Range<uint8_t> zoomRange,
+ std::function<std::unique_ptr<Tile> (const OverscaledTileID&)> createTile);
+
+ // Removes all tiles (by putting them into the cache).
+ void removeTiles();
+
+ // Remove all tiles and clear the cache.
+ void invalidateTiles();
+
+ // Request that all loaded tiles re-run the layout operation on the existing source
+ // data with fresh style information.
+ void reloadTiles();
+
+ void startRender(const mat4& projMatrix,
+ const mat4& clipMatrix,
+ const TransformState&);
+ void finishRender(Painter&);
+
+ std::map<UnwrappedTileID, RenderTile>& getRenderTiles();
+
+ std::unordered_map<std::string, std::vector<Feature>>
+ queryRenderedFeatures(const ScreenLineString& geometry,
+ const TransformState& transformState,
+ const RenderedQueryOptions& options) const;
+
+ std::vector<Feature> querySourceFeatures(const SourceQueryOptions&) const;
+
+ void setCacheSize(size_t);
+ void onLowMemory();
+
+ void setObserver(TileObserver*);
+ void dumpDebugLogs() const;
+
+ bool enabled = false;
+
+ void removeStaleTiles(const std::set<OverscaledTileID>&);
+
+ std::map<OverscaledTileID, std::unique_ptr<Tile>> tiles;
+ TileCache cache;
+
+ std::map<UnwrappedTileID, RenderTile> renderTiles;
+
+ TileObserver* observer = nullptr;
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/style/source.cpp b/src/mbgl/style/source.cpp
index 51863f8eba..cfb268006b 100644
--- a/src/mbgl/style/source.cpp
+++ b/src/mbgl/style/source.cpp
@@ -18,9 +18,5 @@ optional<std::string> Source::getAttribution() const {
return baseImpl->getAttribution();
}
-optional<Range<uint8_t>> Source::getZoomRange() const {
- return baseImpl->getZoomRange();
-}
-
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/source_impl.cpp b/src/mbgl/style/source_impl.cpp
index 19138bd781..8fdbd038de 100644
--- a/src/mbgl/style/source_impl.cpp
+++ b/src/mbgl/style/source_impl.cpp
@@ -1,23 +1,6 @@
#include <mbgl/style/source_impl.hpp>
#include <mbgl/style/source_observer.hpp>
-#include <mbgl/map/transform.hpp>
-#include <mbgl/renderer/render_tile.hpp>
-#include <mbgl/renderer/painter.hpp>
-#include <mbgl/style/update_parameters.hpp>
-#include <mbgl/text/placement_config.hpp>
#include <mbgl/util/logging.hpp>
-#include <mbgl/math/clamp.hpp>
-#include <mbgl/util/tile_cover.hpp>
-#include <mbgl/util/enum.hpp>
-#include <mbgl/map/query.hpp>
-
-#include <mbgl/algorithm/update_renderables.hpp>
-#include <mbgl/algorithm/generate_clip_ids.hpp>
-#include <mbgl/algorithm/generate_clip_ids_impl.hpp>
-
-#include <mapbox/geometry/envelope.hpp>
-
-#include <algorithm>
namespace mbgl {
namespace style {
@@ -31,271 +14,13 @@ Source::Impl::Impl(SourceType type_, std::string id_, Source& base_)
observer(&nullObserver) {
}
-Source::Impl::~Impl() = default;
-
-bool Source::Impl::isLoaded() const {
- if (!loaded) return false;
-
- for (const auto& pair : tiles) {
- if (!pair.second->isComplete()) {
- return false;
- }
- }
-
- return true;
-}
-
-void Source::Impl::detach() {
- invalidateTiles();
-}
-
-void Source::Impl::invalidateTiles() {
- tiles.clear();
- renderTiles.clear();
- cache.clear();
-}
-
-void Source::Impl::startRender(algorithm::ClipIDGenerator& generator,
- const mat4& projMatrix,
- const mat4& clipMatrix,
- const TransformState& transform) {
- if (type == SourceType::Vector ||
- type == SourceType::GeoJSON ||
- type == SourceType::Annotations) {
- generator.update(renderTiles);
- }
-
- for (auto& pair : renderTiles) {
- auto& tile = pair.second;
- tile.calculateMatrices(projMatrix, clipMatrix, transform);
- }
-}
-
-void Source::Impl::finishRender(Painter& painter) {
- for (auto& pair : renderTiles) {
- auto& tile = pair.second;
- if (tile.used) {
- painter.renderTileDebug(tile);
- }
- }
-}
-
-std::map<UnwrappedTileID, RenderTile>& Source::Impl::getRenderTiles() {
- return renderTiles;
-}
-
-void Source::Impl::updateTiles(const UpdateParameters& parameters) {
- if (!loaded) {
- return;
- }
-
- const uint16_t tileSize = getTileSize();
- const optional<Range<uint8_t>> zoomRange = getZoomRange();
-
- // Determine the overzooming/underzooming amounts and required tiles.
- int32_t overscaledZoom = util::coveringZoomLevel(parameters.transformState.getZoom(), type, tileSize);
- int32_t tileZoom = overscaledZoom;
-
- std::vector<UnwrappedTileID> idealTiles;
- if (overscaledZoom >= zoomRange->min) {
- int32_t idealZoom = std::min<int32_t>(zoomRange->max, overscaledZoom);
-
- // Make sure we're not reparsing overzoomed raster tiles.
- if (type == SourceType::Raster) {
- tileZoom = idealZoom;
- }
-
- idealTiles = util::tileCover(parameters.transformState, idealZoom);
- }
-
- // Stores a list of all the tiles that we're definitely going to retain. There are two
- // kinds of tiles we need: the ideal tiles determined by the tile cover. They may not yet be in
- // use because they're still loading. In addition to that, we also need to retain all tiles that
- // we're actively using, e.g. as a replacement for tile that aren't loaded yet.
- std::set<OverscaledTileID> retain;
-
- auto retainTileFn = [&retain](Tile& tile, Resource::Necessity necessity) -> void {
- retain.emplace(tile.id);
- tile.setNecessity(necessity);
- };
- auto getTileFn = [this](const OverscaledTileID& tileID) -> Tile* {
- auto it = tiles.find(tileID);
- return it == tiles.end() ? nullptr : it->second.get();
- };
- auto createTileFn = [this, &parameters](const OverscaledTileID& tileID) -> Tile* {
- std::unique_ptr<Tile> tile = cache.get(tileID);
- if (!tile) {
- tile = createTile(tileID, parameters);
- if (tile) {
- tile->setObserver(this);
- }
- }
- if (!tile) {
- return nullptr;
- }
- return tiles.emplace(tileID, std::move(tile)).first->second.get();
- };
- auto renderTileFn = [this](const UnwrappedTileID& tileID, Tile& tile) {
- renderTiles.emplace(tileID, RenderTile{ tileID, tile });
- };
-
- renderTiles.clear();
- algorithm::updateRenderables(getTileFn, createTileFn, retainTileFn, renderTileFn,
- idealTiles, *zoomRange, tileZoom);
-
- if (type != SourceType::Annotations) {
- size_t conservativeCacheSize =
- std::max((float)parameters.transformState.getSize().width / tileSize, 1.0f) *
- std::max((float)parameters.transformState.getSize().height / tileSize, 1.0f) *
- (parameters.transformState.getMaxZoom() - parameters.transformState.getMinZoom() + 1) *
- 0.5;
- cache.setSize(conservativeCacheSize);
- }
-
- removeStaleTiles(retain);
-
- const PlacementConfig config { parameters.transformState.getAngle(),
- parameters.transformState.getPitch(),
- parameters.debugOptions & MapDebugOptions::Collision };
-
- for (auto& pair : tiles) {
- pair.second->setPlacementConfig(config);
- }
-}
-
-// Moves all tiles to the cache except for those specified in the retain set.
-void Source::Impl::removeStaleTiles(const std::set<OverscaledTileID>& retain) {
- // Remove stale tiles. This goes through the (sorted!) tiles map and retain set in lockstep
- // and removes items from tiles that don't have the corresponding key in the retain set.
- auto tilesIt = tiles.begin();
- auto retainIt = retain.begin();
- while (tilesIt != tiles.end()) {
- if (retainIt == retain.end() || tilesIt->first < *retainIt) {
- tilesIt->second->setNecessity(Tile::Necessity::Optional);
- cache.add(tilesIt->first, std::move(tilesIt->second));
- tiles.erase(tilesIt++);
- } else {
- if (!(*retainIt < tilesIt->first)) {
- ++tilesIt;
- }
- ++retainIt;
- }
- }
-}
-
-void Source::Impl::removeTiles() {
- renderTiles.clear();
- if (!tiles.empty()) {
- removeStaleTiles({});
- }
-}
-
-void Source::Impl::reloadTiles() {
- cache.clear();
-
- for (auto& pair : tiles) {
- pair.second->redoLayout();
- }
-}
-
-std::unordered_map<std::string, std::vector<Feature>> Source::Impl::queryRenderedFeatures(const ScreenLineString& geometry,
- const TransformState& transformState,
- const RenderedQueryOptions& options) const {
- std::unordered_map<std::string, std::vector<Feature>> result;
- if (renderTiles.empty() || geometry.empty()) {
- return result;
- }
-
- LineString<double> queryGeometry;
-
- for (const auto& p : geometry) {
- queryGeometry.push_back(TileCoordinate::fromScreenCoordinate(
- transformState, 0, { p.x, transformState.getSize().height - p.y }).p);
- }
-
- mapbox::geometry::box<double> box = mapbox::geometry::envelope(queryGeometry);
-
-
- auto sortRenderTiles = [](const RenderTile& a, const RenderTile& b) {
- return std::tie(a.id.canonical.z, a.id.canonical.y, a.id.wrap, a.id.canonical.x) <
- std::tie(b.id.canonical.z, b.id.canonical.y, b.id.wrap, b.id.canonical.x);
- };
- std::vector<std::reference_wrapper<const RenderTile>> sortedTiles;
- std::transform(renderTiles.cbegin(), renderTiles.cend(), std::back_inserter(sortedTiles),
- [](const auto& pair) { return std::ref(pair.second); });
- std::sort(sortedTiles.begin(), sortedTiles.end(), sortRenderTiles);
-
- for (const auto& renderTileRef : sortedTiles) {
- const RenderTile& renderTile = renderTileRef.get();
- GeometryCoordinate tileSpaceBoundsMin = TileCoordinate::toGeometryCoordinate(renderTile.id, box.min);
- if (tileSpaceBoundsMin.x >= util::EXTENT || tileSpaceBoundsMin.y >= util::EXTENT) {
- continue;
- }
-
- GeometryCoordinate tileSpaceBoundsMax = TileCoordinate::toGeometryCoordinate(renderTile.id, box.max);
- if (tileSpaceBoundsMax.x < 0 || tileSpaceBoundsMax.y < 0) {
- continue;
- }
-
- GeometryCoordinates tileSpaceQueryGeometry;
- tileSpaceQueryGeometry.reserve(queryGeometry.size());
- for (const auto& c : queryGeometry) {
- tileSpaceQueryGeometry.push_back(TileCoordinate::toGeometryCoordinate(renderTile.id, c));
- }
-
- renderTile.tile.queryRenderedFeatures(result,
- tileSpaceQueryGeometry,
- transformState,
- options);
- }
-
- return result;
-}
-
-std::vector<Feature> Source::Impl::querySourceFeatures(const SourceQueryOptions& options) {
-
- // Only VectorSource and GeoJSON source supported
- if (type != SourceType::GeoJSON && type != SourceType::Vector) {
- Log::Warning(Event::General, "Source type not supported");
- return {};
- }
-
- std::vector<Feature> result;
-
- for (const auto& pair : tiles) {
- pair.second->querySourceFeatures(result, options);
- }
-
- return result;
-}
-
-void Source::Impl::setCacheSize(size_t size) {
- cache.setSize(size);
-}
-
-void Source::Impl::onLowMemory() {
- cache.clear();
-}
-
-void Source::Impl::setObserver(SourceObserver* observer_) {
- observer = observer_;
-}
-
-void Source::Impl::onTileChanged(Tile& tile) {
- observer->onTileChanged(base, tile.id);
-}
-
-void Source::Impl::onTileError(Tile& tile, std::exception_ptr error) {
- observer->onTileError(base, tile.id, error);
-}
-
void Source::Impl::dumpDebugLogs() const {
Log::Info(Event::General, "Source::id: %s", base.getID().c_str());
Log::Info(Event::General, "Source::loaded: %d", loaded);
+}
- for (const auto& pair : tiles) {
- pair.second->dumpDebugLogs();
- }
+void Source::Impl::setObserver(SourceObserver* observer_) {
+ observer = observer_;
}
} // namespace style
diff --git a/src/mbgl/style/source_impl.hpp b/src/mbgl/style/source_impl.hpp
index 132d1b97f8..2514ec5120 100644
--- a/src/mbgl/style/source_impl.hpp
+++ b/src/mbgl/style/source_impl.hpp
@@ -1,117 +1,37 @@
#pragma once
#include <mbgl/style/source.hpp>
-
-#include <mbgl/tile/tile_id.hpp>
-#include <mbgl/tile/tile_observer.hpp>
-#include <mbgl/tile/tile.hpp>
-#include <mbgl/tile/tile_cache.hpp>
-#include <mbgl/style/types.hpp>
-#include <mbgl/map/query.hpp>
-
#include <mbgl/util/noncopyable.hpp>
-#include <mbgl/util/mat4.hpp>
-#include <mbgl/util/feature.hpp>
-#include <mbgl/util/range.hpp>
-
-#include <memory>
-#include <unordered_map>
-#include <vector>
-#include <map>
namespace mbgl {
-class Painter;
class FileSource;
-class TransformState;
-class RenderTile;
-class RenderedQueryOptions;
-
-namespace algorithm {
-class ClipIDGenerator;
-} // namespace algorithm
+class RenderSource;
namespace style {
-class UpdateParameters;
class SourceObserver;
-class Source::Impl : public TileObserver, private util::noncopyable {
+class Source::Impl : private util::noncopyable {
public:
Impl(SourceType, std::string id, Source&);
- ~Impl() override;
+ virtual ~Impl() = default;
virtual void loadDescription(FileSource&) = 0;
- bool isLoaded() const;
-
- // Called when the camera has changed. May load new tiles, unload obsolete tiles, or
- // trigger re-placement of existing complete tiles.
- void updateTiles(const UpdateParameters&);
-
- // Removes all tiles (by putting them into the cache).
- void removeTiles();
-
- // Remove all tiles and clear the cache.
- void invalidateTiles();
-
- // Request that all loaded tiles re-run the layout operation on the existing source
- // data with fresh style information.
- void reloadTiles();
-
- void startRender(algorithm::ClipIDGenerator&,
- const mat4& projMatrix,
- const mat4& clipMatrix,
- const TransformState&);
- void finishRender(Painter&);
-
- std::map<UnwrappedTileID, RenderTile>& getRenderTiles();
-
- std::unordered_map<std::string, std::vector<Feature>>
- queryRenderedFeatures(const ScreenLineString& geometry,
- const TransformState& transformState,
- const RenderedQueryOptions& options) const;
-
- std::vector<Feature> querySourceFeatures(const SourceQueryOptions&);
-
- void setCacheSize(size_t);
- void onLowMemory();
+ virtual std::unique_ptr<RenderSource> createRenderSource() const = 0;
- void setObserver(SourceObserver*);
- void dumpDebugLogs() const;
+ virtual optional<std::string> getAttribution() const { return {}; };
const SourceType type;
const std::string id;
- virtual optional<std::string> getAttribution() const { return {}; };
- virtual optional<Range<uint8_t>> getZoomRange() const = 0;
-
bool loaded = false;
-
- // Tracks whether the source is used by any layers visible at the current zoom level. Must
- // be initialized to true so that Style::isLoaded() does not produce false positives if
- // called before Style::recalculate().
- bool enabled = true;
-
- // Detaches from the style
- void detach();
-
-protected:
Source& base;
- SourceObserver* observer = nullptr;
- std::map<OverscaledTileID, std::unique_ptr<Tile>> tiles;
- TileCache cache;
-
-private:
- void removeStaleTiles(const std::set<OverscaledTileID>&);
-
- // TileObserver implementation.
- void onTileChanged(Tile&) override;
- void onTileError(Tile&, std::exception_ptr) override;
- virtual uint16_t getTileSize() const = 0;
- virtual std::unique_ptr<Tile> createTile(const OverscaledTileID&, const UpdateParameters&) = 0;
+ void setObserver(SourceObserver*);
+ SourceObserver* observer = nullptr;
- std::map<UnwrappedTileID, RenderTile> renderTiles;
+ void dumpDebugLogs() const;
};
} // namespace style
diff --git a/src/mbgl/style/source_observer.hpp b/src/mbgl/style/source_observer.hpp
index c97ba19e84..c99eda955e 100644
--- a/src/mbgl/style/source_observer.hpp
+++ b/src/mbgl/style/source_observer.hpp
@@ -1,13 +1,8 @@
#pragma once
-#include <mbgl/tile/tile_observer.hpp>
-
#include <exception>
namespace mbgl {
-
-class OverscaledTileID;
-
namespace style {
class Source;
@@ -22,9 +17,6 @@ public:
// Source description needs to be reloaded
virtual void onSourceDescriptionChanged(Source&) {}
-
- virtual void onTileChanged(Source&, const OverscaledTileID&) {}
- virtual void onTileError(Source&, const OverscaledTileID&, std::exception_ptr) {}
};
} // namespace style
diff --git a/src/mbgl/style/sources/geojson_source.cpp b/src/mbgl/style/sources/geojson_source.cpp
index 62726cd127..110c1cd63c 100644
--- a/src/mbgl/style/sources/geojson_source.cpp
+++ b/src/mbgl/style/sources/geojson_source.cpp
@@ -4,7 +4,7 @@
namespace mbgl {
namespace style {
-GeoJSONSource::GeoJSONSource(const std::string& id, const GeoJSONOptions options)
+GeoJSONSource::GeoJSONSource(const std::string& id, const GeoJSONOptions& options)
: Source(SourceType::GeoJSON,
std::make_unique<GeoJSONSource::Impl>(std::move(id), *this, options)),
impl(static_cast<Impl*>(baseImpl.get())) {
diff --git a/src/mbgl/style/sources/geojson_source_impl.cpp b/src/mbgl/style/sources/geojson_source_impl.cpp
index 6431d5faa4..08ed95ea3f 100644
--- a/src/mbgl/style/sources/geojson_source_impl.cpp
+++ b/src/mbgl/style/sources/geojson_source_impl.cpp
@@ -1,10 +1,12 @@
-#include <mbgl/util/logging.hpp>
-#include <mbgl/storage/file_source.hpp>
+#include <mbgl/style/sources/geojson_source_impl.hpp>
#include <mbgl/style/conversion/geojson.hpp>
#include <mbgl/style/source_observer.hpp>
-#include <mbgl/style/sources/geojson_source_impl.hpp>
-#include <mbgl/tile/geojson_tile.hpp>
+#include <mbgl/tile/tile_id.hpp>
+#include <mbgl/storage/file_source.hpp>
+#include <mbgl/renderer/sources/render_geojson_source.hpp>
#include <mbgl/util/rapidjson.hpp>
+#include <mbgl/util/constants.cpp>
+#include <mbgl/util/logging.hpp>
#include <mapbox/geojson.hpp>
#include <mapbox/geojson/rapidjson.hpp>
@@ -31,6 +33,34 @@ optional<GeoJSON> convertGeoJSON(const JSValue& value, Error& error) {
}
} // namespace conversion
+class GeoJSONVTData : public GeoJSONData {
+public:
+ GeoJSONVTData(const GeoJSON& geoJSON,
+ const mapbox::geojsonvt::Options& options)
+ : impl(geoJSON, options) {}
+
+ mapbox::geometry::feature_collection<int16_t> getTile(const CanonicalTileID& tileID) final {
+ return impl.getTile(tileID.z, tileID.x, tileID.y).features;
+ }
+
+private:
+ mapbox::geojsonvt::GeoJSONVT impl;
+};
+
+class SuperclusterData : public GeoJSONData {
+public:
+ SuperclusterData(const mapbox::geometry::feature_collection<double>& features,
+ const mapbox::supercluster::Options& options)
+ : impl(features, options) {}
+
+ mapbox::geometry::feature_collection<int16_t> getTile(const CanonicalTileID& tileID) final {
+ return impl.getTile(tileID.z, tileID.x, tileID.y);
+ }
+
+private:
+ mapbox::supercluster::Supercluster impl;
+};
+
GeoJSONSource::Impl::Impl(std::string id_, Source& base_, const GeoJSONOptions options_)
: Source::Impl(SourceType::GeoJSON, std::move(id_), base_), options(options_) {
}
@@ -52,18 +82,14 @@ optional<std::string> GeoJSONSource::Impl::getURL() const {
return url;
}
-
void GeoJSONSource::Impl::setGeoJSON(const GeoJSON& geoJSON) {
req.reset();
_setGeoJSON(geoJSON);
}
-// Private implementation
void GeoJSONSource::Impl::_setGeoJSON(const GeoJSON& geoJSON) {
double scale = util::EXTENT / util::tileSize;
- cache.clear();
-
if (options.cluster
&& geoJSON.is<mapbox::geometry::feature_collection<double>>()
&& !geoJSON.get<mapbox::geometry::feature_collection<double>>().empty()) {
@@ -71,35 +97,15 @@ void GeoJSONSource::Impl::_setGeoJSON(const GeoJSON& geoJSON) {
clusterOptions.maxZoom = options.clusterMaxZoom;
clusterOptions.extent = util::EXTENT;
clusterOptions.radius = std::round(scale * options.clusterRadius);
-
- const auto& features = geoJSON.get<mapbox::geometry::feature_collection<double>>();
- geoJSONOrSupercluster =
- std::make_unique<mapbox::supercluster::Supercluster>(features, clusterOptions);
+ data = std::make_unique<SuperclusterData>(
+ geoJSON.get<mapbox::geometry::feature_collection<double>>(), clusterOptions);
} else {
mapbox::geojsonvt::Options vtOptions;
vtOptions.maxZoom = options.maxzoom;
vtOptions.extent = util::EXTENT;
vtOptions.buffer = std::round(scale * options.buffer);
vtOptions.tolerance = scale * options.tolerance;
- geoJSONOrSupercluster = std::make_unique<mapbox::geojsonvt::GeoJSONVT>(geoJSON, vtOptions);
- }
-
- for (auto const &item : tiles) {
- GeoJSONTile* geoJSONTile = static_cast<GeoJSONTile*>(item.second.get());
- setTileData(*geoJSONTile, geoJSONTile->id);
- }
-}
-
-void GeoJSONSource::Impl::setTileData(GeoJSONTile& tile, const OverscaledTileID& tileID) {
- if (geoJSONOrSupercluster.is<GeoJSONVTPointer>()) {
- tile.updateData(geoJSONOrSupercluster.get<GeoJSONVTPointer>()->getTile(tileID.canonical.z,
- tileID.canonical.x,
- tileID.canonical.y).features);
- } else {
- assert(geoJSONOrSupercluster.is<SuperclusterPointer>());
- tile.updateData(geoJSONOrSupercluster.get<SuperclusterPointer>()->getTile(tileID.canonical.z,
- tileID.canonical.x,
- tileID.canonical.y));
+ data = std::make_unique<GeoJSONVTData>(geoJSON, vtOptions);
}
}
@@ -135,8 +141,6 @@ void GeoJSONSource::Impl::loadDescription(FileSource& fileSource) {
return;
}
- invalidateTiles();
-
conversion::Error error;
optional<GeoJSON> geoJSON = conversion::convertGeoJSON<JSValue>(d, error);
if (!geoJSON) {
@@ -155,19 +159,16 @@ void GeoJSONSource::Impl::loadDescription(FileSource& fileSource) {
});
}
-optional<Range<uint8_t>> GeoJSONSource::Impl::getZoomRange() const {
- if (loaded) {
- return { { 0, options.maxzoom }};
- }
- return {};
+std::unique_ptr<RenderSource> GeoJSONSource::Impl::createRenderSource() const {
+ return std::make_unique<RenderGeoJSONSource>(*this);
+}
+
+Range<uint8_t> GeoJSONSource::Impl::getZoomRange() const {
+ return { 0, options.maxzoom };
}
-std::unique_ptr<Tile> GeoJSONSource::Impl::createTile(const OverscaledTileID& tileID,
- const UpdateParameters& parameters) {
- assert(loaded);
- auto tilePointer = std::make_unique<GeoJSONTile>(tileID, base.getID(), parameters);
- setTileData(*tilePointer.get(), tileID);
- return std::move(tilePointer);
+GeoJSONData* GeoJSONSource::Impl::getData() const {
+ return data.get();
}
} // namespace style
diff --git a/src/mbgl/style/sources/geojson_source_impl.hpp b/src/mbgl/style/sources/geojson_source_impl.hpp
index b827a0b26c..e8b881d05e 100644
--- a/src/mbgl/style/sources/geojson_source_impl.hpp
+++ b/src/mbgl/style/sources/geojson_source_impl.hpp
@@ -3,14 +3,19 @@
#include <mbgl/style/source_impl.hpp>
#include <mbgl/style/sources/geojson_source.hpp>
#include <mbgl/util/variant.hpp>
-#include <mbgl/tile/geojson_tile.hpp>
namespace mbgl {
class AsyncRequest;
+class CanonicalTileID;
namespace style {
+class GeoJSONData {
+public:
+ virtual mapbox::geometry::feature_collection<int16_t> getTile(const CanonicalTileID&) = 0;
+};
+
class GeoJSONSource::Impl : public Source::Impl {
public:
Impl(std::string id, Source&, const GeoJSONOptions);
@@ -18,27 +23,21 @@ public:
void setURL(std::string);
optional<std::string> getURL() const;
+ Range<uint8_t> getZoomRange() const;
void setGeoJSON(const GeoJSON&);
- void setTileData(GeoJSONTile&, const OverscaledTileID& tileID);
+ GeoJSONData* getData() const;
void loadDescription(FileSource&) final;
-
- uint16_t getTileSize() const final {
- return util::tileSize;
- }
-
- optional<Range<uint8_t>> getZoomRange() const final;
+ std::unique_ptr<RenderSource> createRenderSource() const final;
private:
void _setGeoJSON(const GeoJSON&);
- std::unique_ptr<Tile> createTile(const OverscaledTileID&, const UpdateParameters&) final;
-
GeoJSONOptions options;
optional<std::string> url;
std::unique_ptr<AsyncRequest> req;
- variant<GeoJSONVTPointer, SuperclusterPointer> geoJSONOrSupercluster;
+ std::unique_ptr<GeoJSONData> data;
};
} // namespace style
diff --git a/src/mbgl/style/sources/raster_source_impl.cpp b/src/mbgl/style/sources/raster_source_impl.cpp
index b727651260..b85d221f2e 100644
--- a/src/mbgl/style/sources/raster_source_impl.cpp
+++ b/src/mbgl/style/sources/raster_source_impl.cpp
@@ -1,5 +1,5 @@
#include <mbgl/style/sources/raster_source_impl.hpp>
-#include <mbgl/tile/raster_tile.hpp>
+#include <mbgl/renderer/sources/render_raster_source.hpp>
namespace mbgl {
namespace style {
@@ -10,9 +10,8 @@ RasterSource::Impl::Impl(std::string id_, Source& base_,
: TileSourceImpl(SourceType::Raster, std::move(id_), base_, std::move(urlOrTileset_), tileSize_) {
}
-std::unique_ptr<Tile> RasterSource::Impl::createTile(const OverscaledTileID& tileID,
- const UpdateParameters& parameters) {
- return std::make_unique<RasterTile>(tileID, parameters, tileset);
+std::unique_ptr<RenderSource> RasterSource::Impl::createRenderSource() const {
+ return std::make_unique<RenderRasterSource>(*this);
}
} // namespace style
diff --git a/src/mbgl/style/sources/raster_source_impl.hpp b/src/mbgl/style/sources/raster_source_impl.hpp
index 6f34a050bb..4bc76560f8 100644
--- a/src/mbgl/style/sources/raster_source_impl.hpp
+++ b/src/mbgl/style/sources/raster_source_impl.hpp
@@ -10,8 +10,7 @@ class RasterSource::Impl : public TileSourceImpl {
public:
Impl(std::string id, Source&, variant<std::string, Tileset>, uint16_t tileSize);
-private:
- std::unique_ptr<Tile> createTile(const OverscaledTileID&, const UpdateParameters&) final;
+ std::unique_ptr<RenderSource> createRenderSource() const final;
};
} // namespace style
diff --git a/src/mbgl/style/sources/vector_source_impl.cpp b/src/mbgl/style/sources/vector_source_impl.cpp
index efe8afbbea..158abf8575 100644
--- a/src/mbgl/style/sources/vector_source_impl.cpp
+++ b/src/mbgl/style/sources/vector_source_impl.cpp
@@ -1,5 +1,6 @@
#include <mbgl/style/sources/vector_source_impl.hpp>
-#include <mbgl/tile/vector_tile.hpp>
+#include <mbgl/renderer/sources/render_vector_source.hpp>
+#include <mbgl/util/constants.hpp>
namespace mbgl {
namespace style {
@@ -8,9 +9,8 @@ VectorSource::Impl::Impl(std::string id_, Source& base_, variant<std::string, Ti
: TileSourceImpl(SourceType::Vector, std::move(id_), base_, std::move(urlOrTileset_), util::tileSize) {
}
-std::unique_ptr<Tile> VectorSource::Impl::createTile(const OverscaledTileID& tileID,
- const UpdateParameters& parameters) {
- return std::make_unique<VectorTile>(tileID, base.getID(), parameters, tileset);
+std::unique_ptr<RenderSource> VectorSource::Impl::createRenderSource() const {
+ return std::make_unique<RenderVectorSource>(*this);
}
} // namespace style
diff --git a/src/mbgl/style/sources/vector_source_impl.hpp b/src/mbgl/style/sources/vector_source_impl.hpp
index 6726fa6955..844739948c 100644
--- a/src/mbgl/style/sources/vector_source_impl.hpp
+++ b/src/mbgl/style/sources/vector_source_impl.hpp
@@ -10,8 +10,7 @@ class VectorSource::Impl : public TileSourceImpl {
public:
Impl(std::string id, Source&, variant<std::string, Tileset>);
-private:
- std::unique_ptr<Tile> createTile(const OverscaledTileID&, const UpdateParameters&) final;
+ std::unique_ptr<RenderSource> createRenderSource() const final;
};
} // namespace style
diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp
index 0bc1841566..5fc9c40eba 100644
--- a/src/mbgl/style/style.cpp
+++ b/src/mbgl/style/style.cpp
@@ -22,6 +22,7 @@
#include <mbgl/sprite/sprite_atlas.hpp>
#include <mbgl/text/glyph_atlas.hpp>
#include <mbgl/geometry/line_atlas.hpp>
+#include <mbgl/renderer/render_source.hpp>
#include <mbgl/renderer/render_item.hpp>
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/renderer/render_background_layer.hpp>
@@ -32,12 +33,14 @@
#include <mbgl/renderer/render_line_layer.hpp>
#include <mbgl/renderer/render_raster_layer.hpp>
#include <mbgl/renderer/render_symbol_layer.hpp>
+#include <mbgl/tile/tile.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/exception.hpp>
#include <mbgl/util/geometry.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/math.hpp>
+#include <mbgl/util/std.hpp>
#include <mbgl/math/minmax.hpp>
#include <mbgl/map/query.hpp>
@@ -112,6 +115,7 @@ TransitionOptions Style::getTransitionOptions() const {
void Style::setJSON(const std::string& json) {
sources.clear();
+ renderSources.clear();
layers.clear();
renderLayers.clear();
classes.clear();
@@ -166,6 +170,10 @@ void Style::addSource(std::unique_ptr<Source> source) {
source->baseImpl->setObserver(this);
source->baseImpl->loadDescription(fileSource);
+ std::unique_ptr<RenderSource> renderSource = source->baseImpl->createRenderSource();
+ renderSource->setObserver(this);
+ renderSources.emplace_back(std::move(renderSource));
+
sources.emplace_back(std::move(source));
}
@@ -178,11 +186,14 @@ std::unique_ptr<Source> Style::removeSource(const std::string& id) {
return nullptr;
}
+ util::erase_if(renderSources, [&](const auto& source) {
+ return source->baseImpl.id == id;
+ });
+
auto source = std::move(*it);
sources.erase(it);
updateBatch.sourceIDs.erase(id);
- source->baseImpl->detach();
return source;
}
@@ -317,20 +328,20 @@ double Style::getDefaultPitch() const {
}
void Style::updateTiles(const UpdateParameters& parameters) {
- for (const auto& source : sources) {
- if (source->baseImpl->enabled) {
- source->baseImpl->updateTiles(parameters);
+ for (const auto& renderSource : renderSources) {
+ if (renderSource->enabled) {
+ renderSource->updateTiles(parameters);
}
}
}
void Style::relayout() {
for (const auto& sourceID : updateBatch.sourceIDs) {
- Source* source = getSource(sourceID);
- if (source && source->baseImpl->enabled) {
- source->baseImpl->reloadTiles();
- } else if (source) {
- source->baseImpl->invalidateTiles();
+ RenderSource* renderSource = getRenderSource(sourceID);
+ if (renderSource && renderSource->enabled) {
+ renderSource->reloadTiles();
+ } else if (renderSource) {
+ renderSource->invalidateTiles();
}
}
updateBatch.sourceIDs.clear();
@@ -363,8 +374,8 @@ void Style::cascade(const TimePoint& timePoint, MapMode mode) {
void Style::recalculate(float z, const TimePoint& timePoint, MapMode mode) {
// Disable all sources first. If we find an enabled layer that uses this source, we will
// re-enable it later.
- for (const auto& source : sources) {
- source->baseImpl->enabled = false;
+ for (const auto& renderSource : renderSources) {
+ renderSource->enabled = false;
}
zoomHistory.update(z, timePoint);
@@ -380,24 +391,19 @@ void Style::recalculate(float z, const TimePoint& timePoint, MapMode mode) {
for (const auto& layer : renderLayers) {
hasPendingTransitions |= layer->evaluate(parameters);
- // Disable this layer if it doesn't need to be rendered.
- const bool needsRendering = layer->needsRendering(zoomHistory.lastZoom);
- if (!needsRendering) {
- continue;
- }
-
- // If this layer has a source, make sure that it gets loaded.
- if (Source* source = getSource(layer->baseImpl.source)) {
- source->baseImpl->enabled = true;
+ if (layer->needsRendering(zoomHistory.lastZoom)) {
+ if (RenderSource* renderSource = getRenderSource(layer->baseImpl.source)) {
+ renderSource->enabled = true;
+ }
}
}
evaluatedLight = EvaluatedLight(transitioningLight, parameters);
// Remove the existing tiles if we didn't end up re-enabling the source.
- for (const auto& source : sources) {
- if (!source->baseImpl->enabled) {
- source->baseImpl->removeTiles();
+ for (const auto& renderSource : renderSources) {
+ if (!renderSource->enabled) {
+ renderSource->removeTiles();
}
}
}
@@ -428,6 +434,14 @@ Source* Style::getSource(const std::string& id) const {
return it != sources.end() ? it->get() : nullptr;
}
+RenderSource* Style::getRenderSource(const std::string& id) const {
+ const auto it = std::find_if(renderSources.begin(), renderSources.end(), [&](const auto& source) {
+ return source->baseImpl.id == id;
+ });
+
+ return it != renderSources.end() ? it->get() : nullptr;
+}
+
bool Style::hasTransitions() const {
return hasPendingTransitions;
}
@@ -438,7 +452,13 @@ bool Style::isLoaded() const {
}
for (const auto& source: sources) {
- if (source->baseImpl->enabled && !source->baseImpl->isLoaded()) {
+ if (!source->baseImpl->loaded) {
+ return false;
+ }
+ }
+
+ for (const auto& renderSource: renderSources) {
+ if (!renderSource->isLoaded()) {
return false;
}
}
@@ -453,9 +473,9 @@ bool Style::isLoaded() const {
RenderData Style::getRenderData(MapDebugOptions debugOptions, float angle) const {
RenderData result;
- for (const auto& source : sources) {
- if (source->baseImpl->enabled) {
- result.sources.insert(source.get());
+ for (const auto& renderSource: renderSources) {
+ if (renderSource->enabled) {
+ result.sources.insert(renderSource.get());
}
}
@@ -486,13 +506,13 @@ RenderData Style::getRenderData(MapDebugOptions debugOptions, float angle) const
continue;
}
- Source* source = getSource(layer->baseImpl.source);
+ RenderSource* source = getRenderSource(layer->baseImpl.source);
if (!source) {
Log::Warning(Event::Render, "can't find source for layer '%s'", layer->baseImpl.id.c_str());
continue;
}
- auto& renderTiles = source->baseImpl->getRenderTiles();
+ auto& renderTiles = source->getRenderTiles();
const bool symbolLayer = layer->is<RenderSymbolLayer>();
// Sort symbol tiles in opposite y position, so tiles with overlapping
@@ -557,26 +577,29 @@ RenderData Style::getRenderData(MapDebugOptions debugOptions, float angle) const
std::vector<Feature> Style::queryRenderedFeatures(const ScreenLineString& geometry,
const TransformState& transformState,
const RenderedQueryOptions& options) const {
- std::unordered_set<std::string> sourceFilter;
+ std::unordered_map<std::string, std::vector<Feature>> resultsByLayer;
if (options.layerIDs) {
+ std::unordered_set<std::string> sourceIDs;
for (const auto& layerID : *options.layerIDs) {
- auto layer = getLayer(layerID);
- if (layer) sourceFilter.emplace(layer->baseImpl->source);
+ if (Layer* layer = getLayer(layerID)) {
+ sourceIDs.emplace(layer->baseImpl->source);
+ }
+ }
+ for (const auto& sourceID : sourceIDs) {
+ if (RenderSource* renderSource = getRenderSource(sourceID)) {
+ auto sourceResults = renderSource->queryRenderedFeatures(geometry, transformState, options);
+ std::move(sourceResults.begin(), sourceResults.end(), std::inserter(resultsByLayer, resultsByLayer.begin()));
+ }
+ }
+ } else {
+ for (const auto& renderSource : renderSources) {
+ auto sourceResults = renderSource->queryRenderedFeatures(geometry, transformState, options);
+ std::move(sourceResults.begin(), sourceResults.end(), std::inserter(resultsByLayer, resultsByLayer.begin()));
}
}
std::vector<Feature> result;
- std::unordered_map<std::string, std::vector<Feature>> resultsByLayer;
-
- for (const auto& source : sources) {
- if (!sourceFilter.empty() && sourceFilter.find(source->getID()) == sourceFilter.end()) {
- continue;
- }
-
- auto sourceResults = source->baseImpl->queryRenderedFeatures(geometry, transformState, options);
- std::move(sourceResults.begin(), sourceResults.end(), std::inserter(resultsByLayer, resultsByLayer.begin()));
- }
if (resultsByLayer.empty()) {
return result;
@@ -597,14 +620,14 @@ std::vector<Feature> Style::queryRenderedFeatures(const ScreenLineString& geomet
}
void Style::setSourceTileCacheSize(size_t size) {
- for (const auto& source : sources) {
- source->baseImpl->setCacheSize(size);
+ for (const auto& renderSource : renderSources) {
+ renderSource->setCacheSize(size);
}
}
void Style::onLowMemory() {
- for (const auto& source : sources) {
- source->baseImpl->onLowMemory();
+ for (const auto& renderSource : renderSources) {
+ renderSource->onLowMemory();
}
}
@@ -648,16 +671,14 @@ void Style::onSourceDescriptionChanged(Source& source) {
}
}
-void Style::onTileChanged(Source& source, const OverscaledTileID& tileID) {
- observer->onTileChanged(source, tileID);
+void Style::onTileChanged(RenderSource&, const OverscaledTileID&) {
observer->onUpdate(Update::Repaint);
}
-void Style::onTileError(Source& source, const OverscaledTileID& tileID, std::exception_ptr error) {
+void Style::onTileError(RenderSource& source, const OverscaledTileID& tileID, std::exception_ptr error) {
lastError = error;
Log::Error(Event::Style, "Failed to load tile %s for source %s: %s",
- util::toString(tileID).c_str(), source.getID().c_str(), util::toString(error).c_str());
- observer->onTileError(source, tileID, error);
+ util::toString(tileID).c_str(), source.baseImpl.id.c_str(), util::toString(error).c_str());
observer->onResourceError(error);
}
@@ -725,6 +746,10 @@ void Style::dumpDebugLogs() const {
source->baseImpl->dumpDebugLogs();
}
+ for (const auto& renderSource : renderSources) {
+ renderSource->dumpDebugLogs();
+ }
+
spriteAtlas->dumpDebugLogs();
}
diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp
index 26959c9fbf..6c80a2ef59 100644
--- a/src/mbgl/style/style.hpp
+++ b/src/mbgl/style/style.hpp
@@ -3,6 +3,7 @@
#include <mbgl/style/transition_options.hpp>
#include <mbgl/style/observer.hpp>
#include <mbgl/style/source_observer.hpp>
+#include <mbgl/renderer/render_source_observer.hpp>
#include <mbgl/style/layer_observer.hpp>
#include <mbgl/style/update_batch.hpp>
#include <mbgl/renderer/render_layer.hpp>
@@ -34,6 +35,7 @@ class TransformState;
class RenderedQueryOptions;
class Scheduler;
class RenderLayer;
+class RenderSource;
namespace style {
@@ -44,6 +46,7 @@ class QueryParameters;
class Style : public GlyphAtlasObserver,
public SpriteAtlasObserver,
public SourceObserver,
+ public RenderSourceObserver,
public LayerObserver,
public util::noncopyable {
public:
@@ -125,8 +128,12 @@ public:
TransitioningLight transitioningLight;
EvaluatedLight evaluatedLight;
+ RenderSource* getRenderSource(const std::string& id) const;
+
private:
std::vector<std::unique_ptr<Source>> sources;
+ std::vector<std::unique_ptr<RenderSource>> renderSources;
+
std::vector<std::unique_ptr<Layer>> layers;
std::vector<std::unique_ptr<RenderLayer>> renderLayers;
std::vector<std::string> classes;
@@ -156,8 +163,8 @@ private:
void onSourceChanged(Source&) override;
void onSourceError(Source&, std::exception_ptr) override;
void onSourceDescriptionChanged(Source&) override;
- void onTileChanged(Source&, const OverscaledTileID&) override;
- void onTileError(Source&, const OverscaledTileID&, std::exception_ptr) override;
+ void onTileChanged(RenderSource&, const OverscaledTileID&) override;
+ void onTileError(RenderSource&, const OverscaledTileID&, std::exception_ptr) override;
// LayerObserver implementation.
void onLayerFilterChanged(Layer&) override;
diff --git a/src/mbgl/style/tile_source_impl.cpp b/src/mbgl/style/tile_source_impl.cpp
index 9ea596d38b..4623714794 100644
--- a/src/mbgl/style/tile_source_impl.cpp
+++ b/src/mbgl/style/tile_source_impl.cpp
@@ -82,26 +82,7 @@ void TileSourceImpl::loadDescription(FileSource& fileSource) {
return;
}
- // Check whether previous information specifies different tile
- bool attributionChanged = false;
- if (tileset.tiles != newTileset.tiles) {
- // Tile URLs changed: force tiles to be reloaded.
- invalidateTiles();
-
- // Tile size changed: We need to recalculate the tiles we need to load because we
- // might have to load tiles for a different zoom level
- // This is done automatically when we trigger the onSourceLoaded observer below.
-
- // Min/Max zoom changed: We need to recalculate what tiles to load, if we have tiles
- // loaded that are outside the new zoom range
- // This is done automatically when we trigger the onSourceLoaded observer below.
-
- // Attribution changed: We need to notify the embedding application that this
- // changed.
- attributionChanged = true;
-
- // Center/bounds changed: We're not using these values currently
- }
+ bool attributionChanged = tileset.attribution != newTileset.attribution;
tileset = newTileset;
loaded = true;
@@ -114,9 +95,9 @@ void TileSourceImpl::loadDescription(FileSource& fileSource) {
});
}
-optional<Range<uint8_t>> TileSourceImpl::getZoomRange() const {
+optional<Tileset> TileSourceImpl::getTileset() const {
if (loaded) {
- return tileset.zoomRange;
+ return tileset;
}
return {};
}
diff --git a/src/mbgl/style/tile_source_impl.hpp b/src/mbgl/style/tile_source_impl.hpp
index 2993caf20a..405408ff54 100644
--- a/src/mbgl/style/tile_source_impl.hpp
+++ b/src/mbgl/style/tile_source_impl.hpp
@@ -26,7 +26,7 @@ public:
void loadDescription(FileSource&) final;
- uint16_t getTileSize() const final {
+ uint16_t getTileSize() const {
return tileSize;
}
@@ -35,7 +35,7 @@ public:
}
optional<std::string> getAttribution() const override;
- optional<Range<uint8_t>> getZoomRange() const final;
+ optional<Tileset> getTileset() const;
protected:
const variant<std::string, Tileset> urlOrTileset;
diff --git a/src/mbgl/tile/geojson_tile.cpp b/src/mbgl/tile/geojson_tile.cpp
index f989bc2ce6..4e0623c18b 100644
--- a/src/mbgl/tile/geojson_tile.cpp
+++ b/src/mbgl/tile/geojson_tile.cpp
@@ -84,14 +84,16 @@ public:
GeoJSONTile::GeoJSONTile(const OverscaledTileID& overscaledTileID,
std::string sourceID_,
- const style::UpdateParameters& parameters)
+ const style::UpdateParameters& parameters,
+ mapbox::geometry::feature_collection<int16_t> features)
: GeometryTile(overscaledTileID, sourceID_, parameters,
*parameters.style.glyphAtlas,
*parameters.style.spriteAtlas) {
+ updateData(std::move(features));
}
-void GeoJSONTile::updateData(const mapbox::geometry::feature_collection<int16_t>& features) {
- setData(std::make_unique<GeoJSONTileData>(features));
+void GeoJSONTile::updateData(mapbox::geometry::feature_collection<int16_t> features) {
+ setData(std::make_unique<GeoJSONTileData>(std::move(features)));
}
void GeoJSONTile::setNecessity(Necessity) {}
diff --git a/src/mbgl/tile/geojson_tile.hpp b/src/mbgl/tile/geojson_tile.hpp
index f8cde75106..0bafe14bdc 100644
--- a/src/mbgl/tile/geojson_tile.hpp
+++ b/src/mbgl/tile/geojson_tile.hpp
@@ -13,9 +13,10 @@ class GeoJSONTile : public GeometryTile {
public:
GeoJSONTile(const OverscaledTileID&,
std::string sourceID,
- const style::UpdateParameters&);
+ const style::UpdateParameters&,
+ mapbox::geometry::feature_collection<int16_t>);
- void updateData(const mapbox::geometry::feature_collection<int16_t>&);
+ void updateData(mapbox::geometry::feature_collection<int16_t>);
void setNecessity(Necessity) final;
diff --git a/test/src/mbgl/test/stub_render_source_observer.hpp b/test/src/mbgl/test/stub_render_source_observer.hpp
new file mode 100644
index 0000000000..ff20fff80c
--- /dev/null
+++ b/test/src/mbgl/test/stub_render_source_observer.hpp
@@ -0,0 +1,23 @@
+#pragma once
+
+#include <mbgl/renderer/render_source_observer.hpp>
+
+using namespace mbgl;
+
+/**
+ * An implementation of style::Observer that forwards all methods to dynamically-settable lambdas.
+ */
+class StubRenderSourceObserver : public RenderSourceObserver {
+public:
+ void onTileChanged(RenderSource& source, const OverscaledTileID& tileID) override {
+ if (tileChanged) tileChanged(source, tileID);
+ };
+
+ void
+ onTileError(RenderSource& source, const OverscaledTileID& tileID, std::exception_ptr error) override {
+ if (tileError) tileError(source, tileID, error);
+ }
+
+ std::function<void (RenderSource&, const OverscaledTileID&)> tileChanged;
+ std::function<void (RenderSource&, const OverscaledTileID&, std::exception_ptr)> tileError;
+};
diff --git a/test/src/mbgl/test/stub_style_observer.hpp b/test/src/mbgl/test/stub_style_observer.hpp
index 9312cfa550..7e22c68823 100644
--- a/test/src/mbgl/test/stub_style_observer.hpp
+++ b/test/src/mbgl/test/stub_style_observer.hpp
@@ -42,15 +42,6 @@ public:
if (sourceDescriptionChanged) sourceDescriptionChanged(source);
}
- void onTileChanged(Source& source, const OverscaledTileID& tileID) override {
- if (tileChanged) tileChanged(source, tileID);
- };
-
- void
- onTileError(Source& source, const OverscaledTileID& tileID, std::exception_ptr error) override {
- if (tileError) tileError(source, tileID, error);
- }
-
void onResourceError(std::exception_ptr error) override {
if (resourceError) resourceError(error);
};
@@ -63,7 +54,5 @@ public:
std::function<void (Source&)> sourceChanged;
std::function<void (Source&, std::exception_ptr)> sourceError;
std::function<void (Source&)> sourceDescriptionChanged;
- std::function<void (Source&, const OverscaledTileID&)> tileChanged;
- std::function<void (Source&, const OverscaledTileID&, std::exception_ptr)> tileError;
std::function<void (std::exception_ptr)> resourceError;
};
diff --git a/test/style/source.test.cpp b/test/style/source.test.cpp
index 24ddba8aaf..6a336a8c23 100644
--- a/test/style/source.test.cpp
+++ b/test/style/source.test.cpp
@@ -1,12 +1,17 @@
#include <mbgl/test/util.hpp>
#include <mbgl/test/stub_file_source.hpp>
#include <mbgl/test/stub_style_observer.hpp>
+#include <mbgl/test/stub_render_source_observer.hpp>
#include <mbgl/style/source_impl.hpp>
#include <mbgl/style/sources/raster_source.hpp>
#include <mbgl/style/sources/vector_source.hpp>
#include <mbgl/style/sources/geojson_source.hpp>
+#include <mbgl/renderer/sources/render_raster_source.hpp>
+#include <mbgl/renderer/sources/render_vector_source.hpp>
+#include <mbgl/renderer/sources/render_geojson_source.hpp>
+
#include <mbgl/util/run_loop.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/io.hpp>
@@ -33,7 +38,8 @@ class SourceTest {
public:
util::RunLoop loop;
StubFileSource fileSource;
- StubStyleObserver observer;
+ StubStyleObserver styleObserver;
+ StubRenderSourceObserver renderSourceObserver;
Transform transform;
TransformState transformState;
ThreadPool threadPool { 1 };
@@ -70,32 +76,6 @@ public:
}
};
-TEST(Source, DefaultZoomRange) {
- VectorSource vectorSource("vectorSource", "url");
- EXPECT_FALSE(vectorSource.getZoomRange());
- vectorSource.baseImpl->loaded = true;
- EXPECT_EQ(vectorSource.getZoomRange()->min, 0u);
- EXPECT_EQ(vectorSource.getZoomRange()->max, 22u);
-
- GeoJSONSource geojsonSource("source");
- EXPECT_FALSE(geojsonSource.getZoomRange());
- geojsonSource.baseImpl->loaded = true;
- EXPECT_EQ(geojsonSource.getZoomRange()->min, 0u);
- EXPECT_EQ(geojsonSource.getZoomRange()->max, 18u);
-
- Tileset tileset;
- RasterSource rasterSource("source", tileset, 512);
- EXPECT_FALSE(rasterSource.getZoomRange());
- rasterSource.baseImpl->loaded = true;
- EXPECT_EQ(rasterSource.getZoomRange()->min, 0u);
- EXPECT_EQ(rasterSource.getZoomRange()->max, 22u);
- EXPECT_EQ(*rasterSource.getZoomRange(), tileset.zoomRange);
-
- AnnotationSource annotationSource;
- EXPECT_EQ(annotationSource.getZoomRange()->min, 0u);
- EXPECT_EQ(annotationSource.getZoomRange()->max, 22u);
-}
-
TEST(Source, LoadingFail) {
SourceTest test;
@@ -108,14 +88,14 @@ TEST(Source, LoadingFail) {
return response;
};
- test.observer.sourceError = [&] (Source& source, std::exception_ptr error) {
+ test.styleObserver.sourceError = [&] (Source& source, std::exception_ptr error) {
EXPECT_EQ("source", source.getID());
EXPECT_EQ("Failed by the test case", util::toString(error));
test.end();
};
VectorSource source("source", "url");
- source.baseImpl->setObserver(&test.observer);
+ source.baseImpl->setObserver(&test.styleObserver);
source.baseImpl->loadDescription(test.fileSource);
test.run();
@@ -131,14 +111,14 @@ TEST(Source, LoadingCorrupt) {
return response;
};
- test.observer.sourceError = [&] (Source& source, std::exception_ptr error) {
+ test.styleObserver.sourceError = [&] (Source& source, std::exception_ptr error) {
EXPECT_EQ("source", source.getID());
EXPECT_EQ("0 - Invalid value.", util::toString(error));
test.end();
};
VectorSource source("source", "url");
- source.baseImpl->setObserver(&test.observer);
+ source.baseImpl->setObserver(&test.styleObserver);
source.baseImpl->loadDescription(test.fileSource);
test.run();
@@ -153,22 +133,24 @@ TEST(Source, RasterTileEmpty) {
return response;
};
- test.observer.tileChanged = [&] (Source& source, const OverscaledTileID&) {
- EXPECT_EQ("source", source.getID());
+ Tileset tileset;
+ tileset.tiles = { "tiles" };
+
+ RasterSource source("source", tileset, 512);
+ source.baseImpl->loadDescription(test.fileSource);
+
+ test.renderSourceObserver.tileChanged = [&] (RenderSource& source_, const OverscaledTileID&) {
+ EXPECT_EQ("source", source_.baseImpl.id);
test.end();
};
- test.observer.tileError = [&] (Source&, const OverscaledTileID&, std::exception_ptr) {
+ test.renderSourceObserver.tileError = [&] (RenderSource&, const OverscaledTileID&, std::exception_ptr) {
FAIL() << "Should never be called";
};
- Tileset tileset;
- tileset.tiles = { "tiles" };
-
- RasterSource source("source", tileset, 512);
- source.baseImpl->setObserver(&test.observer);
- source.baseImpl->loadDescription(test.fileSource);
- source.baseImpl->updateTiles(test.updateParameters);
+ RenderRasterSource renderSource(*source.impl);
+ renderSource.setObserver(&test.renderSourceObserver);
+ renderSource.updateTiles(test.updateParameters);
test.run();
}
@@ -182,22 +164,24 @@ TEST(Source, VectorTileEmpty) {
return response;
};
- test.observer.tileChanged = [&] (Source& source, const OverscaledTileID&) {
- EXPECT_EQ("source", source.getID());
+ Tileset tileset;
+ tileset.tiles = { "tiles" };
+
+ VectorSource source("source", tileset);
+ source.baseImpl->loadDescription(test.fileSource);
+
+ test.renderSourceObserver.tileChanged = [&] (RenderSource& source_, const OverscaledTileID&) {
+ EXPECT_EQ("source", source_.baseImpl.id);
test.end();
};
- test.observer.tileError = [&] (Source&, const OverscaledTileID&, std::exception_ptr) {
+ test.renderSourceObserver.tileError = [&] (RenderSource&, const OverscaledTileID&, std::exception_ptr) {
FAIL() << "Should never be called";
};
- Tileset tileset;
- tileset.tiles = { "tiles" };
-
- VectorSource source("source", tileset);
- source.baseImpl->setObserver(&test.observer);
- source.baseImpl->loadDescription(test.fileSource);
- source.baseImpl->updateTiles(test.updateParameters);
+ RenderVectorSource renderSource(*source.impl);
+ renderSource.setObserver(&test.renderSourceObserver);
+ renderSource.updateTiles(test.updateParameters);
test.run();
}
@@ -213,20 +197,22 @@ TEST(Source, RasterTileFail) {
return response;
};
- test.observer.tileError = [&] (Source& source, const OverscaledTileID& tileID, std::exception_ptr error) {
- EXPECT_EQ(SourceType::Raster, source.baseImpl->type);
- EXPECT_EQ(OverscaledTileID(0, 0, 0), tileID);
- EXPECT_EQ("Failed by the test case", util::toString(error));
- test.end();
- };
-
Tileset tileset;
tileset.tiles = { "tiles" };
RasterSource source("source", tileset, 512);
- source.baseImpl->setObserver(&test.observer);
source.baseImpl->loadDescription(test.fileSource);
- source.baseImpl->updateTiles(test.updateParameters);
+
+ test.renderSourceObserver.tileError = [&] (RenderSource& source_, const OverscaledTileID& tileID, std::exception_ptr error) {
+ EXPECT_EQ(SourceType::Raster, source_.baseImpl.type);
+ EXPECT_EQ(OverscaledTileID(0, 0, 0), tileID);
+ EXPECT_EQ("Failed by the test case", util::toString(error));
+ test.end();
+ };
+
+ RenderRasterSource renderSource(*source.impl);
+ renderSource.setObserver(&test.renderSourceObserver);
+ renderSource.updateTiles(test.updateParameters);
test.run();
}
@@ -242,20 +228,22 @@ TEST(Source, VectorTileFail) {
return response;
};
- test.observer.tileError = [&] (Source& source, const OverscaledTileID& tileID, std::exception_ptr error) {
- EXPECT_EQ(SourceType::Vector, source.baseImpl->type);
- EXPECT_EQ(OverscaledTileID(0, 0, 0), tileID);
- EXPECT_EQ("Failed by the test case", util::toString(error));
- test.end();
- };
-
Tileset tileset;
tileset.tiles = { "tiles" };
VectorSource source("source", tileset);
- source.baseImpl->setObserver(&test.observer);
source.baseImpl->loadDescription(test.fileSource);
- source.baseImpl->updateTiles(test.updateParameters);
+
+ test.renderSourceObserver.tileError = [&] (RenderSource& source_, const OverscaledTileID& tileID, std::exception_ptr error) {
+ EXPECT_EQ(SourceType::Vector, source_.baseImpl.type);
+ EXPECT_EQ(OverscaledTileID(0, 0, 0), tileID);
+ EXPECT_EQ("Failed by the test case", util::toString(error));
+ test.end();
+ };
+
+ RenderVectorSource renderSource(*source.impl);
+ renderSource.setObserver(&test.renderSourceObserver);
+ renderSource.updateTiles(test.updateParameters);
test.run();
}
@@ -269,21 +257,23 @@ TEST(Source, RasterTileCorrupt) {
return response;
};
- test.observer.tileError = [&] (Source& source, const OverscaledTileID& tileID, std::exception_ptr error) {
- EXPECT_EQ(source.baseImpl->type, SourceType::Raster);
+ Tileset tileset;
+ tileset.tiles = { "tiles" };
+
+ RasterSource source("source", tileset, 512);
+ source.baseImpl->loadDescription(test.fileSource);
+
+ test.renderSourceObserver.tileError = [&] (RenderSource& source_, const OverscaledTileID& tileID, std::exception_ptr error) {
+ EXPECT_EQ(source_.baseImpl.type, SourceType::Raster);
EXPECT_EQ(OverscaledTileID(0, 0, 0), tileID);
EXPECT_TRUE(bool(error));
// Not asserting on platform-specific error text.
test.end();
};
- Tileset tileset;
- tileset.tiles = { "tiles" };
-
- RasterSource source("source", tileset, 512);
- source.baseImpl->setObserver(&test.observer);
- source.baseImpl->loadDescription(test.fileSource);
- source.baseImpl->updateTiles(test.updateParameters);
+ RenderRasterSource renderSource(*source.impl);
+ renderSource.setObserver(&test.renderSourceObserver);
+ renderSource.updateTiles(test.updateParameters);
test.run();
}
@@ -297,13 +287,6 @@ TEST(Source, VectorTileCorrupt) {
return response;
};
- test.observer.tileError = [&] (Source& source, const OverscaledTileID& tileID, std::exception_ptr error) {
- EXPECT_EQ(source.baseImpl->type, SourceType::Vector);
- EXPECT_EQ(OverscaledTileID(0, 0, 0), tileID);
- EXPECT_EQ(util::toString(error), "unknown pbf field type exception");
- test.end();
- };
-
// Need to have at least one layer that uses the source.
auto layer = std::make_unique<LineLayer>("id", "source");
layer->setSourceLayer("water");
@@ -313,9 +296,18 @@ TEST(Source, VectorTileCorrupt) {
tileset.tiles = { "tiles" };
VectorSource source("source", tileset);
- source.baseImpl->setObserver(&test.observer);
source.baseImpl->loadDescription(test.fileSource);
- source.baseImpl->updateTiles(test.updateParameters);
+
+ test.renderSourceObserver.tileError = [&] (RenderSource& source_, const OverscaledTileID& tileID, std::exception_ptr error) {
+ EXPECT_EQ(source_.baseImpl.type, SourceType::Vector);
+ EXPECT_EQ(OverscaledTileID(0, 0, 0), tileID);
+ EXPECT_EQ(util::toString(error), "unknown pbf field type exception");
+ test.end();
+ };
+
+ RenderVectorSource renderSource(*source.impl);
+ renderSource.setObserver(&test.renderSourceObserver);
+ renderSource.updateTiles(test.updateParameters);
test.run();
}
@@ -328,21 +320,23 @@ TEST(Source, RasterTileCancel) {
return optional<Response>();
};
- test.observer.tileChanged = [&] (Source&, const OverscaledTileID&) {
+ Tileset tileset;
+ tileset.tiles = { "tiles" };
+
+ RasterSource source("source", tileset, 512);
+ source.baseImpl->loadDescription(test.fileSource);
+
+ test.renderSourceObserver.tileChanged = [&] (RenderSource&, const OverscaledTileID&) {
FAIL() << "Should never be called";
};
- test.observer.tileError = [&] (Source&, const OverscaledTileID&, std::exception_ptr) {
+ test.renderSourceObserver.tileError = [&] (RenderSource&, const OverscaledTileID&, std::exception_ptr) {
FAIL() << "Should never be called";
};
- Tileset tileset;
- tileset.tiles = { "tiles" };
-
- RasterSource source("source", tileset, 512);
- source.baseImpl->setObserver(&test.observer);
- source.baseImpl->loadDescription(test.fileSource);
- source.baseImpl->updateTiles(test.updateParameters);
+ RenderRasterSource renderSource(*source.impl);
+ renderSource.setObserver(&test.renderSourceObserver);
+ renderSource.updateTiles(test.updateParameters);
test.run();
}
@@ -355,21 +349,23 @@ TEST(Source, VectorTileCancel) {
return optional<Response>();
};
- test.observer.tileChanged = [&] (Source&, const OverscaledTileID&) {
+ Tileset tileset;
+ tileset.tiles = { "tiles" };
+
+ VectorSource source("source", tileset);
+ source.baseImpl->loadDescription(test.fileSource);
+
+ test.renderSourceObserver.tileChanged = [&] (RenderSource&, const OverscaledTileID&) {
FAIL() << "Should never be called";
};
- test.observer.tileError = [&] (Source&, const OverscaledTileID&, std::exception_ptr) {
+ test.renderSourceObserver.tileError = [&] (RenderSource&, const OverscaledTileID&, std::exception_ptr) {
FAIL() << "Should never be called";
};
- Tileset tileset;
- tileset.tiles = { "tiles" };
-
- VectorSource source("source", tileset);
- source.baseImpl->setObserver(&test.observer);
- source.baseImpl->loadDescription(test.fileSource);
- source.baseImpl->updateTiles(test.updateParameters);
+ RenderVectorSource renderSource(*source.impl);
+ renderSource.setObserver(&test.renderSourceObserver);
+ renderSource.updateTiles(test.updateParameters);
test.run();
}
@@ -395,20 +391,18 @@ TEST(Source, RasterTileAttribution) {
return response;
};
- test.observer.sourceChanged = [&] (Source& source) {
+ test.styleObserver.sourceChanged = [&] (Source& source) {
EXPECT_EQ(mapboxOSM, source.getAttribution());
EXPECT_FALSE(mapboxOSM.find("©️ OpenStreetMap") == std::string::npos);
test.end();
};
- test.observer.tileError = [&] (Source&, const OverscaledTileID&, std::exception_ptr) {
- FAIL() << "Should never be called";
- };
-
RasterSource source("source", "url", 512);
- source.baseImpl->setObserver(&test.observer);
+ source.baseImpl->setObserver(&test.styleObserver);
source.baseImpl->loadDescription(test.fileSource);
- source.baseImpl->updateTiles(test.updateParameters);
+
+ RenderRasterSource renderSource(*source.impl);
+ renderSource.updateTiles(test.updateParameters);
test.run();
}
@@ -423,17 +417,13 @@ TEST(Source, GeoJSonSourceUrlUpdate) {
return response;
};
- test.observer.sourceDescriptionChanged = [&] (Source&) {
+ test.styleObserver.sourceDescriptionChanged = [&] (Source&) {
// Should be called (test will hang if it doesn't)
test.end();
};
- test.observer.tileError = [&] (Source&, const OverscaledTileID&, std::exception_ptr) {
- FAIL() << "Should never be called";
- };
-
GeoJSONSource source("source");
- source.baseImpl->setObserver(&test.observer);
+ source.baseImpl->setObserver(&test.styleObserver);
// Load initial, so the source state will be loaded=true
source.baseImpl->loadDescription(test.fileSource);
diff --git a/test/tile/geojson_tile.test.cpp b/test/tile/geojson_tile.test.cpp
index 46cbe209b6..f39ff0a4cd 100644
--- a/test/tile/geojson_tile.test.cpp
+++ b/test/tile/geojson_tile.test.cpp
@@ -41,26 +41,26 @@ public:
TEST(GeoJSONTile, Issue7648) {
GeoJSONTileTest test;
- GeoJSONTile tile(OverscaledTileID(0, 0, 0), "source", test.updateParameters);
test.style.addLayer(std::make_unique<CircleLayer>("circle", "source"));
+ mapbox::geometry::feature_collection<int16_t> features;
+ features.push_back(mapbox::geometry::feature<int16_t> {
+ mapbox::geometry::point<int16_t>(0, 0)
+ });
+
+ GeoJSONTile tile(OverscaledTileID(0, 0, 0), "source", test.updateParameters, features);
+
StubTileObserver observer;
observer.tileChanged = [&] (const Tile&) {
// Once present, the bucket should never "disappear", which would cause
// flickering.
ASSERT_NE(nullptr, tile.getBucket(*test.style.getRenderLayer("circle")));
};
- tile.setObserver(&observer);
+ tile.setObserver(&observer);
tile.setPlacementConfig({});
- mapbox::geometry::feature_collection<int16_t> features;
- features.push_back(mapbox::geometry::feature<int16_t> {
- mapbox::geometry::point<int16_t>(0, 0)
- });
-
- tile.updateData(features);
while (!tile.isComplete()) {
test.loop.runOnce();
}