diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2017-04-20 17:11:50 -0700 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2017-05-02 08:45:09 -0700 |
commit | 3f0c89d633a5056006557ad5f4b9e446807d00ee (patch) | |
tree | 5405c50dd26a5a393a982e8e0f76b764dbbccf48 /src/mbgl/style | |
parent | 197751bace6181f2c2dbe4c890f277a0dc7e58b1 (diff) | |
download | qtlocation-mapboxgl-3f0c89d633a5056006557ad5f4b9e446807d00ee.tar.gz |
[core] Refactor Source::*Impls into RenderSources and TilePyramid
Diffstat (limited to 'src/mbgl/style')
-rw-r--r-- | src/mbgl/style/source.cpp | 4 | ||||
-rw-r--r-- | src/mbgl/style/source_impl.cpp | 281 | ||||
-rw-r--r-- | src/mbgl/style/source_impl.hpp | 96 | ||||
-rw-r--r-- | src/mbgl/style/source_observer.hpp | 8 | ||||
-rw-r--r-- | src/mbgl/style/sources/geojson_source.cpp | 2 | ||||
-rw-r--r-- | src/mbgl/style/sources/geojson_source_impl.cpp | 89 | ||||
-rw-r--r-- | src/mbgl/style/sources/geojson_source_impl.hpp | 21 | ||||
-rw-r--r-- | src/mbgl/style/sources/raster_source_impl.cpp | 7 | ||||
-rw-r--r-- | src/mbgl/style/sources/raster_source_impl.hpp | 3 | ||||
-rw-r--r-- | src/mbgl/style/sources/vector_source_impl.cpp | 8 | ||||
-rw-r--r-- | src/mbgl/style/sources/vector_source_impl.hpp | 3 | ||||
-rw-r--r-- | src/mbgl/style/style.cpp | 127 | ||||
-rw-r--r-- | src/mbgl/style/style.hpp | 11 | ||||
-rw-r--r-- | src/mbgl/style/tile_source_impl.cpp | 25 | ||||
-rw-r--r-- | src/mbgl/style/tile_source_impl.hpp | 4 |
15 files changed, 166 insertions, 523 deletions
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, ¶meters](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; |