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

Commit

Permalink
[core] generate masks for raster tiles to avoid painting over children
Browse files Browse the repository at this point in the history
  • Loading branch information
kkaefer committed Jul 20, 2017
1 parent 794cb09 commit 1eff949
Show file tree
Hide file tree
Showing 13 changed files with 265 additions and 9 deletions.
1 change: 1 addition & 0 deletions src/mbgl/gl/index_buffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class IndexVector {
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;
Expand Down
1 change: 1 addition & 0 deletions src/mbgl/gl/vertex_buffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class VertexVector {
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;
Expand Down
65 changes: 64 additions & 1 deletion src/mbgl/renderer/buckets/raster_bucket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
Expand All @@ -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;
}
Expand Down
4 changes: 4 additions & 0 deletions src/mbgl/renderer/buckets/raster_bucket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -21,8 +22,11 @@ class RasterBucket : public Bucket {

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
Expand Down
17 changes: 13 additions & 4 deletions src/mbgl/renderer/layers/render_raster_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/mbgl/renderer/render_tile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 2 additions & 0 deletions src/mbgl/renderer/render_tile.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down Expand Up @@ -36,6 +37,7 @@ class RenderTile final {
style::TranslateAnchorType anchor,
const TransformState&) const;

void setMask(TileMask&&);
void startRender(PaintParameters&);
void finishRender(PaintParameters&);

Expand Down
2 changes: 2 additions & 0 deletions src/mbgl/renderer/sources/render_raster_source.cpp
Original file line number Diff line number Diff line change
@@ -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 {

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

void RenderRasterSource::startRender(PaintParameters& parameters) {
algorithm::updateTileMasks(tilePyramid.getRenderTiles());
tilePyramid.startRender(parameters);
}

Expand Down
8 changes: 7 additions & 1 deletion src/mbgl/tile/raster_tile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
}
Expand Down
7 changes: 5 additions & 2 deletions src/mbgl/tile/raster_tile.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace mbgl {

class Tileset;
class TileParameters;
class RasterBucket;

namespace style {
class Layer;
Expand All @@ -33,7 +34,9 @@ class RasterTile : public Tile {
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:
Expand All @@ -44,7 +47,7 @@ class RasterTile : public Tile {

// 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
2 changes: 2 additions & 0 deletions src/mbgl/tile/tile.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -54,6 +55,7 @@ class Tile : private util::noncopyable {

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,
Expand Down
Loading

0 comments on commit 1eff949

Please sign in to comment.