diff options
author | Alexander Shalamov <alexander.shalamov@mapbox.com> | 2019-07-21 12:16:02 +0300 |
---|---|---|
committer | Alexander Shalamov <alexander.shalamov@mapbox.com> | 2019-07-23 15:43:27 +0300 |
commit | ac74fc6d005e334ff7126e49b4c737ecb10666b3 (patch) | |
tree | ca810576c0ed0f0fba393c7040254d3e919d5195 /src/mbgl/layout | |
parent | dabf5d0c3a76f9fbe8b866f64f51accf12d1a2a6 (diff) | |
download | qtlocation-mapboxgl-ac74fc6d005e334ff7126e49b4c737ecb10666b3.tar.gz |
[core] Release quad data after vertex buffers are created
Diffstat (limited to 'src/mbgl/layout')
-rw-r--r-- | src/mbgl/layout/symbol_instance.cpp | 136 | ||||
-rw-r--r-- | src/mbgl/layout/symbol_instance.hpp | 59 | ||||
-rw-r--r-- | src/mbgl/layout/symbol_layout.cpp | 62 | ||||
-rw-r--r-- | src/mbgl/layout/symbol_layout.hpp | 2 |
4 files changed, 172 insertions, 87 deletions
diff --git a/src/mbgl/layout/symbol_instance.cpp b/src/mbgl/layout/symbol_instance.cpp index 809aa2f451..133cdec698 100644 --- a/src/mbgl/layout/symbol_instance.cpp +++ b/src/mbgl/layout/symbol_instance.cpp @@ -18,20 +18,63 @@ const Shaping& getAnyShaping(const ShapedTextOrientations& shapedTextOrientation } // namespace +SymbolInstanceSharedData::SymbolInstanceSharedData(GeometryCoordinates line_, + const ShapedTextOrientations& shapedTextOrientations, + const optional<PositionedIcon>& shapedIcon, + const style::SymbolLayoutProperties::Evaluated& layout, + const float layoutTextSize, + const style::SymbolPlacementType textPlacement, + const std::array<float, 2>& textOffset, + const GlyphPositions& positions) : line(std::move(line_)) { + // Create the quads used for rendering the icon and glyphs. + if (shapedIcon) { + iconQuad = getIconQuad(*shapedIcon, layout, layoutTextSize, shapedTextOrientations.horizontal); + } + + bool singleLineInitialized = false; + const auto initHorizontalGlyphQuads = [&] (SymbolQuads& quads, const Shaping& shaping) { + if (!shapedTextOrientations.singleLine) { + quads = getGlyphQuads(shaping, textOffset, layout, textPlacement, positions); + return; + } + if (!singleLineInitialized) { + rightJustifiedGlyphQuads = getGlyphQuads(shaping, textOffset, layout, textPlacement, positions); + singleLineInitialized = true; + } + }; + + if (shapedTextOrientations.right) { + initHorizontalGlyphQuads(rightJustifiedGlyphQuads, shapedTextOrientations.right); + } + + if (shapedTextOrientations.center) { + initHorizontalGlyphQuads(centerJustifiedGlyphQuads, shapedTextOrientations.center); + } + + if (shapedTextOrientations.left) { + initHorizontalGlyphQuads(leftJustifiedGlyphQuads, shapedTextOrientations.left); + } + + if (shapedTextOrientations.vertical) { + verticalGlyphQuads = getGlyphQuads(shapedTextOrientations.vertical, textOffset, layout, textPlacement, positions); + } +} + +bool SymbolInstanceSharedData::empty() const { + return rightJustifiedGlyphQuads.empty() && centerJustifiedGlyphQuads.empty() && leftJustifiedGlyphQuads.empty() && verticalGlyphQuads.empty(); +} + SymbolInstance::SymbolInstance(Anchor& anchor_, - GeometryCoordinates line_, + std::shared_ptr<SymbolInstanceSharedData> sharedData_, const ShapedTextOrientations& shapedTextOrientations, - optional<PositionedIcon> shapedIcon, - const SymbolLayoutProperties::Evaluated& layout, - const float layoutTextSize, + const optional<PositionedIcon>& shapedIcon, const float textBoxScale_, const float textPadding, const SymbolPlacementType textPlacement, - const std::array<float, 2> textOffset_, + const std::array<float, 2>& textOffset_, const float iconBoxScale, const float iconPadding, - const std::array<float, 2> iconOffset_, - const GlyphPositions& positions, + const std::array<float, 2>& iconOffset_, const IndexedSubfeature& indexedFeature, const std::size_t layoutFeatureIndex_, const std::size_t dataFeatureIndex_, @@ -39,15 +82,15 @@ SymbolInstance::SymbolInstance(Anchor& anchor_, const float overscaling, const float rotate, float radialTextOffset_) : + sharedData(std::move(sharedData_)), anchor(anchor_), - line(line_), - hasText(false), + // 'hasText' depends on finding at least one glyph in the shaping that's also in the GlyphPositionMap + hasText(!sharedData->empty()), hasIcon(shapedIcon), - // Create the collision features that will be used to check whether this symbol instance can be placed // As a collision approximation, we can use either the vertical or any of the horizontal versions of the feature - textCollisionFeature(line_, anchor, getAnyShaping(shapedTextOrientations), textBoxScale_, textPadding, textPlacement, indexedFeature, overscaling, rotate), - iconCollisionFeature(line_, anchor, shapedIcon, iconBoxScale, iconPadding, indexedFeature, rotate), + textCollisionFeature(sharedData->line, anchor, getAnyShaping(shapedTextOrientations), textBoxScale_, textPadding, textPlacement, indexedFeature, overscaling, rotate), + iconCollisionFeature(sharedData->line, anchor, shapedIcon, iconBoxScale, iconPadding, indexedFeature, rotate), writingModes(WritingModeType::None), layoutFeatureIndex(layoutFeatureIndex_), dataFeatureIndex(dataFeatureIndex_), @@ -58,43 +101,52 @@ SymbolInstance::SymbolInstance(Anchor& anchor_, radialTextOffset(radialTextOffset_), singleLine(shapedTextOrientations.singleLine) { - // Create the quads used for rendering the icon and glyphs. - if (shapedIcon) { - iconQuad = getIconQuad(*shapedIcon, layout, layoutTextSize, shapedTextOrientations.horizontal); - } - - bool singleLineInitialized = false; - const auto initHorizontalGlyphQuads = [&] (SymbolQuads& quads, const Shaping& shaping) { + rightJustifiedGlyphQuadsSize = sharedData->rightJustifiedGlyphQuads.size(); + centerJustifiedGlyphQuadsSize = sharedData->centerJustifiedGlyphQuads.size(); + leftJustifiedGlyphQuadsSize = sharedData->leftJustifiedGlyphQuads.size(); + verticalGlyphQuadsSize = sharedData->verticalGlyphQuads.size(); + + if (rightJustifiedGlyphQuadsSize || centerJustifiedGlyphQuadsSize || leftJustifiedGlyphQuadsSize) { writingModes |= WritingModeType::Horizontal; - if (!singleLine) { - quads = getGlyphQuads(shaping, textOffset, layout, textPlacement, positions); - return; - } - if (!singleLineInitialized) { - rightJustifiedGlyphQuads = getGlyphQuads(shaping, textOffset, layout, textPlacement, positions); - singleLineInitialized = true; - } - }; - - if (shapedTextOrientations.right) { - initHorizontalGlyphQuads(rightJustifiedGlyphQuads, shapedTextOrientations.right); } - if (shapedTextOrientations.center) { - initHorizontalGlyphQuads(centerJustifiedGlyphQuads, shapedTextOrientations.center); + if (verticalGlyphQuadsSize) { + writingModes |= WritingModeType::Vertical; } +} - if (shapedTextOrientations.left) { - initHorizontalGlyphQuads(leftJustifiedGlyphQuads, shapedTextOrientations.left); - } +const GeometryCoordinates& SymbolInstance::line() const { + assert(sharedData); + return sharedData->line; +} - if (shapedTextOrientations.vertical) { - writingModes |= WritingModeType::Vertical; - verticalGlyphQuads = getGlyphQuads(shapedTextOrientations.vertical, textOffset, layout, textPlacement, positions); - } +const SymbolQuads& SymbolInstance::rightJustifiedGlyphQuads() const { + assert(sharedData); + return sharedData->rightJustifiedGlyphQuads; +} - // 'hasText' depends on finding at least one glyph in the shaping that's also in the GlyphPositionMap - hasText = !rightJustifiedGlyphQuads.empty() || !centerJustifiedGlyphQuads.empty() || !leftJustifiedGlyphQuads.empty() || !verticalGlyphQuads.empty(); +const SymbolQuads& SymbolInstance::leftJustifiedGlyphQuads() const { + assert(sharedData); + return sharedData->leftJustifiedGlyphQuads; +} + +const SymbolQuads& SymbolInstance::centerJustifiedGlyphQuads() const { + assert(sharedData); + return sharedData->centerJustifiedGlyphQuads; +} + +const SymbolQuads& SymbolInstance::verticalGlyphQuads() const { + assert(sharedData); + return sharedData->verticalGlyphQuads; +} + +const optional<SymbolQuad>& SymbolInstance::iconQuad() const { + assert(sharedData); + return sharedData->iconQuad; +} + +void SymbolInstance::releaseSharedData() { + sharedData.reset(); } optional<size_t> SymbolInstance::getDefaultHorizontalPlacedTextIndex() const { diff --git a/src/mbgl/layout/symbol_instance.hpp b/src/mbgl/layout/symbol_instance.hpp index 95159deeb1..48bb2f0cbc 100644 --- a/src/mbgl/layout/symbol_instance.hpp +++ b/src/mbgl/layout/symbol_instance.hpp @@ -21,23 +21,39 @@ struct ShapedTextOrientations { bool singleLine = false; }; +struct SymbolInstanceSharedData { + SymbolInstanceSharedData(GeometryCoordinates line, + const ShapedTextOrientations& shapedTextOrientations, + const optional<PositionedIcon>& shapedIcon, + const style::SymbolLayoutProperties::Evaluated& layout, + const float layoutTextSize, + const style::SymbolPlacementType textPlacement, + const std::array<float, 2>& textOffset, + const GlyphPositions& positions); + bool empty() const; + GeometryCoordinates line; + // Note: When singleLine == true, only `rightJustifiedGlyphQuads` is populated. + SymbolQuads rightJustifiedGlyphQuads; + SymbolQuads centerJustifiedGlyphQuads; + SymbolQuads leftJustifiedGlyphQuads; + SymbolQuads verticalGlyphQuads; + optional<SymbolQuad> iconQuad; +}; + class SymbolInstance { public: - SymbolInstance(Anchor& anchor, - GeometryCoordinates line, + SymbolInstance(Anchor& anchor_, + std::shared_ptr<SymbolInstanceSharedData> sharedData, const ShapedTextOrientations& shapedTextOrientations, - optional<PositionedIcon> shapedIcon, - const style::SymbolLayoutProperties::Evaluated&, - const float layoutTextSize, + const optional<PositionedIcon>& shapedIcon, const float textBoxScale, const float textPadding, - style::SymbolPlacementType textPlacement, - const std::array<float, 2> textOffset, + const style::SymbolPlacementType textPlacement, + const std::array<float, 2>& textOffset, const float iconBoxScale, const float iconPadding, - const std::array<float, 2> iconOffset, - const GlyphPositions&, - const IndexedSubfeature&, + const std::array<float, 2>& iconOffset, + const IndexedSubfeature& indexedFeature, const std::size_t layoutFeatureIndex, const std::size_t dataFeatureIndex, std::u16string key, @@ -46,18 +62,27 @@ public: float radialTextOffset); optional<size_t> getDefaultHorizontalPlacedTextIndex() const; + const GeometryCoordinates& line() const; + const SymbolQuads& rightJustifiedGlyphQuads() const; + const SymbolQuads& leftJustifiedGlyphQuads() const; + const SymbolQuads& centerJustifiedGlyphQuads() const; + const SymbolQuads& verticalGlyphQuads() const; + const optional<SymbolQuad>& iconQuad() const; + void releaseSharedData(); + +private: + std::shared_ptr<SymbolInstanceSharedData> sharedData; + +public: Anchor anchor; - GeometryCoordinates line; bool hasText; bool hasIcon; - // Note: When singleLine == true, only `rightJustifiedGlyphQuads` is populated. - SymbolQuads rightJustifiedGlyphQuads; - SymbolQuads centerJustifiedGlyphQuads; - SymbolQuads leftJustifiedGlyphQuads; - SymbolQuads verticalGlyphQuads; + std::size_t rightJustifiedGlyphQuadsSize; + std::size_t centerJustifiedGlyphQuadsSize; + std::size_t leftJustifiedGlyphQuadsSize; + std::size_t verticalGlyphQuadsSize; - optional<SymbolQuad> iconQuad; CollisionFeature textCollisionFeature; CollisionFeature iconCollisionFeature; WritingModeType writingModes; diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp index 21642b01e3..d269ca4144 100644 --- a/src/mbgl/layout/symbol_layout.cpp +++ b/src/mbgl/layout/symbol_layout.cpp @@ -397,7 +397,7 @@ void SymbolLayout::prepareSymbols(const GlyphMap& glyphMap, const GlyphPositions void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex, const SymbolFeature& feature, const ShapedTextOrientations& shapedTextOrientations, - optional<PositionedIcon> shapedIcon, + const optional<PositionedIcon>& shapedIcon, const GlyphPositions& glyphPositions, Point<float> offset) { const float minScale = 0.5f; @@ -433,7 +433,8 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex, const auto evaluatedLayoutProperties = layout->evaluate(zoom, feature); IndexedSubfeature indexedFeature(feature.index, sourceLayer->getName(), bucketLeaderID, symbolInstances.size()); - auto addSymbolInstance = [&] (const GeometryCoordinates& line, Anchor& anchor) { + auto addSymbolInstance = [&] (Anchor& anchor, std::shared_ptr<SymbolInstanceSharedData> sharedData) { + assert(sharedData); const bool anchorInsideTile = anchor.point.x >= 0 && anchor.point.x < util::EXTENT && anchor.point.y >= 0 && anchor.point.y < util::EXTENT; if (mode == MapMode::Tile || anchorInsideTile) { @@ -442,20 +443,26 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex, // In tiled rendering mode, add all symbols in the buffers so that we can: // (1) render symbols that overlap into this tile // (2) approximate collision detection effects from neighboring symbols - symbolInstances.emplace_back(anchor, line, shapedTextOrientations, shapedIcon, - evaluatedLayoutProperties, layoutTextSize, + symbolInstances.emplace_back(anchor, std::move(sharedData), shapedTextOrientations, shapedIcon, textBoxScale, textPadding, textPlacement, textOffset, - iconBoxScale, iconPadding, iconOffset, - glyphPositions, indexedFeature, layoutFeatureIndex, feature.index, - feature.formattedText ? feature.formattedText->rawText() : std::u16string(), overscaling, rotation, radialTextOffset); + iconBoxScale, iconPadding, iconOffset, indexedFeature, + layoutFeatureIndex, feature.index, + feature.formattedText ? feature.formattedText->rawText() : std::u16string(), + overscaling, rotation, radialTextOffset); } }; + const auto createSymbolInstanceSharedData = [&] (GeometryCoordinates line) { + return std::make_shared<SymbolInstanceSharedData>(std::move(line), + shapedTextOrientations, shapedIcon, evaluatedLayoutProperties, layoutTextSize, + textPlacement, textOffset, glyphPositions); + }; + const auto& type = feature.getType(); if (layout->get<SymbolPlacement>() == SymbolPlacementType::Line) { auto clippedLines = util::clipLines(feature.geometry, 0, 0, util::EXTENT, util::EXTENT); - for (const auto& line : clippedLines) { + for (auto& line : clippedLines) { Anchors anchors = getAnchors(line, symbolSpacing, textMaxAngle, @@ -466,10 +473,10 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex, glyphSize, textMaxBoxScale, overscaling); - + auto sharedData = createSymbolInstanceSharedData(std::move(line)); for (auto& anchor : anchors) { if (!feature.formattedText || !anchorIsTooClose(feature.formattedText->rawText(), textRepeatDistance, anchor)) { - addSymbolInstance(line, anchor); + addSymbolInstance(anchor, sharedData); } } } @@ -487,7 +494,7 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex, glyphSize, textMaxBoxScale); if (anchor) { - addSymbolInstance(line, *anchor); + addSymbolInstance(*anchor, createSymbolInstanceSharedData(line)); } } } @@ -505,18 +512,18 @@ void SymbolLayout::addFeature(const std::size_t layoutFeatureIndex, // 1 pixel worth of precision, in tile coordinates auto poi = mapbox::polylabel(poly, double(util::EXTENT / util::tileSize)); Anchor anchor(poi.x, poi.y, 0, minScale); - addSymbolInstance(polygon[0], anchor); + addSymbolInstance(anchor, createSymbolInstanceSharedData(polygon[0])); } } else if (type == FeatureType::LineString) { for (const auto& line : feature.geometry) { Anchor anchor(line[0].x, line[0].y, 0, minScale); - addSymbolInstance(line, anchor); + addSymbolInstance(anchor, createSymbolInstanceSharedData(line)); } } else if (type == FeatureType::Point) { for (const auto& points : feature.geometry) { for (const auto& point : points) { Anchor anchor(point.x, point.y, 0, minScale); - addSymbolInstance({point}, anchor); + addSymbolInstance(anchor, createSymbolInstanceSharedData({point})); } } } @@ -576,36 +583,36 @@ void SymbolLayout::createBucket(const ImagePositions&, std::unique_ptr<FeatureIn optional<std::size_t> lastAddedSection; if (singleLine) { optional<std::size_t> placedTextIndex; - lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, placedTextIndex, symbolInstance.rightJustifiedGlyphQuads, lastAddedSection); + lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, placedTextIndex, symbolInstance.rightJustifiedGlyphQuads(), lastAddedSection); symbolInstance.placedRightTextIndex = placedTextIndex; symbolInstance.placedCenterTextIndex = placedTextIndex; symbolInstance.placedLeftTextIndex = placedTextIndex; } else { - if (!symbolInstance.rightJustifiedGlyphQuads.empty()) { - lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, symbolInstance.placedRightTextIndex, symbolInstance.rightJustifiedGlyphQuads, lastAddedSection); + if (symbolInstance.rightJustifiedGlyphQuadsSize) { + lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, symbolInstance.placedRightTextIndex, symbolInstance.rightJustifiedGlyphQuads(), lastAddedSection); } - if (!symbolInstance.centerJustifiedGlyphQuads.empty()) { - lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, symbolInstance.placedCenterTextIndex, symbolInstance.centerJustifiedGlyphQuads, lastAddedSection); + if (symbolInstance.centerJustifiedGlyphQuadsSize) { + lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, symbolInstance.placedCenterTextIndex, symbolInstance.centerJustifiedGlyphQuads(), lastAddedSection); } - if (!symbolInstance.leftJustifiedGlyphQuads.empty()) { - lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, symbolInstance.placedLeftTextIndex, symbolInstance.leftJustifiedGlyphQuads, lastAddedSection); + if (symbolInstance.leftJustifiedGlyphQuadsSize) { + lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, symbolInstance.writingModes, symbolInstance.placedLeftTextIndex, symbolInstance.leftJustifiedGlyphQuads(), lastAddedSection); } } - if (symbolInstance.writingModes & WritingModeType::Vertical) { - lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, WritingModeType::Vertical, symbolInstance.placedVerticalTextIndex, symbolInstance.verticalGlyphQuads, lastAddedSection); + if (symbolInstance.writingModes & WritingModeType::Vertical && symbolInstance.verticalGlyphQuadsSize) { + lastAddedSection = addSymbolGlyphQuads(*bucket, symbolInstance, feature, WritingModeType::Vertical, symbolInstance.placedVerticalTextIndex, symbolInstance.verticalGlyphQuads(), lastAddedSection); } assert(lastAddedSection); // True, as hasText == true; updatePaintPropertiesForSection(*bucket, feature, *lastAddedSection); } if (hasIcon) { - if (symbolInstance.iconQuad) { + if (symbolInstance.hasIcon) { const Range<float> sizeData = bucket->iconSizeBinder->getVertexSizeData(feature); bucket->icon.placedSymbols.emplace_back(symbolInstance.anchor.point, symbolInstance.anchor.segment, sizeData.min, sizeData.max, - symbolInstance.iconOffset, WritingModeType::None, symbolInstance.line, std::vector<float>()); + symbolInstance.iconOffset, WritingModeType::None, symbolInstance.line(), std::vector<float>()); symbolInstance.placedIconIndex = bucket->icon.placedSymbols.size() - 1; PlacedSymbol& iconSymbol = bucket->icon.placedSymbols.back(); - iconSymbol.vertexStartIndex = addSymbol(bucket->icon, sizeData, *symbolInstance.iconQuad, + iconSymbol.vertexStartIndex = addSymbol(bucket->icon, sizeData, *symbolInstance.iconQuad(), symbolInstance.anchor, iconSymbol, feature.sortKey); for (auto& pair : bucket->paintProperties) { @@ -613,6 +620,7 @@ void SymbolLayout::createBucket(const ImagePositions&, std::unique_ptr<FeatureIn } } } + symbolInstance.releaseSharedData(); } if (showCollisionBoxes) { @@ -649,7 +657,7 @@ std::size_t SymbolLayout::addSymbolGlyphQuads(SymbolBucket& bucket, const bool hasFormatSectionOverrides = bucket.hasFormatSectionOverrides(); bucket.text.placedSymbols.emplace_back(symbolInstance.anchor.point, symbolInstance.anchor.segment, sizeData.min, sizeData.max, - symbolInstance.textOffset, writingMode, symbolInstance.line, CalculateTileDistances(symbolInstance.line, symbolInstance.anchor)); + symbolInstance.textOffset, writingMode, symbolInstance.line(), CalculateTileDistances(symbolInstance.line(), symbolInstance.anchor)); placedIndex = bucket.text.placedSymbols.size() - 1; PlacedSymbol& placedSymbol = bucket.text.placedSymbols.back(); diff --git a/src/mbgl/layout/symbol_layout.hpp b/src/mbgl/layout/symbol_layout.hpp index 23f883f56c..581c3ccb04 100644 --- a/src/mbgl/layout/symbol_layout.hpp +++ b/src/mbgl/layout/symbol_layout.hpp @@ -51,7 +51,7 @@ private: void addFeature(const size_t, const SymbolFeature&, const ShapedTextOrientations& shapedTextOrientations, - optional<PositionedIcon> shapedIcon, + const optional<PositionedIcon>& shapedIcon, const GlyphPositions&, Point<float> textOffset); |