diff options
Diffstat (limited to 'src/mbgl/renderer/layers')
-rw-r--r-- | src/mbgl/renderer/layers/render_background_layer.cpp | 19 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_background_layer.hpp | 1 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_heatmap_layer.cpp | 19 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_heatmap_layer.hpp | 1 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_hillshade_layer.cpp | 8 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_line_layer.cpp | 43 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_line_layer.hpp | 1 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_raster_layer.cpp | 4 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_symbol_layer.cpp | 244 | ||||
-rw-r--r-- | src/mbgl/renderer/layers/render_symbol_layer.hpp | 2 |
10 files changed, 221 insertions, 121 deletions
diff --git a/src/mbgl/renderer/layers/render_background_layer.cpp b/src/mbgl/renderer/layers/render_background_layer.cpp index 3eb9bc2a30..51c4f2ae4f 100644 --- a/src/mbgl/renderer/layers/render_background_layer.cpp +++ b/src/mbgl/renderer/layers/render_background_layer.cpp @@ -1,6 +1,7 @@ #include <mbgl/renderer/layers/render_background_layer.hpp> #include <mbgl/style/layers/background_layer_impl.hpp> #include <mbgl/renderer/bucket.hpp> +#include <mbgl/renderer/upload_parameters.hpp> #include <mbgl/renderer/paint_parameters.hpp> #include <mbgl/renderer/image_manager.hpp> #include <mbgl/renderer/render_static_data.hpp> @@ -37,6 +38,9 @@ void RenderBackgroundLayer::evaluate(const PropertyEvaluationParameters ¶met passes = properties->evaluated.get<style::BackgroundOpacity>() > 0 ? RenderPass::Translucent : RenderPass::None; + if (passes != RenderPass::None && !properties->evaluated.get<style::BackgroundPattern>().to.empty()) { + passes |= RenderPass::Upload; + } evaluatedProperties = std::move(properties); } @@ -48,6 +52,15 @@ bool RenderBackgroundLayer::hasCrossfade() const { return getCrossfade<BackgroundLayerProperties>(evaluatedProperties).t != 1; } +void RenderBackgroundLayer::upload(gfx::UploadPass&, UploadParameters& parameters) { + const auto& evaluated = static_cast<const BackgroundLayerProperties&>(*evaluatedProperties).evaluated; + if (!evaluated.get<BackgroundPattern>().to.empty()) { + // Ensures that the texture gets added and uploaded to the atlas. + parameters.imageManager.getPattern(evaluated.get<BackgroundPattern>().from); + parameters.imageManager.getPattern(evaluated.get<BackgroundPattern>().to); + } +} + void RenderBackgroundLayer::render(PaintParameters& parameters, RenderSource*) { // Note that for bottommost layers without a pattern, the background color is drawn with // glClear rather than this method. @@ -63,7 +76,7 @@ void RenderBackgroundLayer::render(PaintParameters& parameters, RenderSource*) { parameters.state.getZoom() ); const auto allAttributeBindings = program.computeAllAttributeBindings( - parameters.staticData.tileVertexBuffer, + *parameters.staticData.tileVertexBuffer, paintAttributeData, properties ); @@ -78,7 +91,7 @@ void RenderBackgroundLayer::render(PaintParameters& parameters, RenderSource*) { gfx::StencilMode::disabled(), parameters.colorModeForRenderPass(), gfx::CullFaceMode::disabled(), - parameters.staticData.quadTriangleIndexBuffer, + *parameters.staticData.quadTriangleIndexBuffer, parameters.staticData.tileTriangleSegments, allUniformValues, allAttributeBindings, @@ -109,7 +122,7 @@ void RenderBackgroundLayer::render(PaintParameters& parameters, RenderSource*) { parameters.state ), BackgroundPatternProgram::TextureBindings{ - textures::image::Value{ parameters.imageManager.textureBinding(parameters.context) }, + textures::image::Value{ parameters.imageManager.textureBinding() }, } ); } diff --git a/src/mbgl/renderer/layers/render_background_layer.hpp b/src/mbgl/renderer/layers/render_background_layer.hpp index de553eef90..248a3e1457 100644 --- a/src/mbgl/renderer/layers/render_background_layer.hpp +++ b/src/mbgl/renderer/layers/render_background_layer.hpp @@ -17,6 +17,7 @@ private: bool hasTransition() const override; bool hasCrossfade() const override; optional<Color> getSolidBackground() const override; + void upload(gfx::UploadPass&, UploadParameters&) override; void render(PaintParameters&, RenderSource*) override; // Paint properties diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.cpp b/src/mbgl/renderer/layers/render_heatmap_layer.cpp index f1cce31ea4..053503bbaa 100644 --- a/src/mbgl/renderer/layers/render_heatmap_layer.cpp +++ b/src/mbgl/renderer/layers/render_heatmap_layer.cpp @@ -41,7 +41,7 @@ void RenderHeatmapLayer::evaluate(const PropertyEvaluationParameters& parameters unevaluated.evaluate(parameters)); passes = (properties->evaluated.get<style::HeatmapOpacity>() > 0) - ? (RenderPass::Translucent | RenderPass::Pass3D) + ? (RenderPass::Translucent | RenderPass::Pass3D | RenderPass::Upload) : RenderPass::None; evaluatedProperties = std::move(properties); @@ -55,6 +55,13 @@ bool RenderHeatmapLayer::hasCrossfade() const { return false; } +void RenderHeatmapLayer::upload(gfx::UploadPass& uploadPass, UploadParameters&) { + if (!colorRampTexture) { + colorRampTexture = + uploadPass.createTexture(colorRamp, gfx::TextureChannelDataType::UnsignedByte); + } +} + void RenderHeatmapLayer::render(PaintParameters& parameters, RenderSource*) { if (parameters.pass == RenderPass::Opaque) { return; @@ -64,9 +71,7 @@ void RenderHeatmapLayer::render(PaintParameters& parameters, RenderSource*) { const auto& viewportSize = parameters.staticData.backendSize; const auto size = Size{viewportSize.width / 4, viewportSize.height / 4}; - if (!colorRampTexture) { - colorRampTexture = parameters.context.createTexture(colorRamp, gfx::TextureChannelDataType::UnsignedByte); - } + assert(colorRampTexture); if (!renderTexture || renderTexture->getSize() != size) { renderTexture.reset(); @@ -101,7 +106,7 @@ void RenderHeatmapLayer::render(PaintParameters& parameters, RenderSource*) { const auto& paintPropertyBinders = bucket.paintPropertyBinders.at(getID()); auto& programInstance = parameters.programs.getHeatmapLayerPrograms().heatmap; - + const auto allUniformValues = programInstance.computeAllUniformValues( HeatmapProgram::LayoutUniformValues { uniforms::intensity::Value( evaluated.get<style::HeatmapIntensity>() ), @@ -159,7 +164,7 @@ void RenderHeatmapLayer::render(PaintParameters& parameters, RenderSource*) { parameters.state.getZoom() ); const auto allAttributeBindings = programInstance.computeAllAttributeBindings( - parameters.staticData.heatmapTextureVertexBuffer, + *parameters.staticData.heatmapTextureVertexBuffer, paintAttributeData, properties ); @@ -174,7 +179,7 @@ void RenderHeatmapLayer::render(PaintParameters& parameters, RenderSource*) { gfx::StencilMode::disabled(), parameters.colorModeForRenderPass(), gfx::CullFaceMode::disabled(), - parameters.staticData.quadTriangleIndexBuffer, + *parameters.staticData.quadTriangleIndexBuffer, parameters.staticData.heatmapTextureSegments, allUniformValues, allAttributeBindings, diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.hpp b/src/mbgl/renderer/layers/render_heatmap_layer.hpp index 65dad9828b..f4c0299dd9 100644 --- a/src/mbgl/renderer/layers/render_heatmap_layer.hpp +++ b/src/mbgl/renderer/layers/render_heatmap_layer.hpp @@ -19,6 +19,7 @@ private: void evaluate(const PropertyEvaluationParameters&) override; bool hasTransition() const override; bool hasCrossfade() const override; + void upload(gfx::UploadPass&, UploadParameters&) override; void render(PaintParameters&, RenderSource*) override; bool queryIntersectsFeature( diff --git a/src/mbgl/renderer/layers/render_hillshade_layer.cpp b/src/mbgl/renderer/layers/render_hillshade_layer.cpp index 19af5b6202..a13de7c4cd 100644 --- a/src/mbgl/renderer/layers/render_hillshade_layer.cpp +++ b/src/mbgl/renderer/layers/render_hillshade_layer.cpp @@ -162,7 +162,7 @@ void RenderHillshadeLayer::render(PaintParameters& parameters, RenderSource* src parameters.state.getZoom() ); const auto allAttributeBindings = programInstance.computeAllAttributeBindings( - parameters.staticData.rasterVertexBuffer, + *parameters.staticData.rasterVertexBuffer, paintAttributeData, properties ); @@ -177,7 +177,7 @@ void RenderHillshadeLayer::render(PaintParameters& parameters, RenderSource* src gfx::StencilMode::disabled(), parameters.colorModeForRenderPass(), gfx::CullFaceMode::disabled(), - parameters.staticData.quadTriangleIndexBuffer, + *parameters.staticData.quadTriangleIndexBuffer, parameters.staticData.rasterSegments, allUniformValues, allAttributeBindings, @@ -204,8 +204,8 @@ void RenderHillshadeLayer::render(PaintParameters& parameters, RenderSource* src } else { // Draw the full tile. draw(parameters.matrixForTile(tile.id, true), - parameters.staticData.rasterVertexBuffer, - parameters.staticData.quadTriangleIndexBuffer, + *parameters.staticData.rasterVertexBuffer, + *parameters.staticData.quadTriangleIndexBuffer, parameters.staticData.rasterSegments, tile.id, HillshadeProgram::TextureBindings{ diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp index a34c634f58..bfb6ac619e 100644 --- a/src/mbgl/renderer/layers/render_line_layer.cpp +++ b/src/mbgl/renderer/layers/render_line_layer.cpp @@ -2,6 +2,7 @@ #include <mbgl/renderer/buckets/line_bucket.hpp> #include <mbgl/renderer/render_tile.hpp> #include <mbgl/renderer/render_source.hpp> +#include <mbgl/renderer/upload_parameters.hpp> #include <mbgl/renderer/paint_parameters.hpp> #include <mbgl/renderer/image_manager.hpp> #include <mbgl/programs/programs.hpp> @@ -46,7 +47,7 @@ void RenderLineLayer::evaluate(const PropertyEvaluationParameters& parameters) { passes = (evaluated.get<style::LineOpacity>().constantOr(1.0) > 0 && evaluated.get<style::LineColor>().constantOr(Color::black()).a > 0 && evaluated.get<style::LineWidth>().constantOr(1.0) > 0) - ? RenderPass::Translucent : RenderPass::None; + ? RenderPass::Translucent | RenderPass::Upload : RenderPass::None; evaluatedProperties = std::move(properties); } @@ -58,6 +59,38 @@ bool RenderLineLayer::hasCrossfade() const { return getCrossfade<LineLayerProperties>(evaluatedProperties).t != 1; } +void RenderLineLayer::upload(gfx::UploadPass& uploadPass, UploadParameters& uploadParameters) { + for (const RenderTile& tile : renderTiles) { + const LayerRenderData* renderData = tile.tile.getLayerRenderData(*baseImpl); + if (!renderData) { + continue; + } + auto& bucket = static_cast<LineBucket&>(*renderData->bucket); + const auto& evaluated = getEvaluated<LineLayerProperties>(renderData->layerProperties); + + if (!evaluated.get<LineDasharray>().from.empty()) { + const LinePatternCap cap = bucket.layout.get<LineCap>() == LineCapType::Round + ? LinePatternCap::Round : LinePatternCap::Square; + // Ensures that the dash data gets added and uploaded to the atlas. + uploadParameters.lineAtlas.getDashPosition(evaluated.get<LineDasharray>().from, cap); + uploadParameters.lineAtlas.getDashPosition(evaluated.get<LineDasharray>().to, cap); + + } else if (!unevaluated.get<LinePattern>().isUndefined()) { + const auto& linePatternValue = evaluated.get<LinePattern>().constantOr(Faded<std::basic_string<char>>{ "", ""}); + auto& geometryTile = static_cast<GeometryTile&>(tile.tile); + + // Ensures that the pattern gets added and uplodated to the atlas. + geometryTile.getPattern(linePatternValue.from); + geometryTile.getPattern(linePatternValue.to); + + } else if (!unevaluated.get<LineGradient>().getValue().isUndefined()) { + if (!colorRampTexture) { + colorRampTexture = uploadPass.createTexture(colorRamp); + } + } + } +} + void RenderLineLayer::render(PaintParameters& parameters, RenderSource*) { if (parameters.pass == RenderPass::Opaque) { return; @@ -133,12 +166,12 @@ void RenderLineLayer::render(PaintParameters& parameters, RenderSource*) { {}, {}, LineSDFProgram::TextureBindings{ - parameters.lineAtlas.textureBinding(parameters.context), + parameters.lineAtlas.textureBinding(), }); } else if (!unevaluated.get<LinePattern>().isUndefined()) { const auto& linePatternValue = evaluated.get<LinePattern>().constantOr(Faded<std::basic_string<char>>{ "", ""}); - auto& geometryTile = static_cast<GeometryTile&>(tile.tile); + auto& geometryTile = static_cast<GeometryTile&>(tile.tile); const Size texsize = geometryTile.iconAtlasTexture->size; optional<ImagePosition> posA = geometryTile.getPattern(linePatternValue.from); @@ -159,9 +192,7 @@ void RenderLineLayer::render(PaintParameters& parameters, RenderSource*) { textures::image::Value{ geometryTile.iconAtlasTexture->getResource(), gfx::TextureFilterType::Linear }, }); } else if (!unevaluated.get<LineGradient>().getValue().isUndefined()) { - if (!colorRampTexture) { - colorRampTexture = parameters.context.createTexture(colorRamp); - } + assert(colorRampTexture); draw(parameters.programs.getLineLayerPrograms().lineGradient, LineGradientProgram::layoutUniformValues( diff --git a/src/mbgl/renderer/layers/render_line_layer.hpp b/src/mbgl/renderer/layers/render_line_layer.hpp index 657f72e5f1..0e1e81e557 100644 --- a/src/mbgl/renderer/layers/render_line_layer.hpp +++ b/src/mbgl/renderer/layers/render_line_layer.hpp @@ -20,6 +20,7 @@ private: void evaluate(const PropertyEvaluationParameters&) override; bool hasTransition() const override; bool hasCrossfade() const override; + void upload(gfx::UploadPass&, UploadParameters&) override; void render(PaintParameters&, RenderSource*) override; bool queryIntersectsFeature( diff --git a/src/mbgl/renderer/layers/render_raster_layer.cpp b/src/mbgl/renderer/layers/render_raster_layer.cpp index 8569303a06..ce4fb05929 100644 --- a/src/mbgl/renderer/layers/render_raster_layer.cpp +++ b/src/mbgl/renderer/layers/render_raster_layer.cpp @@ -175,8 +175,8 @@ void RenderRasterLayer::render(PaintParameters& parameters, RenderSource* source } else { // Draw the full tile. draw(parameters.matrixForTile(tile.id, true), - parameters.staticData.rasterVertexBuffer, - parameters.staticData.quadTriangleIndexBuffer, + *parameters.staticData.rasterVertexBuffer, + *parameters.staticData.quadTriangleIndexBuffer, parameters.staticData.rasterSegments, RasterProgram::TextureBindings{ textures::image0::Value{ bucket.texture->getResource(), filter }, diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp index 9429cff469..576bdd92d8 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.cpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp @@ -3,6 +3,7 @@ #include <mbgl/renderer/bucket_parameters.hpp> #include <mbgl/renderer/property_evaluation_parameters.hpp> #include <mbgl/renderer/render_tile.hpp> +#include <mbgl/renderer/upload_parameters.hpp> #include <mbgl/renderer/paint_parameters.hpp> #include <mbgl/text/glyph_atlas.hpp> #include <mbgl/text/shaping.hpp> @@ -13,9 +14,11 @@ #include <mbgl/tile/geometry_tile.hpp> #include <mbgl/tile/geometry_tile_data.hpp> #include <mbgl/style/layers/symbol_layer_impl.hpp> +#include <mbgl/text/placement.hpp> #include <mbgl/gfx/cull_face_mode.hpp> #include <mbgl/layout/symbol_projection.hpp> #include <mbgl/layout/symbol_layout.hpp> +#include <mbgl/layout/symbol_layout.hpp> #include <mbgl/util/math.hpp> #include <cmath> @@ -112,6 +115,122 @@ struct RenderableSegment { } }; +void uploadIcon(gfx::UploadPass& uploadPass, + UploadParameters& uploadParameters, + const RenderTile& tile, + const LayerRenderData& renderData) { + assert(tile.tile.kind == Tile::Kind::Geometry); + auto& bucket = static_cast<SymbolBucket&>(*renderData.bucket); + const auto& layout = bucket.layout; + + const bool alongLine = layout.get<SymbolPlacement>() != SymbolPlacementType::Point && + layout.get<IconRotationAlignment>() == AlignmentType::Map; + + if (alongLine) { + const auto& evaluated = getEvaluated<SymbolLayerProperties>(renderData.layerProperties); + reprojectLineLabels(bucket.icon.dynamicVertices, bucket.icon.placedSymbols, tile.matrix, + iconPropertyValues(evaluated, layout), tile, *bucket.iconSizeBinder, + uploadParameters.state); + + uploadPass.updateVertexBuffer(*bucket.icon.dynamicVertexBuffer, + std::move(bucket.icon.dynamicVertices)); + } +} + +void uploadText(gfx::UploadPass& uploadPass, + UploadParameters& uploadParameters, + const RenderTile& tile, + const LayerRenderData& renderData, + bool& hasVariablePlacement) { + assert(tile.tile.kind == Tile::Kind::Geometry); + auto& bucket = static_cast<SymbolBucket&>(*renderData.bucket); + const auto& layout = bucket.layout; + + const bool alongLine = layout.get<SymbolPlacement>() != SymbolPlacementType::Point && + layout.get<TextRotationAlignment>() == AlignmentType::Map; + + if (alongLine) { + const auto& evaluated = getEvaluated<SymbolLayerProperties>(renderData.layerProperties); + reprojectLineLabels(bucket.text.dynamicVertices, + bucket.text.placedSymbols, + tile.matrix, + textPropertyValues(evaluated, layout), + tile, + *bucket.textSizeBinder, + uploadParameters.state); + + uploadPass.updateVertexBuffer(*bucket.text.dynamicVertexBuffer, std::move(bucket.text.dynamicVertices)); + } else if (!layout.get<TextVariableAnchor>().empty()) { + bucket.text.dynamicVertices.clear(); + + hasVariablePlacement = false; + + const auto partiallyEvaluatedSize = bucket.textSizeBinder->evaluateForZoom(uploadParameters.state.getZoom()); + const float tileScale = std::pow(2, uploadParameters.state.getZoom() - tile.tile.id.overscaledZ); + const bool rotateWithMap = layout.get<TextRotationAlignment>() == AlignmentType::Map; + const bool pitchWithMap = layout.get<TextPitchAlignment>() == AlignmentType::Map; + const float pixelsToTileUnits = tile.id.pixelsToTileUnits(1.0, uploadParameters.state.getZoom()); + const auto labelPlaneMatrix = getLabelPlaneMatrix(tile.matrix, pitchWithMap, rotateWithMap, uploadParameters.state, pixelsToTileUnits); + + for (const PlacedSymbol& symbol : bucket.text.placedSymbols) { + optional<VariableOffset> variableOffset; + if (!symbol.hidden && symbol.crossTileID != 0u) { + auto it = uploadParameters.variableOffsets.find(symbol.crossTileID); + if (it != uploadParameters.variableOffsets.end()) { + hasVariablePlacement |= true; + variableOffset = it->second; + } + } + + if (!variableOffset) { + // These symbols are from a justification that is not being used, or a label that wasn't placed + // so we don't need to do the extra math to figure out what incremental shift to apply. + hideGlyphs(symbol.glyphOffsets.size(), bucket.text.dynamicVertices); + } else { + const Point<float> tileAnchor = symbol.anchorPoint; + const auto projectedAnchor = project(tileAnchor, pitchWithMap ? tile.matrix : labelPlaneMatrix); + const float perspectiveRatio = 0.5f + 0.5f * (uploadParameters.state.getCameraToCenterDistance() / projectedAnchor.second); + float renderTextSize = evaluateSizeForFeature(partiallyEvaluatedSize, symbol) * perspectiveRatio / util::ONE_EM; + if (pitchWithMap) { + // Go from size in pixels to equivalent size in tile units + renderTextSize *= bucket.tilePixelRatio / tileScale; + } + + auto shift = calculateVariableRenderShift( + (*variableOffset).anchor, + (*variableOffset).width, + (*variableOffset).height, + (*variableOffset).radialOffset, + (*variableOffset).textBoxScale, + renderTextSize); + + // Usual case is that we take the projected anchor and add the pixel-based shift + // calculated above. In the (somewhat weird) case of pitch-aligned text, we add an equivalent + // tile-unit based shift to the anchor before projecting to the label plane. + Point<float> shiftedAnchor; + if (pitchWithMap) { + shiftedAnchor = project(Point<float>(tileAnchor.x + shift.x, tileAnchor.y + shift.y), + labelPlaneMatrix).first; + } else { + if (rotateWithMap) { + auto rotated = util::rotate(shift, -uploadParameters.state.getPitch()); + shiftedAnchor = Point<float>(projectedAnchor.first.x + rotated.x, + projectedAnchor.first.y + rotated.y); + } else { + shiftedAnchor = Point<float>(projectedAnchor.first.x + shift.x, + projectedAnchor.first.y + shift.y); + } + } + + for (std::size_t i = 0; i < symbol.glyphOffsets.size(); i++) { + addDynamicAttributes(shiftedAnchor, 0, bucket.text.dynamicVertices); + } + } + } + uploadPass.updateVertexBuffer(*bucket.text.dynamicVertexBuffer, std::move(bucket.text.dynamicVertices)); + } +} + template <typename DrawFn> void drawIcon(const DrawFn& draw, const RenderTile& tile, @@ -130,18 +249,6 @@ void drawIcon(const DrawFn& draw, const bool alongLine = layout.get<SymbolPlacement>() != SymbolPlacementType::Point && layout.get<IconRotationAlignment>() == AlignmentType::Map; - if (alongLine) { - reprojectLineLabels(bucket.icon.dynamicVertices, - bucket.icon.placedSymbols, - tile.matrix, - values, - tile, - *bucket.iconSizeBinder, - parameters.state); - - parameters.context.updateVertexBuffer(*bucket.icon.dynamicVertexBuffer, std::move(bucket.icon.dynamicVertices)); - } - const bool iconScaled = layout.get<IconSize>().constantOr(1.0) != 1.0 || bucket.iconsNeedLinear; const bool iconTransformed = values.rotationAlignment == AlignmentType::Map || parameters.state.getPitch() != 0; @@ -206,7 +313,8 @@ void drawText(const DrawFn& draw, const LayerRenderData& renderData, SegmentsWrapper textSegments, const SymbolBucket::PaintProperties& bucketPaintProperties, - const PaintParameters& parameters) { + const PaintParameters& parameters, + bool hasVariablePlacement) { assert(tile.tile.kind == Tile::Kind::Geometry); auto& geometryTile = static_cast<GeometryTile&>(tile.tile); auto& bucket = static_cast<SymbolBucket&>(*renderData.bucket); @@ -218,94 +326,15 @@ void drawText(const DrawFn& draw, auto values = textPropertyValues(evaluated, layout); const auto& paintPropertyValues = RenderSymbolLayer::textPaintProperties(evaluated); - bool hasVariablePacement = false; const bool alongLine = layout.get<SymbolPlacement>() != SymbolPlacementType::Point && layout.get<TextRotationAlignment>() == AlignmentType::Map; - if (alongLine) { - reprojectLineLabels(bucket.text.dynamicVertices, - bucket.text.placedSymbols, - tile.matrix, - values, - tile, - *bucket.textSizeBinder, - parameters.state); - - parameters.context.updateVertexBuffer(*bucket.text.dynamicVertexBuffer, std::move(bucket.text.dynamicVertices)); - } else if (!layout.get<TextVariableAnchor>().empty()) { - bucket.text.dynamicVertices.clear(); - - const auto partiallyEvaluatedSize = bucket.textSizeBinder->evaluateForZoom(parameters.state.getZoom()); - const float tileScale = std::pow(2, parameters.state.getZoom() - tile.tile.id.overscaledZ); - const bool rotateWithMap = layout.get<TextRotationAlignment>() == AlignmentType::Map; - const bool pitchWithMap = layout.get<TextPitchAlignment>() == AlignmentType::Map; - const float pixelsToTileUnits = tile.id.pixelsToTileUnits(1.0, parameters.state.getZoom()); - const auto labelPlaneMatrix = getLabelPlaneMatrix(tile.matrix, pitchWithMap, rotateWithMap, parameters.state, pixelsToTileUnits); - - for (const PlacedSymbol& symbol : bucket.text.placedSymbols) { - optional<VariableOffset> variableOffset; - if (!symbol.hidden && symbol.crossTileID != 0u) { - auto it = parameters.variableOffsets.get().find(symbol.crossTileID); - if (it != parameters.variableOffsets.get().end()) { - variableOffset = it->second; - hasVariablePacement |= true; - } - } - - if (!variableOffset) { - // These symbols are from a justification that is not being used, or a label that wasn't placed - // so we don't need to do the extra math to figure out what incremental shift to apply. - hideGlyphs(symbol.glyphOffsets.size(), bucket.text.dynamicVertices); - } else { - const Point<float> tileAnchor = symbol.anchorPoint; - const auto projectedAnchor = project(tileAnchor, pitchWithMap ? tile.matrix : labelPlaneMatrix); - const float perspectiveRatio = 0.5f + 0.5f * (parameters.state.getCameraToCenterDistance() / projectedAnchor.second); - float renderTextSize = evaluateSizeForFeature(partiallyEvaluatedSize, symbol) * perspectiveRatio / util::ONE_EM; - if (pitchWithMap) { - // Go from size in pixels to equivalent size in tile units - renderTextSize *= bucket.tilePixelRatio / tileScale; - } - - auto shift = calculateVariableRenderShift( - (*variableOffset).anchor, - (*variableOffset).width, - (*variableOffset).height, - (*variableOffset).radialOffset, - (*variableOffset).textBoxScale, - renderTextSize); - - // Usual case is that we take the projected anchor and add the pixel-based shift - // calculated above. In the (somewhat weird) case of pitch-aligned text, we add an equivalent - // tile-unit based shift to the anchor before projecting to the label plane. - Point<float> shiftedAnchor; - if (pitchWithMap) { - shiftedAnchor = project(Point<float>(tileAnchor.x + shift.x, tileAnchor.y + shift.y), - labelPlaneMatrix).first; - } else { - if (rotateWithMap) { - auto rotated = util::rotate(shift, -parameters.state.getPitch()); - shiftedAnchor = Point<float>(projectedAnchor.first.x + rotated.x, - projectedAnchor.first.y + rotated.y); - } else { - shiftedAnchor = Point<float>(projectedAnchor.first.x + shift.x, - projectedAnchor.first.y + shift.y); - } - } - - for (std::size_t i = 0; i < symbol.glyphOffsets.size(); i++) { - addDynamicAttributes(shiftedAnchor, 0, bucket.text.dynamicVertices); - } - } - } - parameters.context.updateVertexBuffer(*bucket.text.dynamicVertexBuffer, std::move(bucket.text.dynamicVertices)); - } - const Size texsize = geometryTile.glyphAtlasTexture->size; if (values.hasHalo) { draw(parameters.programs.getSymbolLayerPrograms().symbolGlyph, - SymbolSDFTextProgram::layoutUniformValues(true, hasVariablePacement, values, texsize, parameters.pixelsToGLUnits, parameters.pixelRatio, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Halo), + SymbolSDFTextProgram::layoutUniformValues(true, hasVariablePlacement, values, texsize, parameters.pixelsToGLUnits, parameters.pixelRatio, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Halo), bucket.text, textSegments, bucket.textSizeBinder, @@ -320,7 +349,7 @@ void drawText(const DrawFn& draw, if (values.hasFill) { draw(parameters.programs.getSymbolLayerPrograms().symbolGlyph, - SymbolSDFTextProgram::layoutUniformValues(true, hasVariablePacement, values, texsize, parameters.pixelsToGLUnits, parameters.pixelRatio, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Fill), + SymbolSDFTextProgram::layoutUniformValues(true, hasVariablePlacement, values, texsize, parameters.pixelsToGLUnits, parameters.pixelRatio, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Fill), bucket.text, textSegments, bucket.textSizeBinder, @@ -370,7 +399,8 @@ void RenderSymbolLayer::evaluate(const PropertyEvaluationParameters& parameters) passes = ((evaluated.get<style::IconOpacity>().constantOr(1) > 0 && hasIconOpacity && iconSize > 0) || (evaluated.get<style::TextOpacity>().constantOr(1) > 0 && hasTextOpacity && textSize > 0)) - ? RenderPass::Translucent : RenderPass::None; + ? RenderPass::Translucent | RenderPass::Upload : RenderPass::None; + evaluatedProperties = std::move(properties); } @@ -398,6 +428,24 @@ SymbolBucket* RenderSymbolLayer::getSymbolBucket(const RenderTile& renderTile) c return renderTile.tile.getBucket<SymbolBucket>(*baseImpl); } +void RenderSymbolLayer::upload(gfx::UploadPass& uploadPass, UploadParameters& uploadParameters) { + for (const RenderTile& tile : renderTiles) { + const LayerRenderData* renderData = tile.tile.getLayerRenderData(*baseImpl); + if (!renderData) { + continue; + } + + auto& bucket = static_cast<SymbolBucket&>(*renderData->bucket); + if (bucket.hasIconData()) { + uploadIcon(uploadPass, uploadParameters, tile, *renderData); + } + + if (bucket.hasTextData()) { + uploadText(uploadPass, uploadParameters, tile, *renderData, hasVariablePlacement); + } + } +} + void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { if (parameters.pass == RenderPass::Opaque) { return; @@ -504,7 +552,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { if (sortFeaturesByKey) { addRenderables(bucket.text.segments, true /*isText*/); } else { - drawText(draw, tile, *renderData, std::ref(bucket.text.segments), bucketPaintProperties, parameters); + drawText(draw, tile, *renderData, std::ref(bucket.text.segments), bucketPaintProperties, parameters, hasVariablePlacement); } } @@ -518,7 +566,6 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { {{ parameters.pixelsToGLUnits[0] / (pixelRatio * scale), parameters.pixelsToGLUnits[1] / (pixelRatio * scale) - }}; parameters.programs.getSymbolLayerPrograms().collisionBox.draw( parameters.context, @@ -555,7 +602,6 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { {{ parameters.pixelsToGLUnits[0] / (pixelRatio * scale), parameters.pixelsToGLUnits[1] / (pixelRatio * scale) - }}; parameters.programs.getSymbolLayerPrograms().collisionCircle.draw( @@ -588,7 +634,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { if (sortFeaturesByKey) { for (auto& renderable : renderableSegments) { if (renderable.isText) { - drawText(draw, renderable.tile, renderable.renderData, renderable.segment, renderable.bucketPaintProperties, parameters); + drawText(draw, renderable.tile, renderable.renderData, renderable.segment, renderable.bucketPaintProperties, parameters, hasVariablePlacement); } else { drawIcon(draw, renderable.tile, renderable.renderData, renderable.segment, renderable.bucketPaintProperties, parameters); } diff --git a/src/mbgl/renderer/layers/render_symbol_layer.hpp b/src/mbgl/renderer/layers/render_symbol_layer.hpp index ad33a2ab0e..67b8a58314 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.hpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.hpp @@ -66,6 +66,7 @@ private: void evaluate(const PropertyEvaluationParameters&) override; bool hasTransition() const override; bool hasCrossfade() const override; + void upload(gfx::UploadPass&, UploadParameters&) override; void render(PaintParameters&, RenderSource*) override; void setRenderTiles(RenderTiles, const TransformState&) override; @@ -82,6 +83,7 @@ private: float textSize = 16.0f; bool hasFormatSectionOverrides = false; + bool hasVariablePlacement = false; }; } // namespace mbgl |