Skip to content
This repository was archived by the owner on Aug 8, 2023. It is now read-only.

Commit c0efad5

Browse files
committed
[core] generate masks for raster tiles to avoid painting over children
1 parent 4dff517 commit c0efad5

13 files changed

+265
-9
lines changed

src/mbgl/gl/index_buffer.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class IndexVector {
2626
bool empty() const { return v.empty(); }
2727
void clear() { v.clear(); }
2828
const uint16_t* data() const { return v.data(); }
29+
const std::vector<uint16_t>& vector() const { return v; }
2930

3031
private:
3132
std::vector<uint16_t> v;

src/mbgl/gl/vertex_buffer.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class VertexVector {
2828
bool empty() const { return v.empty(); }
2929
void clear() { v.clear(); }
3030
const Vertex* data() const { return v.data(); }
31+
const std::vector<Vertex>& vector() const { return v; }
3132

3233
private:
3334
std::vector<Vertex> v;

src/mbgl/renderer/buckets/raster_bucket.cpp

+64-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ void RasterBucket::upload(gl::Context& context) {
2222
if (!texture) {
2323
texture = context.createTexture(*image);
2424
}
25-
if (!vertices.empty()) {
25+
if (!segments.empty()) {
2626
vertexBuffer = context.createVertexBuffer(std::move(vertices));
2727
indexBuffer = context.createIndexBuffer(std::move(indices));
2828
}
@@ -45,6 +45,69 @@ void RasterBucket::setImage(std::shared_ptr<PremultipliedImage> image_) {
4545
uploaded = false;
4646
}
4747

48+
void RasterBucket::setMask(TileMask&& mask_) {
49+
if (mask == mask_) {
50+
return;
51+
}
52+
53+
mask = std::move(mask_);
54+
clear();
55+
56+
if (mask == TileMask{ { 0, 0, 0 } }) {
57+
// We want to render the full tile, and keeping the segments/vertices/indices empty means
58+
// using the global shared buffers for covering the entire tile.
59+
return;
60+
}
61+
62+
// Create a new segment so that we will upload (empty) buffers even when there is nothing to
63+
// draw for this tile.
64+
segments.emplace_back(0, 0);
65+
66+
constexpr const uint16_t vertexLength = 4;
67+
68+
// Create the vertex buffer for the specified tile mask.
69+
for (const auto& id : mask) {
70+
// Create a quad for every masked tile.
71+
const int32_t vertexExtent = util::EXTENT >> id.z;
72+
const int32_t textureExtent = 32768 >> id.z;
73+
74+
const Point<int16_t> tlVertex = { static_cast<int16_t>(id.x * vertexExtent),
75+
static_cast<int16_t>(id.y * vertexExtent) };
76+
const Point<int16_t> brVertex = { static_cast<int16_t>(tlVertex.x + vertexExtent),
77+
static_cast<int16_t>(tlVertex.y + vertexExtent) };
78+
const Point<uint16_t> tlTexture = { static_cast<uint16_t>(id.x * textureExtent),
79+
static_cast<uint16_t>(id.y * textureExtent) };
80+
const Point<uint16_t> brTexture = { static_cast<uint16_t>(tlTexture.x + textureExtent),
81+
static_cast<uint16_t>(tlTexture.y + textureExtent) };
82+
83+
if (segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::max()) {
84+
// Move to a new segments because the old one can't hold the geometry.
85+
segments.emplace_back(vertices.vertexSize(), indices.indexSize());
86+
}
87+
88+
vertices.emplace_back(
89+
RasterProgram::layoutVertex({ tlVertex.x, tlVertex.y }, { tlTexture.x, tlTexture.y }));
90+
vertices.emplace_back(
91+
RasterProgram::layoutVertex({ brVertex.x, tlVertex.y }, { brTexture.x, tlTexture.y }));
92+
vertices.emplace_back(
93+
RasterProgram::layoutVertex({ tlVertex.x, brVertex.y }, { tlTexture.x, brTexture.y }));
94+
vertices.emplace_back(
95+
RasterProgram::layoutVertex({ brVertex.x, brVertex.y }, { brTexture.x, brTexture.y }));
96+
97+
auto& segment = segments.back();
98+
assert(segment.vertexLength <= std::numeric_limits<uint16_t>::max());
99+
const uint16_t offset = segment.vertexLength;
100+
101+
// 0, 1, 2
102+
// 1, 2, 3
103+
indices.emplace_back(offset, offset + 1, offset + 2);
104+
indices.emplace_back(offset + 1, offset + 2, offset + 3);
105+
106+
segment.vertexLength += vertexLength;
107+
segment.indexLength += 6;
108+
}
109+
}
110+
48111
bool RasterBucket::hasData() const {
49112
return !!image;
50113
}

src/mbgl/renderer/buckets/raster_bucket.hpp

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <mbgl/gl/vertex_buffer.hpp>
66
#include <mbgl/programs/raster_program.hpp>
77
#include <mbgl/renderer/bucket.hpp>
8+
#include <mbgl/renderer/tile_mask.hpp>
89
#include <mbgl/util/image.hpp>
910
#include <mbgl/util/mat4.hpp>
1011
#include <mbgl/util/optional.hpp>
@@ -21,8 +22,11 @@ class RasterBucket : public Bucket {
2122

2223
void clear();
2324
void setImage(std::shared_ptr<PremultipliedImage>);
25+
void setMask(TileMask&&);
26+
2427
std::shared_ptr<PremultipliedImage> image;
2528
optional<gl::Texture> texture;
29+
TileMask mask{ { 0, 0, 0 } };
2630

2731
// Bucket specific vertices are used for Image Sources only
2832
// Raster Tile Sources use the default buffers from Painter

src/mbgl/renderer/layers/render_raster_layer.cpp

+13-4
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,19 @@ void RenderRasterLayer::render(PaintParameters& parameters, RenderSource* source
135135
parameters.context.bindTexture(*bucket.texture, 0, gl::TextureFilter::Linear);
136136
parameters.context.bindTexture(*bucket.texture, 1, gl::TextureFilter::Linear);
137137

138-
draw(tile.matrix,
139-
parameters.staticData.rasterVertexBuffer,
140-
parameters.staticData.quadTriangleIndexBuffer,
141-
parameters.staticData.rasterSegments);
138+
if (bucket.vertexBuffer && bucket.indexBuffer && !bucket.segments.empty()) {
139+
// Draw only the parts of the tile that aren't drawn by another tile in the layer.
140+
draw(tile.matrix,
141+
*bucket.vertexBuffer,
142+
*bucket.indexBuffer,
143+
bucket.segments);
144+
} else {
145+
// Draw the full tile.
146+
draw(tile.matrix,
147+
parameters.staticData.rasterVertexBuffer,
148+
parameters.staticData.quadTriangleIndexBuffer,
149+
parameters.staticData.rasterSegments);
150+
}
142151
}
143152
}
144153
}

src/mbgl/renderer/render_tile.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ mat4 RenderTile::translatedClipMatrix(const std::array<float, 2>& translation,
5252
return translateVtxMatrix(nearClippedMatrix, translation, anchor, state, false);
5353
}
5454

55+
void RenderTile::setMask(TileMask&& mask) {
56+
tile.setMask(std::move(mask));
57+
}
58+
5559
void RenderTile::startRender(PaintParameters& parameters) {
5660
tile.upload(parameters.context);
5761

src/mbgl/renderer/render_tile.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <mbgl/util/mat4.hpp>
55
#include <mbgl/util/clip_id.hpp>
66
#include <mbgl/style/types.hpp>
7+
#include <mbgl/renderer/tile_mask.hpp>
78

89
#include <array>
910

@@ -36,6 +37,7 @@ class RenderTile final {
3637
style::TranslateAnchorType anchor,
3738
const TransformState&) const;
3839

40+
void setMask(TileMask&&);
3941
void startRender(PaintParameters&);
4042
void finishRender(PaintParameters&);
4143

src/mbgl/renderer/sources/render_raster_source.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <mbgl/renderer/sources/render_raster_source.hpp>
22
#include <mbgl/renderer/render_tile.hpp>
33
#include <mbgl/tile/raster_tile.hpp>
4+
#include <mbgl/algorithm/update_tile_masks.hpp>
45

56
namespace mbgl {
67

@@ -57,6 +58,7 @@ void RenderRasterSource::update(Immutable<style::Source::Impl> baseImpl_,
5758
}
5859

5960
void RenderRasterSource::startRender(PaintParameters& parameters) {
61+
algorithm::updateTileMasks(tilePyramid.getRenderTiles());
6062
tilePyramid.startRender(parameters);
6163
}
6264

src/mbgl/tile/raster_tile.cpp

+7-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ void RasterTile::setData(std::shared_ptr<const std::string> data,
4141
worker.invoke(&RasterTileWorker::parse, data);
4242
}
4343

44-
void RasterTile::onParsed(std::unique_ptr<Bucket> result) {
44+
void RasterTile::onParsed(std::unique_ptr<RasterBucket> result) {
4545
bucket = std::move(result);
4646
loaded = true;
4747
renderable = bucket ? true : false;
@@ -65,6 +65,12 @@ Bucket* RasterTile::getBucket(const style::Layer::Impl&) const {
6565
return bucket.get();
6666
}
6767

68+
void RasterTile::setMask(TileMask&& mask) {
69+
if (bucket) {
70+
bucket->setMask(std::move(mask));
71+
}
72+
}
73+
6874
void RasterTile::setNecessity(Necessity necessity) {
6975
loader.setNecessity(necessity);
7076
}

src/mbgl/tile/raster_tile.hpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace mbgl {
99

1010
class Tileset;
1111
class TileParameters;
12+
class RasterBucket;
1213

1314
namespace style {
1415
class Layer;
@@ -33,7 +34,9 @@ class RasterTile : public Tile {
3334
void upload(gl::Context&) override;
3435
Bucket* getBucket(const style::Layer::Impl&) const override;
3536

36-
void onParsed(std::unique_ptr<Bucket> result);
37+
void setMask(TileMask&&) override;
38+
39+
void onParsed(std::unique_ptr<RasterBucket> result);
3740
void onError(std::exception_ptr);
3841

3942
private:
@@ -44,7 +47,7 @@ class RasterTile : public Tile {
4447

4548
// Contains the Bucket object for the tile. Buckets are render
4649
// objects and they get added by tile parsing operations.
47-
std::unique_ptr<Bucket> bucket;
50+
std::unique_ptr<RasterBucket> bucket;
4851
};
4952

5053
} // namespace mbgl

src/mbgl/tile/tile.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <mbgl/util/feature.hpp>
77
#include <mbgl/util/tile_coordinate.hpp>
88
#include <mbgl/tile/tile_id.hpp>
9+
#include <mbgl/renderer/tile_mask.hpp>
910
#include <mbgl/renderer/bucket.hpp>
1011
#include <mbgl/tile/geometry_tile_data.hpp>
1112
#include <mbgl/storage/resource.hpp>
@@ -54,6 +55,7 @@ class Tile : private util::noncopyable {
5455

5556
virtual void setPlacementConfig(const PlacementConfig&) {}
5657
virtual void setLayers(const std::vector<Immutable<style::Layer::Impl>>&) {}
58+
virtual void setMask(TileMask&&) {}
5759

5860
virtual void queryRenderedFeatures(
5961
std::unordered_map<std::string, std::vector<Feature>>& result,

0 commit comments

Comments
 (0)