diff options
Diffstat (limited to 'src/mbgl/renderer')
33 files changed, 659 insertions, 340 deletions
diff --git a/src/mbgl/renderer/buckets/circle_bucket.cpp b/src/mbgl/renderer/buckets/circle_bucket.cpp index 04126990b3..c442b661de 100644 --- a/src/mbgl/renderer/buckets/circle_bucket.cpp +++ b/src/mbgl/renderer/buckets/circle_bucket.cpp @@ -49,7 +49,7 @@ void CircleBucket::addFeature(const GeometryTileFeature& feature, // Do not include points that are outside the tile boundaries. // Include all points in Still mode. You need to include points from // neighbouring tiles so that they are not clipped at tile boundaries. - if ((mode != MapMode::Still) && + if ((mode == MapMode::Continuous) && (x < 0 || x >= util::EXTENT || y < 0 || y >= util::EXTENT)) continue; if (segments.empty() || segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::max()) { @@ -108,8 +108,9 @@ float CircleBucket::getQueryRadius(const RenderLayer& layer) const { auto circleLayer = layer.as<RenderCircleLayer>(); float radius = get<CircleRadius>(*circleLayer, paintPropertyBinders); + float stroke = get<CircleStrokeWidth>(*circleLayer, paintPropertyBinders); auto translate = circleLayer->evaluated.get<CircleTranslate>(); - return radius + util::length(translate[0], translate[1]); + return radius + stroke + util::length(translate[0], translate[1]); } } // namespace mbgl diff --git a/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp b/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp index 7f53326fe1..5e2c937091 100644 --- a/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp +++ b/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp @@ -101,13 +101,17 @@ void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature, const auto d2 = convertPoint<double>(p2); const Point<double> perp = util::unit(util::perp(d1 - d2)); + const auto dist = util::dist<int16_t>(d1, d2); + if (dist > std::numeric_limits<int16_t>::max()) { + edgeDistance = 0; + } vertices.emplace_back( FillExtrusionProgram::layoutVertex(p1, perp.x, perp.y, 0, 0, edgeDistance)); vertices.emplace_back( FillExtrusionProgram::layoutVertex(p1, perp.x, perp.y, 0, 1, edgeDistance)); - edgeDistance += util::dist<int16_t>(d1, d2); + edgeDistance += dist; vertices.emplace_back( FillExtrusionProgram::layoutVertex(p2, perp.x, perp.y, 0, 0, edgeDistance)); diff --git a/src/mbgl/renderer/buckets/symbol_bucket.cpp b/src/mbgl/renderer/buckets/symbol_bucket.cpp index a3f71f1f6e..60e8a0b504 100644 --- a/src/mbgl/renderer/buckets/symbol_bucket.cpp +++ b/src/mbgl/renderer/buckets/symbol_bucket.cpp @@ -16,10 +16,14 @@ SymbolBucket::SymbolBucket(style::SymbolLayoutProperties::PossiblyEvaluated layo const style::DataDrivenPropertyValue<float>& iconSize, float zoom, bool sdfIcons_, - bool iconsNeedLinear_) + bool iconsNeedLinear_, + bool sortFeaturesByY_, + const std::vector<SymbolInstance>&& symbolInstances_) : layout(std::move(layout_)), sdfIcons(sdfIcons_), iconsNeedLinear(iconsNeedLinear_ || iconSize.isDataDriven() || !iconSize.isZoomConstant()), + sortFeaturesByY(sortFeaturesByY_), + symbolInstances(std::move(symbolInstances_)), textSizeBinder(SymbolSizeBinder::create(zoom, textSize, TextSize::defaultValue())), iconSizeBinder(SymbolSizeBinder::create(zoom, iconSize, IconSize::defaultValue())) { @@ -36,28 +40,84 @@ SymbolBucket::SymbolBucket(style::SymbolLayoutProperties::PossiblyEvaluated layo void SymbolBucket::upload(gl::Context& context) { if (hasTextData()) { - text.vertexBuffer = context.createVertexBuffer(std::move(text.vertices)); - text.dynamicVertexBuffer = context.createVertexBuffer(std::move(text.dynamicVertices), gl::BufferUsage::StreamDraw); - text.indexBuffer = context.createIndexBuffer(std::move(text.triangles)); + if (!staticUploaded) { + text.indexBuffer = context.createIndexBuffer(std::move(text.triangles), sortFeaturesByY ? gl::BufferUsage::StreamDraw : gl::BufferUsage::StaticDraw); + text.vertexBuffer = context.createVertexBuffer(std::move(text.vertices)); + } else if (!sortUploaded) { + context.updateIndexBuffer(*text.indexBuffer, std::move(text.triangles)); + } + + if (!dynamicUploaded) { + text.dynamicVertexBuffer = context.createVertexBuffer(std::move(text.dynamicVertices), gl::BufferUsage::StreamDraw); + } + if (!placementChangesUploaded) { + if (!text.opacityVertexBuffer) { + text.opacityVertexBuffer = context.createVertexBuffer(std::move(text.opacityVertices), gl::BufferUsage::StreamDraw); + } else { + context.updateVertexBuffer(*text.opacityVertexBuffer, std::move(text.opacityVertices)); + } + } } if (hasIconData()) { - icon.vertexBuffer = context.createVertexBuffer(std::move(icon.vertices)); - icon.dynamicVertexBuffer = context.createVertexBuffer(std::move(icon.dynamicVertices), gl::BufferUsage::StreamDraw); - icon.indexBuffer = context.createIndexBuffer(std::move(icon.triangles)); + if (!staticUploaded) { + icon.indexBuffer = context.createIndexBuffer(std::move(icon.triangles), sortFeaturesByY ? gl::BufferUsage::StreamDraw : gl::BufferUsage::StaticDraw); + icon.vertexBuffer = context.createVertexBuffer(std::move(icon.vertices)); + } else if (!sortUploaded) { + context.updateIndexBuffer(*icon.indexBuffer, std::move(icon.triangles)); + } + if (!dynamicUploaded) { + icon.dynamicVertexBuffer = context.createVertexBuffer(std::move(icon.dynamicVertices), gl::BufferUsage::StreamDraw); + } + if (!placementChangesUploaded) { + if (!icon.opacityVertexBuffer) { + icon.opacityVertexBuffer = context.createVertexBuffer(std::move(icon.opacityVertices), gl::BufferUsage::StreamDraw); + } else { + context.updateVertexBuffer(*icon.opacityVertexBuffer, std::move(icon.opacityVertices)); + } + } } - if (!collisionBox.vertices.empty()) { - collisionBox.vertexBuffer = context.createVertexBuffer(std::move(collisionBox.vertices)); - collisionBox.indexBuffer = context.createIndexBuffer(std::move(collisionBox.lines)); + if (hasCollisionBoxData()) { + if (!staticUploaded) { + collisionBox.indexBuffer = context.createIndexBuffer(std::move(collisionBox.lines)); + collisionBox.vertexBuffer = context.createVertexBuffer(std::move(collisionBox.vertices)); + } + if (!placementChangesUploaded) { + if (!collisionBox.dynamicVertexBuffer) { + collisionBox.dynamicVertexBuffer = context.createVertexBuffer(std::move(collisionBox.dynamicVertices), gl::BufferUsage::StreamDraw); + } else { + context.updateVertexBuffer(*collisionBox.dynamicVertexBuffer, std::move(collisionBox.dynamicVertices)); + } + } } - - for (auto& pair : paintPropertyBinders) { - pair.second.first.upload(context); - pair.second.second.upload(context); + + if (hasCollisionCircleData()) { + if (!staticUploaded) { + collisionCircle.indexBuffer = context.createIndexBuffer(std::move(collisionCircle.triangles)); + collisionCircle.vertexBuffer = context.createVertexBuffer(std::move(collisionCircle.vertices)); + } + if (!placementChangesUploaded) { + if (!collisionCircle.dynamicVertexBuffer) { + collisionCircle.dynamicVertexBuffer = context.createVertexBuffer(std::move(collisionCircle.dynamicVertices), gl::BufferUsage::StreamDraw); + } else { + context.updateVertexBuffer(*collisionCircle.dynamicVertexBuffer, std::move(collisionCircle.dynamicVertices)); + } + } } + if (!staticUploaded) { + for (auto& pair : paintPropertyBinders) { + pair.second.first.upload(context); + pair.second.second.upload(context); + } + } + uploaded = true; + staticUploaded = true; + placementChangesUploaded = true; + dynamicUploaded = true; + sortUploaded = true; } bool SymbolBucket::hasData() const { @@ -76,4 +136,83 @@ bool SymbolBucket::hasCollisionBoxData() const { return !collisionBox.segments.empty(); } +bool SymbolBucket::hasCollisionCircleData() const { + return !collisionCircle.segments.empty(); +} + +void SymbolBucket::updateOpacity() { + placementChangesUploaded = false; + uploaded = false; +} + +void addPlacedSymbol(gl::IndexVector<gl::Triangles>& triangles, const PlacedSymbol& placedSymbol) { + auto endIndex = placedSymbol.vertexStartIndex + placedSymbol.glyphOffsets.size() * 4; + for (auto vertexIndex = placedSymbol.vertexStartIndex; vertexIndex < endIndex; vertexIndex += 4) { + triangles.emplace_back(vertexIndex + 0, vertexIndex + 1, vertexIndex + 2); + triangles.emplace_back(vertexIndex + 1, vertexIndex + 2, vertexIndex + 3); + } +} + +void SymbolBucket::sortFeatures(const float angle) { + if (!sortFeaturesByY) { + return; + } + + if (sortedAngle && *sortedAngle == angle) { + return; + } + + sortedAngle = angle; + + // The current approach to sorting doesn't sort across segments so don't try. + // Sorting within segments separately seemed not to be worth the complexity. + if (text.segments.size() > 1 || icon.segments.size() > 1) { + return; + } + + sortUploaded = false; + uploaded = false; + + // If the symbols are allowed to overlap sort them by their vertical screen position. + // The index array buffer is rewritten to reference the (unchanged) vertices in the + // sorted order. + + // To avoid sorting the actual symbolInstance array we sort an array of indexes. + std::vector<size_t> symbolInstanceIndexes; + symbolInstanceIndexes.reserve(symbolInstances.size()); + for (size_t i = 0; i < symbolInstances.size(); i++) { + symbolInstanceIndexes.push_back(i); + } + + const float sin = std::sin(angle); + const float cos = std::cos(angle); + + std::sort(symbolInstanceIndexes.begin(), symbolInstanceIndexes.end(), [sin, cos, this](size_t &aIndex, size_t &bIndex) { + const SymbolInstance& a = symbolInstances[aIndex]; + const SymbolInstance& b = symbolInstances[bIndex]; + const int32_t aRotated = sin * a.anchor.point.x + cos * a.anchor.point.y; + const int32_t bRotated = sin * b.anchor.point.x + cos * b.anchor.point.y; + return aRotated != bRotated ? + aRotated < bRotated : + a.index > b.index; + }); + + text.triangles.clear(); + icon.triangles.clear(); + + for (auto i : symbolInstanceIndexes) { + const SymbolInstance& symbolInstance = symbolInstances[i]; + + if (symbolInstance.placedTextIndex) { + addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.placedTextIndex]); + } + if (symbolInstance.placedVerticalTextIndex) { + addPlacedSymbol(text.triangles, text.placedSymbols[*symbolInstance.placedVerticalTextIndex]); + } + if (symbolInstance.placedIconIndex) { + addPlacedSymbol(icon.triangles, icon.placedSymbols[*symbolInstance.placedIconIndex]); + } + } +} + } // namespace mbgl diff --git a/src/mbgl/renderer/buckets/symbol_bucket.hpp b/src/mbgl/renderer/buckets/symbol_bucket.hpp index 32f976bcb2..ed8afb052c 100644 --- a/src/mbgl/renderer/buckets/symbol_bucket.hpp +++ b/src/mbgl/renderer/buckets/symbol_bucket.hpp @@ -10,6 +10,7 @@ #include <mbgl/text/glyph_range.hpp> #include <mbgl/style/layers/symbol_layer_properties.hpp> #include <mbgl/layout/symbol_feature.hpp> +#include <mbgl/layout/symbol_instance.hpp> #include <vector> @@ -18,18 +19,22 @@ namespace mbgl { class PlacedSymbol { public: PlacedSymbol(Point<float> anchorPoint_, uint16_t segment_, float lowerSize_, float upperSize_, - std::array<float, 2> lineOffset_, float placementZoom_, bool useVerticalMode_, GeometryCoordinates line_) : + std::array<float, 2> lineOffset_, WritingModeType writingModes_, GeometryCoordinates line_, std::vector<float> tileDistances_) : anchorPoint(anchorPoint_), segment(segment_), lowerSize(lowerSize_), upperSize(upperSize_), - lineOffset(lineOffset_), placementZoom(placementZoom_), useVerticalMode(useVerticalMode_), line(std::move(line_)) {} + lineOffset(lineOffset_), writingModes(writingModes_), line(std::move(line_)), tileDistances(std::move(tileDistances_)), hidden(false), vertexStartIndex(0) + { + } Point<float> anchorPoint; uint16_t segment; float lowerSize; float upperSize; std::array<float, 2> lineOffset; - float placementZoom; - bool useVerticalMode; + WritingModeType writingModes; GeometryCoordinates line; + std::vector<float> tileDistances; std::vector<float> glyphOffsets; + bool hidden; + size_t vertexStartIndex; }; class SymbolBucket : public Bucket { @@ -40,17 +45,33 @@ public: const style::DataDrivenPropertyValue<float>& iconSize, float zoom, bool sdfIcons, - bool iconsNeedLinear); + bool iconsNeedLinear, + bool sortFeaturesByY, + const std::vector<SymbolInstance>&&); void upload(gl::Context&) override; bool hasData() const override; bool hasTextData() const; bool hasIconData() const; bool hasCollisionBoxData() const; + bool hasCollisionCircleData() const; + + void updateOpacity(); + void sortFeatures(const float angle); const style::SymbolLayoutProperties::PossiblyEvaluated layout; const bool sdfIcons; const bool iconsNeedLinear; + const bool sortFeaturesByY; + + optional<float> sortedAngle; + + bool staticUploaded = false; + bool placementChangesUploaded = false; + bool dynamicUploaded = false; + bool sortUploaded = false; + + std::vector<SymbolInstance> symbolInstances; std::map<std::string, std::pair< SymbolIconProgram::PaintPropertyBinders, @@ -61,12 +82,14 @@ public: struct TextBuffer { gl::VertexVector<SymbolLayoutVertex> vertices; gl::VertexVector<SymbolDynamicLayoutAttributes::Vertex> dynamicVertices; + gl::VertexVector<SymbolOpacityAttributes::Vertex> opacityVertices; gl::IndexVector<gl::Triangles> triangles; SegmentVector<SymbolTextAttributes> segments; std::vector<PlacedSymbol> placedSymbols; optional<gl::VertexBuffer<SymbolLayoutVertex>> vertexBuffer; optional<gl::VertexBuffer<SymbolDynamicLayoutAttributes::Vertex>> dynamicVertexBuffer; + optional<gl::VertexBuffer<SymbolOpacityAttributes::Vertex>> opacityVertexBuffer; optional<gl::IndexBuffer<gl::Triangles>> indexBuffer; } text; @@ -75,6 +98,7 @@ public: struct IconBuffer { gl::VertexVector<SymbolLayoutVertex> vertices; gl::VertexVector<SymbolDynamicLayoutAttributes::Vertex> dynamicVertices; + gl::VertexVector<SymbolOpacityAttributes::Vertex> opacityVertices; gl::IndexVector<gl::Triangles> triangles; SegmentVector<SymbolIconAttributes> segments; std::vector<PlacedSymbol> placedSymbols; @@ -82,18 +106,31 @@ public: optional<gl::VertexBuffer<SymbolLayoutVertex>> vertexBuffer; optional<gl::VertexBuffer<SymbolDynamicLayoutAttributes::Vertex>> dynamicVertexBuffer; + optional<gl::VertexBuffer<SymbolOpacityAttributes::Vertex>> opacityVertexBuffer; optional<gl::IndexBuffer<gl::Triangles>> indexBuffer; } icon; - struct CollisionBoxBuffer { - gl::VertexVector<CollisionBoxVertex> vertices; - gl::IndexVector<gl::Lines> lines; - SegmentVector<CollisionBoxAttributes> segments; + struct CollisionBuffer { + gl::VertexVector<CollisionBoxLayoutAttributes::Vertex> vertices; + gl::VertexVector<CollisionBoxDynamicAttributes::Vertex> dynamicVertices; + SegmentVector<CollisionBoxProgram::Attributes> segments; - optional<gl::VertexBuffer<CollisionBoxVertex>> vertexBuffer; - optional<gl::VertexBuffer<SymbolDynamicLayoutAttributes::Vertex>> dynamicVertexBuffer; + optional<gl::VertexBuffer<CollisionBoxLayoutAttributes::Vertex>> vertexBuffer; + optional<gl::VertexBuffer<CollisionBoxDynamicAttributes::Vertex>> dynamicVertexBuffer; + }; + + struct CollisionBoxBuffer : public CollisionBuffer { + gl::IndexVector<gl::Lines> lines; optional<gl::IndexBuffer<gl::Lines>> indexBuffer; } collisionBox; + + struct CollisionCircleBuffer : public CollisionBuffer { + gl::IndexVector<gl::Triangles> triangles; + optional<gl::IndexBuffer<gl::Triangles>> indexBuffer; + } collisionCircle; + + uint32_t bucketInstanceId = 0; + bool justReloaded = false; }; } // namespace mbgl diff --git a/src/mbgl/renderer/frame_history.cpp b/src/mbgl/renderer/frame_history.cpp deleted file mode 100644 index de153b6963..0000000000 --- a/src/mbgl/renderer/frame_history.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include <mbgl/renderer/frame_history.hpp> -#include <mbgl/math/minmax.hpp> -#include <mbgl/gl/context.hpp> - -#include <cassert> - -namespace mbgl { - -FrameHistory::FrameHistory() { - changeOpacities.fill(0); - opacities.fill(0); -} - -void FrameHistory::record(const TimePoint& now, float zoom, const Duration& duration) { - - int16_t zoomIndex = std::floor(zoom * 10.0); - - if (firstFrame) { - changeTimes.fill(now); - - for (int16_t z = 0; z <= zoomIndex; z++) { - opacities.data[z] = 255u; - } - firstFrame = false; - } - - if (zoomIndex < previousZoomIndex) { - for (int16_t z = zoomIndex + 1; z <= previousZoomIndex; z++) { - changeTimes[z] = now; - changeOpacities[z] = opacities.data[z]; - } - } else { - for (int16_t z = zoomIndex; z > previousZoomIndex; z--) { - changeTimes[z] = now; - changeOpacities[z] = opacities.data[z]; - } - } - - for (int16_t z = 0; z <= 255; z++) { - const std::chrono::duration<float> timeDiff = now - changeTimes[z]; - const int32_t opacityChange = (duration == Milliseconds(0) ? 1 : (timeDiff / duration)) * 255; - const uint8_t opacity = z <= zoomIndex - ? util::min(255, changeOpacities[z] + opacityChange) - : util::max(0, changeOpacities[z] - opacityChange); - if (opacities.data[z] != opacity) { - opacities.data[z] = opacity; - dirty = true; - } - } - - if (zoomIndex != previousZoomIndex) { - previousZoomIndex = zoomIndex; - previousTime = now; - } - - time = now; -} - -bool FrameHistory::needsAnimation(const Duration& duration) const { - return (time - previousTime) < duration; -} - -void FrameHistory::upload(gl::Context& context, uint32_t unit) { - if (!texture) { - texture = context.createTexture(opacities, unit); - } else if (dirty) { - context.updateTexture(*texture, opacities, unit); - } - dirty = false; -} - -void FrameHistory::bind(gl::Context& context, uint32_t unit) { - upload(context, unit); - context.bindTexture(*texture, unit); -} - -bool FrameHistory::isVisible(const float zoom) const { - return opacities.data[std::floor(zoom * 10)] != 0; -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/frame_history.hpp b/src/mbgl/renderer/frame_history.hpp deleted file mode 100644 index 75a8b60a71..0000000000 --- a/src/mbgl/renderer/frame_history.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include <array> - -#include <mbgl/util/platform.hpp> -#include <mbgl/gl/texture.hpp> -#include <mbgl/util/chrono.hpp> -#include <mbgl/util/image.hpp> -#include <mbgl/util/optional.hpp> - -namespace mbgl { - -namespace gl { -class Context; -} // namespace gl - -class FrameHistory { -public: - FrameHistory(); - void record(const TimePoint&, float zoom, const Duration&); - - bool needsAnimation(const Duration&) const; - void bind(gl::Context&, uint32_t); - void upload(gl::Context&, uint32_t); - bool isVisible(const float zoom) const; - -private: - std::array<TimePoint, 256> changeTimes; - std::array<uint8_t, 256> changeOpacities; - AlphaImage opacities{ { 256, 1 } }; - - int16_t previousZoomIndex = 0; - TimePoint previousTime; - TimePoint time; - bool firstFrame = true; - bool dirty = true; - - mbgl::optional<gl::Texture> texture; -}; - -} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_background_layer.cpp b/src/mbgl/renderer/layers/render_background_layer.cpp index 9fddba3f74..aebc4cc9aa 100644 --- a/src/mbgl/renderer/layers/render_background_layer.cpp +++ b/src/mbgl/renderer/layers/render_background_layer.cpp @@ -5,7 +5,7 @@ #include <mbgl/renderer/image_manager.hpp> #include <mbgl/renderer/render_static_data.hpp> #include <mbgl/programs/programs.hpp> -#include <mbgl/programs/fill_program.hpp> +#include <mbgl/programs/background_program.hpp> #include <mbgl/util/tile_cover.hpp> namespace mbgl { @@ -46,12 +46,8 @@ 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. - style::FillPaintProperties::PossiblyEvaluated properties; - properties.get<FillPattern>() = evaluated.get<BackgroundPattern>(); - properties.get<FillOpacity>() = { evaluated.get<BackgroundOpacity>() }; - properties.get<FillColor>() = { evaluated.get<BackgroundColor>() }; - - const FillProgram::PaintPropertyBinders paintAttibuteData(properties, 0); + const Properties<>::PossiblyEvaluated properties; + const BackgroundProgram::PaintPropertyBinders paintAttributeData(properties, 0); if (!evaluated.get<BackgroundPattern>().to.empty()) { optional<ImagePosition> imagePosA = parameters.imageManager.getPattern(evaluated.get<BackgroundPattern>().from); @@ -63,15 +59,15 @@ void RenderBackgroundLayer::render(PaintParameters& parameters, RenderSource*) { parameters.imageManager.bind(parameters.context, 0); for (const auto& tileID : util::tileCover(parameters.state, parameters.state.getIntegerZoom())) { - parameters.programs.fillPattern.get(properties).draw( + parameters.programs.backgroundPattern.draw( parameters.context, gl::Triangles(), parameters.depthModeForSublayer(0, gl::DepthMode::ReadOnly), gl::StencilMode::disabled(), parameters.colorModeForRenderPass(), - FillPatternUniforms::values( + BackgroundPatternUniforms::values( parameters.matrixForTile(tileID), - parameters.context.viewport.getCurrentValue().size, + evaluated.get<BackgroundOpacity>(), parameters.imageManager.getPixelSize(), *imagePosA, *imagePosB, @@ -82,7 +78,7 @@ void RenderBackgroundLayer::render(PaintParameters& parameters, RenderSource*) { parameters.staticData.tileVertexBuffer, parameters.staticData.quadTriangleIndexBuffer, parameters.staticData.tileTriangleSegments, - paintAttibuteData, + paintAttributeData, properties, parameters.state.getZoom(), getID() @@ -90,20 +86,21 @@ void RenderBackgroundLayer::render(PaintParameters& parameters, RenderSource*) { } } else { for (const auto& tileID : util::tileCover(parameters.state, parameters.state.getIntegerZoom())) { - parameters.programs.fill.get(properties).draw( + parameters.programs.background.draw( parameters.context, gl::Triangles(), parameters.depthModeForSublayer(0, gl::DepthMode::ReadOnly), gl::StencilMode::disabled(), parameters.colorModeForRenderPass(), - FillProgram::UniformValues { + BackgroundProgram::UniformValues { uniforms::u_matrix::Value{ parameters.matrixForTile(tileID) }, - uniforms::u_world::Value{ parameters.context.viewport.getCurrentValue().size }, + uniforms::u_color::Value{ evaluated.get<BackgroundColor>() }, + uniforms::u_opacity::Value{ evaluated.get<BackgroundOpacity>() }, }, parameters.staticData.tileVertexBuffer, parameters.staticData.quadTriangleIndexBuffer, parameters.staticData.tileTriangleSegments, - paintAttibuteData, + paintAttributeData, properties, parameters.state.getZoom(), getID() diff --git a/src/mbgl/renderer/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp index e7b022f3ee..6092ff5452 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.cpp +++ b/src/mbgl/renderer/layers/render_circle_layer.cpp @@ -63,7 +63,7 @@ void RenderCircleLayer::render(PaintParameters& parameters, RenderSource*) { parameters.context, gl::Triangles(), parameters.depthModeForSublayer(0, gl::DepthMode::ReadOnly), - parameters.mapMode == MapMode::Still + parameters.mapMode != MapMode::Continuous ? parameters.stencilModeForClipping(tile.clip) : gl::StencilMode::disabled(), parameters.colorModeForRenderPass(), @@ -108,13 +108,12 @@ bool RenderCircleLayer::queryIntersectsFeature( bearing, pixelsToTileUnits); - // Evaluate function - auto circleRadius = evaluated.get<style::CircleRadius>() - .evaluate(feature, zoom, style::CircleRadius::defaultValue()) - * pixelsToTileUnits; + // Evaluate functions + auto radius = evaluated.evaluate<style::CircleRadius>(zoom, feature) * pixelsToTileUnits; + auto stroke = evaluated.evaluate<style::CircleStrokeWidth>(zoom, feature) * pixelsToTileUnits; // Test intersection - return util::polygonIntersectsBufferedMultiPoint(translatedQueryGeometry.value_or(queryGeometry), feature.getGeometries(), circleRadius); + return util::polygonIntersectsBufferedMultiPoint(translatedQueryGeometry.value_or(queryGeometry), feature.getGeometries(), radius + stroke); } } // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp index 1376e8a3d8..04fcb2c3ab 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.cpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp @@ -4,7 +4,6 @@ #include <mbgl/renderer/property_evaluation_parameters.hpp> #include <mbgl/renderer/render_tile.hpp> #include <mbgl/renderer/paint_parameters.hpp> -#include <mbgl/renderer/frame_history.hpp> #include <mbgl/text/glyph_atlas.hpp> #include <mbgl/programs/programs.hpp> #include <mbgl/programs/symbol_program.hpp> @@ -81,8 +80,6 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { const auto& layout = bucket.layout; - parameters.frameHistory.bind(parameters.context, 1); - auto draw = [&] (auto& program, auto&& uniformValues, const auto& buffers, @@ -91,22 +88,18 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { const auto& binders, const auto& paintProperties) { - // We clip symbols to their tile extent in still mode. - const bool needsClipping = parameters.mapMode == MapMode::Still; - program.get(paintProperties).draw( parameters.context, gl::Triangles(), values_.pitchAlignment == AlignmentType::Map ? parameters.depthModeForSublayer(0, gl::DepthMode::ReadOnly) : gl::DepthMode::disabled(), - needsClipping - ? parameters.stencilModeForClipping(tile.clip) - : gl::StencilMode::disabled(), + gl::StencilMode::disabled(), parameters.colorModeForRenderPass(), std::move(uniformValues), *buffers.vertexBuffer, *buffers.dynamicVertexBuffer, + *buffers.opacityVertexBuffer, *symbolSizeBinder, *buffers.indexBuffer, buffers.segments, @@ -134,8 +127,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { values, tile, *bucket.iconSizeBinder, - parameters.state, - parameters.frameHistory); + parameters.state); parameters.context.updateVertexBuffer(*bucket.icon.dynamicVertexBuffer, std::move(bucket.icon.dynamicVertices)); } @@ -152,7 +144,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { if (bucket.sdfIcons) { if (values.hasHalo) { draw(parameters.programs.symbolIconSDF, - SymbolSDFIconProgram::uniformValues(false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, SymbolSDFPart::Halo), + SymbolSDFIconProgram::uniformValues(false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Halo), bucket.icon, bucket.iconSizeBinder, values, @@ -162,7 +154,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { if (values.hasFill) { draw(parameters.programs.symbolIconSDF, - SymbolSDFIconProgram::uniformValues(false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, SymbolSDFPart::Fill), + SymbolSDFIconProgram::uniformValues(false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Fill), bucket.icon, bucket.iconSizeBinder, values, @@ -171,7 +163,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { } } else { draw(parameters.programs.symbolIcon, - SymbolIconProgram::uniformValues(false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state), + SymbolIconProgram::uniformValues(false, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange), bucket.icon, bucket.iconSizeBinder, values, @@ -196,8 +188,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { values, tile, *bucket.textSizeBinder, - parameters.state, - parameters.frameHistory); + parameters.state); parameters.context.updateVertexBuffer(*bucket.text.dynamicVertexBuffer, std::move(bucket.text.dynamicVertices)); } @@ -206,7 +197,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { if (values.hasHalo) { draw(parameters.programs.symbolGlyph, - SymbolSDFTextProgram::uniformValues(true, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, SymbolSDFPart::Halo), + SymbolSDFTextProgram::uniformValues(true, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Halo), bucket.text, bucket.textSizeBinder, values, @@ -216,7 +207,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { if (values.hasFill) { draw(parameters.programs.symbolGlyph, - SymbolSDFTextProgram::uniformValues(true, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, SymbolSDFPart::Fill), + SymbolSDFTextProgram::uniformValues(true, values, texsize, parameters.pixelsToGLUnits, alongLine, tile, parameters.state, parameters.symbolFadeChange, SymbolSDFPart::Fill), bucket.text, bucket.textSizeBinder, values, @@ -229,23 +220,27 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { static const style::Properties<>::PossiblyEvaluated properties {}; static const CollisionBoxProgram::PaintPropertyBinders paintAttributeData(properties, 0); + auto pixelRatio = tile.id.pixelsToTileUnits(1, parameters.state.getZoom()); + auto scale = std::pow(2.0f, float(parameters.state.getZoom() - tile.tile.id.overscaledZ)); + std::array<float,2> extrudeScale = + {{ + parameters.pixelsToGLUnits[0] / (pixelRatio * scale), + parameters.pixelsToGLUnits[1] / (pixelRatio * scale) + + }}; parameters.programs.collisionBox.draw( parameters.context, gl::Lines { 1.0f }, gl::DepthMode::disabled(), - parameters.stencilModeForClipping(tile.clip), + gl::StencilMode::disabled(), parameters.colorModeForRenderPass(), CollisionBoxProgram::UniformValues { uniforms::u_matrix::Value{ tile.matrix }, - uniforms::u_scale::Value{ std::pow(2.0f, float(parameters.state.getZoom() - tile.tile.id.overscaledZ)) }, - uniforms::u_zoom::Value{ float(parameters.state.getZoom() * 10) }, - uniforms::u_maxzoom::Value{ float((tile.id.canonical.z + 1) * 10) }, - uniforms::u_collision_y_stretch::Value{ tile.tile.yStretch() }, - uniforms::u_camera_to_center_distance::Value{ parameters.state.getCameraToCenterDistance() }, - uniforms::u_pitch::Value{ parameters.state.getPitch() }, - uniforms::u_fadetexture::Value{ 1 } + uniforms::u_extrude_scale::Value{ extrudeScale }, + uniforms::u_camera_to_center_distance::Value{ parameters.state.getCameraToCenterDistance() } }, *bucket.collisionBox.vertexBuffer, + *bucket.collisionBox.dynamicVertexBuffer, *bucket.collisionBox.indexBuffer, bucket.collisionBox.segments, paintAttributeData, @@ -254,6 +249,41 @@ void RenderSymbolLayer::render(PaintParameters& parameters, RenderSource*) { getID() ); } + if (bucket.hasCollisionCircleData()) { + static const style::Properties<>::PossiblyEvaluated properties {}; + static const CollisionBoxProgram::PaintPropertyBinders paintAttributeData(properties, 0); + + auto pixelRatio = tile.id.pixelsToTileUnits(1, parameters.state.getZoom()); + auto scale = std::pow(2.0f, float(parameters.state.getZoom() - tile.tile.id.overscaledZ)); + std::array<float,2> extrudeScale = + {{ + parameters.pixelsToGLUnits[0] / (pixelRatio * scale), + parameters.pixelsToGLUnits[1] / (pixelRatio * scale) + + }}; + + parameters.programs.collisionCircle.draw( + parameters.context, + gl::Triangles(), + gl::DepthMode::disabled(), + gl::StencilMode::disabled(), + parameters.colorModeForRenderPass(), + CollisionBoxProgram::UniformValues { + uniforms::u_matrix::Value{ tile.matrix }, + uniforms::u_extrude_scale::Value{ extrudeScale }, + uniforms::u_camera_to_center_distance::Value{ parameters.state.getCameraToCenterDistance() } + }, + *bucket.collisionCircle.vertexBuffer, + *bucket.collisionCircle.dynamicVertexBuffer, + *bucket.collisionCircle.indexBuffer, + bucket.collisionCircle.segments, + paintAttributeData, + properties, + parameters.state.getZoom(), + getID() + ); + + } } } diff --git a/src/mbgl/renderer/paint_parameters.cpp b/src/mbgl/renderer/paint_parameters.cpp index 299db844bc..58dd5597a5 100644 --- a/src/mbgl/renderer/paint_parameters.cpp +++ b/src/mbgl/renderer/paint_parameters.cpp @@ -12,7 +12,6 @@ PaintParameters::PaintParameters(gl::Context& context_, const UpdateParameters& updateParameters, const EvaluatedLight& evaluatedLight_, RenderStaticData& staticData_, - FrameHistory& frameHistory_, ImageManager& imageManager_, LineAtlas& lineAtlas_) : context(context_), @@ -20,7 +19,6 @@ PaintParameters::PaintParameters(gl::Context& context_, state(updateParameters.transformState), evaluatedLight(evaluatedLight_), staticData(staticData_), - frameHistory(frameHistory_), imageManager(imageManager_), lineAtlas(lineAtlas_), mapMode(updateParameters.mode), diff --git a/src/mbgl/renderer/paint_parameters.hpp b/src/mbgl/renderer/paint_parameters.hpp index 4a2c2c6f12..5c934c2239 100644 --- a/src/mbgl/renderer/paint_parameters.hpp +++ b/src/mbgl/renderer/paint_parameters.hpp @@ -2,6 +2,7 @@ #include <mbgl/renderer/render_pass.hpp> #include <mbgl/renderer/render_light.hpp> +#include <mbgl/renderer/mode.hpp> #include <mbgl/map/mode.hpp> #include <mbgl/gl/depth_mode.hpp> #include <mbgl/gl/stencil_mode.hpp> @@ -16,7 +17,6 @@ namespace mbgl { class RendererBackend; class UpdateParameters; class RenderStaticData; -class FrameHistory; class Programs; class TransformState; class ImageManager; @@ -32,7 +32,6 @@ public: const UpdateParameters&, const EvaluatedLight&, RenderStaticData&, - FrameHistory&, ImageManager&, LineAtlas&); @@ -43,7 +42,6 @@ public: const EvaluatedLight& evaluatedLight; RenderStaticData& staticData; - FrameHistory& frameHistory; ImageManager& imageManager; LineAtlas& lineAtlas; @@ -73,6 +71,8 @@ public: uint32_t currentLayer; float depthRangeSize; const float depthEpsilon = 1.0f / (1 << 16); + + float symbolFadeChange; }; } // namespace mbgl diff --git a/src/mbgl/renderer/paint_property_binder.hpp b/src/mbgl/renderer/paint_property_binder.hpp index 652948c8df..3a49882f12 100644 --- a/src/mbgl/renderer/paint_property_binder.hpp +++ b/src/mbgl/renderer/paint_property_binder.hpp @@ -190,11 +190,11 @@ public: CompositeFunctionPaintPropertyBinder(style::CompositeFunction<T> function_, float zoom, T defaultValue_) : function(std::move(function_)), defaultValue(std::move(defaultValue_)), - rangeOfCoveringRanges(function.rangeOfCoveringRanges({zoom, zoom + 1})) { + zoomRange({zoom, zoom + 1}) { } void populateVertexVector(const GeometryTileFeature& feature, std::size_t length) override { - Range<T> range = function.evaluate(rangeOfCoveringRanges, feature, defaultValue); + Range<T> range = function.evaluate(zoomRange, feature, defaultValue); this->statistics.add(range.min); this->statistics.add(range.max); AttributeValue value = zoomInterpolatedAttributeValue( @@ -219,9 +219,9 @@ public: float interpolationFactor(float currentZoom) const override { if (function.useIntegerZoom) { - return util::interpolationFactor(1.0f, { rangeOfCoveringRanges.min.zoom, rangeOfCoveringRanges.max.zoom }, std::floor(currentZoom)); + return function.interpolationFactor(zoomRange, std::floor(currentZoom)); } else { - return util::interpolationFactor(1.0f, { rangeOfCoveringRanges.min.zoom, rangeOfCoveringRanges.max.zoom }, currentZoom); + return function.interpolationFactor(zoomRange, currentZoom); } } @@ -237,8 +237,7 @@ public: private: style::CompositeFunction<T> function; T defaultValue; - using CoveringRanges = typename style::CompositeFunction<T>::CoveringRanges; - Range<CoveringRanges> rangeOfCoveringRanges; + Range<float> zoomRange; gl::VertexVector<Vertex> vertexVector; optional<gl::VertexBuffer<Vertex>> vertexBuffer; }; diff --git a/src/mbgl/renderer/render_layer.hpp b/src/mbgl/renderer/render_layer.hpp index dfc6bcf2fd..55831cb72c 100644 --- a/src/mbgl/renderer/render_layer.hpp +++ b/src/mbgl/renderer/render_layer.hpp @@ -82,13 +82,16 @@ public: friend std::string layoutKey(const RenderLayer&); protected: + // renderTiles are exposed directly to CrossTileSymbolIndex and Placement so they + // can update opacities in the symbol buckets immediately before rendering + friend class CrossTileSymbolIndex; + friend class Placement; + // Stores current set of tiles to be rendered for this layer. + std::vector<std::reference_wrapper<RenderTile>> renderTiles; + // Stores what render passes this layer is currently enabled for. This depends on the // evaluated StyleProperties object and is updated accordingly. RenderPass passes = RenderPass::None; - - //Stores current set of tiles to be rendered for this layer. - std::vector<std::reference_wrapper<RenderTile>> renderTiles; - }; } // namespace mbgl diff --git a/src/mbgl/renderer/render_source.cpp b/src/mbgl/renderer/render_source.cpp index 7723a1c7ca..6624bb7d96 100644 --- a/src/mbgl/renderer/render_source.cpp +++ b/src/mbgl/renderer/render_source.cpp @@ -6,6 +6,7 @@ #include <mbgl/renderer/tile_parameters.hpp> #include <mbgl/annotation/render_annotation_source.hpp> #include <mbgl/renderer/sources/render_image_source.hpp> +#include <mbgl/renderer/sources/render_custom_geometry_source.hpp> #include <mbgl/tile/tile.hpp> namespace mbgl { @@ -27,6 +28,8 @@ std::unique_ptr<RenderSource> RenderSource::create(Immutable<Source::Impl> impl) return std::make_unique<RenderAnnotationSource>(staticImmutableCast<AnnotationSource::Impl>(impl)); case SourceType::Image: return std::make_unique<RenderImageSource>(staticImmutableCast<ImageSource::Impl>(impl)); + case SourceType::CustomVector: + return std::make_unique<RenderCustomGeometrySource>(staticImmutableCast<CustomGeometrySource::Impl>(impl)); } // Not reachable, but placate GCC. diff --git a/src/mbgl/renderer/render_source.hpp b/src/mbgl/renderer/render_source.hpp index 8293923ff6..8c84af4f1e 100644 --- a/src/mbgl/renderer/render_source.hpp +++ b/src/mbgl/renderer/render_source.hpp @@ -24,6 +24,7 @@ class SourceQueryOptions; class Tile; class RenderSourceObserver; class TileParameters; +class CollisionIndex; class RenderSource : protected TileObserver { public: @@ -63,7 +64,8 @@ public: queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, const std::vector<const RenderLayer*>& layers, - const RenderedQueryOptions& options) const = 0; + const RenderedQueryOptions& options, + const CollisionIndex& collisionIndex) const = 0; virtual std::vector<Feature> querySourceFeatures(const SourceQueryOptions&) const = 0; diff --git a/src/mbgl/renderer/render_static_data.cpp b/src/mbgl/renderer/render_static_data.cpp index ccf239e643..0b3937ded0 100644 --- a/src/mbgl/renderer/render_static_data.cpp +++ b/src/mbgl/renderer/render_static_data.cpp @@ -3,12 +3,12 @@ namespace mbgl { -static gl::VertexVector<FillLayoutVertex> tileVertices() { - gl::VertexVector<FillLayoutVertex> result; - result.emplace_back(FillProgram::layoutVertex({ 0, 0 })); - result.emplace_back(FillProgram::layoutVertex({ util::EXTENT, 0 })); - result.emplace_back(FillProgram::layoutVertex({ 0, util::EXTENT })); - result.emplace_back(FillProgram::layoutVertex({ util::EXTENT, util::EXTENT })); +static gl::VertexVector<PositionOnlyLayoutAttributes::Vertex> tileVertices() { + gl::VertexVector<PositionOnlyLayoutAttributes::Vertex> result; + result.emplace_back(PositionOnlyLayoutAttributes::Vertex({{{ 0, 0 }}})); + result.emplace_back(PositionOnlyLayoutAttributes::Vertex({{{ util::EXTENT, 0 }}})); + result.emplace_back(PositionOnlyLayoutAttributes::Vertex({{{ 0, util::EXTENT }}})); + result.emplace_back(PositionOnlyLayoutAttributes::Vertex({{{ util::EXTENT, util::EXTENT }}})); return result; } diff --git a/src/mbgl/renderer/render_static_data.hpp b/src/mbgl/renderer/render_static_data.hpp index cf58c31f4d..c2b54f3815 100644 --- a/src/mbgl/renderer/render_static_data.hpp +++ b/src/mbgl/renderer/render_static_data.hpp @@ -13,14 +13,14 @@ class RenderStaticData { public: RenderStaticData(gl::Context&, float pixelRatio, const optional<std::string>& programCacheDir); - gl::VertexBuffer<FillLayoutVertex> tileVertexBuffer; + gl::VertexBuffer<PositionOnlyLayoutAttributes::Vertex> tileVertexBuffer; gl::VertexBuffer<RasterLayoutVertex> rasterVertexBuffer; gl::VertexBuffer<ExtrusionTextureLayoutVertex> extrusionTextureVertexBuffer; gl::IndexBuffer<gl::Triangles> quadTriangleIndexBuffer; gl::IndexBuffer<gl::LineStrip> tileBorderIndexBuffer; - SegmentVector<FillAttributes> tileTriangleSegments; + SegmentVector<BackgroundAttributes> tileTriangleSegments; SegmentVector<DebugAttributes> tileBorderSegments; SegmentVector<RasterAttributes> rasterSegments; SegmentVector<ExtrusionTextureAttributes> extrusionTextureSegments; diff --git a/src/mbgl/renderer/render_tile.cpp b/src/mbgl/renderer/render_tile.cpp index 8df31f8d7c..35b34833e4 100644 --- a/src/mbgl/renderer/render_tile.cpp +++ b/src/mbgl/renderer/render_tile.cpp @@ -72,7 +72,7 @@ void RenderTile::finishRender(PaintParameters& parameters) { return; static const style::Properties<>::PossiblyEvaluated properties {}; - static const DebugProgram::PaintPropertyBinders paintAttibuteData(properties, 0); + static const DebugProgram::PaintPropertyBinders paintAttributeData(properties, 0); if (parameters.debugOptions & (MapDebugOptions::Timestamps | MapDebugOptions::ParseStatus)) { if (!tile.debugBucket || tile.debugBucket->renderable != tile.isRenderable() || @@ -98,7 +98,7 @@ void RenderTile::finishRender(PaintParameters& parameters) { *tile.debugBucket->vertexBuffer, *tile.debugBucket->indexBuffer, tile.debugBucket->segments, - paintAttibuteData, + paintAttributeData, properties, parameters.state.getZoom(), "debug" @@ -117,7 +117,7 @@ void RenderTile::finishRender(PaintParameters& parameters) { *tile.debugBucket->vertexBuffer, *tile.debugBucket->indexBuffer, tile.debugBucket->segments, - paintAttibuteData, + paintAttributeData, properties, parameters.state.getZoom(), "debug" @@ -138,7 +138,7 @@ void RenderTile::finishRender(PaintParameters& parameters) { parameters.staticData.tileVertexBuffer, parameters.staticData.tileBorderIndexBuffer, parameters.staticData.tileBorderSegments, - paintAttibuteData, + paintAttributeData, properties, parameters.state.getZoom(), "debug" diff --git a/src/mbgl/renderer/renderer_backend.cpp b/src/mbgl/renderer/renderer_backend.cpp index 159ef432b3..22d263313c 100644 --- a/src/mbgl/renderer/renderer_backend.cpp +++ b/src/mbgl/renderer/renderer_backend.cpp @@ -16,7 +16,7 @@ gl::Context& RendererBackend::getContext() { context = std::make_unique<gl::Context>(); context->enableDebugging(); context->initializeExtensions( - std::bind(&RendererBackend::initializeExtension, this, std::placeholders::_1)); + std::bind(&RendererBackend::getExtensionFunctionPointer, this, std::placeholders::_1)); }); return *context; } diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index 3a7afdb03d..9fe421fa14 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -57,7 +57,8 @@ Renderer::Impl::Impl(RendererBackend& backend_, , imageImpls(makeMutable<std::vector<Immutable<style::Image::Impl>>>()) , sourceImpls(makeMutable<std::vector<Immutable<style::Source::Impl>>>()) , layerImpls(makeMutable<std::vector<Immutable<style::Layer::Impl>>>()) - , renderLight(makeMutable<Light::Impl>()) { + , renderLight(makeMutable<Light::Impl>()) + , placement(std::make_unique<Placement>(TransformState{}, MapMode::Static)) { glyphManager->setObserver(this); } @@ -81,7 +82,7 @@ void Renderer::Impl::setObserver(RendererObserver* observer_) { } void Renderer::Impl::render(const UpdateParameters& updateParameters) { - if (updateParameters.mode == MapMode::Still) { + if (updateParameters.mode != MapMode::Continuous) { // Don't load/render anyting in still mode until explicitly requested. if (!updateParameters.stillImageRequest) { return; @@ -253,13 +254,12 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) { updateParameters, renderLight.getEvaluated(), *staticData, - frameHistory, *imageManager, *lineAtlas }; bool loaded = updateParameters.styleLoaded && isLoaded(); - if (updateParameters.mode == MapMode::Still && !loaded) { + if (updateParameters.mode != MapMode::Continuous && !loaded) { return; } @@ -299,7 +299,9 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) { if (const RenderBackgroundLayer* background = layer->as<RenderBackgroundLayer>()) { const BackgroundPaintProperties::PossiblyEvaluated& paint = background->evaluated; - if (layerImpl.get() == layerImpls->at(0).get() && paint.get<BackgroundPattern>().from.empty()) { + if (parameters.contextMode == GLContextMode::Unique + && layerImpl.get() == layerImpls->at(0).get() + && paint.get<BackgroundPattern>().from.empty()) { // This is a solid background. We can use glClear(). backgroundColor = paint.get<BackgroundColor>() * paint.get<BackgroundOpacity>(); } else { @@ -333,11 +335,15 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) { auto par = util::rotate(pa, parameters.state.getAngle()); auto pbr = util::rotate(pb, parameters.state.getAngle()); - return std::tie(par.y, par.x) < std::tie(pbr.y, pbr.x); + return std::tie(b.id.canonical.z, par.y, par.x) < std::tie(a.id.canonical.z, pbr.y, pbr.x); }); } else { std::sort(sortedTiles.begin(), sortedTiles.end(), [](const auto& a, const auto& b) { return a.get().id < b.get().id; }); + // Don't render non-symbol layers for tiles that we're only holding on to for symbol fading + sortedTiles.erase(std::remove_if(sortedTiles.begin(), sortedTiles.end(), + [](const auto& tile) { return tile.get().tile.holdForFade(); }), + sortedTiles.end()); } std::vector<std::reference_wrapper<RenderTile>> sortedTilesForInsertion; @@ -347,35 +353,13 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) { continue; } - // We're not clipping symbol layers, so when we have both parents and children of symbol - // layers, we drop all children in favor of their parent to avoid duplicate labels. - // See https://github.com/mapbox/mapbox-gl-native/issues/2482 - if (symbolLayer) { - bool skip = false; - // Look back through the buckets we decided to render to find out whether there is - // already a bucket from this layer that is a parent of this tile. Tiles are ordered - // by zoom level when we obtain them from getTiles(). - for (auto it = sortedTilesForInsertion.rbegin(); - it != sortedTilesForInsertion.rend(); ++it) { - if (tile.tile.id.isChildOf(it->get().tile.id)) { - skip = true; - break; - } - } - if (skip) { - continue; - } - } - auto bucket = tile.tile.getBucket(*layer->baseImpl); if (bucket) { sortedTilesForInsertion.emplace_back(tile); tile.used = true; - // We only need clipping when we're _not_ drawing a symbol layer. The only exception - // for symbol layers is when we're rendering still images. See render_symbol_layer.cpp - // for the exception we make there. - if (!symbolLayer || parameters.mapMode == MapMode::Still) { + // We only need clipping when we're _not_ drawing a symbol layer. + if (!symbolLayer) { tile.needsClipping = true; } } @@ -384,9 +368,47 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) { order.emplace_back(RenderItem { *layer, source }); } - frameHistory.record(parameters.timePoint, - parameters.state.getZoom(), - parameters.mapMode == MapMode::Continuous ? util::DEFAULT_TRANSITION_DURATION : Milliseconds(0)); + bool symbolBucketsChanged = false; + if (parameters.mapMode != MapMode::Continuous) { + // TODO: Think about right way for symbol index to handle still rendering + crossTileSymbolIndex.reset(); + } + for (auto it = order.rbegin(); it != order.rend(); ++it) { + if (it->layer.is<RenderSymbolLayer>()) { + if (crossTileSymbolIndex.addLayer(*it->layer.as<RenderSymbolLayer>())) symbolBucketsChanged = true; + } + } + + bool placementChanged = false; + if (!placement->stillRecent(parameters.timePoint)) { + auto newPlacement = std::make_unique<Placement>(parameters.state, parameters.mapMode); + for (auto it = order.rbegin(); it != order.rend(); ++it) { + if (it->layer.is<RenderSymbolLayer>()) { + newPlacement->placeLayer(*it->layer.as<RenderSymbolLayer>(), parameters.projMatrix, parameters.debugOptions & MapDebugOptions::Collision); + } + } + + placementChanged = newPlacement->commit(*placement, parameters.timePoint); + if (placementChanged || symbolBucketsChanged) { + placement = std::move(newPlacement); + } + + placement->setRecent(parameters.timePoint); + + updateFadingTiles(); + } else { + placement->setStale(); + } + + parameters.symbolFadeChange = placement->symbolFadeChange(parameters.timePoint); + + if (placementChanged || symbolBucketsChanged) { + for (auto it = order.rbegin(); it != order.rend(); ++it) { + if (it->layer.is<RenderSymbolLayer>()) { + placement->updateLayerOpacities(*it->layer.as<RenderSymbolLayer>()); + } + } + } // - UPLOAD PASS ------------------------------------------------------------------------------- // Uploads all required buffers and images before we do any actual rendering. @@ -395,8 +417,7 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) { parameters.imageManager.upload(parameters.context, 0); parameters.lineAtlas.upload(parameters.context, 0); - parameters.frameHistory.upload(parameters.context, 0); - + // Update all clipping IDs + upload buckets. for (const auto& entry : renderSources) { if (entry.second->isEnabled()) { @@ -435,13 +456,17 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) { // Renders the backdrop of the OpenGL view. This also paints in areas where we don't have any // tiles whatsoever. { + using namespace gl::value; + MBGL_DEBUG_GROUP(parameters.context, "clear"); parameters.backend.bind(); - parameters.context.clear((parameters.debugOptions & MapDebugOptions::Overdraw) - ? Color::black() - : backgroundColor, - 1.0f, - 0); + if (parameters.debugOptions & MapDebugOptions::Overdraw) { + parameters.context.clear(Color::black(), ClearDepth::Default, ClearStencil::Default); + } else if (parameters.contextMode == GLContextMode::Shared) { + parameters.context.clear({}, ClearDepth::Default, ClearStencil::Default); + } else { + parameters.context.clear(backgroundColor, ClearDepth::Default, ClearStencil::Default); + } } // - CLIPPING MASKS ---------------------------------------------------------------------------- @@ -449,11 +474,11 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) { { MBGL_DEBUG_GROUP(parameters.context, "clipping masks"); - static const style::FillPaintProperties::PossiblyEvaluated properties {}; - static const FillProgram::PaintPropertyBinders paintAttibuteData(properties, 0); + static const Properties<>::PossiblyEvaluated properties {}; + static const ClippingMaskProgram::PaintPropertyBinders paintAttributeData(properties, 0); for (const auto& clipID : parameters.clipIDGenerator.getClipIDs()) { - parameters.staticData.programs.fill.get(properties).draw( + parameters.staticData.programs.clippingMask.draw( parameters.context, gl::Triangles(), gl::DepthMode::disabled(), @@ -466,14 +491,13 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) { gl::StencilMode::Replace }, gl::ColorMode::disabled(), - FillProgram::UniformValues { + ClippingMaskProgram::UniformValues { uniforms::u_matrix::Value{ parameters.matrixForTile(clipID.first) }, - uniforms::u_world::Value{ parameters.context.viewport.getCurrentValue().size }, }, parameters.staticData.tileVertexBuffer, parameters.staticData.quadTriangleIndexBuffer, parameters.staticData.tileTriangleSegments, - paintAttibuteData, + paintAttributeData, properties, parameters.state.getZoom(), "clipping" @@ -602,7 +626,7 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) { observer->onDidFinishRenderingFrame( loaded ? RendererObserver::RenderMode::Full : RendererObserver::RenderMode::Partial, - updateParameters.mode == MapMode::Continuous && (hasTransitions() || frameHistory.needsAnimation(util::DEFAULT_TRANSITION_DURATION)) + updateParameters.mode == MapMode::Continuous && hasTransitions(parameters.timePoint) ); if (!loaded) { @@ -642,7 +666,7 @@ std::vector<Feature> Renderer::Impl::queryRenderedFeatures(const ScreenLineStrin std::unordered_map<std::string, std::vector<Feature>> resultsByLayer; for (const auto& sourceID : sourceIDs) { if (RenderSource* renderSource = getRenderSource(sourceID)) { - auto sourceResults = renderSource->queryRenderedFeatures(geometry, transformState, layers, options); + auto sourceResults = renderSource->queryRenderedFeatures(geometry, transformState, layers, options, placement->getCollisionIndex()); std::move(sourceResults.begin(), sourceResults.end(), std::inserter(resultsByLayer, resultsByLayer.begin())); } } @@ -722,7 +746,7 @@ RenderSource* Renderer::Impl::getRenderSource(const std::string& id) const { return it != renderSources.end() ? it->second.get() : nullptr; } -bool Renderer::Impl::hasTransitions() const { +bool Renderer::Impl::hasTransitions(TimePoint timePoint) const { if (renderLight.hasTransition()) { return true; } @@ -733,9 +757,30 @@ bool Renderer::Impl::hasTransitions() const { } } + if (placement->hasTransitions(timePoint)) { + return true; + } + + if (fadingTiles) { + return true; + } + return false; } +void Renderer::Impl::updateFadingTiles() { + fadingTiles = false; + for (auto& source : renderSources) { + for (auto& renderTile : source.second->getRenderTiles()) { + Tile& tile = renderTile.get().tile; + if (tile.holdForFade()) { + fadingTiles = true; + tile.performedFadePlacement(); + } + } + } +} + bool Renderer::Impl::isLoaded() const { for (const auto& entry: renderSources) { if (!entry.second->isLoaded()) { diff --git a/src/mbgl/renderer/renderer_impl.hpp b/src/mbgl/renderer/renderer_impl.hpp index a199cec4d0..5d0200a5df 100644 --- a/src/mbgl/renderer/renderer_impl.hpp +++ b/src/mbgl/renderer/renderer_impl.hpp @@ -1,16 +1,17 @@ #pragma once +#include <mbgl/renderer/mode.hpp> #include <mbgl/renderer/renderer.hpp> #include <mbgl/renderer/render_source_observer.hpp> #include <mbgl/renderer/render_light.hpp> -#include <mbgl/renderer/frame_history.hpp> #include <mbgl/style/image.hpp> #include <mbgl/style/source.hpp> #include <mbgl/style/layer.hpp> #include <mbgl/map/transform_state.hpp> #include <mbgl/map/zoom_history.hpp> -#include <mbgl/map/mode.hpp> +#include <mbgl/text/cross_tile_symbol_index.hpp> #include <mbgl/text/glyph_manager_observer.hpp> +#include <mbgl/text/placement.hpp> #include <memory> #include <string> @@ -31,6 +32,7 @@ class Scheduler; class GlyphManager; class ImageManager; class LineAtlas; +class CrossTileSymbolIndex; class Renderer::Impl : public GlyphManagerObserver, public RenderSourceObserver{ @@ -56,7 +58,7 @@ public: private: bool isLoaded() const; - bool hasTransitions() const; + bool hasTransitions(TimePoint) const; RenderSource* getRenderSource(const std::string& id) const; @@ -72,6 +74,8 @@ private: void onTileChanged(RenderSource&, const OverscaledTileID&) override; void onTileError(RenderSource&, const OverscaledTileID&, std::exception_ptr) override; + void updateFadingTiles(); + friend class Renderer; RendererBackend& backend; @@ -91,7 +95,6 @@ private: }; RenderState renderState = RenderState::Never; - FrameHistory frameHistory; ZoomHistory zoomHistory; TransformState transformState; @@ -108,7 +111,11 @@ private: std::unordered_map<std::string, std::unique_ptr<RenderLayer>> renderLayers; RenderLight renderLight; + CrossTileSymbolIndex crossTileSymbolIndex; + std::unique_ptr<Placement> placement; + bool contextLost = false; + bool fadingTiles = false; }; } // namespace mbgl diff --git a/src/mbgl/renderer/sources/render_custom_geometry_source.cpp b/src/mbgl/renderer/sources/render_custom_geometry_source.cpp new file mode 100644 index 0000000000..df615a7e20 --- /dev/null +++ b/src/mbgl/renderer/sources/render_custom_geometry_source.cpp @@ -0,0 +1,87 @@ +#include <mbgl/renderer/sources/render_custom_geometry_source.hpp> +#include <mbgl/renderer/render_tile.hpp> +#include <mbgl/renderer/paint_parameters.hpp> +#include <mbgl/tile/custom_geometry_tile.hpp> + +#include <mbgl/algorithm/generate_clip_ids.hpp> +#include <mbgl/algorithm/generate_clip_ids_impl.hpp> + +namespace mbgl { + +using namespace style; + +RenderCustomGeometrySource::RenderCustomGeometrySource(Immutable<style::CustomGeometrySource::Impl> impl_) + : RenderSource(impl_) { + tilePyramid.setObserver(this); +} + +const style::CustomGeometrySource::Impl& RenderCustomGeometrySource::impl() const { + return static_cast<const style::CustomGeometrySource::Impl&>(*baseImpl); +} + +bool RenderCustomGeometrySource::isLoaded() const { + return tilePyramid.isLoaded(); +} + +void RenderCustomGeometrySource::update(Immutable<style::Source::Impl> baseImpl_, + const std::vector<Immutable<Layer::Impl>>& layers, + const bool needsRendering, + const bool needsRelayout, + const TileParameters& parameters) { + std::swap(baseImpl, baseImpl_); + + enabled = needsRendering; + + auto tileLoader = impl().getTileLoader(); + if (!tileLoader) { + return; + } + + tilePyramid.update(layers, + needsRendering, + needsRelayout, + parameters, + SourceType::CustomVector, + util::tileSize, + impl().getZoomRange(), + {}, + [&] (const OverscaledTileID& tileID) { + return std::make_unique<CustomGeometryTile>(tileID, impl().id, parameters, impl().getTileOptions(), *tileLoader); + }); +} + +void RenderCustomGeometrySource::startRender(PaintParameters& parameters) { + parameters.clipIDGenerator.update(tilePyramid.getRenderTiles()); + tilePyramid.startRender(parameters); +} + +void RenderCustomGeometrySource::finishRender(PaintParameters& parameters) { + tilePyramid.finishRender(parameters); +} + +std::vector<std::reference_wrapper<RenderTile>> RenderCustomGeometrySource::getRenderTiles() { + return tilePyramid.getRenderTiles(); +} + +std::unordered_map<std::string, std::vector<Feature>> +RenderCustomGeometrySource::queryRenderedFeatures(const ScreenLineString& geometry, + const TransformState& transformState, + const std::vector<const RenderLayer*>& layers, + const RenderedQueryOptions& options, + const CollisionIndex& collisionIndex) const { + return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options, collisionIndex); +} + +std::vector<Feature> RenderCustomGeometrySource::querySourceFeatures(const SourceQueryOptions& options) const { + return tilePyramid.querySourceFeatures(options); +} + +void RenderCustomGeometrySource::onLowMemory() { + tilePyramid.onLowMemory(); +} + +void RenderCustomGeometrySource::dumpDebugLogs() const { + tilePyramid.dumpDebugLogs(); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/sources/render_custom_geometry_source.hpp b/src/mbgl/renderer/sources/render_custom_geometry_source.hpp new file mode 100644 index 0000000000..82e691d5c9 --- /dev/null +++ b/src/mbgl/renderer/sources/render_custom_geometry_source.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include <mbgl/renderer/render_source.hpp> +#include <mbgl/renderer/tile_pyramid.hpp> +#include <mbgl/style/sources/custom_geometry_source_impl.hpp> + +namespace mbgl { + +class RenderCustomGeometrySource : public RenderSource { +public: + RenderCustomGeometrySource(Immutable<style::CustomGeometrySource::Impl>); + + bool isLoaded() const final; + + void update(Immutable<style::Source::Impl>, + const std::vector<Immutable<style::Layer::Impl>>&, + bool needsRendering, + bool needsRelayout, + const TileParameters&) final; + + void startRender(PaintParameters&) final; + void finishRender(PaintParameters&) final; + + std::vector<std::reference_wrapper<RenderTile>> getRenderTiles() final; + + std::unordered_map<std::string, std::vector<Feature>> + queryRenderedFeatures(const ScreenLineString& geometry, + const TransformState& transformState, + const std::vector<const RenderLayer*>& layers, + const RenderedQueryOptions& options, + const CollisionIndex& collisionIndex) const final; + + std::vector<Feature> + querySourceFeatures(const SourceQueryOptions&) const final; + + void onLowMemory() final; + void dumpDebugLogs() const final; + +private: + const style::CustomGeometrySource::Impl& impl() const; + + TilePyramid tilePyramid; +}; + +template <> +inline bool RenderSource::is<RenderCustomGeometrySource>() const { + return baseImpl->type == style::SourceType::CustomVector; +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/sources/render_geojson_source.cpp b/src/mbgl/renderer/sources/render_geojson_source.cpp index 504db78ea3..8ea80cd813 100644 --- a/src/mbgl/renderer/sources/render_geojson_source.cpp +++ b/src/mbgl/renderer/sources/render_geojson_source.cpp @@ -62,6 +62,7 @@ void RenderGeoJSONSource::update(Immutable<style::Source::Impl> baseImpl_, SourceType::GeoJSON, util::tileSize, impl().getZoomRange(), + optional<LatLngBounds>{}, [&] (const OverscaledTileID& tileID) { return std::make_unique<GeoJSONTile>(tileID, impl().id, parameters, data->getTile(tileID.canonical)); }); @@ -84,8 +85,9 @@ std::unordered_map<std::string, std::vector<Feature>> RenderGeoJSONSource::queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, const std::vector<const RenderLayer*>& layers, - const RenderedQueryOptions& options) const { - return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options); + const RenderedQueryOptions& options, + const CollisionIndex& collisionIndex) const { + return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options, collisionIndex); } std::vector<Feature> RenderGeoJSONSource::querySourceFeatures(const SourceQueryOptions& options) const { diff --git a/src/mbgl/renderer/sources/render_geojson_source.hpp b/src/mbgl/renderer/sources/render_geojson_source.hpp index 72ab4879ef..55166ea901 100644 --- a/src/mbgl/renderer/sources/render_geojson_source.hpp +++ b/src/mbgl/renderer/sources/render_geojson_source.hpp @@ -31,7 +31,8 @@ public: queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, const std::vector<const RenderLayer*>& layers, - const RenderedQueryOptions& options) const final; + const RenderedQueryOptions& options, + const CollisionIndex&) const final; std::vector<Feature> querySourceFeatures(const SourceQueryOptions&) const final; @@ -48,7 +49,7 @@ private: template <> inline bool RenderSource::is<RenderGeoJSONSource>() const { - return baseImpl->type == SourceType::GeoJSON; + return baseImpl->type == style::SourceType::GeoJSON; } } // namespace mbgl diff --git a/src/mbgl/renderer/sources/render_image_source.cpp b/src/mbgl/renderer/sources/render_image_source.cpp index 9140e01711..35b80cd998 100644 --- a/src/mbgl/renderer/sources/render_image_source.cpp +++ b/src/mbgl/renderer/sources/render_image_source.cpp @@ -56,7 +56,7 @@ void RenderImageSource::finishRender(PaintParameters& parameters) { } static const style::Properties<>::PossiblyEvaluated properties {}; - static const DebugProgram::PaintPropertyBinders paintAttibuteData(properties, 0); + static const DebugProgram::PaintPropertyBinders paintAttributeData(properties, 0); for (auto matrix : matrices) { parameters.programs.debug.draw( @@ -72,7 +72,7 @@ void RenderImageSource::finishRender(PaintParameters& parameters) { parameters.staticData.tileVertexBuffer, parameters.staticData.tileBorderIndexBuffer, parameters.staticData.tileBorderSegments, - paintAttibuteData, + paintAttributeData, properties, parameters.state.getZoom(), "debug" @@ -84,7 +84,8 @@ std::unordered_map<std::string, std::vector<Feature>> RenderImageSource::queryRenderedFeatures(const ScreenLineString&, const TransformState&, const std::vector<const RenderLayer*>&, - const RenderedQueryOptions&) const { + const RenderedQueryOptions&, + const CollisionIndex&) const { return std::unordered_map<std::string, std::vector<Feature>> {}; } @@ -113,44 +114,43 @@ void RenderImageSource::update(Immutable<style::Source::Impl> baseImpl_, return; } - auto size = transformState.getSize(); - const double viewportHeight = size.height; - - // Compute the screen coordinates at wrap=0 for the given LatLng - ScreenCoordinate nePixel = { -INFINITY, -INFINITY }; - ScreenCoordinate swPixel = { INFINITY, INFINITY }; - + // Compute the z0 tile coordinates for the given LatLngs + TileCoordinatePoint nePoint = { -INFINITY, -INFINITY }; + TileCoordinatePoint swPoint = { INFINITY, INFINITY }; + std::vector<TileCoordinatePoint> tileCoordinates; for (LatLng latLng : coords) { - ScreenCoordinate pixel = transformState.latLngToScreenCoordinate(latLng); - swPixel.x = std::min(swPixel.x, pixel.x); - nePixel.x = std::max(nePixel.x, pixel.x); - swPixel.y = std::min(swPixel.y, viewportHeight - pixel.y); - nePixel.y = std::max(nePixel.y, viewportHeight - pixel.y); - } - const double width = nePixel.x - swPixel.x; - const double height = nePixel.y - swPixel.y; + auto point = TileCoordinate::fromLatLng(0, latLng).p; + tileCoordinates.push_back(point); + swPoint.x = std::min(swPoint.x, point.x); + nePoint.x = std::max(nePoint.x, point.x); + swPoint.y = std::min(swPoint.y, point.y); + nePoint.y = std::max(nePoint.y, point.y); + } - // Don't bother drawing the ImageSource unless it occupies >4 screen pixels - enabled = (width * height > 4); + // Calculate the optimum zoom level to determine the tile ids to use for transforms + auto dx = nePoint.x - swPoint.x; + auto dy = nePoint.y - swPoint.y; + auto dMax = std::max(dx, dy); + double zoom = std::max(0.0, std::floor(-util::log2(dMax))); + + // Only enable if the long side of the image is > 2 pixels. Resulting in a + // display of at least 2 x 1 px image + // A tile coordinate unit represents the length of one tile (tileSize) at a given zoom. + // To convert a tile coordinate to pixels, multiply by tileSize. + // Here dMax is in z0 tile units, so we also scale by 2^z to match current zoom. + enabled = dMax * std::pow(2.0, transformState.getZoom()) * util::tileSize > 2.0; if (!enabled) { return; } - // Calculate the optimum zoom level to determine the tile ids to use for transforms - double minScale = INFINITY; - double scaleX = double(size.width) / width; - double scaleY = double(size.height) / height; - minScale = util::min(scaleX, scaleY); - double zoom = transformState.getZoom() + util::log2(minScale); - zoom = std::floor(util::clamp(zoom, transformState.getMinZoom(), transformState.getMaxZoom())); auto imageBounds = LatLngBounds::hull(coords[0], coords[1]); imageBounds.extend(coords[2]); imageBounds.extend(coords[3]); auto tileCover = util::tileCover(imageBounds, zoom); tileIds.clear(); tileIds.push_back(tileCover[0]); - bool hasVisibleTile = false; + bool hasVisibleTile = false; // Add additional wrapped tile ids if neccessary auto idealTiles = util::tileCover(transformState, transformState.getZoom()); for (auto tile : idealTiles) { @@ -176,9 +176,8 @@ void RenderImageSource::update(Immutable<style::Source::Impl> baseImpl_, // Calculate Geometry Coordinates based on tile cover at ideal zoom GeometryCoordinates geomCoords; - for (auto latLng : coords) { - auto tc = TileCoordinate::fromLatLng(0, latLng); - auto gc = TileCoordinate::toGeometryCoordinate(tileIds[0], tc.p); + for (auto tileCoords : tileCoordinates) { + auto gc = TileCoordinate::toGeometryCoordinate(tileIds[0], tileCoords); geomCoords.push_back(gc); } if (!bucket) { diff --git a/src/mbgl/renderer/sources/render_image_source.hpp b/src/mbgl/renderer/sources/render_image_source.hpp index 7b69d09fa7..72cf4cea61 100644 --- a/src/mbgl/renderer/sources/render_image_source.hpp +++ b/src/mbgl/renderer/sources/render_image_source.hpp @@ -32,7 +32,8 @@ public: queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, const std::vector<const RenderLayer*>& layers, - const RenderedQueryOptions& options) const final; + const RenderedQueryOptions& options, + const CollisionIndex& collisionIndex) const final; std::vector<Feature> querySourceFeatures(const SourceQueryOptions&) const final; @@ -52,7 +53,7 @@ private: template <> inline bool RenderSource::is<RenderImageSource>() const { - return baseImpl->type == SourceType::Image; + return baseImpl->type == style::SourceType::Image; } } // namespace mbgl diff --git a/src/mbgl/renderer/sources/render_raster_source.cpp b/src/mbgl/renderer/sources/render_raster_source.cpp index bcd719365d..e99cd040e9 100644 --- a/src/mbgl/renderer/sources/render_raster_source.cpp +++ b/src/mbgl/renderer/sources/render_raster_source.cpp @@ -52,6 +52,7 @@ void RenderRasterSource::update(Immutable<style::Source::Impl> baseImpl_, SourceType::Raster, impl().getTileSize(), tileset->zoomRange, + tileset->bounds, [&] (const OverscaledTileID& tileID) { return std::make_unique<RasterTile>(tileID, parameters, *tileset); }); @@ -74,7 +75,8 @@ std::unordered_map<std::string, std::vector<Feature>> RenderRasterSource::queryRenderedFeatures(const ScreenLineString&, const TransformState&, const std::vector<const RenderLayer*>&, - const RenderedQueryOptions&) const { + const RenderedQueryOptions&, + const CollisionIndex& ) const { return std::unordered_map<std::string, std::vector<Feature>> {}; } diff --git a/src/mbgl/renderer/sources/render_raster_source.hpp b/src/mbgl/renderer/sources/render_raster_source.hpp index 01de812309..25041fde43 100644 --- a/src/mbgl/renderer/sources/render_raster_source.hpp +++ b/src/mbgl/renderer/sources/render_raster_source.hpp @@ -27,7 +27,8 @@ public: queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, const std::vector<const RenderLayer*>& layers, - const RenderedQueryOptions& options) const final; + const RenderedQueryOptions& options, + const CollisionIndex& collisionIndex) const final; std::vector<Feature> querySourceFeatures(const SourceQueryOptions&) const final; @@ -44,7 +45,7 @@ private: template <> inline bool RenderSource::is<RenderRasterSource>() const { - return baseImpl->type == SourceType::Raster; + return baseImpl->type == style::SourceType::Raster; } } // namespace mbgl diff --git a/src/mbgl/renderer/sources/render_vector_source.cpp b/src/mbgl/renderer/sources/render_vector_source.cpp index ca3071c6b0..d53023e4d0 100644 --- a/src/mbgl/renderer/sources/render_vector_source.cpp +++ b/src/mbgl/renderer/sources/render_vector_source.cpp @@ -55,6 +55,7 @@ void RenderVectorSource::update(Immutable<style::Source::Impl> baseImpl_, SourceType::Vector, util::tileSize, tileset->zoomRange, + tileset->bounds, [&] (const OverscaledTileID& tileID) { return std::make_unique<VectorTile>(tileID, impl().id, parameters, *tileset); }); @@ -77,8 +78,9 @@ std::unordered_map<std::string, std::vector<Feature>> RenderVectorSource::queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, const std::vector<const RenderLayer*>& layers, - const RenderedQueryOptions& options) const { - return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options); + const RenderedQueryOptions& options, + const CollisionIndex& collisionIndex) const { + return tilePyramid.queryRenderedFeatures(geometry, transformState, layers, options, collisionIndex); } std::vector<Feature> RenderVectorSource::querySourceFeatures(const SourceQueryOptions& options) const { diff --git a/src/mbgl/renderer/sources/render_vector_source.hpp b/src/mbgl/renderer/sources/render_vector_source.hpp index 5e5c6d1108..4a992e854f 100644 --- a/src/mbgl/renderer/sources/render_vector_source.hpp +++ b/src/mbgl/renderer/sources/render_vector_source.hpp @@ -27,7 +27,8 @@ public: queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, const std::vector<const RenderLayer*>& layers, - const RenderedQueryOptions& options) const final; + const RenderedQueryOptions& options, + const CollisionIndex& collisionIndex) const final; std::vector<Feature> querySourceFeatures(const SourceQueryOptions&) const final; @@ -44,7 +45,7 @@ private: template <> inline bool RenderSource::is<RenderVectorSource>() const { - return baseImpl->type == SourceType::Vector; + return baseImpl->type == style::SourceType::Vector; } } // namespace mbgl diff --git a/src/mbgl/renderer/tile_pyramid.cpp b/src/mbgl/renderer/tile_pyramid.cpp index 3e2311089d..f6eb62f655 100644 --- a/src/mbgl/renderer/tile_pyramid.cpp +++ b/src/mbgl/renderer/tile_pyramid.cpp @@ -5,9 +5,9 @@ #include <mbgl/renderer/tile_parameters.hpp> #include <mbgl/renderer/query.hpp> #include <mbgl/map/transform.hpp> -#include <mbgl/text/placement_config.hpp> #include <mbgl/math/clamp.hpp> #include <mbgl/util/tile_cover.hpp> +#include <mbgl/util/tile_range.hpp> #include <mbgl/util/enum.hpp> #include <mbgl/util/logging.hpp> @@ -15,6 +15,7 @@ #include <mapbox/geometry/envelope.hpp> +#include <cmath> #include <algorithm> namespace mbgl { @@ -62,6 +63,7 @@ void TilePyramid::update(const std::vector<Immutable<style::Layer::Impl>>& layer const SourceType type, const uint16_t tileSize, const Range<uint8_t> zoomRange, + optional<LatLngBounds> bounds, std::function<std::unique_ptr<Tile> (const OverscaledTileID&)> createTile) { // If we need a relayout, abandon any cached tiles; they're now stale. if (needsRelayout) { @@ -94,20 +96,21 @@ void TilePyramid::update(const std::vector<Immutable<style::Layer::Impl>>& layer if (overscaledZoom >= zoomRange.min) { int32_t idealZoom = std::min<int32_t>(zoomRange.max, overscaledZoom); + // Make sure we're not reparsing overzoomed raster tiles. if (type == SourceType::Raster) { tileZoom = idealZoom; + } - // FIXME: Prefetching is only enabled for raster - // tiles until we fix #7026. - - // Request lower zoom level tiles (if configure to do so) in an attempt + // Only attempt prefetching in continuous mode. + if (parameters.mode == MapMode::Continuous) { + // Request lower zoom level tiles (if configured to do so) in an attempt // to show something on the screen faster at the cost of a little of bandwidth. if (parameters.prefetchZoomDelta) { panZoom = std::max<int32_t>(tileZoom - parameters.prefetchZoomDelta, zoomRange.min); } - if (panZoom < tileZoom) { + if (panZoom < idealZoom) { panTiles = util::tileCover(parameters.transformState, panZoom); } } @@ -120,6 +123,7 @@ void TilePyramid::update(const std::vector<Immutable<style::Layer::Impl>>& layer // use because they're still loading. In addition to that, we also need to retain all tiles that // we're actively using, e.g. as a replacement for tile that aren't loaded yet. std::set<OverscaledTileID> retain; + std::set<UnwrappedTileID> rendered; auto retainTileFn = [&](Tile& tile, TileNecessity necessity) -> void { if (retain.emplace(tile.id).second) { @@ -134,7 +138,15 @@ void TilePyramid::update(const std::vector<Immutable<style::Layer::Impl>>& layer auto it = tiles.find(tileID); return it == tiles.end() ? nullptr : it->second.get(); }; + + optional<util::TileRange> tileRange = {}; + if (bounds) { + tileRange = util::TileRange::fromLatLngBounds(*bounds, std::min(tileZoom, (int32_t)zoomRange.max)); + } auto createTileFn = [&](const OverscaledTileID& tileID) -> Tile* { + if (tileRange && !tileRange->contains(tileID.canonical)) { + return nullptr; + } std::unique_ptr<Tile> tile = cache.get(tileID); if (!tile) { tile = createTile(tileID); @@ -148,8 +160,17 @@ void TilePyramid::update(const std::vector<Immutable<style::Layer::Impl>>& layer } return tiles.emplace(tileID, std::move(tile)).first->second.get(); }; + + std::map<UnwrappedTileID, Tile*> previouslyRenderedTiles; + for (auto& renderTile : renderTiles) { + previouslyRenderedTiles[renderTile.id] = &renderTile.tile; + } + auto renderTileFn = [&](const UnwrappedTileID& tileID, Tile& tile) { renderTiles.emplace_back(tileID, tile); + rendered.emplace(tileID); + previouslyRenderedTiles.erase(tileID); // Still rendering this tile, no need for special fading logic. + tile.markRenderedIdeal(); }; renderTiles.clear(); @@ -161,6 +182,18 @@ void TilePyramid::update(const std::vector<Immutable<style::Layer::Impl>>& layer algorithm::updateRenderables(getTileFn, createTileFn, retainTileFn, renderTileFn, idealTiles, zoomRange, tileZoom); + + for (auto previouslyRenderedTile : previouslyRenderedTiles) { + Tile& tile = *previouslyRenderedTile.second; + tile.markRenderedPreviously(); + if (tile.holdForFade()) { + // Since it was rendered in the last frame, we know we have it + // Don't mark the tile "Required" to avoid triggering a new network request + retainTileFn(tile, TileNecessity::Optional); + renderTiles.emplace_back(previouslyRenderedTile.first, tile); + rendered.emplace(previouslyRenderedTile.first); + } + } if (type != SourceType::Annotations) { size_t conservativeCacheSize = @@ -193,20 +226,15 @@ void TilePyramid::update(const std::vector<Immutable<style::Layer::Impl>>& layer } for (auto& pair : tiles) { - const PlacementConfig config { parameters.transformState.getAngle(), - parameters.transformState.getPitch(), - parameters.transformState.getCameraToCenterDistance(), - parameters.transformState.getCameraToTileDistance(pair.first.toUnwrapped()), - parameters.debugOptions & MapDebugOptions::Collision }; - - pair.second->setPlacementConfig(config); + pair.second->setShowCollisionBoxes(parameters.debugOptions & MapDebugOptions::Collision); } } std::unordered_map<std::string, std::vector<Feature>> TilePyramid::queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, const std::vector<const RenderLayer*>& layers, - const RenderedQueryOptions& options) const { + const RenderedQueryOptions& options, + const CollisionIndex& collisionIndex) const { std::unordered_map<std::string, std::vector<Feature>> result; if (renderTiles.empty() || geometry.empty()) { return result; @@ -249,7 +277,8 @@ std::unordered_map<std::string, std::vector<Feature>> TilePyramid::queryRendered tileSpaceQueryGeometry, transformState, layers, - options); + options, + collisionIndex); } return result; diff --git a/src/mbgl/renderer/tile_pyramid.hpp b/src/mbgl/renderer/tile_pyramid.hpp index 73a8d34c1c..3755cee06d 100644 --- a/src/mbgl/renderer/tile_pyramid.hpp +++ b/src/mbgl/renderer/tile_pyramid.hpp @@ -37,9 +37,10 @@ public: bool needsRendering, bool needsRelayout, const TileParameters&, - SourceType type, + style::SourceType type, uint16_t tileSize, Range<uint8_t> zoomRange, + optional<LatLngBounds> bounds, std::function<std::unique_ptr<Tile> (const OverscaledTileID&)> createTile); void startRender(PaintParameters&); @@ -51,7 +52,8 @@ public: queryRenderedFeatures(const ScreenLineString& geometry, const TransformState& transformState, const std::vector<const RenderLayer*>&, - const RenderedQueryOptions& options) const; + const RenderedQueryOptions& options, + const CollisionIndex& collisionIndex) const; std::vector<Feature> querySourceFeatures(const SourceQueryOptions&) const; |