From 054645042a52de4d0b6d22d1ec033bc9197c9297 Mon Sep 17 00:00:00 2001 From: Mikhail Pozdnyakov Date: Sat, 25 May 2019 16:17:45 +0300 Subject: [core] Encapsulate symbol bucket placement code in Placement::placeLayerBucket() --- src/mbgl/renderer/bucket.hpp | 4 +- src/mbgl/renderer/buckets/symbol_bucket.cpp | 3 +- src/mbgl/renderer/buckets/symbol_bucket.hpp | 2 +- src/mbgl/renderer/layers/render_symbol_layer.cpp | 6 +- src/mbgl/renderer/render_layer.hpp | 3 - src/mbgl/text/placement.cpp | 134 +++++++++++------------ src/mbgl/text/placement.hpp | 10 +- 7 files changed, 71 insertions(+), 91 deletions(-) diff --git a/src/mbgl/renderer/bucket.hpp b/src/mbgl/renderer/bucket.hpp index 665fc1bfa5..6840d8c47a 100644 --- a/src/mbgl/renderer/bucket.hpp +++ b/src/mbgl/renderer/bucket.hpp @@ -58,8 +58,8 @@ public: virtual std::pair registerAtCrossTileIndex(CrossTileSymbolLayerIndex&, const OverscaledTileID&, uint32_t&) { return std::make_pair(0u, false); } - // Places this bucket to the given placement. Returns bucket cross-tile id on success call; `0` otherwise. - virtual uint32_t place(Placement&, const BucketPlacementParameters&, std::set&) { return 0u; } + // Places this bucket to the given placement. + virtual void place(Placement&, const BucketPlacementParameters&, std::set&) {} virtual void updateVertices(Placement&, bool /*updateOpacities*/, const RenderTile&, std::set&) {} protected: diff --git a/src/mbgl/renderer/buckets/symbol_bucket.cpp b/src/mbgl/renderer/buckets/symbol_bucket.cpp index 06fccb8ffd..33ddd4d53c 100644 --- a/src/mbgl/renderer/buckets/symbol_bucket.cpp +++ b/src/mbgl/renderer/buckets/symbol_bucket.cpp @@ -249,9 +249,8 @@ std::pair SymbolBucket::registerAtCrossTileIndex(CrossTileSymbol return std::make_pair(bucketInstanceId, firstTimeAdded); } -uint32_t SymbolBucket::place(Placement& placement, const BucketPlacementParameters& params, std::set& seenIds) { +void SymbolBucket::place(Placement& placement, const BucketPlacementParameters& params, std::set& seenIds) { placement.placeLayerBucket(*this, params, seenIds); - return bucketInstanceId; } void SymbolBucket::updateVertices(Placement& placement, bool updateOpacities, const RenderTile& tile, std::set& seenIds) { diff --git a/src/mbgl/renderer/buckets/symbol_bucket.hpp b/src/mbgl/renderer/buckets/symbol_bucket.hpp index e47672f1cd..ed2ccd98c8 100644 --- a/src/mbgl/renderer/buckets/symbol_bucket.hpp +++ b/src/mbgl/renderer/buckets/symbol_bucket.hpp @@ -59,7 +59,7 @@ public: void upload(gfx::UploadPass&) override; bool hasData() const override; std::pair registerAtCrossTileIndex(CrossTileSymbolLayerIndex&, const OverscaledTileID&, uint32_t& maxCrossTileID) override; - uint32_t place(Placement&, const BucketPlacementParameters&, std::set&) override; + void place(Placement&, const BucketPlacementParameters&, std::set&) override; void updateVertices(Placement&, bool updateOpacities, const RenderTile&, std::set&) override; bool hasTextData() const; bool hasIconData() const; diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp index 235f0dfdfb..11469f27cc 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.cpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp @@ -521,12 +521,8 @@ void RenderSymbolLayer::prepare(const LayerPrepareParameters& params) { for (RenderTile& renderTile : renderTiles) { auto* bucket = static_cast(renderTile.getBucket(*baseImpl)); if (bucket && bucket->bucketLeaderID == getID()) { - auto& layout = bucket->layout; - bool pitchWithMap = layout.get() == style::AlignmentType::Map; - bool rotateWithMap = layout.get() == style::AlignmentType::Map; - // Only place this layer if it's the "group leader" for the bucket - placementData.push_back({*bucket, renderTile, pitchWithMap, rotateWithMap}); + placementData.push_back({*bucket, renderTile}); } } } diff --git a/src/mbgl/renderer/render_layer.hpp b/src/mbgl/renderer/render_layer.hpp index 3208bf1320..3d5bc2c545 100644 --- a/src/mbgl/renderer/render_layer.hpp +++ b/src/mbgl/renderer/render_layer.hpp @@ -18,7 +18,6 @@ class PaintParameters; class RenderSource; class RenderTile; class TransformState; -class GeometryTile; class LayerRenderData { public: @@ -30,8 +29,6 @@ class LayerPlacementData { public: std::reference_wrapper bucket; std::reference_wrapper tile; - bool pitchWithMap; - bool rotateWithMap; }; class LayerPrepareParameters { diff --git a/src/mbgl/text/placement.cpp b/src/mbgl/text/placement.cpp index dfe663a8a2..49bf3844c8 100644 --- a/src/mbgl/text/placement.cpp +++ b/src/mbgl/text/placement.cpp @@ -72,52 +72,15 @@ Placement::Placement(const TransformState& state_, MapMode mapMode_, style::Tran } void Placement::placeLayer(const RenderLayer& layer, const mat4& projMatrix, bool showCollisionBoxes) { - std::set seenCrossTileIDs; - for (const auto& item : layer.getPlacementData()) { - RenderTile& renderTile = item.tile; Bucket& bucket = item.bucket; - - const float pixelsToTileUnits = renderTile.id.pixelsToTileUnits(1, state.getZoom()); - const OverscaledTileID& overscaledID = renderTile.getOverscaledTileID(); - const float scale = std::pow(2, state.getZoom() - overscaledID.overscaledZ); - const float textPixelRatio = (util::tileSize * overscaledID.overscaleFactor()) / util::EXTENT; - - mat4 posMatrix; - state.matrixFor(posMatrix, renderTile.id); - matrix::multiply(posMatrix, projMatrix, posMatrix); - - mat4 textLabelPlaneMatrix = getLabelPlaneMatrix(posMatrix, - item.pitchWithMap, - item.rotateWithMap, - state, - pixelsToTileUnits); - - mat4 iconLabelPlaneMatrix = getLabelPlaneMatrix(posMatrix, - item.pitchWithMap, - item.rotateWithMap, - state, - pixelsToTileUnits); - - const auto& collisionGroup = collisionGroups.get(layer.baseImpl->source); BucketPlacementParameters params{ - posMatrix, - textLabelPlaneMatrix, - iconLabelPlaneMatrix, - scale, - textPixelRatio, - showCollisionBoxes, - renderTile.holdForFade(), - collisionGroup}; - auto bucketInstanceId = bucket.place(*this, params, seenCrossTileIDs); - assert(bucketInstanceId != 0u); - - // As long as this placement lives, we have to hold onto this bucket's - // matching FeatureIndex/data for querying purposes - retainedQueryData.emplace(std::piecewise_construct, - std::forward_as_tuple(bucketInstanceId), - std::forward_as_tuple(bucketInstanceId, renderTile.getFeatureIndex(), overscaledID)); + item.tile, + projMatrix, + layer.baseImpl->source, + showCollisionBoxes}; + bucket.place(*this, params, seenCrossTileIDs); } } @@ -138,19 +101,42 @@ void Placement::placeLayerBucket( SymbolBucket& bucket, const BucketPlacementParameters& params, std::set& seenCrossTileIDs) { - + const auto& layout = bucket.layout; + const auto& renderTile = params.tile; + const float pixelsToTileUnits = renderTile.id.pixelsToTileUnits(1, state.getZoom()); + const OverscaledTileID& overscaledID = renderTile.getOverscaledTileID(); + const float scale = std::pow(2, state.getZoom() - overscaledID.overscaledZ); + const float pixelRatio = (util::tileSize * overscaledID.overscaleFactor()) / util::EXTENT; + + mat4 posMatrix; + state.matrixFor(posMatrix, renderTile.id); + matrix::multiply(posMatrix, params.projMatrix, posMatrix); + + mat4 textLabelPlaneMatrix = getLabelPlaneMatrix(posMatrix, + layout.get() == style::AlignmentType::Map, + layout.get() == style::AlignmentType::Map, + state, + pixelsToTileUnits); + + mat4 iconLabelPlaneMatrix = getLabelPlaneMatrix(posMatrix, + layout.get() == style::AlignmentType::Map, + layout.get() == style::AlignmentType::Map, + state, + pixelsToTileUnits); + + const auto& collisionGroup = collisionGroups.get(params.sourceId); auto partiallyEvaluatedTextSize = bucket.textSizeBinder->evaluateForZoom(state.getZoom()); auto partiallyEvaluatedIconSize = bucket.iconSizeBinder->evaluateForZoom(state.getZoom()); optional avoidEdges; if (mapMode == MapMode::Tile && - (bucket.layout.get() || - bucket.layout.get() == style::SymbolPlacementType::Line)) { - avoidEdges = collisionIndex.projectTileBoundaries(params.posMatrix); + (layout.get() || + layout.get() == style::SymbolPlacementType::Line)) { + avoidEdges = collisionIndex.projectTileBoundaries(posMatrix); } - const bool textAllowOverlap = bucket.layout.get(); - const bool iconAllowOverlap = bucket.layout.get(); + const bool textAllowOverlap = layout.get(); + const bool iconAllowOverlap = layout.get(); // This logic is similar to the "defaultOpacityState" logic below in updateBucketOpacities // If we know a symbol is always supposed to show, force it to be marked visible even if // it wasn't placed into the collision index (because some or all of it was outside the range @@ -165,18 +151,18 @@ void Placement::placeLayerBucket( // This is the reverse of our normal policy of "fade in on pan", but should look like any other // collision and hopefully not be too noticeable. // See https://github.com/mapbox/mapbox-gl-native/issues/12683 - const bool alwaysShowText = textAllowOverlap && (iconAllowOverlap || !bucket.hasIconData() || bucket.layout.get()); - const bool alwaysShowIcon = iconAllowOverlap && (textAllowOverlap || !bucket.hasTextData() || bucket.layout.get()); - std::vector variableTextAnchors = bucket.layout.get(); - const bool rotateWithMap = bucket.layout.get() == style::AlignmentType::Map; - const bool pitchWithMap = bucket.layout.get() == style::AlignmentType::Map; + const bool alwaysShowText = textAllowOverlap && (iconAllowOverlap || !bucket.hasIconData() || layout.get()); + const bool alwaysShowIcon = iconAllowOverlap && (textAllowOverlap || !bucket.hasTextData() || layout.get()); + std::vector variableTextAnchors = layout.get(); + const bool rotateWithMap = layout.get() == style::AlignmentType::Map; + const bool pitchWithMap = layout.get() == style::AlignmentType::Map; - const bool zOrderByViewportY = bucket.layout.get() == style::SymbolZOrderType::ViewportY; + const bool zOrderByViewportY = layout.get() == style::SymbolZOrderType::ViewportY; auto placeSymbol = [&] (SymbolInstance& symbolInstance) { if (seenCrossTileIDs.count(symbolInstance.crossTileID) != 0u) return; - if (params.holdingForFade) { + if (renderTile.holdForFade()) { // Mark all symbols from this tile as "not placed", but don't add to seenCrossTileIDs, because we don't // know yet if we have a duplicate in a parent tile that _should_ be placed. placements.emplace(symbolInstance.crossTileID, JointPlacement(false, false, false)); @@ -193,11 +179,11 @@ void Placement::placeLayerBucket( const float fontSize = evaluateSizeForFeature(partiallyEvaluatedTextSize, placedSymbol); if (variableTextAnchors.empty()) { auto placed = collisionIndex.placeFeature(textCollisionFeature, {}, - params.posMatrix, params.textLabelPlaneMatrix, params.pixelRatio, - placedSymbol, params.scale, fontSize, - bucket.layout.get(), + posMatrix, textLabelPlaneMatrix, pixelRatio, + placedSymbol, scale, fontSize, + layout.get(), pitchWithMap, - params.showCollisionBoxes, avoidEdges, params.collisionGroup.second); + params.showCollisionBoxes, avoidEdges, collisionGroup.second); placeText = placed.first; offscreen &= placed.second; } else if (!textCollisionFeature.alongLine && !textCollisionFeature.boxes.empty()) { @@ -232,11 +218,11 @@ void Placement::placeLayerBucket( } auto placed = collisionIndex.placeFeature(textCollisionFeature, shift, - params.posMatrix, mat4(), params.pixelRatio, - placedSymbol, params.scale, fontSize, - bucket.layout.get(), + posMatrix, mat4(), pixelRatio, + placedSymbol, scale, fontSize, + layout.get(), pitchWithMap, - params.showCollisionBoxes, avoidEdges, params.collisionGroup.second); + params.showCollisionBoxes, avoidEdges, collisionGroup.second); if (placed.first) { assert(symbolInstance.crossTileID != 0u); @@ -287,17 +273,17 @@ void Placement::placeLayerBucket( const float fontSize = evaluateSizeForFeature(partiallyEvaluatedIconSize, placedSymbol); auto placed = collisionIndex.placeFeature(symbolInstance.iconCollisionFeature, {}, - params.posMatrix, params.iconLabelPlaneMatrix, params.pixelRatio, - placedSymbol, params.scale, fontSize, - bucket.layout.get(), + posMatrix, iconLabelPlaneMatrix, pixelRatio, + placedSymbol, scale, fontSize, + layout.get(), pitchWithMap, - params.showCollisionBoxes, avoidEdges, params.collisionGroup.second); + params.showCollisionBoxes, avoidEdges, collisionGroup.second); placeIcon = placed.first; offscreen &= placed.second; } - const bool iconWithoutText = !symbolInstance.hasText || bucket.layout.get(); - const bool textWithoutIcon = !symbolInstance.hasIcon || bucket.layout.get(); + const bool iconWithoutText = !symbolInstance.hasText || layout.get(); + const bool textWithoutIcon = !symbolInstance.hasIcon || layout.get(); // combine placements for icon and text if (!iconWithoutText && !textWithoutIcon) { @@ -309,11 +295,11 @@ void Placement::placeLayerBucket( } if (placeText) { - collisionIndex.insertFeature(symbolInstance.textCollisionFeature, bucket.layout.get(), bucket.bucketInstanceId, params.collisionGroup.first); + collisionIndex.insertFeature(symbolInstance.textCollisionFeature, layout.get(), bucket.bucketInstanceId, collisionGroup.first); } if (placeIcon) { - collisionIndex.insertFeature(symbolInstance.iconCollisionFeature, bucket.layout.get(), bucket.bucketInstanceId, params.collisionGroup.first); + collisionIndex.insertFeature(symbolInstance.iconCollisionFeature, layout.get(), bucket.bucketInstanceId, collisionGroup.first); } assert(symbolInstance.crossTileID != 0); @@ -341,6 +327,12 @@ void Placement::placeLayerBucket( } bucket.justReloaded = false; + + // As long as this placement lives, we have to hold onto this bucket's + // matching FeatureIndex/data for querying purposes + retainedQueryData.emplace(std::piecewise_construct, + std::forward_as_tuple(bucket.bucketInstanceId), + std::forward_as_tuple(bucket.bucketInstanceId, renderTile.getFeatureIndex(), overscaledID)); } void Placement::commit(TimePoint now) { diff --git a/src/mbgl/text/placement.hpp b/src/mbgl/text/placement.hpp index c159286a2b..30062471da 100644 --- a/src/mbgl/text/placement.hpp +++ b/src/mbgl/text/placement.hpp @@ -90,14 +90,10 @@ private: class BucketPlacementParameters { public: - const mat4& posMatrix; - const mat4& textLabelPlaneMatrix; - const mat4& iconLabelPlaneMatrix; - float scale; - float pixelRatio; + const RenderTile& tile; + const mat4& projMatrix; + std::string sourceId; bool showCollisionBoxes; - bool holdingForFade; - const CollisionGroups::CollisionGroup& collisionGroup; }; class Placement { -- cgit v1.2.1