summaryrefslogtreecommitdiff
path: root/src/mbgl/renderer/buckets/raster_bucket.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/renderer/buckets/raster_bucket.cpp')
-rw-r--r--src/mbgl/renderer/buckets/raster_bucket.cpp65
1 files changed, 64 insertions, 1 deletions
diff --git a/src/mbgl/renderer/buckets/raster_bucket.cpp b/src/mbgl/renderer/buckets/raster_bucket.cpp
index 3f5879262d..1a0409f456 100644
--- a/src/mbgl/renderer/buckets/raster_bucket.cpp
+++ b/src/mbgl/renderer/buckets/raster_bucket.cpp
@@ -22,7 +22,7 @@ void RasterBucket::upload(gl::Context& context) {
if (!texture) {
texture = context.createTexture(*image);
}
- if (!vertices.empty()) {
+ if (!segments.empty()) {
vertexBuffer = context.createVertexBuffer(std::move(vertices));
indexBuffer = context.createIndexBuffer(std::move(indices));
}
@@ -45,6 +45,69 @@ void RasterBucket::setImage(std::shared_ptr<PremultipliedImage> image_) {
uploaded = false;
}
+void RasterBucket::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 int32_t textureExtent = 32768 >> 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) };
+ const Point<uint16_t> tlTexture = { static_cast<uint16_t>(id.x * textureExtent),
+ static_cast<uint16_t>(id.y * textureExtent) };
+ const Point<uint16_t> brTexture = { static_cast<uint16_t>(tlTexture.x + textureExtent),
+ static_cast<uint16_t>(tlTexture.y + textureExtent) };
+
+ 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(
+ RasterProgram::layoutVertex({ tlVertex.x, tlVertex.y }, { tlTexture.x, tlTexture.y }));
+ vertices.emplace_back(
+ RasterProgram::layoutVertex({ brVertex.x, tlVertex.y }, { brTexture.x, tlTexture.y }));
+ vertices.emplace_back(
+ RasterProgram::layoutVertex({ tlVertex.x, brVertex.y }, { tlTexture.x, brTexture.y }));
+ vertices.emplace_back(
+ RasterProgram::layoutVertex({ brVertex.x, brVertex.y }, { brTexture.x, brTexture.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 RasterBucket::hasData() const {
return !!image;
}