From cd10190515693dae6cca7ad9087046a8dd2350a6 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Tue, 7 Nov 2017 16:10:58 -0500 Subject: partially do Placement async --- cmake/core-files.cmake | 2 + src/mbgl/layout/symbol_instance.hpp | 1 - src/mbgl/layout/symbol_layout.cpp | 40 +++--- src/mbgl/layout/symbol_projection.cpp | 13 +- src/mbgl/layout/symbol_projection.hpp | 3 +- src/mbgl/renderer/buckets/symbol_bucket.cpp | 43 ++++-- src/mbgl/renderer/buckets/symbol_bucket.hpp | 32 +++-- src/mbgl/renderer/layers/render_symbol_layer.cpp | 23 ++-- src/mbgl/renderer/renderer_impl.cpp | 35 +++-- src/mbgl/renderer/renderer_impl.hpp | 1 + src/mbgl/text/collision_index.cpp | 6 +- src/mbgl/text/collision_index.hpp | 6 +- src/mbgl/text/cross_tile_symbol_index.cpp | 48 ++++--- src/mbgl/text/cross_tile_symbol_index.hpp | 6 +- src/mbgl/text/placement.cpp | 163 ++++++++--------------- src/mbgl/text/placement.hpp | 41 +++--- src/mbgl/text/placement_worker.cpp | 128 ++++++++++++++++++ src/mbgl/text/placement_worker.hpp | 53 ++++++++ src/mbgl/tile/geometry_tile.cpp | 3 - 19 files changed, 422 insertions(+), 225 deletions(-) create mode 100644 src/mbgl/text/placement_worker.cpp create mode 100644 src/mbgl/text/placement_worker.hpp diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake index 4e35e12ee8..ea3cb0d553 100644 --- a/cmake/core-files.cmake +++ b/cmake/core-files.cmake @@ -495,6 +495,8 @@ set(MBGL_CORE_FILES src/mbgl/text/glyph_range.hpp src/mbgl/text/placement.cpp src/mbgl/text/placement.hpp + src/mbgl/text/placement_worker.cpp + src/mbgl/text/placement_worker.hpp src/mbgl/text/quads.cpp src/mbgl/text/quads.hpp src/mbgl/text/shaping.cpp diff --git a/src/mbgl/layout/symbol_instance.hpp b/src/mbgl/layout/symbol_instance.hpp index 827a5dbbdb..a4dd837559 100644 --- a/src/mbgl/layout/symbol_instance.hpp +++ b/src/mbgl/layout/symbol_instance.hpp @@ -52,7 +52,6 @@ public: optional placedTextIndex; optional placedVerticalTextIndex; optional placedIconIndex; - uint32_t crossTileID = 0; }; } // namespace mbgl diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp index 09d8883544..0946f606b5 100644 --- a/src/mbgl/layout/symbol_layout.cpp +++ b/src/mbgl/layout/symbol_layout.cpp @@ -423,7 +423,11 @@ std::unique_ptr SymbolLayout::place(const bool showCollisionBoxes) auto bucket = std::make_unique(layout, layerPaintProperties, textSize, iconSize, zoom, sdfIcons, iconsNeedLinear, mayOverlap, std::move(symbolInstances)); - for (SymbolInstance &symbolInstance : bucket->symbolInstances) { + auto& core = *bucket->mutableCore; + auto& placedTextSymbols = core.placedTextSymbols; + auto& placedIconSymbols = core.placedIconSymbols; + + for (SymbolInstance &symbolInstance : bucket->mutableCore->symbolInstances) { const bool hasText = symbolInstance.hasText; const bool hasIcon = symbolInstance.hasIcon; @@ -433,11 +437,11 @@ std::unique_ptr SymbolLayout::place(const bool showCollisionBoxes) // Insert final placement into collision tree and add glyphs/icons to buffers if (hasText) { - const Range sizeData = bucket->textSizeBinder->getVertexSizeData(feature); - bucket->text.placedSymbols.emplace_back(symbolInstance.anchor.point, symbolInstance.anchor.segment, sizeData.min, sizeData.max, + const Range sizeData = core.textSizeBinder->getVertexSizeData(feature); + placedTextSymbols.emplace_back(symbolInstance.anchor.point, symbolInstance.anchor.segment, sizeData.min, sizeData.max, symbolInstance.textOffset, symbolInstance.writingModes, symbolInstance.line, CalculateTileDistances(symbolInstance.line, symbolInstance.anchor)); - symbolInstance.placedTextIndex = bucket->text.placedSymbols.size() - 1; - PlacedSymbol& horizontalSymbol = bucket->text.placedSymbols.back(); + symbolInstance.placedTextIndex = placedTextSymbols.size() - 1; + PlacedSymbol& horizontalSymbol = placedTextSymbols.back(); bool firstHorizontal = true; for (const auto& symbol : symbolInstance.horizontalGlyphQuads) { @@ -451,11 +455,10 @@ std::unique_ptr SymbolLayout::place(const bool showCollisionBoxes) } if (symbolInstance.writingModes & WritingModeType::Vertical) { - bucket->text.placedSymbols.emplace_back(symbolInstance.anchor.point, symbolInstance.anchor.segment, sizeData.min, sizeData.max, + placedTextSymbols.emplace_back(symbolInstance.anchor.point, symbolInstance.anchor.segment, sizeData.min, sizeData.max, symbolInstance.textOffset, WritingModeType::Vertical, symbolInstance.line, CalculateTileDistances(symbolInstance.line, symbolInstance.anchor)); - symbolInstance.placedVerticalTextIndex = bucket->text.placedSymbols.size() - 1; - - PlacedSymbol& verticalSymbol = bucket->text.placedSymbols.back(); + symbolInstance.placedVerticalTextIndex = placedTextSymbols.size() - 1; + PlacedSymbol& verticalSymbol = placedTextSymbols.back(); bool firstVertical = true; for (const auto& symbol : symbolInstance.verticalGlyphQuads) { @@ -473,11 +476,11 @@ std::unique_ptr SymbolLayout::place(const bool showCollisionBoxes) if (hasIcon) { if (symbolInstance.iconQuad) { - const Range sizeData = bucket->iconSizeBinder->getVertexSizeData(feature); - bucket->icon.placedSymbols.emplace_back(symbolInstance.anchor.point, symbolInstance.anchor.segment, sizeData.min, sizeData.max, + const Range sizeData = core.iconSizeBinder->getVertexSizeData(feature); + placedIconSymbols.emplace_back(symbolInstance.anchor.point, symbolInstance.anchor.segment, sizeData.min, sizeData.max, symbolInstance.iconOffset, WritingModeType::None, symbolInstance.line, std::vector()); - symbolInstance.placedIconIndex = bucket->icon.placedSymbols.size() - 1; - PlacedSymbol& iconSymbol = bucket->icon.placedSymbols.back(); + symbolInstance.placedIconIndex = placedIconSymbols.size() - 1; + PlacedSymbol& iconSymbol = placedIconSymbols.back(); iconSymbol.vertexStartIndex = addSymbol( bucket->icon, sizeData, *symbolInstance.iconQuad, symbolInstance.anchor, iconSymbol); @@ -490,10 +493,15 @@ std::unique_ptr SymbolLayout::place(const bool showCollisionBoxes) } } + core.hasTextData = bucket->hasTextData(); + core.hasIconData = bucket->hasIconData(); + if (showCollisionBoxes) { addToDebugBuffers(*bucket); } + bucket->core = std::make_unique>(std::move(bucket->mutableCore)); + return bucket; } @@ -555,11 +563,7 @@ size_t SymbolLayout::addSymbol(Buffer& buffer, void SymbolLayout::addToDebugBuffers(SymbolBucket& bucket) { - if (!hasSymbolInstances()) { - return; - } - - for (const SymbolInstance &symbolInstance : symbolInstances) { + for (const SymbolInstance &symbolInstance : bucket.mutableCore->symbolInstances) { auto populateCollisionBox = [&](const auto& feature) { SymbolBucket::CollisionBuffer& collisionBuffer = feature.alongLine ? static_cast(bucket.collisionCircle) : diff --git a/src/mbgl/layout/symbol_projection.cpp b/src/mbgl/layout/symbol_projection.cpp index fa88ffdf22..393ae1f808 100644 --- a/src/mbgl/layout/symbol_projection.cpp +++ b/src/mbgl/layout/symbol_projection.cpp @@ -353,7 +353,8 @@ namespace mbgl { } - void reprojectLineLabels(gl::VertexVector& dynamicVertexArray, const std::vector& placedSymbols, + void reprojectLineLabels(gl::VertexVector& dynamicVertexArray, + const std::vector& placedSymbols, const std::vector& placedSymbolVisibility, const mat4& posMatrix, const style::SymbolPropertyValues& values, const RenderTile& tile, const SymbolSizeBinder& sizeBinder, const TransformState& state) { @@ -374,11 +375,17 @@ namespace mbgl { bool useVertical = false; - for (auto& placedSymbol : placedSymbols) { + assert(placedSymbols.size() == placedSymbolVisibility.size()); + auto visibilityIt = placedSymbolVisibility.begin(); + for (auto it = placedSymbols.begin(); it != placedSymbols.end(); it++, visibilityIt++) { + + const PlacedSymbol& placedSymbol = *it; + const bool hidden = *visibilityIt; + // Don't do calculations for vertical glyphs unless the previous symbol was horizontal // and we determined that vertical glyphs were necessary. // Also don't do calculations for symbols that are collided and fully faded out - if (placedSymbol.hidden || (placedSymbol.writingModes == WritingModeType::Vertical && !useVertical)) { + if (hidden || (placedSymbol.writingModes == WritingModeType::Vertical && !useVertical)) { hideGlyphs(placedSymbol.glyphOffsets.size(), dynamicVertexArray); continue; } diff --git a/src/mbgl/layout/symbol_projection.hpp b/src/mbgl/layout/symbol_projection.hpp index 8535014f22..19fa6517ae 100644 --- a/src/mbgl/layout/symbol_projection.hpp +++ b/src/mbgl/layout/symbol_projection.hpp @@ -38,7 +38,8 @@ namespace mbgl { using PointAndCameraDistance = std::pair,float>; PointAndCameraDistance project(const Point& point, const mat4& matrix); - void reprojectLineLabels(gl::VertexVector&, const std::vector&, + void reprojectLineLabels(gl::VertexVector&, + const std::vector&, const std::vector&, const mat4& posMatrix, const style::SymbolPropertyValues&, const RenderTile&, const SymbolSizeBinder& sizeBinder, const TransformState&); diff --git a/src/mbgl/renderer/buckets/symbol_bucket.cpp b/src/mbgl/renderer/buckets/symbol_bucket.cpp index ebcf93f2b1..fbed45c25e 100644 --- a/src/mbgl/renderer/buckets/symbol_bucket.cpp +++ b/src/mbgl/renderer/buckets/symbol_bucket.cpp @@ -8,6 +8,17 @@ namespace mbgl { using namespace style; +SymbolBucket::Core::Core( + std::vector&& symbolInstances_, + style::SymbolLayoutProperties::PossiblyEvaluated layout_, + std::unique_ptr textSizeBinder_, + std::unique_ptr iconSizeBinder_) : + symbolInstances(std::move(symbolInstances_)), + layout(std::move(layout_)), + textSizeBinder(std::move(textSizeBinder_)), + iconSizeBinder(std::move(iconSizeBinder_)) + {} + SymbolBucket::SymbolBucket(style::SymbolLayoutProperties::PossiblyEvaluated layout_, const std::map&& symbolInstances_) - : layout(std::move(layout_)), - sdfIcons(sdfIcons_), + std::vector&& symbolInstances_) + : sdfIcons(sdfIcons_), iconsNeedLinear(iconsNeedLinear_ || iconSize.isDataDriven() || !iconSize.isZoomConstant()), sortFeaturesByY(sortFeaturesByY_), - symbolInstances(std::move(symbolInstances_)), - textSizeBinder(SymbolSizeBinder::create(zoom, textSize, TextSize::defaultValue())), - iconSizeBinder(SymbolSizeBinder::create(zoom, iconSize, IconSize::defaultValue())) { + mutableCore(makeMutable( + std::move(symbolInstances_), + std::move(layout_), + SymbolSizeBinder::create(zoom, textSize, TextSize::defaultValue()), + SymbolSizeBinder::create(zoom, iconSize, IconSize::defaultValue()) + )) { for (const auto& pair : layerPaintProperties) { paintPropertyBinders.emplace( @@ -177,6 +190,10 @@ void SymbolBucket::sortFeatures(const float angle) { // The index array buffer is rewritten to reference the (unchanged) vertices in the // sorted order. + auto& symbolInstances = (*core)->symbolInstances; + auto& placedTextSymbols = (*core)->placedTextSymbols; + auto& placedIconSymbols = (*core)->placedIconSymbols; + // To avoid sorting the actual symbolInstance array we sort an array of indexes. std::vector symbolInstanceIndexes; for (size_t i = 0; i < symbolInstances.size(); i++) { @@ -186,9 +203,9 @@ void SymbolBucket::sortFeatures(const float angle) { const float sin = std::sin(angle); const float cos = std::cos(angle); - std::sort(symbolInstanceIndexes.begin(), symbolInstanceIndexes.end(), [sin, cos, this](size_t &aIndex, size_t &bIndex) { - const SymbolInstance& a = symbolInstances[aIndex]; - const SymbolInstance& b = symbolInstances[bIndex]; + std::sort(symbolInstanceIndexes.begin(), symbolInstanceIndexes.end(), [sin, cos, symbolInstances](size_t &aIndex, size_t &bIndex) { + const SymbolInstance& a = symbolInstances.at(aIndex); + const SymbolInstance& b = symbolInstances.at(bIndex); const int32_t aRotated = sin * a.anchor.point.x + cos * a.anchor.point.y; const int32_t bRotated = sin * b.anchor.point.x + cos * b.anchor.point.y; return aRotated != bRotated ? @@ -200,16 +217,16 @@ void SymbolBucket::sortFeatures(const float angle) { icon.triangles.clear(); for (auto i : symbolInstanceIndexes) { - const SymbolInstance& symbolInstance = symbolInstances[i]; + const SymbolInstance& symbolInstance = symbolInstances.at(i); if (symbolInstance.placedTextIndex) { - addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.placedTextIndex]); + addPlacedSymbol(text.triangles, placedTextSymbols[*symbolInstance.placedTextIndex]); } if (symbolInstance.placedVerticalTextIndex) { - addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.placedVerticalTextIndex]); + addPlacedSymbol(text.triangles, placedTextSymbols[*symbolInstance.placedVerticalTextIndex]); } if (symbolInstance.placedIconIndex) { - addPlacedSymbol(icon.triangles, icon.placedSymbols[*symbolInstance.placedIconIndex]); + addPlacedSymbol(icon.triangles, placedIconSymbols[*symbolInstance.placedIconIndex]); } } } diff --git a/src/mbgl/renderer/buckets/symbol_bucket.hpp b/src/mbgl/renderer/buckets/symbol_bucket.hpp index 4abea90508..f2f3f6197c 100644 --- a/src/mbgl/renderer/buckets/symbol_bucket.hpp +++ b/src/mbgl/renderer/buckets/symbol_bucket.hpp @@ -21,7 +21,7 @@ public: PlacedSymbol(Point anchorPoint_, uint16_t segment_, float lowerSize_, float upperSize_, std::array lineOffset_, WritingModeType writingModes_, GeometryCoordinates line_, std::vector tileDistances_) : anchorPoint(anchorPoint_), segment(segment_), lowerSize(lowerSize_), upperSize(upperSize_), - lineOffset(lineOffset_), writingModes(writingModes_), line(std::move(line_)), tileDistances(std::move(tileDistances_)), hidden(false), vertexStartIndex(0) + lineOffset(lineOffset_), writingModes(writingModes_), line(std::move(line_)), tileDistances(std::move(tileDistances_)), vertexStartIndex(0) { } Point anchorPoint; @@ -33,7 +33,6 @@ public: GeometryCoordinates line; std::vector tileDistances; std::vector glyphOffsets; - bool hidden; size_t vertexStartIndex; }; @@ -47,7 +46,7 @@ public: bool sdfIcons, bool iconsNeedLinear, bool sortFeaturesByY, - const std::vector&&); + std::vector&&); void upload(gl::Context&) override; bool hasData() const override; @@ -59,7 +58,6 @@ public: void updateOpacity(); void sortFeatures(const float angle); - const style::SymbolLayoutProperties::PossiblyEvaluated layout; const bool sdfIcons; const bool iconsNeedLinear; const bool sortFeaturesByY; @@ -71,21 +69,35 @@ public: bool dynamicUploaded = false; bool sortUploaded = false; - std::vector symbolInstances; + std::unique_ptr>> symbolCrossTileIDs; + + class Core { + public: + Core(std::vector&&, style::SymbolLayoutProperties::PossiblyEvaluated, std::unique_ptr, std::unique_ptr); + std::vector symbolInstances; + const style::SymbolLayoutProperties::PossiblyEvaluated layout; + const std::unique_ptr textSizeBinder; + const std::unique_ptr iconSizeBinder; + std::vector placedTextSymbols; + std::vector placedIconSymbols; + bool hasTextData; + bool hasIconData; + }; + + Mutable mutableCore; + std::unique_ptr> core; std::map> paintPropertyBinders; - std::unique_ptr textSizeBinder; - struct TextBuffer { gl::VertexVector vertices; gl::VertexVector dynamicVertices; gl::VertexVector opacityVertices; gl::IndexVector triangles; SegmentVector segments; - std::vector placedSymbols; + std::vector placedSymbolVisibility; optional> vertexBuffer; optional> dynamicVertexBuffer; @@ -93,15 +105,13 @@ public: optional> indexBuffer; } text; - std::unique_ptr iconSizeBinder; - struct IconBuffer { gl::VertexVector vertices; gl::VertexVector dynamicVertices; gl::VertexVector opacityVertices; gl::IndexVector triangles; SegmentVector segments; - std::vector placedSymbols; + std::vector placedSymbolVisibility; PremultipliedImage atlasImage; optional> vertexBuffer; diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp index e194c9c857..9a3aceed77 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.cpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp @@ -78,7 +78,8 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { assert(dynamic_cast(tile.tile.getBucket(*baseImpl))); SymbolBucket& bucket = *reinterpret_cast(tile.tile.getBucket(*baseImpl)); - const auto& layout = bucket.layout; + const auto& core = **bucket.core; + const auto& layout = core.layout; auto draw = [&] (auto& program, auto&& uniformValues, @@ -127,11 +128,12 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { if (alongLine) { reprojectLineLabels(bucket.icon.dynamicVertices, - bucket.icon.placedSymbols, + core.placedIconSymbols, + bucket.icon.placedSymbolVisibility, tile.matrix, values, tile, - *bucket.iconSizeBinder, + *core.iconSizeBinder, parameters.state); parameters.context.updateVertexBuffer(*bucket.icon.dynamicVertexBuffer, std::move(bucket.icon.dynamicVertices)); @@ -151,7 +153,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { draw(parameters.programs.symbolIconSDF, SymbolSDFIconProgram::uniformValues(false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Halo), bucket.icon, - bucket.iconSizeBinder, + core.iconSizeBinder, values, bucket.paintPropertyBinders.at(getID()).first, paintPropertyValues); @@ -161,7 +163,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { draw(parameters.programs.symbolIconSDF, SymbolSDFIconProgram::uniformValues(false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Fill), bucket.icon, - bucket.iconSizeBinder, + core.iconSizeBinder, values, bucket.paintPropertyBinders.at(getID()).first, paintPropertyValues); @@ -170,7 +172,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { draw(parameters.programs.symbolIcon, SymbolIconProgram::uniformValues(false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange), bucket.icon, - bucket.iconSizeBinder, + core.iconSizeBinder, values, bucket.paintPropertyBinders.at(getID()).first, paintPropertyValues); @@ -188,11 +190,12 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { if (alongLine) { reprojectLineLabels(bucket.text.dynamicVertices, - bucket.text.placedSymbols, + core.placedTextSymbols, + bucket.text.placedSymbolVisibility, tile.matrix, values, tile, - *bucket.textSizeBinder, + *core.textSizeBinder, parameters.state); parameters.context.updateVertexBuffer(*bucket.text.dynamicVertexBuffer, std::move(bucket.text.dynamicVertices)); @@ -204,7 +207,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { draw(parameters.programs.symbolGlyph, SymbolSDFTextProgram::uniformValues(true, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Halo), bucket.text, - bucket.textSizeBinder, + core.textSizeBinder, values, bucket.paintPropertyBinders.at(getID()).second, paintPropertyValues); @@ -214,7 +217,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { draw(parameters.programs.symbolGlyph, SymbolSDFTextProgram::uniformValues(true, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Fill), bucket.text, - bucket.textSizeBinder, + core.textSizeBinder, values, bucket.paintPropertyBinders.at(getID()).second, paintPropertyValues); diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index af0c491e15..ddd5718601 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -59,7 +59,7 @@ Renderer::Impl::Impl(RendererBackend& backend_, , layerImpls(makeMutable>>()) , renderLight(makeMutable()) , crossTileSymbolIndex(std::make_unique()) - , placement(std::make_unique(TransformState{}, MapMode::Still)) { + , placement(std::make_unique(TransformState{}, MapMode::Still, mat4(), false, scheduler_)) { glyphManager->setObserver(this); } @@ -376,21 +376,30 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) { } } - bool placementChanged = false; if (!placement->stillRecent(parameters.timePoint)) { - auto newPlacement = std::make_unique(parameters.state, parameters.mapMode); - for (auto it = order.rbegin(); it != order.rend(); ++it) { - if (it->layer.is()) { - newPlacement->placeLayer(*it->layer.as(), parameters.projMatrix, parameters.debugOptions & MapDebugOptions::Collision); + if (!placementInProgress) { + placementInProgress = std::make_unique(parameters.state, parameters.mapMode, parameters.projMatrix, parameters.debugOptions & MapDebugOptions::Collision, scheduler); + for (auto it = order.rbegin(); it != order.rend(); ++it) { + if (it->layer.is()) { + placementInProgress->addLayer(*it->layer.as()); + } } + placementInProgress->place(); } + } - placementChanged = newPlacement->commit(*placement, parameters.timePoint); - if (placementChanged || symbolBucketsChanged) { - placement = std::move(newPlacement); + bool placementChanged = false; + if (placementInProgress) { + if (placementInProgress->isReady()) { + placementChanged = placementInProgress->commit(*placement, parameters.timePoint); + if (placementChanged || symbolBucketsChanged) { + placement = std::move(placementInProgress); + placement->setStale(); + } else { + placement->setRecent(parameters.timePoint); + placementInProgress.reset(); + } } - - placement->setRecent(parameters.timePoint); } else { placement->setStale(); } @@ -654,7 +663,7 @@ std::vector Renderer::Impl::queryRenderedFeatures(const ScreenLineStrin std::unordered_map> resultsByLayer; for (const auto& sourceID : sourceIDs) { if (RenderSource* renderSource = getRenderSource(sourceID)) { - auto sourceResults = renderSource->queryRenderedFeatures(geometry, transformState, layers, options, placement->collisionIndex); + auto sourceResults = renderSource->queryRenderedFeatures(geometry, transformState, layers, options, placement->result->collisionIndex); std::move(sourceResults.begin(), sourceResults.end(), std::inserter(resultsByLayer, resultsByLayer.begin())); } } @@ -730,7 +739,7 @@ bool Renderer::Impl::hasTransitions(TimePoint timePoint) const { } } - if (placement->hasTransitions(timePoint)) { + if (placement->hasTransitions(timePoint) || placementInProgress) { return true; } diff --git a/src/mbgl/renderer/renderer_impl.hpp b/src/mbgl/renderer/renderer_impl.hpp index dc19e84995..8e98c63497 100644 --- a/src/mbgl/renderer/renderer_impl.hpp +++ b/src/mbgl/renderer/renderer_impl.hpp @@ -107,6 +107,7 @@ private: std::unique_ptr crossTileSymbolIndex; std::unique_ptr placement; + std::unique_ptr placementInProgress; bool contextLost = false; }; diff --git a/src/mbgl/text/collision_index.cpp b/src/mbgl/text/collision_index.cpp index 05a0450465..08910fa619 100644 --- a/src/mbgl/text/collision_index.cpp +++ b/src/mbgl/text/collision_index.cpp @@ -56,7 +56,7 @@ bool CollisionIndex::placeFeature(CollisionFeature& feature, const mat4& posMatrix, const mat4& labelPlaneMatrix, const float textPixelRatio, - PlacedSymbol& symbol, + const PlacedSymbol& symbol, const float scale, const float fontSize, const bool allowOverlap, @@ -87,7 +87,7 @@ bool CollisionIndex::placeLineFeature(CollisionFeature& feature, const mat4& posMatrix, const mat4& labelPlaneMatrix, const float textPixelRatio, - PlacedSymbol& symbol, + const PlacedSymbol& symbol, const float scale, const float fontSize, const bool allowOverlap, @@ -201,7 +201,7 @@ bool CollisionIndex::placeLineFeature(CollisionFeature& feature, } -void CollisionIndex::insertFeature(CollisionFeature& feature, bool ignorePlacement) { +void CollisionIndex::insertFeature(const CollisionFeature& feature, bool ignorePlacement) { if (feature.alongLine) { for (auto& circle : feature.boxes) { if (!circle.used) { diff --git a/src/mbgl/text/collision_index.hpp b/src/mbgl/text/collision_index.hpp index 6f78d8aeda..7eab7b5c28 100644 --- a/src/mbgl/text/collision_index.hpp +++ b/src/mbgl/text/collision_index.hpp @@ -21,14 +21,14 @@ public: const mat4& posMatrix, const mat4& labelPlaneMatrix, const float textPixelRatio, - PlacedSymbol& symbol, + const PlacedSymbol& symbol, const float scale, const float fontSize, const bool allowOverlap, const bool pitchWithMap, const bool collisionDebug); - void insertFeature(CollisionFeature& feature, bool ignorePlacement); + void insertFeature(const CollisionFeature& feature, bool ignorePlacement); std::vector queryRenderedSymbols(const GeometryCoordinates&, const UnwrappedTileID& tileID, const std::string& sourceID) const; @@ -38,7 +38,7 @@ private: const mat4& posMatrix, const mat4& labelPlaneMatrix, const float textPixelRatio, - PlacedSymbol& symbol, + const PlacedSymbol& symbol, const float scale, const float fontSize, const bool allowOverlap, diff --git a/src/mbgl/text/cross_tile_symbol_index.cpp b/src/mbgl/text/cross_tile_symbol_index.cpp index 779bec283c..f701b47694 100644 --- a/src/mbgl/text/cross_tile_symbol_index.cpp +++ b/src/mbgl/text/cross_tile_symbol_index.cpp @@ -7,14 +7,18 @@ namespace mbgl { -TileLayerIndex::TileLayerIndex(OverscaledTileID coord_, std::vector& symbolInstances, uint32_t bucketInstanceId_) +TileLayerIndex::TileLayerIndex(OverscaledTileID coord_, const std::vector& symbolInstances, std::vector& symbolCrossTileIDs, uint32_t bucketInstanceId_) : coord(coord_), bucketInstanceId(bucketInstanceId_) { - for (SymbolInstance& symbolInstance : symbolInstances) { - indexedSymbolInstances[symbolInstance.key].emplace_back(symbolInstance.crossTileID, getScaledCoordinates(symbolInstance, coord)); + assert(symbolInstances.size() == symbolCrossTileIDs.size()); + auto idIt = symbolCrossTileIDs.begin(); + for (auto it = symbolInstances.begin(); it != symbolInstances.end(); it++, idIt++) { + auto& symbolInstance = *it; + auto crossTileID = *idIt; + indexedSymbolInstances[symbolInstance.key].emplace_back(crossTileID, getScaledCoordinates(symbolInstance, coord)); } } -Point TileLayerIndex::getScaledCoordinates(SymbolInstance& symbolInstance, const OverscaledTileID& childTileCoord) { +Point TileLayerIndex::getScaledCoordinates(const SymbolInstance& symbolInstance, const OverscaledTileID& childTileCoord) const { // Round anchor positions to roughly 4 pixel grid const double roundingFactor = 512.0 / util::EXTENT / 2.0; const double scale = roundingFactor / std::pow(2, childTileCoord.canonical.z - coord.canonical.z); @@ -24,30 +28,34 @@ Point TileLayerIndex::getScaledCoordinates(SymbolInstance& symbolInstan }; } -void TileLayerIndex::findMatches(std::vector& symbolInstances, const OverscaledTileID& newCoord) { +void TileLayerIndex::findMatches(const std::vector& symbolInstances, std::vector& symbolCrossTileIDs, const OverscaledTileID& newCoord) { float tolerance = coord.canonical.z < newCoord.canonical.z ? 1 : std::pow(2, coord.canonical.z - newCoord.canonical.z); - for (auto& symbolInstance : symbolInstances) { - if (symbolInstance.crossTileID) { + assert(symbolInstances.size() == symbolCrossTileIDs.size()); + auto idIt = symbolCrossTileIDs.begin(); + for (auto it = symbolInstances.begin(); it != symbolInstances.end(); it++, idIt++) { + auto& symbolInstance = *it; + auto& crossTileID = *idIt; + if (crossTileID) { // already has a match, skip continue; } - auto it = indexedSymbolInstances.find(symbolInstance.key); - if (it == indexedSymbolInstances.end()) { + auto indexedSymbolInstance = indexedSymbolInstances.find(symbolInstance.key); + if (indexedSymbolInstance == indexedSymbolInstances.end()) { // No symbol with this key in this bucket continue; } auto scaledSymbolCoord = getScaledCoordinates(symbolInstance, newCoord); - for (IndexedSymbolInstance& thisTileSymbol: it->second) { + for (IndexedSymbolInstance& thisTileSymbol: indexedSymbolInstance->second) { // Return any symbol with the same keys whose coordinates are within 1 // grid unit. (with a 4px grid, this covers a 12px by 12px area) if (std::abs(thisTileSymbol.coord.x - scaledSymbolCoord.x) <= tolerance && std::abs(thisTileSymbol.coord.y - scaledSymbolCoord.y) <= tolerance) { - symbolInstance.crossTileID = thisTileSymbol.crossTileID; + crossTileID = thisTileSymbol.crossTileID; break; } } @@ -63,6 +71,10 @@ void CrossTileSymbolLayerIndex::addBucket(const OverscaledTileID& coord, SymbolB if (bucket.bucketInstanceId) return; bucket.bucketInstanceId = ++maxBucketInstanceId; + auto& symbolInstances = (*bucket.core)->symbolInstances; + + Mutable> symbolCrossTileIDs = makeMutable>(symbolInstances.size(), 0); + uint8_t minZoom = 25; uint8_t maxZoom = 0; for (auto& it : indexes) { @@ -80,7 +92,7 @@ void CrossTileSymbolLayerIndex::addBucket(const OverscaledTileID& coord, SymbolB if (!childIndex.second.coord.isChildOf(coord)) { continue; } - childIndex.second.findMatches(bucket.symbolInstances, coord); + childIndex.second.findMatches(symbolInstances, *symbolCrossTileIDs, coord); } } if (z == 0) { @@ -95,7 +107,7 @@ void CrossTileSymbolLayerIndex::addBucket(const OverscaledTileID& coord, SymbolB if (zoomIndexes != indexes.end()) { auto parentIndex = zoomIndexes->second.find(parentCoord); if (parentIndex != zoomIndexes->second.end()) { - parentIndex->second.findMatches(bucket.symbolInstances, coord); + parentIndex->second.findMatches(symbolInstances, *symbolCrossTileIDs, coord); } } if (z == 0) { @@ -103,14 +115,16 @@ void CrossTileSymbolLayerIndex::addBucket(const OverscaledTileID& coord, SymbolB } } - for (auto& symbolInstance : bucket.symbolInstances) { - if (!symbolInstance.crossTileID) { + for (auto& crossTileID : *symbolCrossTileIDs) { + if (!crossTileID) { // symbol did not match any known symbol, assign a new id - symbolInstance.crossTileID = ++maxCrossTileID; + crossTileID = ++maxCrossTileID; } } - indexes[coord.overscaledZ].emplace(coord, TileLayerIndex(coord, bucket.symbolInstances, bucket.bucketInstanceId)); + indexes[coord.overscaledZ].emplace(coord, TileLayerIndex(coord, symbolInstances, *symbolCrossTileIDs, bucket.bucketInstanceId)); + + bucket.symbolCrossTileIDs = std::make_unique>>(std::move(symbolCrossTileIDs)); } bool CrossTileSymbolLayerIndex::removeStaleBuckets(const std::unordered_set& currentIDs) { diff --git a/src/mbgl/text/cross_tile_symbol_index.hpp b/src/mbgl/text/cross_tile_symbol_index.hpp index 0b8c5c4780..ec0a5677de 100644 --- a/src/mbgl/text/cross_tile_symbol_index.hpp +++ b/src/mbgl/text/cross_tile_symbol_index.hpp @@ -32,10 +32,10 @@ class IndexedSymbolInstance { class TileLayerIndex { public: - TileLayerIndex(OverscaledTileID coord, std::vector&, uint32_t bucketInstanceId); + TileLayerIndex(OverscaledTileID coord, const std::vector&, std::vector& symbolCrossTileIDs, uint32_t bucketInstanceId); - Point getScaledCoordinates(SymbolInstance&, const OverscaledTileID&); - void findMatches(std::vector&, const OverscaledTileID&); + Point getScaledCoordinates(const SymbolInstance&, const OverscaledTileID&) const; + void findMatches(const std::vector&, std::vector& symbolCrossTileIDs, const OverscaledTileID&); OverscaledTileID coord; uint32_t bucketInstanceId; diff --git a/src/mbgl/text/placement.cpp b/src/mbgl/text/placement.cpp index 2a24a803a7..546635c51d 100644 --- a/src/mbgl/text/placement.cpp +++ b/src/mbgl/text/placement.cpp @@ -30,16 +30,21 @@ bool JointOpacityState::isHidden() const { return icon.isHidden() && text.isHidden(); } -Placement::Placement(const TransformState& state_, MapMode mapMode_) - : collisionIndex(state_) +Placement::Placement(const TransformState& state_, MapMode mapMode_, const mat4& projMatrix_, const bool showCollisionBoxes_, Scheduler& scheduler) + : result(makeMutable(state_)) , state(state_) , mapMode(mapMode_) + , showCollisionBoxes(showCollisionBoxes_) + , projMatrix(projMatrix_) + , worker(scheduler, state_, projMatrix_, showCollisionBoxes_) + , placementBucketLayers(makeMutable>>()) , recentUntil(TimePoint::min()) {} -void Placement::placeLayer(RenderSymbolLayer& symbolLayer, const mat4& projMatrix, bool showCollisionBoxes) { +void Placement::addLayer(RenderSymbolLayer& symbolLayer) { - std::unordered_set seenCrossTileIDs; + placementBucketLayers->emplace_back(); + auto& placementBuckets = placementBucketLayers->back(); for (RenderTile& renderTile : symbolLayer.renderTiles) { @@ -51,111 +56,47 @@ void Placement::placeLayer(RenderSymbolLayer& symbolLayer, const mat4& projMatri assert(dynamic_cast(bucket)); SymbolBucket& symbolBucket = *reinterpret_cast(bucket); - auto& layout = symbolBucket.layout; - - const float pixelsToTileUnits = renderTile.id.pixelsToTileUnits(1, state.getZoom()); - - const float scale = std::pow(2, state.getZoom() - renderTile.tile.id.overscaledZ); - const float textPixelRatio = util::EXTENT / (util::tileSize * renderTile.tile.id.overscaleFactor()); - - mat4 posMatrix; - state.matrixFor(posMatrix, renderTile.id); - matrix::multiply(posMatrix, projMatrix, posMatrix); - - mat4 textLabelPlaneMatrix = getLabelPlaneMatrix(renderTile.matrix, - layout.get() == style::AlignmentType::Map, - layout.get() == style::AlignmentType::Map, - state, - pixelsToTileUnits); - - mat4 iconLabelPlaneMatrix = getLabelPlaneMatrix(renderTile.matrix, - layout.get() == style::AlignmentType::Map, - layout.get() == style::AlignmentType::Map, - state, - pixelsToTileUnits); - - placeLayerBucket(symbolBucket, posMatrix, textLabelPlaneMatrix, iconLabelPlaneMatrix, scale, textPixelRatio, showCollisionBoxes, seenCrossTileIDs); + assert(symbolBucket.core); + placementBuckets.emplace_back(*symbolBucket.core, *symbolBucket.symbolCrossTileIDs, renderTile.id, renderTile.tile.id); } } -void Placement::placeLayerBucket( - SymbolBucket& bucket, - const mat4& posMatrix, - const mat4& textLabelPlaneMatrix, - const mat4& iconLabelPlaneMatrix, - const float scale, - const float textPixelRatio, - const bool showCollisionBoxes, - std::unordered_set& seenCrossTileIDs) { - - auto partiallyEvaluatedTextSize = bucket.textSizeBinder->evaluateForZoom(state.getZoom()); - auto partiallyEvaluatedIconSize = bucket.iconSizeBinder->evaluateForZoom(state.getZoom()); - - const bool iconWithoutText = !bucket.hasTextData() || bucket.layout.get(); - const bool textWithoutIcon = !bucket.hasIconData() || bucket.layout.get(); - - for (auto& symbolInstance : bucket.symbolInstances) { - - if (seenCrossTileIDs.count(symbolInstance.crossTileID) == 0) { - bool placeText = false; - bool placeIcon = false; - - if (symbolInstance.placedTextIndex) { - PlacedSymbol& placedSymbol = bucket.text.placedSymbols.at(*symbolInstance.placedTextIndex); - const float fontSize = evaluateSizeForFeature(partiallyEvaluatedTextSize, placedSymbol); - - placeText = collisionIndex.placeFeature(symbolInstance.textCollisionFeature, - posMatrix, textLabelPlaneMatrix, textPixelRatio, - placedSymbol, scale, fontSize, - bucket.layout.get(), - bucket.layout.get() == style::AlignmentType::Map, - showCollisionBoxes); - } - - if (symbolInstance.placedIconIndex) { - PlacedSymbol& placedSymbol = bucket.icon.placedSymbols.at(*symbolInstance.placedIconIndex); - const float fontSize = evaluateSizeForFeature(partiallyEvaluatedIconSize, placedSymbol); - - placeIcon = collisionIndex.placeFeature(symbolInstance.iconCollisionFeature, - posMatrix, iconLabelPlaneMatrix, textPixelRatio, - placedSymbol, scale, fontSize, - bucket.layout.get(), - bucket.layout.get() == style::AlignmentType::Map, - showCollisionBoxes); - } - - // combine placements for icon and text - if (!iconWithoutText && !textWithoutIcon) { - placeText = placeIcon = placeText && placeIcon; - } else if (!textWithoutIcon) { - placeText = placeText && placeIcon; - } else if (!iconWithoutText) { - placeIcon = placeText && placeIcon; - } - - if (placeText) { - collisionIndex.insertFeature(symbolInstance.textCollisionFeature, bucket.layout.get()); - } - - if (placeIcon) { - collisionIndex.insertFeature(symbolInstance.iconCollisionFeature, bucket.layout.get()); - } - - assert(symbolInstance.crossTileID != 0); +void Placement::place() { + if (mapMode == MapMode::Still) { + // synchronous + PlacementWorker placement(state, projMatrix, showCollisionBoxes); + result = placement.place(std::move(placementBucketLayers)); + } else { + // asynchronous + future = worker.ask(&PlacementWorker::place, std::move(placementBucketLayers)); + } +} - placements.emplace(symbolInstance.crossTileID, PlacementPair(placeText, placeIcon)); - seenCrossTileIDs.insert(symbolInstance.crossTileID); - } - } +bool Placement::isReady() { + if (mapMode == MapMode::Still) { + // synchronous + return true; + } else { + // asynchronous + return future.wait_for(Duration(0)) == std::future_status::ready; + } } bool Placement::commit(const Placement& prevPlacement, TimePoint now) { + + if (mapMode != MapMode::Still) { + // asynchronous result + result = future.get(); + } + commitTime = now; bool placementChanged = false; float increment = mapMode == MapMode::Still ? 1.0 : std::chrono::duration(commitTime - prevPlacement.commitTime) / Duration(std::chrono::milliseconds(300)); + auto& placements = result->placements; + if (increment) {} // add the opacities from the current placement, and copy their current values from the previous placement for (auto& placementPair : placements) { @@ -200,17 +141,29 @@ void Placement::updateLayerOpacities(RenderSymbolLayer& symbolLayer) { } void Placement::updateBucketOpacities(SymbolBucket& bucket, std::unordered_set& seenCrossTileIDs) { - if (bucket.hasTextData()) bucket.text.opacityVertices.clear(); - if (bucket.hasIconData()) bucket.icon.opacityVertices.clear(); + if (bucket.hasTextData()) { + bucket.text.opacityVertices.clear(); + bucket.text.placedSymbolVisibility.clear(); + } + if (bucket.hasIconData()) { + bucket.icon.opacityVertices.clear(); + bucket.icon.placedSymbolVisibility.clear(); + } if (bucket.hasCollisionBoxData()) bucket.collisionBox.dynamicVertices.clear(); if (bucket.hasCollisionCircleData()) bucket.collisionCircle.dynamicVertices.clear(); - for (SymbolInstance& symbolInstance : bucket.symbolInstances) { - auto opacityState = seenCrossTileIDs.count(symbolInstance.crossTileID) == 0 ? - getOpacity(symbolInstance.crossTileID) : + auto& symbolInstances = (*bucket.core)->symbolInstances; + + auto idIt = (*bucket.symbolCrossTileIDs)->begin(); + for (auto it = symbolInstances.begin(); it != symbolInstances.end(); it++, idIt++) { + auto& symbolInstance = *it; + auto crossTileID = *idIt; + + auto opacityState = seenCrossTileIDs.count(crossTileID) == 0 ? + getOpacity(crossTileID) : JointOpacityState(false, false); - seenCrossTileIDs.insert(symbolInstance.crossTileID); + seenCrossTileIDs.insert(crossTileID); if (symbolInstance.hasText) { auto opacityVertex = SymbolOpacityAttributes::vertex(opacityState.text.placed, opacityState.text.opacity); @@ -221,10 +174,10 @@ void Placement::updateBucketOpacities(SymbolBucket& bucket, std::unordered_set #include +#include #include -#include +#include #include +#include #include namespace mbgl { class RenderSymbolLayer; - class SymbolBucket; class OpacityState { public: @@ -30,17 +31,12 @@ namespace mbgl { OpacityState text; }; - class PlacementPair { - public: - PlacementPair(bool text_, bool icon_) : text(text_), icon(icon_) {} - bool text; - bool icon; - }; - class Placement { public: - Placement(const TransformState&, MapMode mapMode); - void placeLayer(RenderSymbolLayer&, const mat4&, bool showCollisionBoxes); + Placement(const TransformState&, MapMode mapMode, const mat4& projMatrix, const bool showCollisionBoxes, Scheduler&); + void addLayer(RenderSymbolLayer&); + void place(); + bool isReady(); bool commit(const Placement& prevPlacement, TimePoint); void updateLayerOpacities(RenderSymbolLayer&); JointOpacityState getOpacity(uint32_t crossTileSymbolID) const; @@ -48,7 +44,7 @@ namespace mbgl { bool hasTransitions(TimePoint now) const; // TODO: public for queryRenderedFeatures - CollisionIndex collisionIndex; + Immutable result; bool stillRecent(TimePoint now) const; void setRecent(TimePoint now); @@ -56,22 +52,25 @@ namespace mbgl { private: void placeLayerBucket( - SymbolBucket&, - const mat4& posMatrix, - const mat4& textLabelPlaneMatrix, - const mat4& iconLabelPlaneMatrix, - const float scale, - const float pixelRatio, - const bool showCollisionBoxes, + const SymbolBucket::Core&, + const std::vector& symbolCrossTileIDs, + const UnwrappedTileID&, + const OverscaledTileID&, std::unordered_set& seenCrossTileIDs); void updateBucketOpacities(SymbolBucket&, std::unordered_set&); TransformState state; - MapMode mapMode; + const MapMode mapMode; TimePoint commitTime; + const bool showCollisionBoxes; + const mat4 projMatrix; + + Actor worker; + std::future> future; + + Mutable>> placementBucketLayers; - std::unordered_map placements; std::unordered_map opacities; TimePoint recentUntil; diff --git a/src/mbgl/text/placement_worker.cpp b/src/mbgl/text/placement_worker.cpp new file mode 100644 index 0000000000..041f48e805 --- /dev/null +++ b/src/mbgl/text/placement_worker.cpp @@ -0,0 +1,128 @@ +#include +#include + +namespace mbgl { + +PlacementBucket::PlacementBucket(Immutable& core, Immutable>& ids, const UnwrappedTileID& unwrapped, const OverscaledTileID& overscaled) : + symbolBucketCore(core), symbolCrossTileIDs(ids), unwrappedTileID(unwrapped), overscaledTileID(overscaled) {} + +PlacementWorker::PlacementWorker(const TransformState& state_, const mat4& projMatrix_, const bool showCollisionBoxes_) : + state(state_), + projMatrix(projMatrix_), + showCollisionBoxes(showCollisionBoxes_) + {} + +Immutable PlacementWorker::place(Immutable>> placementBucketLayers) { + Mutable result = makeMutable(state); + + for (auto& placementBuckets : *placementBucketLayers) { + std::unordered_set seenCrossTileIDs; + for (auto& placementBucket: placementBuckets) { + placeLayerBucket(result->placements, result->collisionIndex, *placementBucket.symbolBucketCore, *placementBucket.symbolCrossTileIDs, placementBucket.unwrappedTileID, placementBucket.overscaledTileID, seenCrossTileIDs); + } + } + + return std::move(result); +} + +void PlacementWorker::placeLayerBucket( + std::unordered_map& placements, + CollisionIndex& collisionIndex, + const SymbolBucket::Core& bucketCore, + const std::vector& symbolCrossTileIDs, + const UnwrappedTileID& unwrappedTileID, + const OverscaledTileID& overscaledTileID, + std::unordered_set& seenCrossTileIDs) { + + const float scale = std::pow(2, state.getZoom() - overscaledTileID.overscaledZ); + const float textPixelRatio = util::EXTENT / (util::tileSize * overscaledTileID.overscaleFactor()); + + const float pixelsToTileUnits = unwrappedTileID.pixelsToTileUnits(1, state.getZoom()); + + mat4 posMatrix; + state.matrixFor(posMatrix, unwrappedTileID); + matrix::multiply(posMatrix, projMatrix, posMatrix); + + mat4 textLabelPlaneMatrix = getLabelPlaneMatrix(posMatrix, + bucketCore.layout.get() == style::AlignmentType::Map, + bucketCore.layout.get() == style::AlignmentType::Map, + state, + pixelsToTileUnits); + + mat4 iconLabelPlaneMatrix = getLabelPlaneMatrix(posMatrix, + bucketCore.layout.get() == style::AlignmentType::Map, + bucketCore.layout.get() == style::AlignmentType::Map, + state, + pixelsToTileUnits); + + auto partiallyEvaluatedTextSize = bucketCore.textSizeBinder->evaluateForZoom(state.getZoom()); + auto partiallyEvaluatedIconSize = bucketCore.iconSizeBinder->evaluateForZoom(state.getZoom()); + + const bool iconWithoutText = !bucketCore.hasTextData || bucketCore.layout.get(); + const bool textWithoutIcon = !bucketCore.hasIconData || bucketCore.layout.get(); + + assert(bucketCore.symbolInstances.size() == symbolCrossTileIDs.size()); + + auto idIt = symbolCrossTileIDs.begin(); + for (auto it = bucketCore.symbolInstances.begin(); it != bucketCore.symbolInstances.end(); it++, idIt++) { + auto& symbolInstance = *it; + const uint32_t crossTileID = *idIt; + + if (seenCrossTileIDs.count(crossTileID) == 0) { + bool placeText = false; + bool placeIcon = false; + + // TODO eliminate this copy + CollisionFeature textCollisionFeature = symbolInstance.textCollisionFeature; + if (symbolInstance.placedTextIndex) { + const PlacedSymbol& placedSymbol = bucketCore.placedTextSymbols.at(*symbolInstance.placedTextIndex); + const float fontSize = evaluateSizeForFeature(partiallyEvaluatedTextSize, placedSymbol); + + placeText = collisionIndex.placeFeature(textCollisionFeature, + posMatrix, textLabelPlaneMatrix, textPixelRatio, + placedSymbol, scale, fontSize, + bucketCore.layout.get(), + bucketCore.layout.get() == style::AlignmentType::Map, + showCollisionBoxes); + } + + // TODO eliminate this copy + CollisionFeature iconCollisionFeature = symbolInstance.iconCollisionFeature; + if (symbolInstance.placedIconIndex) { + const PlacedSymbol& placedSymbol = bucketCore.placedIconSymbols.at(*symbolInstance.placedIconIndex); + const float fontSize = evaluateSizeForFeature(partiallyEvaluatedIconSize, placedSymbol); + + placeIcon = collisionIndex.placeFeature(iconCollisionFeature, + posMatrix, iconLabelPlaneMatrix, textPixelRatio, + placedSymbol, scale, fontSize, + bucketCore.layout.get(), + bucketCore.layout.get() == style::AlignmentType::Map, + showCollisionBoxes); + } + + // combine placements for icon and text + if (!iconWithoutText && !textWithoutIcon) { + placeText = placeIcon = placeText && placeIcon; + } else if (!textWithoutIcon) { + placeText = placeText && placeIcon; + } else if (!iconWithoutText) { + placeIcon = placeText && placeIcon; + } + + if (placeText) { + collisionIndex.insertFeature(textCollisionFeature, bucketCore.layout.get()); + } + + if (placeIcon) { + collisionIndex.insertFeature(iconCollisionFeature, bucketCore.layout.get()); + } + + assert(crossTileID != 0); + + placements.emplace(crossTileID, PlacementPair(placeText, placeIcon)); + seenCrossTileIDs.insert(crossTileID); + } + } +} + +} // namespace mbgl diff --git a/src/mbgl/text/placement_worker.hpp b/src/mbgl/text/placement_worker.hpp new file mode 100644 index 0000000000..86bc16088e --- /dev/null +++ b/src/mbgl/text/placement_worker.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include +#include +#include +#include + +namespace mbgl { + +class PlacementBucket { + public: + PlacementBucket(Immutable&, Immutable>& ids, const UnwrappedTileID&, const OverscaledTileID&); + Immutable symbolBucketCore; + Immutable> symbolCrossTileIDs; + UnwrappedTileID unwrappedTileID; + OverscaledTileID overscaledTileID; +}; + +class PlacementPair { + public: + PlacementPair(bool text_, bool icon_) : text(text_), icon(icon_) {} + bool text; + bool icon; +}; + +class PlacementResult { + public: + PlacementResult(const TransformState& state) : collisionIndex(state) {} + CollisionIndex collisionIndex; + std::unordered_map placements; +}; + +class PlacementWorker { + public: + PlacementWorker(const TransformState&, const mat4& projMatrix, const bool showCollisionBoxes); + Immutable place(Immutable>> placementBucketLayers); + + private: + TransformState state; + const mat4 projMatrix; + const bool showCollisionBoxes; + + void placeLayerBucket( + std::unordered_map& placements, + CollisionIndex& collisionIndex, + const SymbolBucket::Core&, + const std::vector& symbolCrossTileIDs, + const UnwrappedTileID&, + const OverscaledTileID&, + std::unordered_set& seenCrossTileIDs); +}; + +} // namespace mbgl diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index 576c23b682..c73cdfddd9 100644 --- a/src/mbgl/tile/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -287,9 +287,6 @@ void GeometryTile::resetCrossTileIDs() { auto symbolBucket = dynamic_cast(bucket.second.get()); if (symbolBucket && symbolBucket->bucketInstanceId) { symbolBucket->bucketInstanceId = 0; - for (auto& symbolInstance : symbolBucket->symbolInstances) { - symbolInstance.crossTileID = 0; - } } } } -- cgit v1.2.1