From 57402314e1be3180ce6f67d8ba29c17aceba6b60 Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Mon, 17 Jun 2019 15:04:10 +0300 Subject: [core] Improve performance for query rendered features - query rendered symbols only from layers that support it - remove unnecessary iterations over vectors --- src/mbgl/annotation/render_annotation_source.cpp | 2 +- src/mbgl/annotation/render_annotation_source.hpp | 2 +- src/mbgl/geometry/feature_index.cpp | 21 ++++------- src/mbgl/geometry/feature_index.hpp | 6 ++-- src/mbgl/renderer/render_orchestrator.cpp | 42 ++++++++++++++-------- src/mbgl/renderer/render_orchestrator.hpp | 4 +-- src/mbgl/renderer/render_source.hpp | 2 +- src/mbgl/renderer/sources/render_image_source.cpp | 2 +- src/mbgl/renderer/sources/render_image_source.hpp | 2 +- .../renderer/sources/render_raster_dem_source.cpp | 2 +- .../renderer/sources/render_raster_dem_source.hpp | 2 +- src/mbgl/renderer/sources/render_raster_source.cpp | 2 +- src/mbgl/renderer/sources/render_raster_source.hpp | 2 +- src/mbgl/renderer/sources/render_tile_source.cpp | 2 +- src/mbgl/renderer/sources/render_tile_source.hpp | 2 +- src/mbgl/renderer/tile_pyramid.cpp | 2 +- src/mbgl/renderer/tile_pyramid.hpp | 2 +- src/mbgl/tile/geometry_tile.cpp | 10 +++--- src/mbgl/tile/geometry_tile.hpp | 4 +-- src/mbgl/tile/tile.cpp | 4 +-- src/mbgl/tile/tile.hpp | 4 +-- 21 files changed, 63 insertions(+), 58 deletions(-) diff --git a/src/mbgl/annotation/render_annotation_source.cpp b/src/mbgl/annotation/render_annotation_source.cpp index 123a776754..903825d5f5 100644 --- a/src/mbgl/annotation/render_annotation_source.cpp +++ b/src/mbgl/annotation/render_annotation_source.cpp @@ -46,7 +46,7 @@ void RenderAnnotationSource::update(Immutable baseImpl_, std::unordered_map> RenderAnnotationSource::queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, - const std::vector& layers, + const std::unordered_map& layers, const RenderedQueryOptions& options, const mat4& projMatrix) const { return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options, projMatrix); diff --git a/src/mbgl/annotation/render_annotation_source.hpp b/src/mbgl/annotation/render_annotation_source.hpp index 948a0b0d8d..c920d760c2 100644 --- a/src/mbgl/annotation/render_annotation_source.hpp +++ b/src/mbgl/annotation/render_annotation_source.hpp @@ -18,7 +18,7 @@ public: std::unordered_map> queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, - const std::vector& layers, + const std::unordered_map& layers, const RenderedQueryOptions& options, const mat4& projMatrix) const final; diff --git a/src/mbgl/geometry/feature_index.cpp b/src/mbgl/geometry/feature_index.cpp index f61f89b8e7..3675e8bc6e 100644 --- a/src/mbgl/geometry/feature_index.cpp +++ b/src/mbgl/geometry/feature_index.cpp @@ -47,7 +47,7 @@ void FeatureIndex::query( const double scale, const RenderedQueryOptions& queryOptions, const UnwrappedTileID& tileID, - const std::vector& layers, + const std::unordered_map& layers, const float additionalQueryPadding) const { if (!tileData) { @@ -81,7 +81,7 @@ void FeatureIndex::query( std::unordered_map> FeatureIndex::lookupSymbolFeatures(const std::vector& symbolFeatures, const RenderedQueryOptions& queryOptions, - const std::vector& layers, + const std::unordered_map& layers, const OverscaledTileID& tileID, const std::shared_ptr>& featureSortOrder) const { std::unordered_map> result; @@ -123,31 +123,24 @@ void FeatureIndex::addFeature( const IndexedSubfeature& indexedFeature, const RenderedQueryOptions& options, const CanonicalTileID& tileID, - const std::vector& layers, + const std::unordered_map& layers, const GeometryCoordinates& queryGeometry, const TransformState& transformState, const float pixelsToTileUnits, const mat4& posMatrix) const { - auto getRenderLayer = [&] (const std::string& layerID) -> const RenderLayer* { - for (const auto& layer : layers) { - if (layer->getID() == layerID) { - return layer; - } - } - return nullptr; - }; - // Lazily calculated. std::unique_ptr sourceLayer; std::unique_ptr geometryTileFeature; for (const std::string& layerID : bucketLayerIDs.at(indexedFeature.bucketLeaderID)) { - const RenderLayer* renderLayer = getRenderLayer(layerID); - if (!renderLayer) { + const auto it = layers.find(layerID); + if (it == layers.end()) { continue; } + const RenderLayer* renderLayer = it->second; + if (!geometryTileFeature) { sourceLayer = tileData->getLayer(indexedFeature.sourceLayerName); assert(sourceLayer); diff --git a/src/mbgl/geometry/feature_index.hpp b/src/mbgl/geometry/feature_index.hpp index cd041a7fdb..1a212761fa 100644 --- a/src/mbgl/geometry/feature_index.hpp +++ b/src/mbgl/geometry/feature_index.hpp @@ -67,7 +67,7 @@ public: const double scale, const RenderedQueryOptions& options, const UnwrappedTileID&, - const std::vector&, + const std::unordered_map&, const float additionalQueryPadding) const; static optional translateQueryGeometry( @@ -82,7 +82,7 @@ public: std::unordered_map> lookupSymbolFeatures( const std::vector& symbolFeatures, const RenderedQueryOptions& options, - const std::vector& layers, + const std::unordered_map& layers, const OverscaledTileID& tileID, const std::shared_ptr>& featureSortOrder) const; @@ -92,7 +92,7 @@ private: const IndexedSubfeature&, const RenderedQueryOptions& options, const CanonicalTileID&, - const std::vector&, + const std::unordered_map&, const GeometryCoordinates& queryGeometry, const TransformState& transformState, const float pixelsToTileUnits, diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp index fafbc8b635..c42273eca2 100644 --- a/src/mbgl/renderer/render_orchestrator.cpp +++ b/src/mbgl/renderer/render_orchestrator.cpp @@ -409,16 +409,16 @@ std::unique_ptr RenderOrchestrator::createRenderTree(const UpdatePar } std::vector RenderOrchestrator::queryRenderedFeatures(const ScreenLineString& geometry, const RenderedQueryOptions& options) const { - std::vector layers; + std::unordered_map layers; if (options.layerIDs) { for (const auto& layerID : *options.layerIDs) { if (const RenderLayer* layer = getRenderLayer(layerID)) { - layers.emplace_back(layer); + layers.emplace(layer->getID(), layer); } } } else { for (const auto& entry : renderLayers) { - layers.emplace_back(entry.second.get()); + layers.emplace(entry.second->getID(), entry.second.get()); } } @@ -427,9 +427,22 @@ std::vector RenderOrchestrator::queryRenderedFeatures(const ScreenLineS void RenderOrchestrator::queryRenderedSymbols(std::unordered_map>& resultsByLayer, const ScreenLineString& geometry, - const std::vector& layers, + const std::unordered_map& layers, const RenderedQueryOptions& options) const { - + const auto hasCrossTileIndex = [] (const auto& pair) { + return pair.second->baseImpl->getTypeInfo()->crossTileIndex == style::LayerTypeInfo::CrossTileIndex::Required; + }; + + std::unordered_map crossTileSymbolIndexLayers; + std::copy_if(layers.begin(), + layers.end(), + std::inserter(crossTileSymbolIndexLayers, crossTileSymbolIndexLayers.begin()), + hasCrossTileIndex); + + if (crossTileSymbolIndexLayers.empty()) { + return; + } + auto renderedSymbols = placement->getCollisionIndex().queryRenderedSymbols(geometry); std::vector> bucketQueryData; for (auto entry : renderedSymbols) { @@ -447,7 +460,7 @@ void RenderOrchestrator::queryRenderedSymbols(std::unordered_maplookupSymbolFeatures(renderedSymbols[queryData.bucketInstanceId], options, - layers, + crossTileSymbolIndexLayers, queryData.tileID, queryData.featureSortOrder); @@ -458,10 +471,10 @@ void RenderOrchestrator::queryRenderedSymbols(std::unordered_map RenderOrchestrator::queryRenderedFeatures(const ScreenLineString& geometry, const RenderedQueryOptions& options, const std::vector& layers) const { +std::vector RenderOrchestrator::queryRenderedFeatures(const ScreenLineString& geometry, const RenderedQueryOptions& options, const std::unordered_map& layers) const { std::unordered_set sourceIDs; - for (const RenderLayer* layer : layers) { - sourceIDs.emplace(layer->baseImpl->source); + for (const auto& pair : layers) { + sourceIDs.emplace(pair.second->baseImpl->source); } mat4 projMatrix; @@ -484,13 +497,12 @@ std::vector RenderOrchestrator::queryRenderedFeatures(const ScreenLineS } // Combine all results based on the style layer renderItems. - for (const auto& layerImpl : *layerImpls) { - const RenderLayer* layer = getRenderLayer(layerImpl->id); - if (!layer->needsRendering() || !layer->supportsZoom(zoomHistory.lastZoom)) { + for (const auto& pair : layers) { + if (!pair.second->needsRendering() || !pair.second->supportsZoom(zoomHistory.lastZoom)) { continue; } - auto it = resultsByLayer.find(layer->baseImpl->id); + auto it = resultsByLayer.find(pair.second->baseImpl->id); if (it != resultsByLayer.end()) { std::move(it->second.begin(), it->second.end(), std::back_inserter(result)); } @@ -501,13 +513,13 @@ std::vector RenderOrchestrator::queryRenderedFeatures(const ScreenLineS std::vector RenderOrchestrator::queryShapeAnnotations(const ScreenLineString& geometry) const { assert(LayerManager::annotationsEnabled); - std::vector shapeAnnotationLayers; + std::unordered_map shapeAnnotationLayers; RenderedQueryOptions options; for (const auto& layerImpl : *layerImpls) { if (std::mismatch(layerImpl->id.begin(), layerImpl->id.end(), AnnotationManager::ShapeLayerID.begin(), AnnotationManager::ShapeLayerID.end()).second == AnnotationManager::ShapeLayerID.end()) { if (const RenderLayer* layer = getRenderLayer(layerImpl->id)) { - shapeAnnotationLayers.emplace_back(layer); + shapeAnnotationLayers.emplace(layer->getID(), layer); } } } diff --git a/src/mbgl/renderer/render_orchestrator.hpp b/src/mbgl/renderer/render_orchestrator.hpp index a60bac2e16..4622ac1749 100644 --- a/src/mbgl/renderer/render_orchestrator.hpp +++ b/src/mbgl/renderer/render_orchestrator.hpp @@ -74,10 +74,10 @@ private: void queryRenderedSymbols(std::unordered_map>& resultsByLayer, const ScreenLineString& geometry, - const std::vector& layers, + const std::unordered_map& layers, const RenderedQueryOptions& options) const; - std::vector queryRenderedFeatures(const ScreenLineString&, const RenderedQueryOptions&, const std::vector&) const; + std::vector queryRenderedFeatures(const ScreenLineString&, const RenderedQueryOptions&, const std::unordered_map&) const; // GlyphManagerObserver implementation. void onGlyphsError(const FontStack&, const GlyphRange&, std::exception_ptr) override; diff --git a/src/mbgl/renderer/render_source.hpp b/src/mbgl/renderer/render_source.hpp index fc770f83cf..2a4983e799 100644 --- a/src/mbgl/renderer/render_source.hpp +++ b/src/mbgl/renderer/render_source.hpp @@ -72,7 +72,7 @@ public: virtual std::unordered_map> queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, - const std::vector& layers, + const std::unordered_map& layers, const RenderedQueryOptions& options, const mat4& projMatrix) const = 0; diff --git a/src/mbgl/renderer/sources/render_image_source.cpp b/src/mbgl/renderer/sources/render_image_source.cpp index 7e793c6a4a..6d197df9db 100644 --- a/src/mbgl/renderer/sources/render_image_source.cpp +++ b/src/mbgl/renderer/sources/render_image_source.cpp @@ -106,7 +106,7 @@ void RenderImageSource::prepare(const SourcePrepareParameters& parameters) { std::unordered_map> RenderImageSource::queryRenderedFeatures(const ScreenLineString&, const TransformState&, - const std::vector&, + const std::unordered_map&, const RenderedQueryOptions&, const mat4&) const { return std::unordered_map> {}; diff --git a/src/mbgl/renderer/sources/render_image_source.hpp b/src/mbgl/renderer/sources/render_image_source.hpp index d21f4fae10..4264f74564 100644 --- a/src/mbgl/renderer/sources/render_image_source.hpp +++ b/src/mbgl/renderer/sources/render_image_source.hpp @@ -57,7 +57,7 @@ public: std::unordered_map> queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, - const std::vector& layers, + const std::unordered_map& layers, const RenderedQueryOptions& options, const mat4& projMatrix) const final; diff --git a/src/mbgl/renderer/sources/render_raster_dem_source.cpp b/src/mbgl/renderer/sources/render_raster_dem_source.cpp index 9854b4fdc3..841124fa4a 100644 --- a/src/mbgl/renderer/sources/render_raster_dem_source.cpp +++ b/src/mbgl/renderer/sources/render_raster_dem_source.cpp @@ -125,7 +125,7 @@ void RenderRasterDEMSource::onTileChanged(Tile& tile){ std::unordered_map> RenderRasterDEMSource::queryRenderedFeatures(const ScreenLineString&, const TransformState&, - const std::vector&, + const std::unordered_map&, const RenderedQueryOptions&, const mat4&) const { return std::unordered_map>{}; diff --git a/src/mbgl/renderer/sources/render_raster_dem_source.hpp b/src/mbgl/renderer/sources/render_raster_dem_source.hpp index e49ad1d1d4..dd74f4d7e7 100644 --- a/src/mbgl/renderer/sources/render_raster_dem_source.hpp +++ b/src/mbgl/renderer/sources/render_raster_dem_source.hpp @@ -19,7 +19,7 @@ public: std::unordered_map> queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, - const std::vector& layers, + const std::unordered_map& layers, const RenderedQueryOptions& options, const mat4& projMatrix) const override; diff --git a/src/mbgl/renderer/sources/render_raster_source.cpp b/src/mbgl/renderer/sources/render_raster_source.cpp index 827ffb9759..06eb36795b 100644 --- a/src/mbgl/renderer/sources/render_raster_source.cpp +++ b/src/mbgl/renderer/sources/render_raster_source.cpp @@ -60,7 +60,7 @@ void RenderRasterSource::prepare(const SourcePrepareParameters& parameters) { std::unordered_map> RenderRasterSource::queryRenderedFeatures(const ScreenLineString&, const TransformState&, - const std::vector&, + const std::unordered_map&, const RenderedQueryOptions&, const mat4&) const { return std::unordered_map>{}; diff --git a/src/mbgl/renderer/sources/render_raster_source.hpp b/src/mbgl/renderer/sources/render_raster_source.hpp index dc80630add..0071dddec9 100644 --- a/src/mbgl/renderer/sources/render_raster_source.hpp +++ b/src/mbgl/renderer/sources/render_raster_source.hpp @@ -19,7 +19,7 @@ public: std::unordered_map> queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, - const std::vector& layers, + const std::unordered_map& layers, const RenderedQueryOptions& options, const mat4& projMatrix) const override; diff --git a/src/mbgl/renderer/sources/render_tile_source.cpp b/src/mbgl/renderer/sources/render_tile_source.cpp index 99bdfde485..93c41940b6 100644 --- a/src/mbgl/renderer/sources/render_tile_source.cpp +++ b/src/mbgl/renderer/sources/render_tile_source.cpp @@ -84,7 +84,7 @@ const Tile* RenderTileSource::getRenderedTile(const UnwrappedTileID& tileID) con std::unordered_map> RenderTileSource::queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, - const std::vector& layers, + const std::unordered_map& layers, const RenderedQueryOptions& options, const mat4& projMatrix) const { return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options, projMatrix); diff --git a/src/mbgl/renderer/sources/render_tile_source.hpp b/src/mbgl/renderer/sources/render_tile_source.hpp index e3148b45b9..8ec1439306 100644 --- a/src/mbgl/renderer/sources/render_tile_source.hpp +++ b/src/mbgl/renderer/sources/render_tile_source.hpp @@ -27,7 +27,7 @@ public: std::unordered_map> queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, - const std::vector& layers, + const std::unordered_map& layers, const RenderedQueryOptions& options, const mat4& projMatrix) const override; diff --git a/src/mbgl/renderer/tile_pyramid.cpp b/src/mbgl/renderer/tile_pyramid.cpp index e08803134d..f47198e275 100644 --- a/src/mbgl/renderer/tile_pyramid.cpp +++ b/src/mbgl/renderer/tile_pyramid.cpp @@ -284,7 +284,7 @@ void TilePyramid::handleWrapJump(float lng) { std::unordered_map> TilePyramid::queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, - const std::vector& layers, + const std::unordered_map& layers, const RenderedQueryOptions& options, const mat4& projMatrix) const { std::unordered_map> result; diff --git a/src/mbgl/renderer/tile_pyramid.hpp b/src/mbgl/renderer/tile_pyramid.hpp index 675831fbc9..f80eb0db78 100644 --- a/src/mbgl/renderer/tile_pyramid.hpp +++ b/src/mbgl/renderer/tile_pyramid.hpp @@ -52,7 +52,7 @@ public: std::unordered_map> queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, - const std::vector&, + const std::unordered_map&, const RenderedQueryOptions& options, const mat4& projMatrix) const; diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index e87d21503a..7f1bed49f4 100644 --- a/src/mbgl/tile/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -291,12 +291,12 @@ LayerRenderData* GeometryTile::getLayerRenderData(const style::Layer::Impl& laye return layoutResult ? layoutResult->getLayerRenderData(layerImpl) : nullptr; } -float GeometryTile::getQueryPadding(const std::vector& layers) { +float GeometryTile::getQueryPadding(const std::unordered_map& layers) { float queryPadding = 0; - for (const RenderLayer* layer : layers) { - const LayerRenderData* data = getLayerRenderData(*layer->baseImpl); + for (const auto& pair : layers) { + const LayerRenderData* data = getLayerRenderData(*pair.second->baseImpl); if (data && data->bucket && data->bucket->hasData()) { - queryPadding = std::max(queryPadding, data->bucket->getQueryRadius(*layer)); + queryPadding = std::max(queryPadding, data->bucket->getQueryRadius(*pair.second)); } } return queryPadding; @@ -306,7 +306,7 @@ void GeometryTile::queryRenderedFeatures( std::unordered_map>& result, const GeometryCoordinates& queryGeometry, const TransformState& transformState, - const std::vector& layers, + const std::unordered_map& layers, const RenderedQueryOptions& options, const mat4& projMatrix) { diff --git a/src/mbgl/tile/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp index 3d75dfc456..7c46edfc1d 100644 --- a/src/mbgl/tile/geometry_tile.hpp +++ b/src/mbgl/tile/geometry_tile.hpp @@ -52,7 +52,7 @@ public: std::unordered_map>& result, const GeometryCoordinates& queryGeometry, const TransformState&, - const std::vector& layers, + const std::unordered_map& layers, const RenderedQueryOptions& options, const mat4& projMatrix) override; @@ -60,7 +60,7 @@ public: std::vector& result, const SourceQueryOptions&) override; - float getQueryPadding(const std::vector&) override; + float getQueryPadding(const std::unordered_map&) override; void cancel() override; diff --git a/src/mbgl/tile/tile.cpp b/src/mbgl/tile/tile.cpp index 5e31898caf..2f342c092d 100644 --- a/src/mbgl/tile/tile.cpp +++ b/src/mbgl/tile/tile.cpp @@ -43,11 +43,11 @@ void Tile::queryRenderedFeatures( std::unordered_map>&, const GeometryCoordinates&, const TransformState&, - const std::vector&, + const std::unordered_map&, const RenderedQueryOptions&, const mat4&) {} -float Tile::getQueryPadding(const std::vector&) { +float Tile::getQueryPadding(const std::unordered_map&) { return 0; } diff --git a/src/mbgl/tile/tile.hpp b/src/mbgl/tile/tile.hpp index 4ba8bc1160..7a7d246aa6 100644 --- a/src/mbgl/tile/tile.hpp +++ b/src/mbgl/tile/tile.hpp @@ -71,7 +71,7 @@ public: std::unordered_map>& result, const GeometryCoordinates& queryGeometry, const TransformState&, - const std::vector&, + const std::unordered_map&, const RenderedQueryOptions& options, const mat4& projMatrix); @@ -79,7 +79,7 @@ public: std::vector& result, const SourceQueryOptions&); - virtual float getQueryPadding(const std::vector&); + virtual float getQueryPadding(const std::unordered_map&); void setTriedCache(); -- cgit v1.2.1 From 8d94bb1be0abfb03e958abe740976e920ea53f27 Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Mon, 8 Jul 2019 10:59:45 +0300 Subject: [core] Reserve size for filtered render layers --- src/mbgl/renderer/render_orchestrator.cpp | 11 +++++++++-- src/mbgl/renderer/render_orchestrator.hpp | 8 ++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp index c42273eca2..7df74cda71 100644 --- a/src/mbgl/renderer/render_orchestrator.cpp +++ b/src/mbgl/renderer/render_orchestrator.cpp @@ -271,11 +271,17 @@ std::unique_ptr RenderOrchestrator::createRenderTree(const UpdatePar std::vector> layersNeedPlacement; auto renderItemsEmplaceHint = layerRenderItems.begin(); + // Reserve size for filteredLayersForSource if there are sources. + if (!sourceImpls->empty()) { + filteredLayersForSource.reserve(layerImpls->size()); + if (filteredLayersForSource.capacity() > layerImpls->size()) { + filteredLayersForSource.shrink_to_fit(); + } + } + // Update all sources and initialize renderItems. for (const auto& sourceImpl : *sourceImpls) { RenderSource* source = renderSources.at(sourceImpl->id).get(); - std::vector> filteredLayersForSource; - filteredLayersForSource.reserve(layerImpls->size()); bool sourceNeedsRendering = false; bool sourceNeedsRelayout = false; @@ -321,6 +327,7 @@ std::unique_ptr RenderOrchestrator::createRenderTree(const UpdatePar sourceNeedsRendering, sourceNeedsRelayout, tileParameters); + filteredLayersForSource.clear(); } renderTreeParameters->loaded = updateParameters.styleLoaded && isLoaded(); diff --git a/src/mbgl/renderer/render_orchestrator.hpp b/src/mbgl/renderer/render_orchestrator.hpp index 4622ac1749..884bd21b7b 100644 --- a/src/mbgl/renderer/render_orchestrator.hpp +++ b/src/mbgl/renderer/render_orchestrator.hpp @@ -33,6 +33,10 @@ class PatternAtlas; class CrossTileSymbolIndex; class RenderTree; +namespace style { + class LayerProperties; +} // namespace style + class RenderOrchestrator final : public GlyphManagerObserver, public ImageManagerObserver, public RenderSourceObserver { @@ -113,6 +117,10 @@ private: const bool backgroundLayerAsColor; bool contextLost = false; + + // Vector with reserved capacity of layerImpls->size() to avoid reallocation + // on each frame. + std::vector> filteredLayersForSource; }; } // namespace mbgl -- cgit v1.2.1 From 81fc49502307dcf6a390b86fc62f6affc5f2b365 Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Mon, 8 Jul 2019 12:26:37 +0300 Subject: [android][ios][macos] Update changelog for #14930 --- platform/android/CHANGELOG.md | 2 ++ platform/ios/CHANGELOG.md | 4 ++++ platform/macos/CHANGELOG.md | 1 + 3 files changed, 7 insertions(+) diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index 9288256692..c699349bec 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -4,6 +4,8 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to ## master +* Performance improvements for queryRenderedFeatures API and optimization that allocates containers based on a number of rendered layers. ([#14930](https://github.com/mapbox/mapbox-gl-native/pull/14930)) + ## 8.2.0-alpha.2 - July 3, 2019 ### Bugs diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index 6154e6e2c5..201f92590c 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -2,6 +2,10 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONTRIBUTING.md](../../CONTRIBUTING.md) to get started. +## master + +* Performance improvements for queryRenderedFeatures API and optimization that allocates containers based on a number of rendered layers. ([#14930](https://github.com/mapbox/mapbox-gl-native/pull/14930)) + ## 5.2.0 ### Offline maps diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md index 241499432b..bf4ff55156 100644 --- a/platform/macos/CHANGELOG.md +++ b/platform/macos/CHANGELOG.md @@ -4,6 +4,7 @@ * Added an `MGLMapView.prefetchesTiles` property to configure lower-resolution tile prefetching behavior. ([#14816](https://github.com/mapbox/mapbox-gl-native/pull/14816)) * Fixed queryRenderedFeatues bug caused by incorrect sort feature index calculation. ([#14884](https://github.com/mapbox/mapbox-gl-native/pull/14884)) +* Performance improvements for queryRenderedFeatures API and optimization that allocates containers based on a number of rendered layers. ([#14930](https://github.com/mapbox/mapbox-gl-native/pull/14930)) ### Styles and rendering -- cgit v1.2.1 From 929824ecc3176c01a5f3e74d80e2ae2ba2cf1e51 Mon Sep 17 00:00:00 2001 From: Mikhail Pozdnyakov Date: Mon, 8 Jul 2019 17:49:32 +0300 Subject: [core] Share render tiles lists between layers This helps to avoid unneeded allocations. --- src/mbgl/renderer/layers/render_circle_layer.cpp | 3 +- .../layers/render_fill_extrusion_layer.cpp | 5 +-- src/mbgl/renderer/layers/render_fill_layer.cpp | 5 +-- src/mbgl/renderer/layers/render_heatmap_layer.cpp | 3 +- .../renderer/layers/render_hillshade_layer.cpp | 3 +- src/mbgl/renderer/layers/render_line_layer.cpp | 5 +-- src/mbgl/renderer/layers/render_raster_layer.cpp | 7 ++-- src/mbgl/renderer/layers/render_symbol_layer.cpp | 20 +++-------- src/mbgl/renderer/paint_parameters.cpp | 13 +++---- src/mbgl/renderer/render_layer.cpp | 15 ++------ src/mbgl/renderer/render_layer.hpp | 5 +-- src/mbgl/renderer/render_source.hpp | 12 +++++-- src/mbgl/renderer/sources/render_image_source.hpp | 2 -- src/mbgl/renderer/sources/render_tile_source.cpp | 41 ++++++++++++++++++++-- src/mbgl/renderer/sources/render_tile_source.hpp | 6 +++- 15 files changed, 87 insertions(+), 58 deletions(-) diff --git a/src/mbgl/renderer/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp index e7496df074..3888e9fec6 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.cpp +++ b/src/mbgl/renderer/layers/render_circle_layer.cpp @@ -53,11 +53,12 @@ bool RenderCircleLayer::hasCrossfade() const { } void RenderCircleLayer::render(PaintParameters& parameters) { + assert(renderTiles); if (parameters.pass == RenderPass::Opaque) { return; } - for (const RenderTile& tile : renderTiles) { + for (const RenderTile& tile : *renderTiles) { const LayerRenderData* renderData = tile.getLayerRenderData(*baseImpl); if (!renderData) { continue; diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp index 29002d8bdf..b8d195cfa1 100644 --- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp @@ -56,6 +56,7 @@ bool RenderFillExtrusionLayer::hasCrossfade() const { } void RenderFillExtrusionLayer::render(PaintParameters& parameters) { + assert(renderTiles); if (parameters.pass != RenderPass::Translucent) { return; } @@ -115,7 +116,7 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters) { if (unevaluated.get().isUndefined()) { // Draw solid color extrusions auto drawTiles = [&](const gfx::StencilMode& stencilMode_, const gfx::ColorMode& colorMode_, const std::string& name) { - for (const RenderTile& tile : renderTiles) { + for (const RenderTile& tile : *renderTiles) { const LayerRenderData* renderData = tile.getLayerRenderData(*baseImpl); if (!renderData) { continue; @@ -162,7 +163,7 @@ void RenderFillExtrusionLayer::render(PaintParameters& parameters) { // Draw textured extrusions const auto fillPatternValue = evaluated.get().constantOr(mbgl::Faded >{"", ""}); auto drawTiles = [&](const gfx::StencilMode& stencilMode_, const gfx::ColorMode& colorMode_, const std::string& name) { - for (const RenderTile& tile : renderTiles) { + for (const RenderTile& tile : *renderTiles) { const LayerRenderData* renderData = tile.getLayerRenderData(*baseImpl); if (!renderData) { continue; diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index c549b338df..6a3c247fbb 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -73,9 +73,10 @@ bool RenderFillLayer::hasCrossfade() const { } void RenderFillLayer::render(PaintParameters& parameters) { + assert(renderTiles); if (unevaluated.get().isUndefined()) { parameters.renderTileClippingMasks(renderTiles); - for (const RenderTile& tile : renderTiles) { + for (const RenderTile& tile : *renderTiles) { const LayerRenderData* renderData = tile.getLayerRenderData(*baseImpl); if (!renderData) { continue; @@ -162,7 +163,7 @@ void RenderFillLayer::render(PaintParameters& parameters) { parameters.renderTileClippingMasks(renderTiles); - for (const RenderTile& tile : renderTiles) { + for (const RenderTile& tile : *renderTiles) { const LayerRenderData* renderData = tile.getLayerRenderData(*baseImpl); if (!renderData) { continue; diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.cpp b/src/mbgl/renderer/layers/render_heatmap_layer.cpp index 4b80dee5e7..e087d2ca69 100644 --- a/src/mbgl/renderer/layers/render_heatmap_layer.cpp +++ b/src/mbgl/renderer/layers/render_heatmap_layer.cpp @@ -63,6 +63,7 @@ void RenderHeatmapLayer::upload(gfx::UploadPass& uploadPass) { } void RenderHeatmapLayer::render(PaintParameters& parameters) { + assert(renderTiles); if (parameters.pass == RenderPass::Opaque) { return; } @@ -93,7 +94,7 @@ void RenderHeatmapLayer::render(PaintParameters& parameters) { auto renderPass = parameters.encoder->createRenderPass( "heatmap texture", { *renderTexture, Color{ 0.0f, 0.0f, 0.0f, 1.0f }, {}, {} }); - for (const RenderTile& tile : renderTiles) { + for (const RenderTile& tile : *renderTiles) { const LayerRenderData* renderData = tile.getLayerRenderData(*baseImpl); if (!renderData) { continue; diff --git a/src/mbgl/renderer/layers/render_hillshade_layer.cpp b/src/mbgl/renderer/layers/render_hillshade_layer.cpp index 2cbb77f24b..9d1b5293c1 100644 --- a/src/mbgl/renderer/layers/render_hillshade_layer.cpp +++ b/src/mbgl/renderer/layers/render_hillshade_layer.cpp @@ -71,6 +71,7 @@ void RenderHillshadeLayer::prepare(const LayerPrepareParameters& params) { } void RenderHillshadeLayer::render(PaintParameters& parameters) { + assert(renderTiles); if (parameters.pass != RenderPass::Translucent && parameters.pass != RenderPass::Pass3D) return; const auto& evaluated = static_cast(*evaluatedProperties).evaluated; @@ -126,7 +127,7 @@ void RenderHillshadeLayer::render(PaintParameters& parameters) { matrix::ortho(mat, 0, util::EXTENT, -util::EXTENT, 0, 0, 1); matrix::translate(mat, mat, 0, -util::EXTENT, 0); - for (const RenderTile& tile : renderTiles) { + for (const RenderTile& tile : *renderTiles) { auto* bucket_ = tile.getBucket(*baseImpl); if (!bucket_) { continue; diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp index 595140634d..061be0aba1 100644 --- a/src/mbgl/renderer/layers/render_line_layer.cpp +++ b/src/mbgl/renderer/layers/render_line_layer.cpp @@ -61,7 +61,7 @@ bool RenderLineLayer::hasCrossfade() const { void RenderLineLayer::prepare(const LayerPrepareParameters& params) { RenderLayer::prepare(params); - for (const RenderTile& tile : renderTiles) { + for (const RenderTile& tile : *renderTiles) { const LayerRenderData* renderData = tile.getLayerRenderData(*baseImpl); if (!renderData) continue; @@ -84,13 +84,14 @@ void RenderLineLayer::upload(gfx::UploadPass& uploadPass) { } void RenderLineLayer::render(PaintParameters& parameters) { + assert(renderTiles); if (parameters.pass == RenderPass::Opaque) { return; } parameters.renderTileClippingMasks(renderTiles); - for (const RenderTile& tile : renderTiles) { + for (const RenderTile& tile : *renderTiles) { const LayerRenderData* renderData = tile.getLayerRenderData(*baseImpl); if (!renderData) { continue; diff --git a/src/mbgl/renderer/layers/render_raster_layer.cpp b/src/mbgl/renderer/layers/render_raster_layer.cpp index e22e14275c..ce1fa52f5e 100644 --- a/src/mbgl/renderer/layers/render_raster_layer.cpp +++ b/src/mbgl/renderer/layers/render_raster_layer.cpp @@ -74,8 +74,9 @@ static std::array spinWeights(float spin) { } void RenderRasterLayer::prepare(const LayerPrepareParameters& params) { - RenderLayer::prepare(params); + renderTiles = params.source->getRenderTiles(); imageData = params.source->getImageRenderData(); + assert(renderTiles || imageData); } void RenderRasterLayer::render(PaintParameters& parameters) { @@ -153,8 +154,8 @@ void RenderRasterLayer::render(PaintParameters& parameters) { }, bucket.drawScopeID + std::to_string(i++)); } - } else { - for (const RenderTile& tile : renderTiles) { + } else if (renderTiles) { + for (const RenderTile& tile : *renderTiles) { auto* bucket_ = tile.getBucket(*baseImpl); if (!bucket_) { continue; diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp index 60b0c8e2d8..b24e088ac4 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.cpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp @@ -276,6 +276,7 @@ bool RenderSymbolLayer::hasCrossfade() const { } void RenderSymbolLayer::render(PaintParameters& parameters) { + assert(renderTiles); if (parameters.pass == RenderPass::Opaque) { return; } @@ -348,7 +349,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters) { ); }; - for (const RenderTile& tile : renderTiles) { + for (const RenderTile& tile : *renderTiles) { const LayerRenderData* renderData = tile.getLayerRenderData(*baseImpl); if (!renderData) { continue; @@ -493,22 +494,11 @@ style::TextPaintProperties::PossiblyEvaluated RenderSymbolLayer::textPaintProper } void RenderSymbolLayer::prepare(const LayerPrepareParameters& params) { - renderTiles = params.source->getRenderTiles(); - const auto comp = [bearing = params.state.getBearing()](const RenderTile& a, const RenderTile& b) { - Point pa(a.id.canonical.x, a.id.canonical.y); - Point pb(b.id.canonical.x, b.id.canonical.y); - - auto par = util::rotate(pa, bearing); - auto pbr = util::rotate(pb, bearing); - - return std::tie(b.id.canonical.z, par.y, par.x) < std::tie(a.id.canonical.z, pbr.y, pbr.x); - }; - // Sort symbol tiles in opposite y position, so tiles with overlapping symbols are drawn - // on top of each other, with lower symbols being drawn on top of higher symbols. - std::sort(renderTiles.begin(), renderTiles.end(), comp); + renderTiles = params.source->getRenderTilesSortedByYPosition(); + assert(renderTiles); placementData.clear(); - for (const RenderTile& renderTile : renderTiles) { + for (const RenderTile& renderTile : *renderTiles) { auto* bucket = static_cast(renderTile.getBucket(*baseImpl)); if (bucket && bucket->bucketLeaderID == getID()) { // Only place this layer if it's the "group leader" for the bucket diff --git a/src/mbgl/renderer/paint_parameters.cpp b/src/mbgl/renderer/paint_parameters.cpp index 0bb66972a8..1539c0fbcb 100644 --- a/src/mbgl/renderer/paint_parameters.cpp +++ b/src/mbgl/renderer/paint_parameters.cpp @@ -92,24 +92,25 @@ namespace { // Detects a difference in keys of renderTiles and tileClippingMaskIDs bool tileIDsIdentical(const RenderTiles& renderTiles, const std::map& tileClippingMaskIDs) { - assert(std::is_sorted(renderTiles.begin(), renderTiles.end(), + assert(renderTiles); + assert(std::is_sorted(renderTiles->begin(), renderTiles->end(), [](const RenderTile& a, const RenderTile& b) { return a.id < b.id; })); - if (renderTiles.size() != tileClippingMaskIDs.size()) { + if (renderTiles->size() != tileClippingMaskIDs.size()) { return false; } - return std::equal(renderTiles.begin(), renderTiles.end(), tileClippingMaskIDs.begin(), + return std::equal(renderTiles->begin(), renderTiles->end(), tileClippingMaskIDs.begin(), [](const RenderTile& a, const auto& b) { return a.id == b.first; }); } } // namespace void PaintParameters::renderTileClippingMasks(const RenderTiles& renderTiles) { - if (renderTiles.empty() || tileIDsIdentical(renderTiles, tileClippingMaskIDs)) { + if (!renderTiles || renderTiles->empty() || tileIDsIdentical(renderTiles, tileClippingMaskIDs)) { // The current stencil mask is for this source already; no need to draw another one. return; } - if (nextStencilID + renderTiles.size() > 256) { + if (nextStencilID + renderTiles->size() > 256) { // we'll run out of fresh IDs so we need to clear and start from scratch clearStencil(); } @@ -120,7 +121,7 @@ void PaintParameters::renderTileClippingMasks(const RenderTiles& renderTiles) { const style::Properties<>::PossiblyEvaluated properties {}; const ClippingMaskProgram::Binders paintAttributeData(properties, 0); - for (const RenderTile& renderTile : renderTiles) { + for (const RenderTile& renderTile : *renderTiles) { const int32_t stencilID = nextStencilID++; tileClippingMaskIDs.emplace(renderTile.id, stencilID); diff --git a/src/mbgl/renderer/render_layer.cpp b/src/mbgl/renderer/render_layer.cpp index 9e79d7338c..b92b28998c 100644 --- a/src/mbgl/renderer/render_layer.cpp +++ b/src/mbgl/renderer/render_layer.cpp @@ -47,25 +47,14 @@ bool RenderLayer::supportsZoom(float zoom) const { void RenderLayer::prepare(const LayerPrepareParameters& params) { assert(params.source); - renderTiles = filterRenderTiles(params.source->getRenderTiles()); + renderTiles = params.source->getRenderTiles(); + assert(renderTiles); } optional RenderLayer::getSolidBackground() const { return nullopt; } -RenderTiles RenderLayer::filterRenderTiles(RenderTiles tiles) const { - RenderTiles filtered; - - for (const RenderTile& tile : tiles) { - if (tile.holdForFade()) { - continue; - } - filtered.emplace_back(tile); - } - return filtered; -} - void RenderLayer::markContextDestroyed() { // no-op } diff --git a/src/mbgl/renderer/render_layer.hpp b/src/mbgl/renderer/render_layer.hpp index 11c7587893..c7efdceab4 100644 --- a/src/mbgl/renderer/render_layer.hpp +++ b/src/mbgl/renderer/render_layer.hpp @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include #include #include @@ -15,7 +16,6 @@ class TransitionParameters; class PropertyEvaluationParameters; class UploadParameters; class PaintParameters; -class RenderSource; class RenderTile; class TransformState; class PatternAtlas; @@ -43,8 +43,6 @@ public: const TransformState& state; }; -using RenderTiles = std::vector>; - class RenderLayer { protected: RenderLayer(Immutable); @@ -127,7 +125,6 @@ protected: std::vector placementData; private: - RenderTiles filterRenderTiles(RenderTiles) const; // Some layers may not render correctly on some hardware when the vertex attribute limit of // that GPU is exceeded. More attributes are used when adding many data driven paint properties // to a layer. diff --git a/src/mbgl/renderer/render_source.hpp b/src/mbgl/renderer/render_source.hpp index 2a4983e799..cd471223a8 100644 --- a/src/mbgl/renderer/render_source.hpp +++ b/src/mbgl/renderer/render_source.hpp @@ -43,7 +43,7 @@ public: const ImageManager& imageManager; }; -using RenderTiles = std::vector>; +using RenderTiles = std::shared_ptr>>; class RenderSource : protected TileObserver { public: @@ -64,8 +64,14 @@ public: virtual void prepare(const SourcePrepareParameters&) = 0; virtual void updateFadingTiles() = 0; virtual bool hasFadingTiles() const = 0; - // Returns a list of RenderTiles, sorted by tile id. - virtual RenderTiles getRenderTiles() = 0; + // If supported, returns a shared list of RenderTiles, sorted by tile id and excluding tiles hold for fade; + // returns nullptr otherwise. + virtual RenderTiles getRenderTiles() const { return nullptr; } + // If supported, returns a shared list of RenderTiles, sorted in opposite y position, so tiles with overlapping + // symbols are drawn on top of each other, with lower symbols being drawn on top of higher symbols; + // returns nullptr otherwise. + virtual RenderTiles getRenderTilesSortedByYPosition() const { return nullptr; } + // If supported, returns pointer to image data; returns nullptr otherwise. virtual const ImageSourceRenderData* getImageRenderData() const { return nullptr; } virtual const Tile* getRenderedTile(const UnwrappedTileID&) const { return nullptr; } diff --git a/src/mbgl/renderer/sources/render_image_source.hpp b/src/mbgl/renderer/sources/render_image_source.hpp index 4264f74564..da0d899624 100644 --- a/src/mbgl/renderer/sources/render_image_source.hpp +++ b/src/mbgl/renderer/sources/render_image_source.hpp @@ -48,8 +48,6 @@ public: bool needsRelayout, const TileParameters&) final; - RenderTiles getRenderTiles() override { return {}; } - const ImageSourceRenderData* getImageRenderData() const override { return renderData.get(); } diff --git a/src/mbgl/renderer/sources/render_tile_source.cpp b/src/mbgl/renderer/sources/render_tile_source.cpp index 93c41940b6..6ee2eca1b1 100644 --- a/src/mbgl/renderer/sources/render_tile_source.cpp +++ b/src/mbgl/renderer/sources/render_tile_source.cpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace mbgl { @@ -56,6 +57,9 @@ std::unique_ptr RenderTileSource::createRenderItem() { } void RenderTileSource::prepare(const SourcePrepareParameters& parameters) { + bearing = parameters.transform.state.getBearing(); + filteredRenderTiles = nullptr; + renderTilesSortedByY = nullptr; auto tiles = makeMutable>(); tiles->reserve(tilePyramid.getRenderedTiles().size()); for (auto& entry : tilePyramid.getRenderedTiles()) { @@ -73,8 +77,41 @@ bool RenderTileSource::hasFadingTiles() const { return tilePyramid.hasFadingTiles(); } -RenderTiles RenderTileSource::getRenderTiles() { - return { renderTiles->begin(), renderTiles->end() }; +RenderTiles RenderTileSource::getRenderTiles() const { + if (!filteredRenderTiles) { + auto result = std::make_shared>>(); + for (const auto& renderTile : *renderTiles) { + if (renderTile.holdForFade()) { + continue; + } + result->emplace_back(renderTile); + } + filteredRenderTiles = std::move(result); + } + return filteredRenderTiles; +} + +RenderTiles RenderTileSource::getRenderTilesSortedByYPosition() const { + if (!renderTilesSortedByY) { + const auto comp = [bearing = this->bearing](const RenderTile& a, const RenderTile& b) { + Point pa(a.id.canonical.x, a.id.canonical.y); + Point pb(b.id.canonical.x, b.id.canonical.y); + + auto par = util::rotate(pa, bearing); + auto pbr = util::rotate(pb, bearing); + + return std::tie(b.id.canonical.z, par.y, par.x) < std::tie(a.id.canonical.z, pbr.y, pbr.x); + }; + + auto result = std::make_shared>>(); + result->reserve(renderTiles->size()); + for (const auto& renderTile : *renderTiles) { + result->emplace_back(renderTile); + } + std::sort(result->begin(), result->end(), comp); + renderTilesSortedByY = std::move(result); + } + return renderTilesSortedByY; } const Tile* RenderTileSource::getRenderedTile(const UnwrappedTileID& tileID) const { diff --git a/src/mbgl/renderer/sources/render_tile_source.hpp b/src/mbgl/renderer/sources/render_tile_source.hpp index 8ec1439306..f961c20561 100644 --- a/src/mbgl/renderer/sources/render_tile_source.hpp +++ b/src/mbgl/renderer/sources/render_tile_source.hpp @@ -21,7 +21,8 @@ public: void updateFadingTiles() override; bool hasFadingTiles() const override; - RenderTiles getRenderTiles() override; + RenderTiles getRenderTiles() const override; + RenderTiles getRenderTilesSortedByYPosition() const override; const Tile* getRenderedTile(const UnwrappedTileID&) const override; std::unordered_map> @@ -40,6 +41,9 @@ public: protected: TilePyramid tilePyramid; Immutable> renderTiles; + mutable RenderTiles filteredRenderTiles; + mutable RenderTiles renderTilesSortedByY; + float bearing = 0.0f; }; } // namespace mbgl -- cgit v1.2.1 From 2c5528e691b502673b16723205c83add62317734 Mon Sep 17 00:00:00 2001 From: Aleksandar Stojiljkovic Date: Sun, 7 Jul 2019 13:40:22 +0300 Subject: Fix layers rendering after fill-extrusion This fixes following issues: * Fix some false passing combinations/fill-extrusion-translucent--XXXX tests * Fix and enable other, failing but ignored, combinations/fill-extrusion-translucent--XXXX tests * Fix rendering of layers that are on top of fill-extrusion layers state.getProjMatrix(nearClippedProjMatrix, 100) caused that tests with size 64x64 were not rendering fill extrusions: far plane calculated as 96.9 and near plane set to 100 was the cause. near plane is changed from hardcoded 100 to depend on state.getCameraToCenterDistance() - producing similar value but one that follows max zoom. This caused that e.g. combinations/fill-extrusion-translucent--fill-opaque was falsely passing as only fill-opaque layer got rendered. combinations/fill-extrusion-translucent--XXXX tests expose regression https://github.com/mapbox/mapbox-gl-native/issues/14844#issuecomment-503600034 in #14844, #14779. Fix (opaquePassCutoff, is3D) is ported from https://github.com/mapbox/mapbox-gl-js/pull/7821 Fixes: #14844, #14779, #15039 --- platform/node/test/ignores.json | 18 ------------------ .../renderer/layers/render_fill_extrusion_layer.cpp | 4 ++++ .../renderer/layers/render_fill_extrusion_layer.hpp | 1 + src/mbgl/renderer/layers/render_fill_layer.cpp | 9 ++++----- src/mbgl/renderer/paint_parameters.cpp | 12 ++++++++---- src/mbgl/renderer/paint_parameters.hpp | 3 +-- src/mbgl/renderer/render_layer.hpp | 3 +++ src/mbgl/renderer/render_orchestrator.cpp | 10 +++++++--- src/mbgl/renderer/render_tile.cpp | 2 +- src/mbgl/renderer/render_tree.hpp | 1 + src/mbgl/renderer/renderer_impl.cpp | 1 + 11 files changed, 31 insertions(+), 33 deletions(-) diff --git a/platform/node/test/ignores.json b/platform/node/test/ignores.json index 63b9764f22..4b2ed7fd3f 100644 --- a/platform/node/test/ignores.json +++ b/platform/node/test/ignores.json @@ -87,25 +87,7 @@ "render-tests/text-rotate/with-offset": "https://github.com/mapbox/mapbox-gl-native/issues/11872", "render-tests/video/default": "skip - https://github.com/mapbox/mapbox-gl-native/issues/601", "render-tests/background-color/colorSpace-hcl": "needs issue", - "render-tests/combinations/fill-extrusion-translucent--heatmap-translucent": "needs investigation", "render-tests/combinations/heatmap-translucent--background-opaque": "needs investigation", - "render-tests/combinations/heatmap-translucent--fill-extrusion-translucent": "needs investigation", - "render-tests/combinations/background-opaque--fill-extrusion-translucent": "needs investigation", - "render-tests/combinations/background-translucent--fill-extrusion-translucent": "needs investigation", - "render-tests/combinations/circle-translucent--fill-extrusion-translucent": "needs investigation", - "render-tests/combinations/fill-extrusion-translucent--background-translucent": "needs investigation", - "render-tests/combinations/fill-extrusion-translucent--circle-translucent": "needs investigation", - "render-tests/combinations/fill-extrusion-translucent--hillshade-translucent": "needs investigation", - "render-tests/combinations/fill-extrusion-translucent--fill-extrusion-translucent": "needs investigation", - "render-tests/combinations/fill-extrusion-translucent--fill-translucent": "needs investigation", - "render-tests/combinations/fill-extrusion-translucent--line-translucent": "needs investigation", - "render-tests/combinations/fill-extrusion-translucent--symbol-translucent": "needs investigation", - "render-tests/combinations/hillshade-translucent--fill-extrusion-translucent": "needs investigation", - "render-tests/combinations/fill-opaque--fill-extrusion-translucent": "needs investigation", - "render-tests/combinations/fill-translucent--fill-extrusion-translucent": "needs investigation", - "render-tests/combinations/line-translucent--fill-extrusion-translucent": "needs investigation", - "render-tests/combinations/raster-translucent--fill-extrusion-translucent": "needs investigation", - "render-tests/combinations/symbol-translucent--fill-extrusion-translucent": "needs investigation", "render-tests/feature-state/composite-expression": "https://github.com/mapbox/mapbox-gl-native/issues/12613", "render-tests/feature-state/data-expression": "https://github.com/mapbox/mapbox-gl-native/issues/12613", "render-tests/feature-state/vector-source": "https://github.com/mapbox/mapbox-gl-native/issues/12613", diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp index b8d195cfa1..5ad2e53a5b 100644 --- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp @@ -55,6 +55,10 @@ bool RenderFillExtrusionLayer::hasCrossfade() const { return getCrossfade(evaluatedProperties).t != 1; } +bool RenderFillExtrusionLayer::is3D() const { + return true; +} + void RenderFillExtrusionLayer::render(PaintParameters& parameters) { assert(renderTiles); if (parameters.pass != RenderPass::Translucent) { diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp index 9118601581..8bd1f52adf 100644 --- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp @@ -17,6 +17,7 @@ private: void evaluate(const PropertyEvaluationParameters&) override; bool hasTransition() const override; bool hasCrossfade() const override; + bool is3D() const override; void render(PaintParameters&) override; bool queryIntersectsFeature( diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index 6a3c247fbb..c2bf149582 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -130,11 +130,10 @@ void RenderFillLayer::render(PaintParameters& parameters) { ); }; - // Only draw the fill when it's opaque and we're drawing opaque fragments, - // or when it's translucent and we're drawing translucent fragments. - if (bucket.triangleIndexBuffer && - (evaluated.get().constantOr(Color()).a >= 1.0f && - evaluated.get().constantOr(0) >= 1.0f) == (parameters.pass == RenderPass::Opaque)) { + auto fillRenderPass = (evaluated.get().constantOr(Color()).a >= 1.0f + && evaluated.get().constantOr(0) >= 1.0f + && parameters.currentLayer >= parameters.opaquePassCutoff) ? RenderPass::Opaque : RenderPass::Translucent; + if (bucket.triangleIndexBuffer && parameters.pass == fillRenderPass) { draw(parameters.programs.getFillLayerPrograms().fill, gfx::Triangles(), parameters.depthModeForSublayer(1, parameters.pass == RenderPass::Opaque diff --git a/src/mbgl/renderer/paint_parameters.cpp b/src/mbgl/renderer/paint_parameters.cpp index 1539c0fbcb..6c6abc008b 100644 --- a/src/mbgl/renderer/paint_parameters.cpp +++ b/src/mbgl/renderer/paint_parameters.cpp @@ -19,10 +19,11 @@ TransformParameters::TransformParameters(const TransformState& state_) // odd viewport sizes. state.getProjMatrix(alignedProjMatrix, 1, true); - // Calculate a second projection matrix with the near plane clipped to 100 so as - // not to waste lots of depth buffer precision on very close empty space, for layer - // types (fill-extrusion) that use the depth buffer to emulate real-world space. - state.getProjMatrix(nearClippedProjMatrix, 100); + // Calculate a second projection matrix with the near plane moved further, + // to a tenth of the far value, so as not to waste depth buffer precision on + // very close empty space, for layer types (fill-extrusion) that use the + // depth buffer to emulate real-world space. + state.getProjMatrix(nearClippedProjMatrix, 0.1 * state.getCameraToCenterDistance()); } PaintParameters::PaintParameters(gfx::Context& context_, @@ -72,6 +73,9 @@ mat4 PaintParameters::matrixForTile(const UnwrappedTileID& tileID, bool aligned) } gfx::DepthMode PaintParameters::depthModeForSublayer(uint8_t n, gfx::DepthMaskType mask) const { + if (currentLayer < opaquePassCutoff) { + return gfx::DepthMode::disabled(); + } float depth = depthRangeSize + ((1 + currentLayer) * numSublayers + n) * depthEpsilon; return gfx::DepthMode { gfx::DepthFunctionType::LessEqual, mask, { depth, depth } }; } diff --git a/src/mbgl/renderer/paint_parameters.hpp b/src/mbgl/renderer/paint_parameters.hpp index a0d26df7c5..a043ad5578 100644 --- a/src/mbgl/renderer/paint_parameters.hpp +++ b/src/mbgl/renderer/paint_parameters.hpp @@ -104,8 +104,7 @@ public: uint32_t currentLayer; float depthRangeSize; const float depthEpsilon = 1.0f / (1 << 16); - - + uint32_t opaquePassCutoff = 0; float symbolFadeChange; }; diff --git a/src/mbgl/renderer/render_layer.hpp b/src/mbgl/renderer/render_layer.hpp index c7efdceab4..fe8b7c6529 100644 --- a/src/mbgl/renderer/render_layer.hpp +++ b/src/mbgl/renderer/render_layer.hpp @@ -66,6 +66,9 @@ public: // Returns true if the layer has a pattern property and is actively crossfading. virtual bool hasCrossfade() const = 0; + // Returns true if layer writes to depth buffer by drawing using PaintParameters::depthModeFor3D(). + virtual bool is3D() const { return false; } + // Returns true is the layer is subject to placement. bool needsPlacement() const; diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp index 7df74cda71..c70ce63c76 100644 --- a/src/mbgl/renderer/render_orchestrator.cpp +++ b/src/mbgl/renderer/render_orchestrator.cpp @@ -342,12 +342,16 @@ std::unique_ptr RenderOrchestrator::createRenderTree(const UpdatePar } } - for (auto& renderItem : layerRenderItems) { - RenderLayer& renderLayer = renderItem.layer; - renderLayer.prepare({renderItem.source, *imageManager, *patternAtlas, *lineAtlas, updateParameters.transformState}); + uint32_t i = static_cast(layerRenderItems.size()) - 1; + for (auto it = layerRenderItems.begin(); it != layerRenderItems.end(); ++it, --i) { + RenderLayer& renderLayer = it->layer; + renderLayer.prepare({it->source, *imageManager, *patternAtlas, *lineAtlas, updateParameters.transformState}); if (renderLayer.needsPlacement()) { layersNeedPlacement.emplace_back(renderLayer); } + if (renderLayer.is3D() && renderTreeParameters->opaquePassCutOff == 0) { + renderTreeParameters->opaquePassCutOff = i; + } } // Symbol placement. { diff --git a/src/mbgl/renderer/render_tile.cpp b/src/mbgl/renderer/render_tile.cpp index fbb2ae81de..65a6cb9f30 100644 --- a/src/mbgl/renderer/render_tile.cpp +++ b/src/mbgl/renderer/render_tile.cpp @@ -121,7 +121,7 @@ void RenderTile::prepare(const SourcePrepareParameters& parameters) { } // Calculate two matrices for this tile: matrix is the standard tile matrix; nearClippedMatrix - // clips the near plane to 100 to save depth buffer precision + // has near plane moved further, to enhance depth buffer precision const auto& transform = parameters.transform; transform.state.matrixFor(matrix, id); transform.state.matrixFor(nearClippedMatrix, id); diff --git a/src/mbgl/renderer/render_tree.hpp b/src/mbgl/renderer/render_tree.hpp index 4266ddec6d..cf62ccb03e 100644 --- a/src/mbgl/renderer/render_tree.hpp +++ b/src/mbgl/renderer/render_tree.hpp @@ -47,6 +47,7 @@ public: TimePoint timePoint; EvaluatedLight light; bool has3D = false; + uint32_t opaquePassCutOff = 0; Color backgroundColor; float symbolFadeChange = 0.0f; bool needsRepaint = false; diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index c536497c30..990d9cd3ab 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -77,6 +77,7 @@ void Renderer::Impl::render(const RenderTree& renderTree) { }; parameters.symbolFadeChange = renderTreeParameters.symbolFadeChange; + parameters.opaquePassCutoff = renderTreeParameters.opaquePassCutOff; const auto& sourceRenderItems = renderTree.getSourceRenderItems(); const auto& layerRenderItems = renderTree.getLayerRenderItems(); -- cgit v1.2.1 From 286bc66ba4eef043af1d67858f8f5ec540717f31 Mon Sep 17 00:00:00 2001 From: Aleksandar Stojiljkovic Date: Tue, 9 Jul 2019 14:07:41 +0300 Subject: Issue #15065 changelogs and nit fix. --- platform/android/CHANGELOG.md | 1 + platform/ios/CHANGELOG.md | 1 + platform/macos/CHANGELOG.md | 1 + src/mbgl/renderer/render_orchestrator.cpp | 11 ++++++----- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index c699349bec..d4545e36a7 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -5,6 +5,7 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to ## master * Performance improvements for queryRenderedFeatures API and optimization that allocates containers based on a number of rendered layers. ([#14930](https://github.com/mapbox/mapbox-gl-native/pull/14930)) +- Fixed rendering layers after fill-extrusion regression caused by optimization of fill-extrusion rendering [#15065](https://github.com/mapbox/mapbox-gl-native/pull/15065) ## 8.2.0-alpha.2 - July 3, 2019 diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index 201f92590c..79e96bb84c 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -5,6 +5,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT ## master * Performance improvements for queryRenderedFeatures API and optimization that allocates containers based on a number of rendered layers. ([#14930](https://github.com/mapbox/mapbox-gl-native/pull/14930)) +* Fixed rendering layers after fill-extrusion regression caused by optimization of fill-extrusion rendering. ([#15065](https://github.com/mapbox/mapbox-gl-native/pull/15065)) ## 5.2.0 diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md index bf4ff55156..8ca9477301 100644 --- a/platform/macos/CHANGELOG.md +++ b/platform/macos/CHANGELOG.md @@ -5,6 +5,7 @@ * Added an `MGLMapView.prefetchesTiles` property to configure lower-resolution tile prefetching behavior. ([#14816](https://github.com/mapbox/mapbox-gl-native/pull/14816)) * Fixed queryRenderedFeatues bug caused by incorrect sort feature index calculation. ([#14884](https://github.com/mapbox/mapbox-gl-native/pull/14884)) * Performance improvements for queryRenderedFeatures API and optimization that allocates containers based on a number of rendered layers. ([#14930](https://github.com/mapbox/mapbox-gl-native/pull/14930)) +* Fixed rendering layers after fill-extrusion regression caused by optimization of fill-extrusion rendering. ([#15065](https://github.com/mapbox/mapbox-gl-native/pull/15065)) ### Styles and rendering diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp index c70ce63c76..cf5a7d190e 100644 --- a/src/mbgl/renderer/render_orchestrator.cpp +++ b/src/mbgl/renderer/render_orchestrator.cpp @@ -342,15 +342,16 @@ std::unique_ptr RenderOrchestrator::createRenderTree(const UpdatePar } } - uint32_t i = static_cast(layerRenderItems.size()) - 1; - for (auto it = layerRenderItems.begin(); it != layerRenderItems.end(); ++it, --i) { - RenderLayer& renderLayer = it->layer; - renderLayer.prepare({it->source, *imageManager, *patternAtlas, *lineAtlas, updateParameters.transformState}); + auto opaquePassCutOffEstimation = layerRenderItems.size(); + for (auto& renderItem : layerRenderItems) { + RenderLayer& renderLayer = renderItem.layer; + renderLayer.prepare({renderItem.source, *imageManager, *patternAtlas, *lineAtlas, updateParameters.transformState}); if (renderLayer.needsPlacement()) { layersNeedPlacement.emplace_back(renderLayer); } if (renderLayer.is3D() && renderTreeParameters->opaquePassCutOff == 0) { - renderTreeParameters->opaquePassCutOff = i; + --opaquePassCutOffEstimation; + renderTreeParameters->opaquePassCutOff = uint32_t(opaquePassCutOffEstimation); } } // Symbol placement. -- cgit v1.2.1 From eaed0036efe04cfaa50218f7041078972427dffb Mon Sep 17 00:00:00 2001 From: Mikhail Pozdnyakov Date: Tue, 9 Jul 2019 16:29:30 +0300 Subject: [glfw] Reduce memory use when window loses focus --- platform/glfw/glfw_view.cpp | 8 ++++++++ platform/glfw/glfw_view.hpp | 1 + 2 files changed, 9 insertions(+) diff --git a/platform/glfw/glfw_view.cpp b/platform/glfw/glfw_view.cpp index 41c3e93b35..43c4de9759 100644 --- a/platform/glfw/glfw_view.cpp +++ b/platform/glfw/glfw_view.cpp @@ -102,6 +102,7 @@ GLFWView::GLFWView(bool fullscreen_, bool benchmark_) glfwSetFramebufferSizeCallback(window, onFramebufferResize); glfwSetScrollCallback(window, onScroll); glfwSetKeyCallback(window, onKey); + glfwSetWindowFocusCallback(window, onWindowFocus); glfwGetWindowSize(window, &width, &height); @@ -559,6 +560,13 @@ void GLFWView::onMouseMove(GLFWwindow *window, double x, double y) { view->lastY = y; } +void GLFWView::onWindowFocus(GLFWwindow *window, int focused) { + if (focused == GLFW_FALSE) { // Focus lost. + auto *view = reinterpret_cast(glfwGetWindowUserPointer(window)); + view->rendererFrontend->getRenderer()->reduceMemoryUse(); + } +} + void GLFWView::run() { auto callback = [&] { if (glfwWindowShouldClose(window)) { diff --git a/platform/glfw/glfw_view.hpp b/platform/glfw/glfw_view.hpp index 9c9661546c..54b89ba2d9 100644 --- a/platform/glfw/glfw_view.hpp +++ b/platform/glfw/glfw_view.hpp @@ -68,6 +68,7 @@ private: static void onFramebufferResize(GLFWwindow *window, int width, int height); static void onMouseClick(GLFWwindow *window, int button, int action, int modifiers); static void onMouseMove(GLFWwindow *window, double x, double y); + static void onWindowFocus(GLFWwindow *window, int focused); // Internal void report(float duration); -- cgit v1.2.1 From 6b8df343ef3a9df77082630435bb4af6df0e798f Mon Sep 17 00:00:00 2001 From: Mikhail Pozdnyakov Date: Tue, 9 Jul 2019 16:32:45 +0300 Subject: [core] Put gfx backend scope guard to Renderer::reduceMemoryUse() --- src/mbgl/renderer/renderer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mbgl/renderer/renderer.cpp b/src/mbgl/renderer/renderer.cpp index 76e618a50f..dd715bd3bc 100644 --- a/src/mbgl/renderer/renderer.cpp +++ b/src/mbgl/renderer/renderer.cpp @@ -116,6 +116,7 @@ void Renderer::dumpDebugLogs() { } void Renderer::reduceMemoryUse() { + gfx::BackendScope guard { impl->backend }; impl->reduceMemoryUse(); impl->orchestrator.reduceMemoryUse(); } -- cgit v1.2.1 From 4d84e52ce23e9abb9f9ca8ee802f324ce2694218 Mon Sep 17 00:00:00 2001 From: Aleksandar Stojiljkovic Date: Tue, 9 Jul 2019 17:16:48 +0300 Subject: Enable ignored but passing run-time styling tests (#6745) --- platform/node/test/ignores.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/platform/node/test/ignores.json b/platform/node/test/ignores.json index 4b2ed7fd3f..a97ee70325 100644 --- a/platform/node/test/ignores.json +++ b/platform/node/test/ignores.json @@ -77,8 +77,6 @@ "render-tests/regressions/mapbox-gl-js#7271": "https://github.com/mapbox/mapbox-gl-native/issues/12888", "render-tests/regressions/mapbox-gl-js#7302": "skip - js specific", "render-tests/regressions/mapbox-gl-native#7357": "https://github.com/mapbox/mapbox-gl-native/issues/7357", - "render-tests/runtime-styling/paint-property-fill-flat-to-extrude": "https://github.com/mapbox/mapbox-gl-native/issues/6745", - "render-tests/runtime-styling/set-style-paint-property-fill-flat-to-extrude": "https://github.com/mapbox/mapbox-gl-native/issues/6745", "render-tests/symbol-cross-fade/chinese": "https://github.com/mapbox/mapbox-gl-native/issues/10619", "render-tests/symbol-visibility/visible": "https://github.com/mapbox/mapbox-gl-native/issues/10409", "render-tests/text-pitch-alignment/auto-text-rotation-alignment-map": "https://github.com/mapbox/mapbox-gl-native/issues/9732", -- cgit v1.2.1 From da8ed930de1e0f8f58f1a50d14cc727c9b7132f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Paczos?= Date: Mon, 8 Jul 2019 16:26:33 +0200 Subject: [core] decrease the minimum pixel distance required to interpolate during camera animation The changes introduced in #9199 changed the minimum required pixel distance between start and end points to >= 1px in order to interpolate, which in scenarios of big zoom changes and low pixel density can result in animation to the previous position and then a jump to the target. --- src/mbgl/map/transform.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp index 88b559592e..a51d4dd4ff 100644 --- a/src/mbgl/map/transform.cpp +++ b/src/mbgl/map/transform.cpp @@ -236,7 +236,7 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima double r1 = r(1); // When u₀ = u₁, the optimal path doesn’t require both ascent and descent. - bool isClose = std::abs(u1) < 1.0 || !std::isfinite(r0) || !std::isfinite(r1); + bool isClose = std::abs(u1) < 0.000001 || !std::isfinite(r0) || !std::isfinite(r1); /** w(s): Returns the visible span on the ground, measured in pixels with respect to the initial scale. -- cgit v1.2.1 From 18f7e4b84d761623a825498398ef58b79ee39ecd Mon Sep 17 00:00:00 2001 From: Jason Wray Date: Mon, 8 Jul 2019 17:06:18 -0700 Subject: [build] Opt out of homebrew cleanup on CI --- circle.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/circle.yml b/circle.yml index e69ef56e0d..b15eb6610d 100644 --- a/circle.yml +++ b/circle.yml @@ -770,6 +770,7 @@ jobs: environment: BUILDTYPE: RelWithDebInfo HOMEBREW_NO_AUTO_UPDATE: 1 + HOMEBREW_NO_INSTALL_CLEANUP: 1 steps: - install-macos-dependencies - install-node-macos-dependencies @@ -950,6 +951,7 @@ jobs: environment: BUILDTYPE: Debug HOMEBREW_NO_AUTO_UPDATE: 1 + HOMEBREW_NO_INSTALL_CLEANUP: 1 steps: - install-macos-dependencies - install-dependencies @@ -990,6 +992,7 @@ jobs: environment: BUILDTYPE: Debug HOMEBREW_NO_AUTO_UPDATE: 1 + HOMEBREW_NO_INSTALL_CLEANUP: 1 SLACK_CHANNEL: C0ACM9Q2C steps: - install-macos-dependencies @@ -1013,6 +1016,7 @@ jobs: environment: BUILDTYPE: Debug HOMEBREW_NO_AUTO_UPDATE: 1 + HOMEBREW_NO_INSTALL_CLEANUP: 1 SLACK_CHANNEL: C0ACM9Q2C steps: - install-macos-dependencies @@ -1032,6 +1036,7 @@ jobs: environment: BUILDTYPE: Debug HOMEBREW_NO_AUTO_UPDATE: 1 + HOMEBREW_NO_INSTALL_CLEANUP: 1 SLACK_CHANNEL: C0ACM9Q2C steps: - install-macos-dependencies @@ -1051,6 +1056,7 @@ jobs: environment: BUILDTYPE: Release HOMEBREW_NO_AUTO_UPDATE: 1 + HOMEBREW_NO_INSTALL_CLEANUP: 1 SLACK_CHANNEL: C0ACM9Q2C steps: - install-macos-dependencies @@ -1091,6 +1097,7 @@ jobs: environment: BUILDTYPE: Release HOMEBREW_NO_AUTO_UPDATE: 1 + HOMEBREW_NO_INSTALL_CLEANUP: 1 SLACK_CHANNEL: C0ACM9Q2C steps: - checkout @@ -1134,6 +1141,7 @@ jobs: environment: BUILDTYPE: Debug HOMEBREW_NO_AUTO_UPDATE: 1 + HOMEBREW_NO_INSTALL_CLEANUP: 1 steps: - install-macos-dependencies - install-dependencies @@ -1159,6 +1167,7 @@ jobs: environment: BUILDTYPE: RelWithDebInfo HOMEBREW_NO_AUTO_UPDATE: 1 + HOMEBREW_NO_INSTALL_CLEANUP: 1 JOBS: 2 steps: - install-macos-dependencies @@ -1203,6 +1212,7 @@ jobs: environment: BUILDTYPE: Debug HOMEBREW_NO_AUTO_UPDATE: 1 + HOMEBREW_NO_INSTALL_CLEANUP: 1 steps: - install-macos-dependencies - install-qt-macos-dependencies -- cgit v1.2.1 From 6b59db8fb0118633e354b4fff5d615a0f095faa7 Mon Sep 17 00:00:00 2001 From: m-stephen Date: Wed, 10 Jul 2019 10:00:35 +0800 Subject: [ios, macos] Default to local rendering of CJK characters, using system font (#14862) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Change default CJK font from "PingFang" to "Helvetica" * Add CHANGELOG. * Update CHANGELOG. * [ios] Enable client-side rendering and use `Helvetica` by default. Set `MGLIdeographicFontFamilyName` to `NULL` for using your custom remote font. * [ios] Update change log * [ios] Change default CJK configuration in `iosapp` project * [ios] Update comment * [ios] return local font name using default system font. * [ios] Update changelog * [ios] update changelogs & comments * [iOS, macOS]Support mac os * [iOS, macOS] fix bug * [iOS, macOS] update change log * [iOS, macOS] fix nit. * [iOS, macOS] Ability to specify an array of fonts for fallbacks for `localIdeographicFontFamily` * [iOS, macOS] Update comments * [iOS, macOS] Update change log * [iOS, macOS] update for mac OS font family names * Fix nit. * Update platform/ios/CHANGELOG.md Co-Authored-By: Minh Nguyễn * [iOS, macOS] Set `MGLIdeographicFontFamilyName` to a Boolean value `NO` for using your custom remote font. * [iOS, macOS] remove `MGLIdeographicFontFamilyName` from info.plist & update Info.plist Keys.md * [iOS, macOS] remove `MGLIdeographicFontFamilyName` from macOS demo app project and update info.plist Keys.md * [iOS, macOS] update macOS changelog * [iOS, macOS] Change docs * Update Change log * [iOS, macOS] Test case * Update platform/macos/docs/guides/Info.plist Keys.md Co-Authored-By: Jason Wray * Update platform/macos/docs/guides/Info.plist Keys.md Co-Authored-By: Jason Wray * Update platform/ios/CHANGELOG.md Co-Authored-By: Jason Wray * Update platform/darwin/src/MGLRendererConfiguration.mm Co-Authored-By: Jason Wray * Update platform/darwin/test/MGLRendererConfigurationTests.mm Co-Authored-By: Jason Wray * Update platform/macos/docs/guides/Info.plist Keys.md Co-Authored-By: Jason Wray * Update platform/macos/docs/guides/Info.plist Keys.md Co-Authored-By: Jason Wray * Update platform/macos/docs/guides/Info.plist Keys.md Co-Authored-By: Jason Wray * [iOS, macOS] update comments * [iOS, macOS] add plist value test && filter for invalid string * [iOS, macOS] fix nit * Update platform/ios/docs/guides/Info.plist Keys.md Co-Authored-By: Jason Wray * Update platform/ios/docs/guides/Info.plist Keys.md Co-Authored-By: Jason Wray * Update platform/ios/docs/guides/Info.plist Keys.md Co-Authored-By: Jason Wray * Update platform/macos/CHANGELOG.md Co-Authored-By: Jason Wray * Update platform/ios/docs/guides/Info.plist Keys.md Co-Authored-By: Jason Wray * Update platform/ios/docs/guides/Info.plist Keys.md Co-Authored-By: Jason Wray * [iOS, macOS] add invalid value type test * Apply own suggestions from code review --- platform/darwin/src/MGLRendererConfiguration.h | 23 +++-- platform/darwin/src/MGLRendererConfiguration.mm | 51 +++++++++- .../darwin/test/MGLRendererConfigurationTests.mm | 105 ++++++++++++++++++++- platform/ios/CHANGELOG.md | 1 + platform/ios/app/Info.plist | 2 - platform/ios/docs/guides/Info.plist Keys.md | 13 ++- platform/macos/CHANGELOG.md | 2 + platform/macos/app/Info.plist | 2 - platform/macos/docs/guides/Info.plist Keys.md | 14 ++- 9 files changed, 191 insertions(+), 22 deletions(-) diff --git a/platform/darwin/src/MGLRendererConfiguration.h b/platform/darwin/src/MGLRendererConfiguration.h index ee5aaef174..bfe88b7209 100644 --- a/platform/darwin/src/MGLRendererConfiguration.h +++ b/platform/darwin/src/MGLRendererConfiguration.h @@ -23,14 +23,21 @@ MGL_EXPORT /** The cache dir to use. */ @property (nonatomic, readonly) mbgl::optional cacheDir; -/** The name of the font family to use for client-side text rendering. - - Currently only used for CJK glyphs. Changing this at run time is not currently - supported. Enable client-side rendering of CJK glyphs by setting - `MGLIdeographicFontFamilyName` in your containing app's Info.plist to a value - which will be available at run time. Default font for local ideograph font family - is "PingFang". */ -@property (nonatomic, readonly) std::string localFontFamilyName; +/** The name of the font family to use for client-side text rendering of CJK ideographs. + + Set MGLIdeographicFontFamilyName in your containing application's Info.plist to + font family name(s) that will be available at run time, such as “PingFang TC” + or “Marker Felt”. This plist key accepts: + + - A string value of a single font family name. + + - An array of font family names. Fonts will be used in the defined order, + eventually falling back to default system font if none are available. + + - A boolean value NO to disable client-side rendering of CJK glyphs — + remote fonts specified in your style will be used instead. + */ +@property (nonatomic, readonly) mbgl::optional localFontFamilyName; /** A Boolean value indicating whether symbol layers may enable per-source symbol diff --git a/platform/darwin/src/MGLRendererConfiguration.mm b/platform/darwin/src/MGLRendererConfiguration.mm index d616e93eb2..54bdcaa691 100644 --- a/platform/darwin/src/MGLRendererConfiguration.mm +++ b/platform/darwin/src/MGLRendererConfiguration.mm @@ -9,6 +9,7 @@ #endif static NSString * const MGLCollisionBehaviorPre4_0Key = @"MGLCollisionBehaviorPre4_0"; +static NSString * const MGLIdeographicFontFamilyNameKey = @"MGLIdeographicFontFamilyName"; @interface MGLRendererConfiguration () @property (nonatomic, readwrite) BOOL perSourceCollisions; @@ -69,10 +70,54 @@ static NSString * const MGLCollisionBehaviorPre4_0Key = @"MGLCollisionBehaviorPr return mbgl::optional(); } -- (std::string)localFontFamilyName { - NSString *fontFamilyName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"MGLIdeographicFontFamilyName"]; +- (mbgl::optional)localFontFamilyName { + return [self _localFontFamilyNameWithPropertyDictionary:[[NSBundle mainBundle] infoDictionary]]; +} - return fontFamilyName ? std::string([fontFamilyName UTF8String]) : std::string("PingFang"); +- (mbgl::optional)_localFontFamilyNameWithPropertyDictionary:(nonnull NSDictionary *)properties { + + std::string systemFontFamilyName; +#if TARGET_OS_IPHONE + systemFontFamilyName = std::string([[UIFont systemFontOfSize:0 weight:UIFontWeightRegular].familyName UTF8String]); +#else + systemFontFamilyName = std::string([[NSFont systemFontOfSize:0 weight:NSFontWeightRegular].familyName UTF8String]); +#endif + + id fontFamilyName = properties[MGLIdeographicFontFamilyNameKey]; + + if([fontFamilyName isKindOfClass:[NSNumber class]] && ![fontFamilyName boolValue]) + { + return mbgl::optional(); + } + else if([fontFamilyName isKindOfClass:[NSString class]]) + { + BOOL isValidFont = NO; +#if TARGET_OS_IPHONE + if([[UIFont familyNames] containsObject:fontFamilyName]){ + isValidFont = YES; + } +#else + if([[[NSFontManager sharedFontManager] availableFontFamilies] containsObject:fontFamilyName]){ + isValidFont = YES; + } +#endif + return (fontFamilyName && isValidFont) ? std::string([fontFamilyName UTF8String]) : systemFontFamilyName; + } + // Ability to specify an array of fonts for fallbacks for `localIdeographicFontFamily` + else if ([fontFamilyName isKindOfClass:[NSArray class]]){ + for(NSString *name in fontFamilyName){ +#if TARGET_OS_IPHONE + if([[UIFont familyNames] containsObject:name]){ + return std::string([name UTF8String]); + } +#else + if([[[NSFontManager sharedFontManager] availableFontFamilies] containsObject:name]){ + return std::string([name UTF8String]); + } +#endif + } + } + return systemFontFamilyName; } @end diff --git a/platform/darwin/test/MGLRendererConfigurationTests.mm b/platform/darwin/test/MGLRendererConfigurationTests.mm index a0c630ebb5..6483aa3587 100644 --- a/platform/darwin/test/MGLRendererConfigurationTests.mm +++ b/platform/darwin/test/MGLRendererConfigurationTests.mm @@ -6,6 +6,7 @@ static NSString * const MGLRendererConfigurationTests_collisionBehaviorKey = @"M @interface MGLRendererConfiguration (Tests) - (instancetype)initWithPropertyDictionary:(nonnull NSDictionary*)bundle; +- (mbgl::optional)_localFontFamilyNameWithPropertyDictionary:(nonnull NSDictionary *)properties; @end @@ -77,14 +78,12 @@ static NSString * const MGLRendererConfigurationTests_collisionBehaviorKey = @"M } - (void)testOverridingMGLCollisionBehaviorPre40 { - // Dictionary = NO, NSUserDefaults = YES { [[NSUserDefaults standardUserDefaults] setObject:@(YES) forKey:MGLRendererConfigurationTests_collisionBehaviorKey]; MGLRendererConfiguration *config = [[MGLRendererConfiguration alloc] initWithPropertyDictionary:@{MGLRendererConfigurationTests_collisionBehaviorKey:@(NO)}]; XCTAssert(config.perSourceCollisions); } - // Dictionary = YES, NSUserDefaults = NO { [[NSUserDefaults standardUserDefaults] setObject:@(NO) forKey:MGLRendererConfigurationTests_collisionBehaviorKey]; @@ -93,4 +92,106 @@ static NSString * const MGLRendererConfigurationTests_collisionBehaviorKey = @"M } } +- (void)testDefaultLocalFontFamilyName { + + MGLRendererConfiguration *config = [[MGLRendererConfiguration alloc] init]; + std::string localFontFamilyName = config.localFontFamilyName.value(); + + std::string systemFontFamilyName; +#if TARGET_OS_IPHONE + systemFontFamilyName = std::string([[UIFont systemFontOfSize:0 weight:UIFontWeightRegular].familyName UTF8String]); +#else + systemFontFamilyName = std::string([[NSFont systemFontOfSize:0 weight:NSFontWeightRegular].familyName UTF8String]); +#endif + + XCTAssertEqual(localFontFamilyName, systemFontFamilyName, @"Default local font family name should match default system font"); +} + +- (void)testSettingMGLIdeographicFontFamilyNameWithPlistValue { + + MGLRendererConfiguration *config = [[MGLRendererConfiguration alloc] init]; + NSDictionary *dic; + + // `MGLIdeographicFontFamilyName` set to bool value `YES` + { + dic = @{@"MGLIdeographicFontFamilyName": @(YES)}; + std::string localFontFamilyName = ([config _localFontFamilyNameWithPropertyDictionary:dic]).value(); + + std::string systemFontFamilyName; +#if TARGET_OS_IPHONE + systemFontFamilyName = std::string([[UIFont systemFontOfSize:0 weight:UIFontWeightRegular].familyName UTF8String]); +#else + systemFontFamilyName = std::string([[NSFont systemFontOfSize:0 weight:NSFontWeightRegular].familyName UTF8String]); +#endif + XCTAssertEqual(localFontFamilyName, systemFontFamilyName, @"Local font family name should match default system font name when setting `YES`"); + } + + // `MGLIdeographicFontFamilyName` set to bool value `NO` + { + dic = @{@"MGLIdeographicFontFamilyName": @(NO)}; + mbgl::optional localFontFamilyName = [config _localFontFamilyNameWithPropertyDictionary:dic]; + XCTAssertFalse(localFontFamilyName.has_value(), @"Client rendering font should use remote font when setting `NO`"); + } + + // `MGLIdeographicFontFamilyName` set to a valid font string value + { + dic = @{@"MGLIdeographicFontFamilyName": @"PingFang TC"}; + std::string localFontFamilyName = ([config _localFontFamilyNameWithPropertyDictionary:dic]).value(); + std::string targetFontFamilyName = std::string([@"PingFang TC" UTF8String]); + XCTAssertEqual(localFontFamilyName, targetFontFamilyName, @"Local font family name should match a custom valid font name"); + } + + // `MGLIdeographicFontFamilyName` set to an invalid font string value + { + dic = @{@"MGLIdeographicFontFamilyName": @"test font"}; + std::string localFontFamilyName = ([config _localFontFamilyNameWithPropertyDictionary:dic]).value(); + + std::string systemFontFamilyName; +#if TARGET_OS_IPHONE + systemFontFamilyName = std::string([[UIFont systemFontOfSize:0 weight:UIFontWeightRegular].familyName UTF8String]); +#else + systemFontFamilyName = std::string([[NSFont systemFontOfSize:0 weight:NSFontWeightRegular].familyName UTF8String]); +#endif + XCTAssertEqual(localFontFamilyName, systemFontFamilyName, @"Local font family name should match default system font name when setting an invalid font string"); + } + + // `MGLIdeographicFontFamilyName` set to a valid font family names array value + { + dic = @{@"MGLIdeographicFontFamilyName": @[@"test font 1", @"PingFang TC", @"test font 2"]}; + std::string localFontFamilyName = ([config _localFontFamilyNameWithPropertyDictionary:dic]).value(); + std::string targetFontFamilyName = std::string([@"PingFang TC" UTF8String]); + XCTAssertEqual(localFontFamilyName, targetFontFamilyName, @"Local font family name should match a custom valid font name in a font family names array"); + } + + // `MGLIdeographicFontFamilyName` set to an invalid font family names array value + { + dic = @{@"MGLIdeographicFontFamilyName": @[@"test font 1", @"test font 2", @"test font 3"]}; + std::string localFontFamilyName = ([config _localFontFamilyNameWithPropertyDictionary:dic]).value(); + + std::string systemFontFamilyName; +#if TARGET_OS_IPHONE + systemFontFamilyName = std::string([[UIFont systemFontOfSize:0 weight:UIFontWeightRegular].familyName UTF8String]); +#else + systemFontFamilyName = std::string([[NSFont systemFontOfSize:0 weight:NSFontWeightRegular].familyName UTF8String]); +#endif + XCTAssertEqual(localFontFamilyName, systemFontFamilyName, @"Local font family name should match default system font name when setting an invalid font family names array"); + } + + // `MGLIdeographicFontFamilyName` set to an invalid value type: NSDictionary, NSNumber, NSData, etc. + { + dic = @{@"MGLIdeographicFontFamilyName": [@"test font 1" dataUsingEncoding:NSUTF8StringEncoding]}; + std::string localFontFamilyName = ([config _localFontFamilyNameWithPropertyDictionary:dic]).value(); + + std::string systemFontFamilyName; +#if TARGET_OS_IPHONE + systemFontFamilyName = std::string([[UIFont systemFontOfSize:0 weight:UIFontWeightRegular].familyName UTF8String]); +#else + systemFontFamilyName = std::string([[NSFont systemFontOfSize:0 weight:NSFontWeightRegular].familyName UTF8String]); +#endif + XCTAssertEqual(localFontFamilyName, systemFontFamilyName, @"Local font family name should match default system font name when setting an invalid value type"); + } +} + + + @end diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index 79e96bb84c..82968a2582 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -4,6 +4,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT ## master +* The `MGLIdeographicFontFamilyName` Info.plist key now also accepts an array of font family names, to customize font fallback behavior. It can also be set to a Boolean value of `NO` to force the SDK to typeset CJK characters in a remote font specified by `MGLSymbolStyleLayer.textFontNames`. ([#14862](https://github.com/mapbox/mapbox-gl-native/pull/14862)) * Performance improvements for queryRenderedFeatures API and optimization that allocates containers based on a number of rendered layers. ([#14930](https://github.com/mapbox/mapbox-gl-native/pull/14930)) * Fixed rendering layers after fill-extrusion regression caused by optimization of fill-extrusion rendering. ([#15065](https://github.com/mapbox/mapbox-gl-native/pull/15065)) diff --git a/platform/ios/app/Info.plist b/platform/ios/app/Info.plist index e2f294a5a5..c302f306a6 100644 --- a/platform/ios/app/Info.plist +++ b/platform/ios/app/Info.plist @@ -24,8 +24,6 @@ 7877 LSRequiresIPhoneOS - MGLIdeographicFontFamilyName - PingFang TC NSHumanReadableCopyright © 2014–2019 Mapbox NSLocationAlwaysUsageDescription diff --git a/platform/ios/docs/guides/Info.plist Keys.md b/platform/ios/docs/guides/Info.plist Keys.md index 97b9d7419e..6322b42dc1 100644 --- a/platform/ios/docs/guides/Info.plist Keys.md +++ b/platform/ios/docs/guides/Info.plist Keys.md @@ -22,7 +22,15 @@ If you have implemented custom opt-out of Mapbox Telemetry within the user inter ## MGLIdeographicFontFamilyName -The name of the font family to use for client-side text rendering of CJK ideographs. Set this to the name of a font family which will be available at run time, e.g. `PingFang TC` (iOS 9+), `Heiti TC` (iOS 8+), another appropriate built-in font, or a font provided by your application. Note that if a non-existent font is specified, iOS will fall back to using Helvetica which is likely not to include support for the glyphs needed to render maps in your application. +The name of the font family to use for client-side text rendering of CJK ideographs. + +Set `MGLIdeographicFontFamilyName` in your containing application's Info.plist to font family name(s) that will be available at run time, such as “PingFang TC” or “Marker Felt”. This plist key accepts: + +- A string value of a single font family name. + +- An array of font family names. Fonts will be used in the defined order, eventually falling back to default system font if none are available. + +- A boolean value `NO` to disable client-side rendering of CJK glyphs — remote fonts specified in your style will be used instead. ## MGLCollisionBehaviorPre4_0 @@ -30,4 +38,5 @@ The name of the font family to use for client-side text rendering of CJK ideogra Beginning in version 4.0, the SDK also performs collision detection between style layers based on different sources by default. For the default behavior, omit the `MGLCollisionBehaviorPre4_0` key or set it to NO (`false`). -This property may also be set using `[[NSUserDefaults standardUserDefaults] setObject:@(YES) forKey:@"MGLCollisionBehaviorPre4_0"]`; it will override any value specified in the `Info.plist`. \ No newline at end of file +This property may also be set using `[[NSUserDefaults standardUserDefaults] setObject:@(YES) forKey:@"MGLCollisionBehaviorPre4_0"]`; it will override any value specified in the `Info.plist`. + diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md index 8ca9477301..8ca6391ff3 100644 --- a/platform/macos/CHANGELOG.md +++ b/platform/macos/CHANGELOG.md @@ -4,9 +4,11 @@ * Added an `MGLMapView.prefetchesTiles` property to configure lower-resolution tile prefetching behavior. ([#14816](https://github.com/mapbox/mapbox-gl-native/pull/14816)) * Fixed queryRenderedFeatues bug caused by incorrect sort feature index calculation. ([#14884](https://github.com/mapbox/mapbox-gl-native/pull/14884)) +* The `MGLIdeographicFontFamilyName` Info.plist key now also accepts an array of font family names, to customize font fallback behavior. It can also be set to a Boolean value of `NO` to force the SDK to typeset CJK characters in a remote font specified by `MGLSymbolStyleLayer.textFontNames`. ([#14862](https://github.com/mapbox/mapbox-gl-native/pull/14862)) * Performance improvements for queryRenderedFeatures API and optimization that allocates containers based on a number of rendered layers. ([#14930](https://github.com/mapbox/mapbox-gl-native/pull/14930)) * Fixed rendering layers after fill-extrusion regression caused by optimization of fill-extrusion rendering. ([#15065](https://github.com/mapbox/mapbox-gl-native/pull/15065)) + ### Styles and rendering * Setting `MGLMapView.contentInset` now moves the map’s focal point to the center of the content frame after insetting. ([#14664](https://github.com/mapbox/mapbox-gl-native/pull/14664)) diff --git a/platform/macos/app/Info.plist b/platform/macos/app/Info.plist index 8bb225358c..21b86bfc75 100644 --- a/platform/macos/app/Info.plist +++ b/platform/macos/app/Info.plist @@ -2,8 +2,6 @@ - MGLIdeographicFontFamilyName - PingFang TC CFBundleDevelopmentRegion en CFBundleDocumentTypes diff --git a/platform/macos/docs/guides/Info.plist Keys.md b/platform/macos/docs/guides/Info.plist Keys.md index fe4c87b0c0..35ecf67e36 100644 --- a/platform/macos/docs/guides/Info.plist Keys.md +++ b/platform/macos/docs/guides/Info.plist Keys.md @@ -16,12 +16,20 @@ Use this key if you need to customize the API base URL used throughout the SDK. The default value is `https://api.mapbox.com`. -## MGLIdeographicFontFamilyName +## MGLIdeographicFontFamilyName -The name of the font family to use for client-side text rendering of CJK ideographs. Set this to the name of a font family which will be available at run time, e.g. `PingFang TC` (iOS 9+), `Heiti TC` (iOS 8+), another appropriate built-in font, or a font provided by your application. Note that if a non-existent font is specified, iOS will fall back to using Helvetica which is likely not to include support for the glyphs needed to render maps in your application. +The name of the font family to use for client-side text rendering of CJK ideographs. + +Set `MGLIdeographicFontFamilyName` in your containing application's Info.plist to font family name(s) that will be available at run time, such as “PingFang TC” or “Marker Felt”. This plist key accepts: + +- A string value of a single font family name. + +- An array of font family names. Fonts will be used in the defined order, eventually falling back to default system font if none are available. + +- A boolean value `NO` to disable client-side rendering of CJK glyphs — remote fonts specified in your style will be used instead. ## MGLCollisionBehaviorPre4_0 If this key is set to YES (`true`), collision detection is performed only between symbol style layers based on the same source, as in versions 0.1–0.7 of the Mapbox Maps SDK for iOS. In other words, symbols in an `MGLSymbolStyleLayer` based on one source (for example, an `MGLShapeSource`) may overlap with symbols in another layer that is based on a different source (such as the Mapbox Streets source). This is the case regardless of the `MGLSymbolStyleLayer.iconAllowsOverlap`, `MGLSymbolStyleLayer.iconIgnoresPlacement`, `MGLSymbolStyleLayer.textAllowsOverlap`, and `MGLSymbolStyleLayer.textIgnoresPlacement` properties. -Beginning in version 0.7, the SDK also performs collision detection between style layers based on different sources by default. For the default behavior, omit the `MGLCollisionBehaviorPre4_0` key or set it to NO (`false`). This property is so named because version 0.7 of the Mapbox Maps SDK for macOS corresponds to version 4.0 of the Mapbox Maps SDK for iOS. \ No newline at end of file +Beginning in version 0.7, the SDK also performs collision detection between style layers based on different sources by default. For the default behavior, omit the `MGLCollisionBehaviorPre4_0` key or set it to NO (`false`). This property is so named because version 0.7 of the Mapbox Maps SDK for macOS corresponds to version 4.0 of the Mapbox Maps SDK for iOS. -- cgit v1.2.1