summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2017-07-20 14:49:56 +0200
committerKonstantin Käfer <mail@kkaefer.com>2017-07-24 12:10:45 +0200
commitc0efad5de22e50a2f2d541a62a07b0786cde0202 (patch)
treef6a3e63ded1ffd317c2af6d5f4a47b4ae623218d /src
parent4dff51719b27988fe4672bd4022d305b6e7d9816 (diff)
downloadqtlocation-mapboxgl-c0efad5de22e50a2f2d541a62a07b0786cde0202.tar.gz
[core] generate masks for raster tiles to avoid painting over children
Diffstat (limited to 'src')
-rw-r--r--src/mbgl/gl/index_buffer.hpp1
-rw-r--r--src/mbgl/gl/vertex_buffer.hpp1
-rw-r--r--src/mbgl/renderer/buckets/raster_bucket.cpp65
-rw-r--r--src/mbgl/renderer/buckets/raster_bucket.hpp4
-rw-r--r--src/mbgl/renderer/layers/render_raster_layer.cpp17
-rw-r--r--src/mbgl/renderer/render_tile.cpp4
-rw-r--r--src/mbgl/renderer/render_tile.hpp2
-rw-r--r--src/mbgl/renderer/sources/render_raster_source.cpp2
-rw-r--r--src/mbgl/tile/raster_tile.cpp8
-rw-r--r--src/mbgl/tile/raster_tile.hpp7
-rw-r--r--src/mbgl/tile/tile.hpp2
11 files changed, 105 insertions, 8 deletions
diff --git a/src/mbgl/gl/index_buffer.hpp b/src/mbgl/gl/index_buffer.hpp
index 1e57fb11f2..01b6396e00 100644
--- a/src/mbgl/gl/index_buffer.hpp
+++ b/src/mbgl/gl/index_buffer.hpp
@@ -26,6 +26,7 @@ public:
bool empty() const { return v.empty(); }
void clear() { v.clear(); }
const uint16_t* data() const { return v.data(); }
+ const std::vector<uint16_t>& vector() const { return v; }
private:
std::vector<uint16_t> v;
diff --git a/src/mbgl/gl/vertex_buffer.hpp b/src/mbgl/gl/vertex_buffer.hpp
index 4808803d00..9f8b156b25 100644
--- a/src/mbgl/gl/vertex_buffer.hpp
+++ b/src/mbgl/gl/vertex_buffer.hpp
@@ -28,6 +28,7 @@ public:
bool empty() const { return v.empty(); }
void clear() { v.clear(); }
const Vertex* data() const { return v.data(); }
+ const std::vector<Vertex>& vector() const { return v; }
private:
std::vector<Vertex> v;
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;
}
diff --git a/src/mbgl/renderer/buckets/raster_bucket.hpp b/src/mbgl/renderer/buckets/raster_bucket.hpp
index 0b8432eaaf..3800eadec8 100644
--- a/src/mbgl/renderer/buckets/raster_bucket.hpp
+++ b/src/mbgl/renderer/buckets/raster_bucket.hpp
@@ -5,6 +5,7 @@
#include <mbgl/gl/vertex_buffer.hpp>
#include <mbgl/programs/raster_program.hpp>
#include <mbgl/renderer/bucket.hpp>
+#include <mbgl/renderer/tile_mask.hpp>
#include <mbgl/util/image.hpp>
#include <mbgl/util/mat4.hpp>
#include <mbgl/util/optional.hpp>
@@ -21,8 +22,11 @@ public:
void clear();
void setImage(std::shared_ptr<PremultipliedImage>);
+ void setMask(TileMask&&);
+
std::shared_ptr<PremultipliedImage> image;
optional<gl::Texture> texture;
+ TileMask mask{ { 0, 0, 0 } };
// Bucket specific vertices are used for Image Sources only
// Raster Tile Sources use the default buffers from Painter
diff --git a/src/mbgl/renderer/layers/render_raster_layer.cpp b/src/mbgl/renderer/layers/render_raster_layer.cpp
index 367fd91fa5..06616d90e5 100644
--- a/src/mbgl/renderer/layers/render_raster_layer.cpp
+++ b/src/mbgl/renderer/layers/render_raster_layer.cpp
@@ -135,10 +135,19 @@ void RenderRasterLayer::render(PaintParameters& parameters, RenderSource* source
parameters.context.bindTexture(*bucket.texture, 0, gl::TextureFilter::Linear);
parameters.context.bindTexture(*bucket.texture, 1, gl::TextureFilter::Linear);
- draw(tile.matrix,
- parameters.staticData.rasterVertexBuffer,
- parameters.staticData.quadTriangleIndexBuffer,
- parameters.staticData.rasterSegments);
+ 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,
+ *bucket.vertexBuffer,
+ *bucket.indexBuffer,
+ bucket.segments);
+ } else {
+ // Draw the full tile.
+ draw(tile.matrix,
+ parameters.staticData.rasterVertexBuffer,
+ parameters.staticData.quadTriangleIndexBuffer,
+ parameters.staticData.rasterSegments);
+ }
}
}
}
diff --git a/src/mbgl/renderer/render_tile.cpp b/src/mbgl/renderer/render_tile.cpp
index 4e924331cc..c9912f0563 100644
--- a/src/mbgl/renderer/render_tile.cpp
+++ b/src/mbgl/renderer/render_tile.cpp
@@ -52,6 +52,10 @@ mat4 RenderTile::translatedClipMatrix(const std::array<float, 2>& translation,
return translateVtxMatrix(nearClippedMatrix, translation, anchor, state, false);
}
+void RenderTile::setMask(TileMask&& mask) {
+ tile.setMask(std::move(mask));
+}
+
void RenderTile::startRender(PaintParameters& parameters) {
tile.upload(parameters.context);
diff --git a/src/mbgl/renderer/render_tile.hpp b/src/mbgl/renderer/render_tile.hpp
index d5ed4f0018..b498972f5c 100644
--- a/src/mbgl/renderer/render_tile.hpp
+++ b/src/mbgl/renderer/render_tile.hpp
@@ -4,6 +4,7 @@
#include <mbgl/util/mat4.hpp>
#include <mbgl/util/clip_id.hpp>
#include <mbgl/style/types.hpp>
+#include <mbgl/renderer/tile_mask.hpp>
#include <array>
@@ -36,6 +37,7 @@ public:
style::TranslateAnchorType anchor,
const TransformState&) const;
+ void setMask(TileMask&&);
void startRender(PaintParameters&);
void finishRender(PaintParameters&);
diff --git a/src/mbgl/renderer/sources/render_raster_source.cpp b/src/mbgl/renderer/sources/render_raster_source.cpp
index 910a812f05..cbd874f647 100644
--- a/src/mbgl/renderer/sources/render_raster_source.cpp
+++ b/src/mbgl/renderer/sources/render_raster_source.cpp
@@ -1,6 +1,7 @@
#include <mbgl/renderer/sources/render_raster_source.hpp>
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/tile/raster_tile.hpp>
+#include <mbgl/algorithm/update_tile_masks.hpp>
namespace mbgl {
@@ -57,6 +58,7 @@ void RenderRasterSource::update(Immutable<style::Source::Impl> baseImpl_,
}
void RenderRasterSource::startRender(PaintParameters& parameters) {
+ algorithm::updateTileMasks(tilePyramid.getRenderTiles());
tilePyramid.startRender(parameters);
}
diff --git a/src/mbgl/tile/raster_tile.cpp b/src/mbgl/tile/raster_tile.cpp
index 8a92c40e4a..1260fd1edd 100644
--- a/src/mbgl/tile/raster_tile.cpp
+++ b/src/mbgl/tile/raster_tile.cpp
@@ -41,7 +41,7 @@ void RasterTile::setData(std::shared_ptr<const std::string> data,
worker.invoke(&RasterTileWorker::parse, data);
}
-void RasterTile::onParsed(std::unique_ptr<Bucket> result) {
+void RasterTile::onParsed(std::unique_ptr<RasterBucket> result) {
bucket = std::move(result);
loaded = true;
renderable = bucket ? true : false;
@@ -65,6 +65,12 @@ Bucket* RasterTile::getBucket(const style::Layer::Impl&) const {
return bucket.get();
}
+void RasterTile::setMask(TileMask&& mask) {
+ if (bucket) {
+ bucket->setMask(std::move(mask));
+ }
+}
+
void RasterTile::setNecessity(Necessity necessity) {
loader.setNecessity(necessity);
}
diff --git a/src/mbgl/tile/raster_tile.hpp b/src/mbgl/tile/raster_tile.hpp
index 51075a2dbc..28a27b2b37 100644
--- a/src/mbgl/tile/raster_tile.hpp
+++ b/src/mbgl/tile/raster_tile.hpp
@@ -9,6 +9,7 @@ namespace mbgl {
class Tileset;
class TileParameters;
+class RasterBucket;
namespace style {
class Layer;
@@ -33,7 +34,9 @@ public:
void upload(gl::Context&) override;
Bucket* getBucket(const style::Layer::Impl&) const override;
- void onParsed(std::unique_ptr<Bucket> result);
+ void setMask(TileMask&&) override;
+
+ void onParsed(std::unique_ptr<RasterBucket> result);
void onError(std::exception_ptr);
private:
@@ -44,7 +47,7 @@ private:
// Contains the Bucket object for the tile. Buckets are render
// objects and they get added by tile parsing operations.
- std::unique_ptr<Bucket> bucket;
+ std::unique_ptr<RasterBucket> bucket;
};
} // namespace mbgl
diff --git a/src/mbgl/tile/tile.hpp b/src/mbgl/tile/tile.hpp
index 1898f76849..a1ab6a84b7 100644
--- a/src/mbgl/tile/tile.hpp
+++ b/src/mbgl/tile/tile.hpp
@@ -6,6 +6,7 @@
#include <mbgl/util/feature.hpp>
#include <mbgl/util/tile_coordinate.hpp>
#include <mbgl/tile/tile_id.hpp>
+#include <mbgl/renderer/tile_mask.hpp>
#include <mbgl/renderer/bucket.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/storage/resource.hpp>
@@ -54,6 +55,7 @@ public:
virtual void setPlacementConfig(const PlacementConfig&) {}
virtual void setLayers(const std::vector<Immutable<style::Layer::Impl>>&) {}
+ virtual void setMask(TileMask&&) {}
virtual void queryRenderedFeatures(
std::unordered_map<std::string, std::vector<Feature>>& result,