summaryrefslogtreecommitdiff
path: root/src/mbgl/renderer/layers
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/renderer/layers')
-rw-r--r--src/mbgl/renderer/layers/render_background_layer.cpp19
-rw-r--r--src/mbgl/renderer/layers/render_background_layer.hpp1
-rw-r--r--src/mbgl/renderer/layers/render_heatmap_layer.cpp19
-rw-r--r--src/mbgl/renderer/layers/render_heatmap_layer.hpp1
-rw-r--r--src/mbgl/renderer/layers/render_hillshade_layer.cpp8
-rw-r--r--src/mbgl/renderer/layers/render_line_layer.cpp43
-rw-r--r--src/mbgl/renderer/layers/render_line_layer.hpp1
-rw-r--r--src/mbgl/renderer/layers/render_raster_layer.cpp4
-rw-r--r--src/mbgl/renderer/layers/render_symbol_layer.cpp244
-rw-r--r--src/mbgl/renderer/layers/render_symbol_layer.hpp2
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 &paramet
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