summaryrefslogtreecommitdiff
path: root/src/mbgl/renderer
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/renderer')
-rw-r--r--src/mbgl/renderer/buckets/circle_bucket.cpp5
-rw-r--r--src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp6
-rw-r--r--src/mbgl/renderer/buckets/hillshade_bucket.cpp113
-rw-r--r--src/mbgl/renderer/buckets/hillshade_bucket.hpp58
-rw-r--r--src/mbgl/renderer/buckets/symbol_bucket.cpp167
-rw-r--r--src/mbgl/renderer/buckets/symbol_bucket.hpp59
-rw-r--r--src/mbgl/renderer/frame_history.cpp81
-rw-r--r--src/mbgl/renderer/frame_history.hpp41
-rw-r--r--src/mbgl/renderer/layers/render_background_layer.cpp27
-rw-r--r--src/mbgl/renderer/layers/render_circle_layer.cpp11
-rw-r--r--src/mbgl/renderer/layers/render_hillshade_layer.cpp158
-rw-r--r--src/mbgl/renderer/layers/render_hillshade_layer.hpp38
-rw-r--r--src/mbgl/renderer/layers/render_raster_layer.cpp4
-rw-r--r--src/mbgl/renderer/layers/render_symbol_layer.cpp83
-rw-r--r--src/mbgl/renderer/paint_parameters.cpp10
-rw-r--r--src/mbgl/renderer/paint_parameters.hpp9
-rw-r--r--src/mbgl/renderer/paint_property_binder.hpp11
-rw-r--r--src/mbgl/renderer/render_layer.cpp3
-rw-r--r--src/mbgl/renderer/render_layer.hpp11
-rw-r--r--src/mbgl/renderer/render_source.cpp6
-rw-r--r--src/mbgl/renderer/render_source.hpp6
-rw-r--r--src/mbgl/renderer/render_static_data.cpp12
-rw-r--r--src/mbgl/renderer/render_static_data.hpp4
-rw-r--r--src/mbgl/renderer/render_tile.cpp8
-rw-r--r--src/mbgl/renderer/renderer_backend.cpp2
-rw-r--r--src/mbgl/renderer/renderer_impl.cpp162
-rw-r--r--src/mbgl/renderer/renderer_impl.hpp16
-rw-r--r--src/mbgl/renderer/renderer_observer.hpp35
-rw-r--r--src/mbgl/renderer/sources/render_custom_geometry_source.cpp87
-rw-r--r--src/mbgl/renderer/sources/render_custom_geometry_source.hpp50
-rw-r--r--src/mbgl/renderer/sources/render_geojson_source.cpp5
-rw-r--r--src/mbgl/renderer/sources/render_geojson_source.hpp5
-rw-r--r--src/mbgl/renderer/sources/render_image_source.cpp63
-rw-r--r--src/mbgl/renderer/sources/render_image_source.hpp5
-rw-r--r--src/mbgl/renderer/sources/render_raster_dem_source.cpp166
-rw-r--r--src/mbgl/renderer/sources/render_raster_dem_source.hpp54
-rw-r--r--src/mbgl/renderer/sources/render_raster_source.cpp3
-rw-r--r--src/mbgl/renderer/sources/render_raster_source.hpp5
-rw-r--r--src/mbgl/renderer/sources/render_vector_source.cpp5
-rw-r--r--src/mbgl/renderer/sources/render_vector_source.hpp5
-rw-r--r--src/mbgl/renderer/tile_pyramid.cpp55
-rw-r--r--src/mbgl/renderer/tile_pyramid.hpp6
42 files changed, 1276 insertions, 384 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/hillshade_bucket.cpp b/src/mbgl/renderer/buckets/hillshade_bucket.cpp
new file mode 100644
index 0000000000..8011681ee0
--- /dev/null
+++ b/src/mbgl/renderer/buckets/hillshade_bucket.cpp
@@ -0,0 +1,113 @@
+#include <mbgl/renderer/buckets/hillshade_bucket.hpp>
+#include <mbgl/renderer/layers/render_hillshade_layer.hpp>
+#include <mbgl/programs/hillshade_program.hpp>
+#include <mbgl/programs/hillshade_prepare_program.hpp>
+#include <mbgl/gl/context.hpp>
+
+namespace mbgl {
+
+using namespace style;
+
+HillshadeBucket::HillshadeBucket(PremultipliedImage&& image_): demdata(image_) {
+}
+
+HillshadeBucket::HillshadeBucket(DEMData&& demdata_) : demdata(std::move(demdata_)) {
+}
+
+const DEMData& HillshadeBucket::getDEMData() const {
+ return demdata;
+}
+
+DEMData& HillshadeBucket::getDEMData() {
+ return demdata;
+}
+
+void HillshadeBucket::upload(gl::Context& context) {
+ if (!hasData()) {
+ return;
+ }
+
+
+ const PremultipliedImage* image = demdata.getImage();
+ dem = context.createTexture(*image);
+
+ if (!segments.empty()) {
+ vertexBuffer = context.createVertexBuffer(std::move(vertices));
+ indexBuffer = context.createIndexBuffer(std::move(indices));
+ }
+ uploaded = true;
+}
+
+void HillshadeBucket::clear() {
+ vertexBuffer = {};
+ indexBuffer = {};
+ segments.clear();
+ vertices.clear();
+ indices.clear();
+
+ uploaded = false;
+}
+
+void HillshadeBucket::setMask(TileMask&& mask_) {
+ if (mask == mask_) {
+ return;
+ }
+
+ mask = std::move(mask_);
+ clear();
+
+ if (mask == TileMask{ { 0, 0, 0 } }) {
+ // We want to render the full tile, and keeping the segments/vertices/indices empty means
+ // using the global shared buffers for covering the entire tile.
+ return;
+ }
+
+ // Create a new segment so that we will upload (empty) buffers even when there is nothing to
+ // draw for this tile.
+ segments.emplace_back(0, 0);
+
+ constexpr const uint16_t vertexLength = 4;
+
+ // Create the vertex buffer for the specified tile mask.
+ for (const auto& id : mask) {
+ // Create a quad for every masked tile.
+ const int32_t vertexExtent = util::EXTENT >> id.z;
+
+ const Point<int16_t> tlVertex = { static_cast<int16_t>(id.x * vertexExtent),
+ static_cast<int16_t>(id.y * vertexExtent) };
+ const Point<int16_t> brVertex = { static_cast<int16_t>(tlVertex.x + vertexExtent),
+ static_cast<int16_t>(tlVertex.y + vertexExtent) };
+
+ if (segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::max()) {
+ // Move to a new segments because the old one can't hold the geometry.
+ segments.emplace_back(vertices.vertexSize(), indices.indexSize());
+ }
+
+ vertices.emplace_back(
+ HillshadeProgram::layoutVertex({ tlVertex.x, tlVertex.y }, { static_cast<uint16_t>(tlVertex.x), static_cast<uint16_t>(tlVertex.y) }));
+ vertices.emplace_back(
+ HillshadeProgram::layoutVertex({ brVertex.x, tlVertex.y }, { static_cast<uint16_t>(brVertex.x), static_cast<uint16_t>(tlVertex.y) }));
+ vertices.emplace_back(
+ HillshadeProgram::layoutVertex({ tlVertex.x, brVertex.y }, { static_cast<uint16_t>(tlVertex.x), static_cast<uint16_t>(brVertex.y) }));
+ vertices.emplace_back(
+ HillshadeProgram::layoutVertex({ brVertex.x, brVertex.y }, { static_cast<uint16_t>(brVertex.x), static_cast<uint16_t>(brVertex.y) }));
+
+ auto& segment = segments.back();
+ assert(segment.vertexLength <= std::numeric_limits<uint16_t>::max());
+ const uint16_t offset = segment.vertexLength;
+
+ // 0, 1, 2
+ // 1, 2, 3
+ indices.emplace_back(offset, offset + 1, offset + 2);
+ indices.emplace_back(offset + 1, offset + 2, offset + 3);
+
+ segment.vertexLength += vertexLength;
+ segment.indexLength += 6;
+ }
+}
+
+bool HillshadeBucket::hasData() const {
+ return demdata.getImage()->valid();
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/buckets/hillshade_bucket.hpp b/src/mbgl/renderer/buckets/hillshade_bucket.hpp
new file mode 100644
index 0000000000..3d9f6c61af
--- /dev/null
+++ b/src/mbgl/renderer/buckets/hillshade_bucket.hpp
@@ -0,0 +1,58 @@
+#pragma once
+
+#include <mbgl/gl/index_buffer.hpp>
+#include <mbgl/gl/texture.hpp>
+#include <mbgl/gl/vertex_buffer.hpp>
+#include <mbgl/programs/hillshade_program.hpp>
+#include <mbgl/programs/hillshade_prepare_program.hpp>
+#include <mbgl/renderer/bucket.hpp>
+#include <mbgl/renderer/tile_mask.hpp>
+#include <mbgl/geometry/dem_data.hpp>
+#include <mbgl/util/image.hpp>
+#include <mbgl/util/mat4.hpp>
+#include <mbgl/util/optional.hpp>
+
+namespace mbgl {
+
+class HillshadeBucket : public Bucket {
+public:
+ HillshadeBucket(PremultipliedImage&&);
+ HillshadeBucket(std::shared_ptr<PremultipliedImage>);
+ HillshadeBucket(DEMData&&);
+
+
+ void upload(gl::Context&) override;
+ bool hasData() const override;
+
+ void clear();
+ void setMask(TileMask&&);
+
+ optional<gl::Texture> dem;
+ optional<gl::Texture> texture;
+
+ TileMask mask{ { 0, 0, 0 } };
+
+ const DEMData& getDEMData() const;
+ DEMData& getDEMData();
+
+ bool isPrepared() const {
+ return prepared;
+ }
+
+ void setPrepared (bool preparedState) {
+ prepared = preparedState;
+ }
+
+ // Raster-DEM Tile Sources use the default buffers from Painter
+ gl::VertexVector<HillshadeLayoutVertex> vertices;
+ gl::IndexVector<gl::Triangles> indices;
+ SegmentVector<HillshadeAttributes> segments;
+
+ optional<gl::VertexBuffer<HillshadeLayoutVertex>> vertexBuffer;
+ optional<gl::IndexBuffer<gl::Triangles>> indexBuffer;
+private:
+ DEMData demdata;
+ bool prepared = false;
+};
+
+} // namespace mbgl
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_hillshade_layer.cpp b/src/mbgl/renderer/layers/render_hillshade_layer.cpp
new file mode 100644
index 0000000000..55702849df
--- /dev/null
+++ b/src/mbgl/renderer/layers/render_hillshade_layer.cpp
@@ -0,0 +1,158 @@
+#include <mbgl/renderer/layers/render_hillshade_layer.hpp>
+#include <mbgl/renderer/buckets/hillshade_bucket.hpp>
+#include <mbgl/renderer/render_tile.hpp>
+#include <mbgl/renderer/paint_parameters.hpp>
+#include <mbgl/renderer/render_static_data.hpp>
+#include <mbgl/programs/programs.hpp>
+#include <mbgl/programs/hillshade_program.hpp>
+#include <mbgl/programs/hillshade_prepare_program.hpp>
+#include <mbgl/tile/tile.hpp>
+#include <mbgl/style/layers/hillshade_layer_impl.hpp>
+#include <mbgl/util/geo.hpp>
+#include <mbgl/util/offscreen_texture.hpp>
+
+namespace mbgl {
+
+using namespace style;
+RenderHillshadeLayer::RenderHillshadeLayer(Immutable<style::HillshadeLayer::Impl> _impl)
+ : RenderLayer(style::LayerType::Hillshade, _impl),
+ unevaluated(impl().paint.untransitioned()) {
+}
+
+const style::HillshadeLayer::Impl& RenderHillshadeLayer::impl() const {
+ return static_cast<const style::HillshadeLayer::Impl&>(*baseImpl);
+}
+
+std::unique_ptr<Bucket> RenderHillshadeLayer::createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const {
+ assert(false);
+ return nullptr;
+}
+
+const std::array<float, 2> RenderHillshadeLayer::getLatRange(const UnwrappedTileID& id) {
+ const LatLng latlng0 = LatLng(id);
+ const LatLng latlng1 = LatLng(UnwrappedTileID(id.canonical.z, id.canonical.x, id.canonical.y + 1));
+ return {{ (float)latlng0.latitude(), (float)latlng1.latitude() }};
+}
+
+const std::array<float, 2> RenderHillshadeLayer::getLight(const PaintParameters& parameters){
+ float azimuthal = evaluated.get<HillshadeIlluminationDirection>() * util::DEG2RAD;
+ if (evaluated.get<HillshadeIlluminationAnchor>() == HillshadeIlluminationAnchorType::Viewport) azimuthal = azimuthal - parameters.state.getAngle();
+ return {{evaluated.get<HillshadeExaggeration>(), azimuthal}};
+}
+
+void RenderHillshadeLayer::transition(const TransitionParameters& parameters) {
+ unevaluated = impl().paint.transitioned(parameters, std::move(unevaluated));
+}
+
+void RenderHillshadeLayer::evaluate(const PropertyEvaluationParameters& parameters) {
+ evaluated = unevaluated.evaluate(parameters);
+ passes = (evaluated.get<style::HillshadeExaggeration >() > 0)
+ ? (RenderPass::Translucent | RenderPass::Pass3D)
+ : RenderPass::None;
+}
+
+bool RenderHillshadeLayer::hasTransition() const {
+ return unevaluated.hasTransition();
+}
+
+void RenderHillshadeLayer::render(PaintParameters& parameters, RenderSource*) {
+ if (parameters.pass != RenderPass::Translucent && parameters.pass != RenderPass::Pass3D)
+ return;
+
+ auto draw = [&] (const mat4& matrix,
+ const auto& vertexBuffer,
+ const auto& indexBuffer,
+ const auto& segments,
+ const UnwrappedTileID& id) {
+ parameters.programs.hillshade.draw(
+ parameters.context,
+ gl::Triangles(),
+ parameters.depthModeForSublayer(0, gl::DepthMode::ReadOnly),
+ gl::StencilMode::disabled(),
+ parameters.colorModeForRenderPass(),
+ HillshadeProgram::UniformValues {
+ uniforms::u_matrix::Value{ matrix },
+ uniforms::u_image::Value{ 0 },
+ uniforms::u_highlight::Value{ evaluated.get<HillshadeHighlightColor>() },
+ uniforms::u_shadow::Value{ evaluated.get<HillshadeShadowColor>() },
+ uniforms::u_accent::Value{ evaluated.get<HillshadeAccentColor>() },
+ uniforms::u_light::Value{ getLight(parameters) },
+ uniforms::u_latrange::Value{ getLatRange(id) },
+ },
+ vertexBuffer,
+ indexBuffer,
+ segments,
+ HillshadeProgram::PaintPropertyBinders { evaluated, 0 },
+ evaluated,
+ parameters.state.getZoom(),
+ getID()
+ );
+ };
+
+ mat4 mat;
+ matrix::ortho(mat, 0, util::EXTENT, -util::EXTENT, 0, 0, 1);
+ matrix::translate(mat, mat, 0, -util::EXTENT, 0);
+
+ for (const RenderTile& tile : renderTiles) {
+ assert(dynamic_cast<HillshadeBucket*>(tile.tile.getBucket(*baseImpl)));
+ HillshadeBucket& bucket = *reinterpret_cast<HillshadeBucket*>(tile.tile.getBucket(*baseImpl));
+ if (!bucket.hasData()){
+ continue;
+ }
+
+ if (!bucket.isPrepared() && parameters.pass == RenderPass::Pass3D) {
+ const uint16_t tilesize = bucket.getDEMData().dim;
+ OffscreenTexture view(parameters.context, { tilesize, tilesize });
+ view.bind();
+
+ parameters.context.bindTexture(*bucket.dem, 0, gl::TextureFilter::Nearest, gl::TextureMipMap::No, gl::TextureWrap::Clamp, gl::TextureWrap::Clamp);
+ const Properties<>::PossiblyEvaluated properties;
+
+ parameters.programs.hillshadePrepare.draw(
+ parameters.context,
+ gl::Triangles(),
+ parameters.depthModeForSublayer(0, gl::DepthMode::ReadOnly),
+ gl::StencilMode::disabled(),
+ parameters.colorModeForRenderPass(),
+ HillshadePrepareProgram::UniformValues {
+ uniforms::u_matrix::Value { mat },
+ uniforms::u_dimension::Value { {{uint16_t(tilesize * 2), uint16_t(tilesize * 2) }} },
+ uniforms::u_zoom::Value{ float(tile.id.canonical.z) },
+ uniforms::u_image::Value{ 0 }
+ },
+ parameters.staticData.rasterVertexBuffer,
+ parameters.staticData.quadTriangleIndexBuffer,
+ parameters.staticData.rasterSegments,
+ HillshadePrepareProgram::PaintPropertyBinders { properties, 0 },
+ properties,
+ parameters.state.getZoom(),
+ getID()
+ );
+ bucket.texture = std::move(view.getTexture());
+ bucket.setPrepared(true);
+ } else if (parameters.pass == RenderPass::Translucent) {
+ assert(bucket.texture);
+ parameters.context.bindTexture(*bucket.texture, 0, gl::TextureFilter::Linear, gl::TextureMipMap::No, gl::TextureWrap::Clamp, gl::TextureWrap::Clamp);
+
+ if (bucket.vertexBuffer && bucket.indexBuffer && !bucket.segments.empty()) {
+ // Draw only the parts of the tile that aren't drawn by another tile in the layer.
+ draw(parameters.matrixForTile(tile.id, true),
+ *bucket.vertexBuffer,
+ *bucket.indexBuffer,
+ bucket.segments,
+ tile.id);
+ } else {
+ // Draw the full tile.
+ draw(parameters.matrixForTile(tile.id, true),
+ parameters.staticData.rasterVertexBuffer,
+ parameters.staticData.quadTriangleIndexBuffer,
+ parameters.staticData.rasterSegments,
+ tile.id);
+ }
+ }
+
+
+ }
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/layers/render_hillshade_layer.hpp b/src/mbgl/renderer/layers/render_hillshade_layer.hpp
new file mode 100644
index 0000000000..e9b9db1ec3
--- /dev/null
+++ b/src/mbgl/renderer/layers/render_hillshade_layer.hpp
@@ -0,0 +1,38 @@
+#pragma once
+
+#include <mbgl/renderer/render_layer.hpp>
+#include <mbgl/style/layers/hillshade_layer_impl.hpp>
+#include <mbgl/style/layers/hillshade_layer_properties.hpp>
+#include <mbgl/tile/tile_id.hpp>
+
+namespace mbgl {
+
+class RenderHillshadeLayer: public RenderLayer {
+public:
+ RenderHillshadeLayer(Immutable<style::HillshadeLayer::Impl>);
+ ~RenderHillshadeLayer() final = default;
+
+ void transition(const TransitionParameters&) override;
+ void evaluate(const PropertyEvaluationParameters&) override;
+ bool hasTransition() const override;
+
+ void render(PaintParameters&, RenderSource*) override;
+
+ std::unique_ptr<Bucket> createBucket(const BucketParameters&, const std::vector<const RenderLayer*>&) const override;
+
+ // Paint properties
+ style::HillshadePaintProperties::Unevaluated unevaluated;
+ style::HillshadePaintProperties::PossiblyEvaluated evaluated;
+
+ const style::HillshadeLayer::Impl& impl() const;
+private:
+ const std::array<float, 2> getLatRange(const UnwrappedTileID& id);
+ const std::array<float, 2> getLight(const PaintParameters& parameters);
+};
+
+template <>
+inline bool RenderLayer::is<RenderHillshadeLayer>() const {
+ return type == style::LayerType::Hillshade;
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/layers/render_raster_layer.cpp b/src/mbgl/renderer/layers/render_raster_layer.cpp
index 06616d90e5..b41b2ac560 100644
--- a/src/mbgl/renderer/layers/render_raster_layer.cpp
+++ b/src/mbgl/renderer/layers/render_raster_layer.cpp
@@ -137,13 +137,13 @@ void RenderRasterLayer::render(PaintParameters& parameters, RenderSource* source
if (bucket.vertexBuffer && bucket.indexBuffer && !bucket.segments.empty()) {
// Draw only the parts of the tile that aren't drawn by another tile in the layer.
- draw(tile.matrix,
+ draw(parameters.matrixForTile(tile.id, true),
*bucket.vertexBuffer,
*bucket.indexBuffer,
bucket.segments);
} else {
// Draw the full tile.
- draw(tile.matrix,
+ draw(parameters.matrixForTile(tile.id, true),
parameters.staticData.rasterVertexBuffer,
parameters.staticData.quadTriangleIndexBuffer,
parameters.staticData.rasterSegments);
diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp
index 1376e8a3d8..9e493003c0 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,42 @@ 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(),
+ CollisionCircleProgram::UniformValues {
+ uniforms::u_matrix::Value{ tile.matrix },
+ uniforms::u_extrude_scale::Value{ extrudeScale },
+ uniforms::u_overscale_factor::Value{ float(tile.tile.id.overscaleFactor()) },
+ 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..a7f621eb61 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),
@@ -37,6 +35,10 @@ PaintParameters::PaintParameters(gl::Context& context_,
// Update the default matrices to the current viewport dimensions.
state.getProjMatrix(projMatrix);
+ // Also compute a projection matrix that aligns with the current pixel grid, taking into account
+ // odd viewport sizes.
+ state.getProjMatrix(alignedProjMatrix, 1, true);
+
// Calculate a second projection matrix with the near plane clipped to 100 so as
// not to waste lots of depth buffer precision on very close empty space, for layer
// types (fill-extrusion) that use the depth buffer to emulate real-world space.
@@ -49,10 +51,10 @@ PaintParameters::PaintParameters(gl::Context& context_,
}
}
-mat4 PaintParameters::matrixForTile(const UnwrappedTileID& tileID) {
+mat4 PaintParameters::matrixForTile(const UnwrappedTileID& tileID, bool aligned) const {
mat4 matrix;
state.matrixFor(matrix, tileID);
- matrix::multiply(matrix, projMatrix, matrix);
+ matrix::multiply(matrix, aligned ? alignedProjMatrix : projMatrix, matrix);
return matrix;
}
diff --git a/src/mbgl/renderer/paint_parameters.hpp b/src/mbgl/renderer/paint_parameters.hpp
index 4a2c2c6f12..41f46ae34e 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;
@@ -64,15 +62,18 @@ public:
gl::StencilMode stencilModeForClipping(const ClipID&) const;
gl::ColorMode colorModeForRenderPass() const;
- mat4 matrixForTile(const UnwrappedTileID&);
+ mat4 matrixForTile(const UnwrappedTileID&, bool aligned = false) const;
mat4 projMatrix;
+ mat4 alignedProjMatrix;
mat4 nearClippedProjMatrix;
int numSublayers = 3;
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.cpp b/src/mbgl/renderer/render_layer.cpp
index eb2b74ffe0..248905f834 100644
--- a/src/mbgl/renderer/render_layer.cpp
+++ b/src/mbgl/renderer/render_layer.cpp
@@ -4,6 +4,7 @@
#include <mbgl/renderer/layers/render_custom_layer.hpp>
#include <mbgl/renderer/layers/render_fill_extrusion_layer.hpp>
#include <mbgl/renderer/layers/render_fill_layer.hpp>
+#include <mbgl/renderer/layers/render_hillshade_layer.hpp>
#include <mbgl/renderer/layers/render_line_layer.hpp>
#include <mbgl/renderer/layers/render_raster_layer.hpp>
#include <mbgl/renderer/layers/render_symbol_layer.hpp>
@@ -26,6 +27,8 @@ std::unique_ptr<RenderLayer> RenderLayer::create(Immutable<Layer::Impl> impl) {
return std::make_unique<RenderSymbolLayer>(staticImmutableCast<SymbolLayer::Impl>(impl));
case LayerType::Raster:
return std::make_unique<RenderRasterLayer>(staticImmutableCast<RasterLayer::Impl>(impl));
+ case LayerType::Hillshade:
+ return std::make_unique<RenderHillshadeLayer>(staticImmutableCast<HillshadeLayer::Impl>(impl));
case LayerType::Background:
return std::make_unique<RenderBackgroundLayer>(staticImmutableCast<BackgroundLayer::Impl>(impl));
case LayerType::Custom:
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..d160eb16e3 100644
--- a/src/mbgl/renderer/render_source.cpp
+++ b/src/mbgl/renderer/render_source.cpp
@@ -2,10 +2,12 @@
#include <mbgl/renderer/render_source_observer.hpp>
#include <mbgl/renderer/sources/render_geojson_source.hpp>
#include <mbgl/renderer/sources/render_raster_source.hpp>
+#include <mbgl/renderer/sources/render_raster_dem_source.hpp>
#include <mbgl/renderer/sources/render_vector_source.hpp>
#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 {
@@ -18,6 +20,8 @@ std::unique_ptr<RenderSource> RenderSource::create(Immutable<Source::Impl> impl)
return std::make_unique<RenderVectorSource>(staticImmutableCast<VectorSource::Impl>(impl));
case SourceType::Raster:
return std::make_unique<RenderRasterSource>(staticImmutableCast<RasterSource::Impl>(impl));
+ case SourceType::RasterDEM:
+ return std::make_unique<RenderRasterDEMSource>(staticImmutableCast<RasterSource::Impl>(impl));
case SourceType::GeoJSON:
return std::make_unique<RenderGeoJSONSource>(staticImmutableCast<GeoJSONSource::Impl>(impl));
case SourceType::Video:
@@ -27,6 +31,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..db88230e53 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;
@@ -82,7 +84,7 @@ protected:
bool enabled = false;
- void onTileChanged(Tile&) final;
+ void onTileChanged(Tile&) override;
void onTileError(Tile&, std::exception_ptr) final;
};
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..61e7d17242 100644
--- a/src/mbgl/renderer/renderer_impl.cpp
+++ b/src/mbgl/renderer/renderer_impl.cpp
@@ -14,6 +14,7 @@
#include <mbgl/renderer/layers/render_background_layer.hpp>
#include <mbgl/renderer/layers/render_custom_layer.hpp>
#include <mbgl/renderer/layers/render_fill_extrusion_layer.hpp>
+#include <mbgl/renderer/layers/render_hillshade_layer.hpp>
#include <mbgl/renderer/style_diff.hpp>
#include <mbgl/renderer/query.hpp>
#include <mbgl/renderer/backend_scope.hpp>
@@ -57,7 +58,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 +83,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 +255,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;
}
@@ -289,7 +290,7 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
RenderLayer* layer = getRenderLayer(layerImpl->id);
assert(layer);
- if (!parameters.staticData.has3D && layer->is<RenderFillExtrusionLayer>()) {
+ if (!parameters.staticData.has3D && (layer->is<RenderFillExtrusionLayer>() || layer->is<RenderHillshadeLayer>())) {
parameters.staticData.has3D = true;
}
@@ -299,7 +300,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 +336,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 +354,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 +369,54 @@ 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);
+ std::set<std::string> usedSymbolLayers;
+ for (auto it = order.rbegin(); it != order.rend(); ++it) {
+ if (it->layer.is<RenderSymbolLayer>()) {
+ usedSymbolLayers.insert(it->layer.getID());
+ newPlacement->placeLayer(*it->layer.as<RenderSymbolLayer>(), parameters.projMatrix, parameters.debugOptions & MapDebugOptions::Collision);
+ }
+ }
+
+ placementChanged = newPlacement->commit(*placement, parameters.timePoint);
+ // commitFeatureIndexes depends on the assumption that no new FeatureIndex has been loaded since placement
+ // started. If we violate this assumption, then we need to either make CollisionIndex completely independendent of
+ // FeatureIndex, or find a way for its entries to point to multiple FeatureIndexes.
+ commitFeatureIndexes();
+ crossTileSymbolIndex.pruneUnusedLayers(usedSymbolLayers);
+ 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 +425,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 +464,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 +482,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 +499,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 +634,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 +674,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 +754,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 +765,39 @@ bool Renderer::Impl::hasTransitions() const {
}
}
+ if (placement->hasTransitions(timePoint)) {
+ return true;
+ }
+
+ if (fadingTiles) {
+ return true;
+ }
+
return false;
}
+void Renderer::Impl::commitFeatureIndexes() {
+ for (auto& source : renderSources) {
+ for (auto& renderTile : source.second->getRenderTiles()) {
+ Tile& tile = renderTile.get().tile;
+ tile.commitFeatureIndex();
+ }
+ }
+}
+
+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..4f45d514a5 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,9 @@ private:
void onTileChanged(RenderSource&, const OverscaledTileID&) override;
void onTileError(RenderSource&, const OverscaledTileID&, std::exception_ptr) override;
+ void commitFeatureIndexes();
+ void updateFadingTiles();
+
friend class Renderer;
RendererBackend& backend;
@@ -91,7 +96,6 @@ private:
};
RenderState renderState = RenderState::Never;
- FrameHistory frameHistory;
ZoomHistory zoomHistory;
TransformState transformState;
@@ -108,7 +112,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/renderer_observer.hpp b/src/mbgl/renderer/renderer_observer.hpp
deleted file mode 100644
index 551b5c803e..0000000000
--- a/src/mbgl/renderer/renderer_observer.hpp
+++ /dev/null
@@ -1,35 +0,0 @@
-#pragma once
-
-#include <exception>
-
-namespace mbgl {
-
-class RendererObserver {
-public:
- virtual ~RendererObserver() = default;
-
- enum class RenderMode : uint32_t {
- Partial,
- Full
- };
-
- // Signals that a repaint is required
- virtual void onInvalidate() {}
-
- // Resource failed to download / parse
- virtual void onResourceError(std::exception_ptr) {}
-
- // First frame
- virtual void onWillStartRenderingMap() {}
-
- // Start of frame, initial is the first frame for this map
- virtual void onWillStartRenderingFrame() {}
-
- // End of frame, boolean flags that a repaint is required
- virtual void onDidFinishRenderingFrame(RenderMode, bool) {}
-
- // Final frame
- virtual void onDidFinishRenderingMap() {}
-};
-
-} // 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 c13cd49f46..8ea80cd813 100644
--- a/src/mbgl/renderer/sources/render_geojson_source.cpp
+++ b/src/mbgl/renderer/sources/render_geojson_source.cpp
@@ -85,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..31a5916a34 100644
--- a/src/mbgl/renderer/sources/render_image_source.cpp
+++ b/src/mbgl/renderer/sources/render_image_source.cpp
@@ -41,7 +41,7 @@ void RenderImageSource::startRender(PaintParameters& parameters) {
mat4 matrix;
matrix::identity(matrix);
parameters.state.matrixFor(matrix, tileIds[i]);
- matrix::multiply(matrix, parameters.projMatrix, matrix);
+ matrix::multiply(matrix, parameters.alignedProjMatrix, matrix);
matrices.push_back(matrix);
}
@@ -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_dem_source.cpp b/src/mbgl/renderer/sources/render_raster_dem_source.cpp
new file mode 100644
index 0000000000..4de949c9f2
--- /dev/null
+++ b/src/mbgl/renderer/sources/render_raster_dem_source.cpp
@@ -0,0 +1,166 @@
+#include <mbgl/renderer/sources/render_raster_dem_source.hpp>
+#include <mbgl/renderer/render_tile.hpp>
+#include <mbgl/tile/raster_dem_tile.hpp>
+#include <mbgl/algorithm/update_tile_masks.hpp>
+#include <mbgl/geometry/dem_data.hpp>
+#include <mbgl/renderer/buckets/hillshade_bucket.hpp>
+#include <iostream>
+
+namespace mbgl {
+
+using namespace style;
+
+RenderRasterDEMSource::RenderRasterDEMSource(Immutable<style::RasterSource::Impl> impl_)
+ : RenderSource(impl_) {
+ tilePyramid.setObserver(this);
+}
+
+const style::RasterSource::Impl& RenderRasterDEMSource::impl() const {
+ return static_cast<const style::RasterSource::Impl&>(*baseImpl);
+}
+
+bool RenderRasterDEMSource::isLoaded() const {
+ return tilePyramid.isLoaded();
+}
+
+void RenderRasterDEMSource::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;
+
+ optional<Tileset> _tileset = impl().getTileset();
+
+ if (tileset != _tileset) {
+ tileset = _tileset;
+
+ // TODO: this removes existing buckets, and will cause flickering.
+ // Should instead refresh tile data in place.
+ tilePyramid.tiles.clear();
+ tilePyramid.renderTiles.clear();
+ tilePyramid.cache.clear();
+ }
+ // Allow clearing the tile pyramid first, before the early return in case
+ // the new tileset is not yet available or has an error in loading
+ if (!_tileset) {
+ return;
+ }
+
+ tilePyramid.update(layers,
+ needsRendering,
+ needsRelayout,
+ parameters,
+ SourceType::RasterDEM,
+ impl().getTileSize(),
+ tileset->zoomRange,
+ tileset->bounds,
+ [&] (const OverscaledTileID& tileID) {
+ return std::make_unique<RasterDEMTile>(tileID, parameters, *tileset);
+ });
+}
+
+void RenderRasterDEMSource::onTileChanged(Tile& tile){
+ RasterDEMTile& demtile = static_cast<RasterDEMTile&>(tile);
+
+ std::map<DEMTileNeighbors, DEMTileNeighbors> opposites = {
+ { DEMTileNeighbors::Left, DEMTileNeighbors::Right },
+ { DEMTileNeighbors::Right, DEMTileNeighbors::Left },
+ { DEMTileNeighbors::TopLeft, DEMTileNeighbors::BottomRight },
+ { DEMTileNeighbors::TopCenter, DEMTileNeighbors::BottomCenter },
+ { DEMTileNeighbors::TopRight, DEMTileNeighbors::BottomLeft },
+ { DEMTileNeighbors::BottomRight, DEMTileNeighbors::TopLeft },
+ { DEMTileNeighbors::BottomCenter, DEMTileNeighbors:: TopCenter },
+ { DEMTileNeighbors::BottomLeft, DEMTileNeighbors::TopRight }
+ };
+
+ if (tile.isRenderable() && demtile.neighboringTiles != DEMTileNeighbors::Complete) {
+ const CanonicalTileID canonical = tile.id.canonical;
+ const uint32_t dim = std::pow(2, canonical.z);
+ const uint32_t px = (canonical.x - 1 + dim) % dim;
+ const int pxw = canonical.x == 0 ? tile.id.wrap - 1 : tile.id.wrap;
+ const uint32_t nx = (canonical.x + 1 + dim) % dim;
+ const int nxw = (canonical.x + 1 == dim) ? tile.id.wrap + 1 : tile.id.wrap;
+
+ auto getNeighbor = [&] (DEMTileNeighbors mask){
+ if (mask == DEMTileNeighbors::Left){
+ return OverscaledTileID(tile.id.overscaledZ, pxw, canonical.z, px, canonical.y);
+ } else if (mask == DEMTileNeighbors::Right){
+ return OverscaledTileID(tile.id.overscaledZ, nxw, canonical.z, nx, canonical.y);
+ } else if (mask == DEMTileNeighbors::TopLeft){
+ return OverscaledTileID(tile.id.overscaledZ, pxw, canonical.z, px, canonical.y - 1);
+ } else if (mask == DEMTileNeighbors::TopCenter){
+ return OverscaledTileID(tile.id.overscaledZ, tile.id.wrap, canonical.z, canonical.x, canonical.y - 1);
+ } else if (mask == DEMTileNeighbors::TopRight){
+ return OverscaledTileID(tile.id.overscaledZ, nxw, canonical.z, nx, canonical.y - 1);
+ } else if (mask == DEMTileNeighbors::BottomLeft){
+ return OverscaledTileID(tile.id.overscaledZ, pxw, canonical.z, px, canonical.y + 1);
+ } else if (mask == DEMTileNeighbors::BottomCenter){
+ return OverscaledTileID(tile.id.overscaledZ, tile.id.wrap, canonical.z, canonical.x, canonical.y + 1);
+ } else if (mask == DEMTileNeighbors::BottomRight){
+ return OverscaledTileID(tile.id.overscaledZ, nxw, canonical.z, nx, canonical.y + 1);
+ } else{
+ throw std::runtime_error("mask is not a valid tile neighbor");
+ }
+ };
+
+ for (uint8_t i = 0; i < 8; i++) {
+ DEMTileNeighbors mask = DEMTileNeighbors(std::pow(2,i));
+ // only backfill if this neighbor has not been previously backfilled
+ if ((demtile.neighboringTiles & mask) != mask) {
+ OverscaledTileID neighborid = getNeighbor(mask);
+ Tile* renderableNeighbor = tilePyramid.getTile(neighborid);
+ if (renderableNeighbor != nullptr && renderableNeighbor->isRenderable()) {
+ RasterDEMTile& borderTile = static_cast<RasterDEMTile&>(*renderableNeighbor);
+ demtile.backfillBorder(borderTile, mask);
+
+ // if the border tile has not been backfilled by a previous instance of the main
+ // tile, backfill its corresponding neighbor as well.
+ const DEMTileNeighbors& borderMask = opposites[mask];
+ if ((borderTile.neighboringTiles & borderMask) != borderMask){
+ borderTile.backfillBorder(demtile, borderMask);
+ }
+ }
+ }
+ }
+ }
+ RenderSource::onTileChanged(tile);
+}
+
+void RenderRasterDEMSource::startRender(PaintParameters& parameters) {
+ algorithm::updateTileMasks(tilePyramid.getRenderTiles());
+ tilePyramid.startRender(parameters);
+}
+
+void RenderRasterDEMSource::finishRender(PaintParameters& parameters) {
+ tilePyramid.finishRender(parameters);
+}
+
+std::vector<std::reference_wrapper<RenderTile>> RenderRasterDEMSource::getRenderTiles() {
+ return tilePyramid.getRenderTiles();
+}
+
+std::unordered_map<std::string, std::vector<Feature>>
+RenderRasterDEMSource::queryRenderedFeatures(const ScreenLineString&,
+ const TransformState&,
+ const std::vector<const RenderLayer*>&,
+ const RenderedQueryOptions&,
+ const CollisionIndex& ) const {
+ return std::unordered_map<std::string, std::vector<Feature>> {};
+}
+
+std::vector<Feature> RenderRasterDEMSource::querySourceFeatures(const SourceQueryOptions&) const {
+ return {};
+}
+
+void RenderRasterDEMSource::onLowMemory() {
+ tilePyramid.onLowMemory();
+}
+
+void RenderRasterDEMSource::dumpDebugLogs() const {
+ tilePyramid.dumpDebugLogs();
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/sources/render_raster_dem_source.hpp b/src/mbgl/renderer/sources/render_raster_dem_source.hpp
new file mode 100644
index 0000000000..87f9bcb563
--- /dev/null
+++ b/src/mbgl/renderer/sources/render_raster_dem_source.hpp
@@ -0,0 +1,54 @@
+#pragma once
+
+#include <mbgl/renderer/render_source.hpp>
+#include <mbgl/renderer/tile_pyramid.hpp>
+#include <mbgl/style/sources/raster_source_impl.hpp>
+
+namespace mbgl {
+
+class RenderRasterDEMSource : public RenderSource {
+public:
+ RenderRasterDEMSource(Immutable<style::RasterSource::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::RasterSource::Impl& impl() const;
+
+ TilePyramid tilePyramid;
+ optional<Tileset> tileset;
+
+protected:
+ void onTileChanged(Tile&) final;
+};
+
+template <>
+inline bool RenderSource::is<RenderRasterDEMSource>() const {
+ return baseImpl->type == style::SourceType::RasterDEM;
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/sources/render_raster_source.cpp b/src/mbgl/renderer/sources/render_raster_source.cpp
index 46e3c2eff6..5d32818663 100644
--- a/src/mbgl/renderer/sources/render_raster_source.cpp
+++ b/src/mbgl/renderer/sources/render_raster_source.cpp
@@ -76,7 +76,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 aebc49bf8a..bc6ac1bd9f 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 310dfe68b8..c01257aea9 100644
--- a/src/mbgl/renderer/sources/render_vector_source.cpp
+++ b/src/mbgl/renderer/sources/render_vector_source.cpp
@@ -79,8 +79,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 f237b4b825..57fe6dbb6c 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 c9e3b0630a..07239b7a1c 100644
--- a/src/mbgl/renderer/tile_pyramid.cpp
+++ b/src/mbgl/renderer/tile_pyramid.cpp
@@ -5,7 +5,6 @@
#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>
@@ -57,6 +56,11 @@ std::vector<std::reference_wrapper<RenderTile>> TilePyramid::getRenderTiles() {
return { renderTiles.begin(), renderTiles.end() };
}
+Tile* TilePyramid::getTile(const OverscaledTileID& tileID){
+ auto it = tiles.find(tileID);
+ return it == tiles.end() ? cache.get(tileID) : it->second.get();
+}
+
void TilePyramid::update(const std::vector<Immutable<style::Layer::Impl>>& layers,
const bool needsRendering,
const bool needsRelayout,
@@ -97,20 +101,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);
}
}
@@ -123,6 +128,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) {
@@ -146,7 +152,7 @@ void TilePyramid::update(const std::vector<Immutable<style::Layer::Impl>>& layer
if (tileRange && !tileRange->contains(tileID.canonical)) {
return nullptr;
}
- std::unique_ptr<Tile> tile = cache.get(tileID);
+ std::unique_ptr<Tile> tile = cache.pop(tileID);
if (!tile) {
tile = createTile(tileID);
if (tile) {
@@ -159,8 +165,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();
@@ -172,6 +187,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 =
@@ -204,20 +231,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;
@@ -260,7 +282,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 e34b050273..ad3f91bf88 100644
--- a/src/mbgl/renderer/tile_pyramid.hpp
+++ b/src/mbgl/renderer/tile_pyramid.hpp
@@ -37,7 +37,7 @@ public:
bool needsRendering,
bool needsRelayout,
const TileParameters&,
- SourceType type,
+ style::SourceType type,
uint16_t tileSize,
Range<uint8_t> zoomRange,
optional<LatLngBounds> bounds,
@@ -47,12 +47,14 @@ public:
void finishRender(PaintParameters&);
std::vector<std::reference_wrapper<RenderTile>> getRenderTiles();
+ Tile* getTile(const OverscaledTileID&);
std::unordered_map<std::string, std::vector<Feature>>
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;