summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDane Springmeyer <dane@mapbox.com>2014-10-29 21:40:02 -0400
committerDane Springmeyer <dane@mapbox.com>2014-10-29 21:40:02 -0400
commit761f753cbdba350411785ce4e82d4e843bf03224 (patch)
treeb4c33738c6d5afe8a93a830e436d82ce8570e4f9 /src
parent9dbcf18d14c0054b9d090d8921c6caa01979382c (diff)
parent88361f02fa9df3d643ed6d5c3fc45b6898f0f32f (diff)
downloadqtlocation-mapboxgl-761f753cbdba350411785ce4e82d4e843bf03224.tar.gz
merge with mbgl-config
Diffstat (limited to 'src')
-rw-r--r--src/geometry/sprite_atlas.cpp53
-rw-r--r--src/map/map.cpp170
-rw-r--r--src/map/raster_tile_data.cpp2
-rw-r--r--src/map/tile_data.cpp10
-rw-r--r--src/map/tile_parser.cpp8
-rw-r--r--src/map/transform.cpp66
-rw-r--r--src/map/transform_state.cpp11
-rw-r--r--src/map/vector_tile_data.cpp23
-rw-r--r--src/renderer/painter.cpp192
-rw-r--r--src/renderer/painter_debug.cpp10
-rw-r--r--src/renderer/painter_fill.cpp18
-rw-r--r--src/renderer/painter_line.cpp25
-rw-r--r--src/renderer/painter_raster.cpp7
-rw-r--r--src/renderer/painter_symbol.cpp65
-rw-r--r--src/renderer/symbol_bucket.cpp5
15 files changed, 323 insertions, 342 deletions
diff --git a/src/geometry/sprite_atlas.cpp b/src/geometry/sprite_atlas.cpp
index 22e6a29a0b..5271122919 100644
--- a/src/geometry/sprite_atlas.cpp
+++ b/src/geometry/sprite_atlas.cpp
@@ -24,7 +24,7 @@ SpriteAtlas::SpriteAtlas(dimension width_, dimension height_)
bool SpriteAtlas::resize(const float newRatio) {
if (pixelRatio == newRatio) return false;
- std::lock_guard<std::mutex> lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
const float oldRatio = pixelRatio;
pixelRatio = newRatio;
@@ -104,15 +104,15 @@ Rect<SpriteAtlas::dimension> SpriteAtlas::allocateImage(size_t pixel_width, size
return rect;
}
-Rect<SpriteAtlas::dimension> SpriteAtlas::getImage(const std::string &name, const Sprite &sprite) {
- std::lock_guard<std::mutex> lock(mtx);
+Rect<SpriteAtlas::dimension> SpriteAtlas::getImage(const std::string& name) {
+ std::lock_guard<std::recursive_mutex> lock(mtx);
auto rect_it = images.find(name);
if (rect_it != images.end()) {
return rect_it->second;
}
- const SpritePosition &pos = sprite.getSpritePosition(name);
+ const SpritePosition &pos = sprite->getSpritePosition(name);
if (!pos.width || !pos.height) {
return Rect<dimension> { 0, 0, 0, 0 };
}
@@ -127,16 +127,17 @@ Rect<SpriteAtlas::dimension> SpriteAtlas::getImage(const std::string &name, cons
images.emplace(name, rect);
- copy(rect, pos, sprite);
+ copy(rect, pos);
return rect;
}
-SpriteAtlasPosition SpriteAtlas::getPosition(const std::string& name, const Sprite& sprite, bool repeating) {
+SpriteAtlasPosition SpriteAtlas::getPosition(const std::string& name, bool repeating) {
+ std::lock_guard<std::recursive_mutex> lock(mtx);
// `repeating` indicates that the image will be used in a repeating pattern
// repeating pattern images are assumed to have a 1px padding that mirrors the opposite edge
// positions for repeating images are adjusted to exclude the edge
- Rect<dimension> rect = getImage(name, sprite);
+ Rect<dimension> rect = getImage(name);
const int r = repeating ? 1 : 0;
return SpriteAtlasPosition {
{{ float(rect.w) / pixelRatio, float(rect.h) / pixelRatio }},
@@ -145,11 +146,6 @@ SpriteAtlasPosition SpriteAtlas::getPosition(const std::string& name, const Spri
};
}
-Rect<SpriteAtlas::dimension> SpriteAtlas::waitForImage(const std::string &name, const Sprite &sprite) {
- sprite.waitUntilLoaded();
- return getImage(name, sprite);
-}
-
void SpriteAtlas::allocate() {
if (!data) {
dimension w = static_cast<dimension>(width * pixelRatio);
@@ -159,15 +155,15 @@ void SpriteAtlas::allocate() {
}
}
-void SpriteAtlas::copy(const Rect<dimension> &dst, const SpritePosition &src, const Sprite &sprite) {
- if (!sprite.raster) return;
- const uint32_t *src_img = reinterpret_cast<const uint32_t *>(sprite.raster->getData());
+void SpriteAtlas::copy(const Rect<dimension>& dst, const SpritePosition& src) {
+ if (!sprite->raster) return;
+ const uint32_t *src_img = reinterpret_cast<const uint32_t *>(sprite->raster->getData());
allocate();
uint32_t *dst_img = reinterpret_cast<uint32_t *>(data);
copy_bitmap(
/* source buffer */ src_img,
- /* source stride */ sprite.raster->getWidth(),
+ /* source stride */ sprite->raster->getWidth(),
/* source x */ src.x,
/* source y */ src.y,
/* dest buffer */ dst_img,
@@ -181,14 +177,16 @@ void SpriteAtlas::copy(const Rect<dimension> &dst, const SpritePosition &src, co
dirty = true;
}
+void SpriteAtlas::setSprite(util::ptr<Sprite> sprite_) {
+ std::lock_guard<std::recursive_mutex> lock(mtx);
+
+ sprite = sprite_;
-void SpriteAtlas::update(const Sprite &sprite) {
- if (!sprite.isLoaded()) return;
+ if (!sprite->isLoaded()) return;
- SpriteAtlas &atlas = *this;
- util::erase_if(uninitialized, [&sprite, &atlas](const std::string &name) {
- Rect<dimension> dst = atlas.getImage(name, sprite);
- const SpritePosition &src = sprite.getSpritePosition(name);
+ util::erase_if(uninitialized, [this](const std::string &name) {
+ Rect<dimension> dst = getImage(name);
+ const SpritePosition& src = sprite->getSpritePosition(name);
if (!src) {
if (debug::spriteWarnings) {
fprintf(stderr, "[WARNING] sprite doesn't have image with name '%s'\n", name.c_str());
@@ -196,8 +194,8 @@ void SpriteAtlas::update(const Sprite &sprite) {
return true;
}
- if (src.width == dst.w * atlas.pixelRatio && src.height == dst.h * atlas.pixelRatio && src.pixelRatio == atlas.pixelRatio) {
- atlas.copy(dst, src, sprite);
+ if (src.width == dst.w * pixelRatio && src.height == dst.h * pixelRatio && src.pixelRatio == pixelRatio) {
+ copy(dst, src);
return true;
} else {
if (debug::spriteWarnings) {
@@ -228,7 +226,7 @@ void SpriteAtlas::bind(bool linear) {
}
if (dirty) {
- std::lock_guard<std::mutex> lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
allocate();
if (first) {
@@ -257,15 +255,12 @@ void SpriteAtlas::bind(bool linear) {
);
}
-#if defined(DEBUG)
- // platform::show_color_debug_image("Sprite Atlas", reinterpret_cast<char *>(data), width, height, width * pixelRatio, height * pixelRatio);
-#endif
dirty = false;
}
};
SpriteAtlas::~SpriteAtlas() {
- std::lock_guard<std::mutex> lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
glDeleteTextures(1, &texture);
texture = 0;
diff --git a/src/map/map.cpp b/src/map/map.cpp
index 2f0dceb427..d0a279b648 100644
--- a/src/map/map.cpp
+++ b/src/map/map.cpp
@@ -31,7 +31,7 @@
using namespace mbgl;
Map::Map(View& view_)
- : loop(std::make_shared<uv::loop>()),
+ : loop(std::make_unique<uv::loop>()),
thread(std::make_unique<uv::thread>()),
async_terminate(new uv_async_t()),
async_render(new uv_async_t()),
@@ -41,13 +41,12 @@ Map::Map(View& view_)
main_thread(uv_thread_self()),
#endif
transform(view_),
- glyphAtlas(std::make_shared<GlyphAtlas>(1024, 1024)),
- spriteAtlas(std::make_shared<SpriteAtlas>(512, 512)),
+ glyphAtlas(1024, 1024),
+ spriteAtlas(512, 512),
texturepool(std::make_shared<Texturepool>()),
- painter(*this) {
-
+ painter(spriteAtlas, glyphAtlas)
+{
view.initialize(this);
-
// Make sure that we're doing an initial drawing in all cases.
is_clean.clear();
is_rendered.clear();
@@ -62,9 +61,7 @@ Map::~Map() {
// Explicitly reset all pointers.
texturepool.reset();
sprite.reset();
- spriteAtlas.reset();
glyphStore.reset();
- glyphAtlas.reset();
style.reset();
fileSource.reset();
workers.reset();
@@ -598,15 +595,6 @@ void Map::updateTiles() {
}
}
-void Map::updateRenderState() {
- // Update all clipping IDs.
- ClipIDGenerator generator;
- for (const util::ptr<StyleSource> &source : getActiveSources()) {
- generator.update(source->source->getLoadedTiles());
- source->source->updateMatrices(painter.projMatrix, state);
- }
-}
-
void Map::prepare() {
if (!fileSource) {
fileSource = std::make_shared<FileSource>(**loop, platform::defaultCacheDatabase());
@@ -645,8 +633,8 @@ void Map::prepare() {
style->updateProperties(state.getNormalizedZoom(), animationTime);
// Allow the sprite atlas to potentially pull new sprite images if needed.
- spriteAtlas->resize(state.getPixelRatio());
- spriteAtlas->update(*getSprite());
+ spriteAtlas.resize(state.getPixelRatio());
+ spriteAtlas.setSprite(getSprite());
updateTiles();
}
@@ -654,152 +642,12 @@ void Map::prepare() {
void Map::render() {
view.make_active();
- painter.clear();
-
- painter.resize();
-
- painter.changeMatrix();
-
- updateRenderState();
-
- painter.drawClippingMasks(getActiveSources());
-
- painter.frameHistory.record(getAnimationTime(), getState().getNormalizedZoom());
-
- // Actually render the layers
- if (debug::renderTree) { std::cout << "{" << std::endl; indent++; }
- renderLayers(style->layers);
- if (debug::renderTree) { std::cout << "}" << std::endl; indent--; }
-
- // Finalize the rendering, e.g. by calling debug render calls per tile.
- // This guarantees that we have at least one function per tile called.
- // When only rendering layers via the stylesheet, it's possible that we don't
- // ever visit a tile during rendering.
- for (const util::ptr<StyleSource> &source : getActiveSources()) {
- source->source->finishRender(painter);
- }
-
+ painter.render(*style, activeSources,
+ state, animationTime);
// Schedule another rerender when we definitely need a next frame.
if (transform.needsTransition() || style->hasTransitions()) {
update();
}
- glFlush();
-
view.make_inactive();
}
-
-void Map::renderLayers(util::ptr<StyleLayerGroup> group) {
- if (!group) {
- // Make sure that we actually do have a layer group.
- return;
- }
-
- // TODO: Correctly compute the number of layers recursively beforehand.
- float strata_thickness = 1.0f / (group->layers.size() + 1);
-
- // - FIRST PASS ------------------------------------------------------------
- // Render everything top-to-bottom by using reverse iterators. Render opaque
- // objects first.
-
- if (debug::renderTree) {
- std::cout << std::string(indent++ * 4, ' ') << "OPAQUE {" << std::endl;
- }
- int i = 0;
- for (auto it = group->layers.rbegin(), end = group->layers.rend(); it != end; ++it, ++i) {
- painter.setOpaque();
- painter.setStrata(i * strata_thickness);
- renderLayer(*it, RenderPass::Opaque);
- }
- if (debug::renderTree) {
- std::cout << std::string(--indent * 4, ' ') << "}" << std::endl;
- }
-
- // - SECOND PASS -----------------------------------------------------------
- // Make a second pass, rendering translucent objects. This time, we render
- // bottom-to-top.
- if (debug::renderTree) {
- std::cout << std::string(indent++ * 4, ' ') << "TRANSLUCENT {" << std::endl;
- }
- --i;
- for (auto it = group->layers.begin(), end = group->layers.end(); it != end; ++it, --i) {
- painter.setTranslucent();
- painter.setStrata(i * strata_thickness);
- renderLayer(*it, RenderPass::Translucent);
- }
- if (debug::renderTree) {
- std::cout << std::string(--indent * 4, ' ') << "}" << std::endl;
- }
-}
-
-void Map::renderLayer(util::ptr<StyleLayer> layer_desc, RenderPass pass, const Tile::ID* id, const mat4* matrix) {
- if (layer_desc->type == StyleLayerType::Background) {
- // This layer defines a background color/image.
-
- if (debug::renderTree) {
- std::cout << std::string(indent * 4, ' ') << "- " << layer_desc->id << " ("
- << layer_desc->type << ")" << std::endl;
- }
-
- painter.renderBackground(layer_desc);
- } else {
- // This is a singular layer.
- if (!layer_desc->bucket) {
- fprintf(stderr, "[WARNING] layer '%s' is missing bucket\n", layer_desc->id.c_str());
- return;
- }
-
- if (!layer_desc->bucket->style_source) {
- fprintf(stderr, "[WARNING] can't find source for layer '%s'\n", layer_desc->id.c_str());
- return;
- }
-
- StyleSource &style_source = *layer_desc->bucket->style_source;
-
- // Skip this layer if there is no data.
- if (!style_source.source) {
- return;
- }
-
- // Skip this layer if it's outside the range of min/maxzoom.
- // This may occur when there /is/ a bucket created for this layer, but the min/max-zoom
- // is set to a fractional value, or value that is larger than the source maxzoom.
- const double zoom = state.getZoom();
- if (layer_desc->bucket->min_zoom > zoom ||
- layer_desc->bucket->max_zoom <= zoom) {
- return;
- }
-
- // Abort early if we can already deduce from the bucket type that
- // we're not going to render anything anyway during this pass.
- switch (layer_desc->type) {
- case StyleLayerType::Fill:
- if (!layer_desc->getProperties<FillProperties>().isVisible()) return;
- break;
- case StyleLayerType::Line:
- if (pass == RenderPass::Opaque) return;
- if (!layer_desc->getProperties<LineProperties>().isVisible()) return;
- break;
- case StyleLayerType::Symbol:
- if (pass == RenderPass::Opaque) return;
- if (!layer_desc->getProperties<SymbolProperties>().isVisible()) return;
- break;
- case StyleLayerType::Raster:
- if (pass == RenderPass::Opaque) return;
- if (!layer_desc->getProperties<RasterProperties>().isVisible()) return;
- break;
- default:
- break;
- }
-
- if (debug::renderTree) {
- std::cout << std::string(indent * 4, ' ') << "- " << layer_desc->id << " ("
- << layer_desc->type << ")" << std::endl;
- }
- if (!id) {
- style_source.source->render(painter, layer_desc);
- } else {
- style_source.source->render(painter, layer_desc, *id, *matrix);
- }
- }
-}
diff --git a/src/map/raster_tile_data.cpp b/src/map/raster_tile_data.cpp
index 99ca327fe7..fbef805f2c 100644
--- a/src/map/raster_tile_data.cpp
+++ b/src/map/raster_tile_data.cpp
@@ -29,6 +29,6 @@ void RasterTileData::render(Painter &painter, util::ptr<StyleLayer> layer_desc,
bucket.render(painter, layer_desc, id, matrix);
}
-bool RasterTileData::hasData(util::ptr<StyleLayer> /*layer_desc*/) const {
+bool RasterTileData::hasData(StyleLayer const& /*layer_desc*/) const {
return bucket.hasData();
}
diff --git a/src/map/tile_data.cpp b/src/map/tile_data.cpp
index 7e4d1a1de1..bb3573ce2d 100644
--- a/src/map/tile_data.cpp
+++ b/src/map/tile_data.cpp
@@ -79,11 +79,8 @@ void TileData::cancel() {
}
}
-void TileData::beforeParse() {}
-
-void TileData::reparse() {
- beforeParse();
-
+void TileData::reparse()
+{
// We're creating a new work request. The work request deletes itself after it executed
// the after work handler
new uv::work<util::ptr<TileData>>(
@@ -92,10 +89,7 @@ void TileData::reparse() {
tile->parse();
},
[](util::ptr<TileData> &tile) {
- tile->afterParse();
tile->map.update();
},
shared_from_this());
}
-
-void TileData::afterParse() {}
diff --git a/src/map/tile_parser.cpp b/src/map/tile_parser.cpp
index 235151cd47..72f97096a0 100644
--- a/src/map/tile_parser.cpp
+++ b/src/map/tile_parser.cpp
@@ -39,9 +39,9 @@ TileParser::~TileParser() = default;
TileParser::TileParser(const std::string &data, VectorTileData &tile_,
const util::ptr<const Style> &style_,
- const util::ptr<GlyphAtlas> &glyphAtlas_,
+ GlyphAtlas & glyphAtlas_,
const util::ptr<GlyphStore> &glyphStore_,
- const util::ptr<SpriteAtlas> &spriteAtlas_,
+ SpriteAtlas & spriteAtlas_,
const util::ptr<Sprite> &sprite_)
: vector_data(pbf((const uint8_t *)data.data(), data.size())),
tile(tile_),
@@ -53,9 +53,7 @@ TileParser::TileParser(const std::string &data, VectorTileData &tile_,
collision(std::make_unique<Collision>(tile.id.z, 4096, tile.source->tile_size, tile.depth)) {
assert(&tile != nullptr);
assert(style);
- assert(glyphAtlas);
assert(glyphStore);
- assert(spriteAtlas);
assert(sprite);
assert(collision);
}
@@ -177,7 +175,7 @@ std::unique_ptr<Bucket> TileParser::createLineBucket(const VectorTileLayer& laye
std::unique_ptr<Bucket> TileParser::createSymbolBucket(const VectorTileLayer& layer, const FilterExpression &filter, const StyleBucketSymbol &symbol) {
std::unique_ptr<SymbolBucket> bucket = std::make_unique<SymbolBucket>(symbol, *collision);
- bucket->addFeatures(layer, filter, tile.id, *spriteAtlas, *sprite, *glyphAtlas, *glyphStore);
+ bucket->addFeatures(layer, filter, tile.id, spriteAtlas, *sprite, glyphAtlas, *glyphStore);
return obsolete() ? nullptr : std::move(bucket);
}
diff --git a/src/map/transform.cpp b/src/map/transform.cpp
index b42f24a83d..25aacd4838 100644
--- a/src/map/transform.cpp
+++ b/src/map/transform.cpp
@@ -5,28 +5,27 @@
#include <mbgl/util/std.hpp>
#include <mbgl/util/math.hpp>
#include <mbgl/util/time.hpp>
-#include <mbgl/util/uv_detail.hpp>
#include <mbgl/util/transition.hpp>
#include <mbgl/platform/platform.hpp>
+
#include <cstdio>
using namespace mbgl;
const double D2R = M_PI / 180.0;
-const double R2D = 180.0 / M_PI;
const double M2PI = 2 * M_PI;
const double MIN_ROTATE_SCALE = 8;
-Transform::Transform(View &view_) : view(view_), mtx(std::make_unique<uv::rwlock>()) {
- setScale(current.scale);
- setAngle(current.angle);
+Transform::Transform(View &view_)
+ : view(view_)
+{
}
#pragma mark - Map View
bool Transform::resize(const uint16_t w, const uint16_t h, const float ratio,
const uint16_t fb_w, const uint16_t fb_h) {
- uv::writelock lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
if (final.width != w || final.height != h || final.pixelRatio != ratio ||
final.framebuffer[0] != fb_w || final.framebuffer[1] != fb_h) {
@@ -52,7 +51,7 @@ bool Transform::resize(const uint16_t w, const uint16_t h, const float ratio,
#pragma mark - Position
void Transform::moveBy(const double dx, const double dy, const timestamp duration) {
- uv::writelock lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
_moveBy(dx, dy, duration);
}
@@ -94,7 +93,7 @@ void Transform::_moveBy(const double dx, const double dy, const timestamp durati
}
void Transform::setLonLat(const double lon, const double lat, const timestamp duration) {
- uv::writelock lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
const double f = std::fmin(std::fmax(std::sin(D2R * lat), -0.9999), 0.9999);
double xn = -lon * Bc;
@@ -105,7 +104,7 @@ void Transform::setLonLat(const double lon, const double lat, const timestamp du
void Transform::setLonLatZoom(const double lon, const double lat, const double zoom,
const timestamp duration) {
- uv::writelock lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
double new_scale = std::pow(2.0, zoom);
@@ -121,21 +120,20 @@ void Transform::setLonLatZoom(const double lon, const double lat, const double z
}
void Transform::getLonLat(double &lon, double &lat) const {
- uv::readlock lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
- lon = -final.x / Bc;
- lat = R2D * (2 * std::atan(std::exp(final.y / Cc)) - 0.5 * M_PI);
+ final.getLonLat(lon, lat);
}
void Transform::getLonLatZoom(double &lon, double &lat, double &zoom) const {
- getLonLat(lon, lat);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
- uv::readlock lock(mtx);
+ getLonLat(lon, lat);
zoom = getZoom();
}
void Transform::startPanning() {
- uv::writelock lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
_clearPanning();
@@ -147,7 +145,7 @@ void Transform::startPanning() {
}
void Transform::stopPanning() {
- uv::writelock lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
_clearPanning();
}
@@ -163,7 +161,7 @@ void Transform::_clearPanning() {
#pragma mark - Zoom
void Transform::scaleBy(const double ds, const double cx, const double cy, const timestamp duration) {
- uv::writelock lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
// clamp scale to min/max values
double new_scale = current.scale * ds;
@@ -178,31 +176,31 @@ void Transform::scaleBy(const double ds, const double cx, const double cy, const
void Transform::setScale(const double scale, const double cx, const double cy,
const timestamp duration) {
- uv::writelock lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
_setScale(scale, cx, cy, duration);
}
void Transform::setZoom(const double zoom, const timestamp duration) {
- uv::writelock lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
_setScale(std::pow(2.0, zoom), -1, -1, duration);
}
double Transform::getZoom() const {
- uv::readlock lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
return std::log(final.scale) / M_LN2;
}
double Transform::getScale() const {
- uv::readlock lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
return final.scale;
}
void Transform::startScaling() {
- uv::writelock lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
_clearScaling();
@@ -214,7 +212,7 @@ void Transform::startScaling() {
}
void Transform::stopScaling() {
- uv::writelock lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
_clearScaling();
}
@@ -333,7 +331,7 @@ void Transform::constrain(double& scale, double& y) const {
void Transform::rotateBy(const double start_x, const double start_y, const double end_x,
const double end_y, const timestamp duration) {
- uv::writelock lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
double center_x = current.width / 2, center_y = current.height / 2;
@@ -363,13 +361,13 @@ void Transform::rotateBy(const double start_x, const double start_y, const doubl
}
void Transform::setAngle(const double new_angle, const timestamp duration) {
- uv::writelock lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
_setAngle(new_angle, duration);
}
void Transform::setAngle(const double new_angle, const double cx, const double cy) {
- uv::writelock lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
double dx = 0, dy = 0;
@@ -418,13 +416,13 @@ void Transform::_setAngle(double new_angle, const timestamp duration) {
}
double Transform::getAngle() const {
- uv::readlock lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
return final.angle;
}
void Transform::startRotating() {
- uv::writelock lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
_clearRotating();
@@ -436,7 +434,7 @@ void Transform::startRotating() {
}
void Transform::stopRotating() {
- uv::writelock lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
_clearRotating();
}
@@ -458,13 +456,13 @@ bool Transform::canRotate() {
#pragma mark - Transition
bool Transform::needsTransition() const {
- uv::readlock lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
return !transitions.empty();
}
void Transform::updateTransitions(const timestamp now) {
- uv::writelock lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
transitions.remove_if([now](const util::ptr<util::transition> &transition) {
return transition->update(now) == util::transition::complete;
@@ -472,7 +470,7 @@ void Transform::updateTransitions(const timestamp now) {
}
void Transform::cancelTransitions() {
- uv::writelock lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
transitions.clear();
}
@@ -480,13 +478,13 @@ void Transform::cancelTransitions() {
#pragma mark - Transform state
const TransformState Transform::currentState() const {
- uv::readlock lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
return current;
}
const TransformState Transform::finalState() const {
- uv::readlock lock(mtx);
+ std::lock_guard<std::recursive_mutex> lock(mtx);
return final;
}
diff --git a/src/map/transform_state.cpp b/src/map/transform_state.cpp
index 0a858bce6a..afc5b59ef1 100644
--- a/src/map/transform_state.cpp
+++ b/src/map/transform_state.cpp
@@ -3,6 +3,8 @@
using namespace mbgl;
+const double R2D = 180.0 / M_PI;
+
#pragma mark - Matrix
void TransformState::matrixFor(mat4& matrix, const Tile::ID& id) const {
@@ -108,6 +110,15 @@ std::array<float, 2> TransformState::locationCoordinate(float lon, float lat) co
}};
}
+void TransformState::getLonLat(double &lon, double &lat) const {
+ const double s = scale * util::tileSize;
+ const double Bc = s / 360;
+ const double Cc = s / (2 * M_PI);
+
+ lon = -x / Bc;
+ lat = R2D * (2 * std::atan(std::exp(y / Cc)) - 0.5 * M_PI);
+}
+
#pragma mark - Zoom
diff --git a/src/map/vector_tile_data.cpp b/src/map/vector_tile_data.cpp
index b94bc66dea..80ad3a3fce 100644
--- a/src/map/vector_tile_data.cpp
+++ b/src/map/vector_tile_data.cpp
@@ -14,16 +14,9 @@ VectorTileData::VectorTileData(Tile::ID id_, Map &map_, const util::ptr<SourceIn
}
VectorTileData::~VectorTileData() {
- util::ptr<GlyphAtlas> glyphAtlas = map.getGlyphAtlas();
- if (glyphAtlas) {
- glyphAtlas->removeGlyphs(id.to_uint64());
- }
+ map.getGlyphAtlas().removeGlyphs(id.to_uint64());
}
-void VectorTileData::beforeParse() {
-
- parser = std::make_unique<TileParser>(data, *this, map.getStyle(), map.getGlyphAtlas(), map.getGlyphStore(), map.getSpriteAtlas(), map.getSprite());
-}
void VectorTileData::parse() {
if (state != State::loaded) {
@@ -34,7 +27,9 @@ void VectorTileData::parse() {
// Parsing creates state that is encapsulated in TileParser. While parsing,
// the TileParser object writes results into this objects. All other state
// is going to be discarded afterwards.
- parser->parse();
+ TileParser parser(data, *this, map.getStyle(), map.getGlyphAtlas(),
+ map.getGlyphStore(), map.getSpriteAtlas(), map.getSprite());
+ parser.parse();
} catch (const std::exception& ex) {
#if defined(DEBUG)
fprintf(stderr, "[%p] exception [%d/%d/%d]... failed: %s\n", this, id.z, id.x, id.y, ex.what());
@@ -48,10 +43,6 @@ void VectorTileData::parse() {
}
}
-void VectorTileData::afterParse() {
- parser.reset();
-}
-
void VectorTileData::render(Painter &painter, util::ptr<StyleLayer> layer_desc, const mat4 &matrix) {
if (state == State::parsed && layer_desc->bucket) {
auto databucket_it = buckets.find(layer_desc->bucket->name);
@@ -62,9 +53,9 @@ void VectorTileData::render(Painter &painter, util::ptr<StyleLayer> layer_desc,
}
}
-bool VectorTileData::hasData(util::ptr<StyleLayer> layer_desc) const {
- if (state == State::parsed && layer_desc->bucket) {
- auto databucket_it = buckets.find(layer_desc->bucket->name);
+bool VectorTileData::hasData(StyleLayer const& layer_desc) const {
+ if (state == State::parsed && layer_desc.bucket) {
+ auto databucket_it = buckets.find(layer_desc.bucket->name);
if (databucket_it != buckets.end()) {
assert(databucket_it->second);
return databucket_it->second->hasData();
diff --git a/src/renderer/painter.cpp b/src/renderer/painter.cpp
index 228783b3c3..960168bd4a 100644
--- a/src/renderer/painter.cpp
+++ b/src/renderer/painter.cpp
@@ -1,7 +1,8 @@
#include <mbgl/renderer/painter.hpp>
-#include <mbgl/map/map.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/style_layer.hpp>
+#include <mbgl/style/style_layer_group.hpp>
+#include <mbgl/style/style_bucket.hpp>
#include <mbgl/util/std.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/time.hpp>
@@ -9,6 +10,7 @@
#include <mbgl/util/constants.hpp>
#include <mbgl/util/mat3.hpp>
#include <mbgl/geometry/sprite_atlas.hpp>
+#include <mbgl/map/source.hpp>
#if defined(DEBUG)
#include <mbgl/util/stopwatch.hpp>
@@ -16,13 +18,16 @@
#include <cassert>
#include <algorithm>
+#include <iostream>
using namespace mbgl;
#define BUFFER_OFFSET(i) ((char *)nullptr + (i))
-Painter::Painter(Map &map_)
- : map(map_) {
+Painter::Painter(SpriteAtlas& spriteAtlas_, GlyphAtlas& glyphAtlas_)
+ : spriteAtlas(spriteAtlas_)
+ , glyphAtlas(glyphAtlas_)
+{
}
Painter::~Painter() {
@@ -109,7 +114,6 @@ void Painter::terminate() {
}
void Painter::resize() {
- const TransformState &state = map.getState();
if (gl_viewport != state.getFramebufferDimensions()) {
gl_viewport = state.getFramebufferDimensions();
assert(gl_viewport[0] > 0 && gl_viewport[1] > 0);
@@ -152,12 +156,12 @@ void Painter::depthRange(const float near, const float far) {
void Painter::changeMatrix() {
// Initialize projection matrix
- matrix::ortho(projMatrix, 0, map.getState().getWidth(), map.getState().getHeight(), 0, 0, 1);
+ matrix::ortho(projMatrix, 0, state.getWidth(), state.getHeight(), 0, 0, 1);
// The extrusion matrix.
matrix::identity(extrudeMatrix);
matrix::multiply(extrudeMatrix, projMatrix, extrudeMatrix);
- matrix::rotate_z(extrudeMatrix, extrudeMatrix, map.getState().getAngle());
+ matrix::rotate_z(extrudeMatrix, extrudeMatrix, state.getAngle());
// The native matrix is a 1:1 matrix that paints the coordinates at the
// same screen position as the vertex specifies.
@@ -200,9 +204,159 @@ void Painter::prepareTile(const Tile& tile) {
glStencilFunc(GL_EQUAL, ref, mask);
}
+void Painter::render(const Style& style, const std::set<util::ptr<StyleSource>>& sources,
+ TransformState state_, timestamp time) {
+ state = state_;
+
+ clear();
+ resize();
+ changeMatrix();
+
+ // Update all clipping IDs.
+ ClipIDGenerator generator;
+ for (const util::ptr<StyleSource> &source : sources) {
+ generator.update(source->source->getLoadedTiles());
+ source->source->updateMatrices(projMatrix, state);
+ }
+
+ drawClippingMasks(sources);
+
+ frameHistory.record(time, state.getNormalizedZoom());
+
+ // Actually render the layers
+ if (debug::renderTree) { std::cout << "{" << std::endl; indent++; }
+ renderLayers(style.layers);
+ if (debug::renderTree) { std::cout << "}" << std::endl; indent--; }
+
+ // Finalize the rendering, e.g. by calling debug render calls per tile.
+ // This guarantees that we have at least one function per tile called.
+ // When only rendering layers via the stylesheet, it's possible that we don't
+ // ever visit a tile during rendering.
+ for (const util::ptr<StyleSource> &source : sources) {
+ source->source->finishRender(*this);
+ }
+
+ glFlush();
+}
+
+void Painter::renderLayers(util::ptr<StyleLayerGroup> group) {
+ if (!group) {
+ // Make sure that we actually do have a layer group.
+ return;
+ }
+
+ // TODO: Correctly compute the number of layers recursively beforehand.
+ float strata_thickness = 1.0f / (group->layers.size() + 1);
+
+ // - FIRST PASS ------------------------------------------------------------
+ // Render everything top-to-bottom by using reverse iterators. Render opaque
+ // objects first.
+
+ if (debug::renderTree) {
+ std::cout << std::string(indent++ * 4, ' ') << "OPAQUE {" << std::endl;
+ }
+ int i = 0;
+ for (auto it = group->layers.rbegin(), end = group->layers.rend(); it != end; ++it, ++i) {
+ setOpaque();
+ setStrata(i * strata_thickness);
+ renderLayer(*it);
+ }
+ if (debug::renderTree) {
+ std::cout << std::string(--indent * 4, ' ') << "}" << std::endl;
+ }
+
+ // - SECOND PASS -----------------------------------------------------------
+ // Make a second pass, rendering translucent objects. This time, we render
+ // bottom-to-top.
+ if (debug::renderTree) {
+ std::cout << std::string(indent++ * 4, ' ') << "TRANSLUCENT {" << std::endl;
+ }
+ --i;
+ for (auto it = group->layers.begin(), end = group->layers.end(); it != end; ++it, --i) {
+ setTranslucent();
+ setStrata(i * strata_thickness);
+ renderLayer(*it);
+ }
+ if (debug::renderTree) {
+ std::cout << std::string(--indent * 4, ' ') << "}" << std::endl;
+ }
+}
+
+void Painter::renderLayer(util::ptr<StyleLayer> layer_desc, const Tile::ID* id, const mat4* matrix) {
+ if (layer_desc->type == StyleLayerType::Background) {
+ // This layer defines a background color/image.
+
+ if (debug::renderTree) {
+ std::cout << std::string(indent * 4, ' ') << "- " << layer_desc->id << " ("
+ << layer_desc->type << ")" << std::endl;
+ }
+
+ renderBackground(layer_desc);
+ } else {
+ // This is a singular layer.
+ if (!layer_desc->bucket) {
+ fprintf(stderr, "[WARNING] layer '%s' is missing bucket\n", layer_desc->id.c_str());
+ return;
+ }
+
+ if (!layer_desc->bucket->style_source) {
+ fprintf(stderr, "[WARNING] can't find source for layer '%s'\n", layer_desc->id.c_str());
+ return;
+ }
+
+ StyleSource const& style_source = *layer_desc->bucket->style_source;
+
+ // Skip this layer if there is no data.
+ if (!style_source.source) {
+ return;
+ }
+
+ // Skip this layer if it's outside the range of min/maxzoom.
+ // This may occur when there /is/ a bucket created for this layer, but the min/max-zoom
+ // is set to a fractional value, or value that is larger than the source maxzoom.
+ const double zoom = state.getZoom();
+ if (layer_desc->bucket->min_zoom > zoom ||
+ layer_desc->bucket->max_zoom <= zoom) {
+ return;
+ }
+
+ // Abort early if we can already deduce from the bucket type that
+ // we're not going to render anything anyway during this pass.
+ switch (layer_desc->type) {
+ case StyleLayerType::Fill:
+ if (!layer_desc->getProperties<FillProperties>().isVisible()) return;
+ break;
+ case StyleLayerType::Line:
+ if (pass == RenderPass::Opaque) return;
+ if (!layer_desc->getProperties<LineProperties>().isVisible()) return;
+ break;
+ case StyleLayerType::Symbol:
+ if (pass == RenderPass::Opaque) return;
+ if (!layer_desc->getProperties<SymbolProperties>().isVisible()) return;
+ break;
+ case StyleLayerType::Raster:
+ if (pass == RenderPass::Opaque) return;
+ if (!layer_desc->getProperties<RasterProperties>().isVisible()) return;
+ break;
+ default:
+ break;
+ }
+
+ if (debug::renderTree) {
+ std::cout << std::string(indent * 4, ' ') << "- " << layer_desc->id << " ("
+ << layer_desc->type << ")" << std::endl;
+ }
+ if (!id) {
+ style_source.source->render(*this, layer_desc);
+ } else {
+ style_source.source->render(*this, layer_desc, *id, *matrix);
+ }
+ }
+}
+
void Painter::renderTileLayer(const Tile& tile, util::ptr<StyleLayer> layer_desc, const mat4 &matrix) {
assert(tile.data);
- if (tile.data->hasData(layer_desc) || layer_desc->type == StyleLayerType::Raster) {
+ if (tile.data->hasData(*layer_desc) || layer_desc->type == StyleLayerType::Raster) {
gl::group group(util::sprintf<32>("render %d/%d/%d\n", tile.id.z, tile.id.y, tile.id.z));
prepareTile(tile);
tile.data->render(*this, layer_desc, matrix);
@@ -211,15 +365,13 @@ void Painter::renderTileLayer(const Tile& tile, util::ptr<StyleLayer> layer_desc
void Painter::renderBackground(util::ptr<StyleLayer> layer_desc) {
const BackgroundProperties& properties = layer_desc->getProperties<BackgroundProperties>();
- const std::shared_ptr<Sprite> sprite = map.getSprite();
- if (properties.image.size() && sprite) {
+ if (properties.image.size()) {
if ((properties.opacity >= 1.0f) != (pass == RenderPass::Opaque))
return;
- SpriteAtlas &spriteAtlas = *map.getSpriteAtlas();
- SpriteAtlasPosition imagePos = spriteAtlas.getPosition(properties.image, *sprite, true);
- float zoomFraction = map.getState().getZoomFraction();
+ SpriteAtlasPosition imagePos = spriteAtlas.getPosition(properties.image, true);
+ float zoomFraction = state.getZoomFraction();
useProgram(patternShader->program);
patternShader->u_matrix = identityMatrix;
@@ -230,8 +382,8 @@ void Painter::renderBackground(util::ptr<StyleLayer> layer_desc) {
std::array<float, 2> size = imagePos.size;
double lon, lat;
- map.getLonLat(lon, lat);
- std::array<float, 2> center = map.getState().locationCoordinate(lon, lat);
+ state.getLonLat(lon, lat);
+ std::array<float, 2> center = state.locationCoordinate(lon, lat);
float scale = 1 / std::pow(2, zoomFraction);
mat3 matrix;
@@ -242,10 +394,10 @@ void Painter::renderBackground(util::ptr<StyleLayer> layer_desc) {
matrix::translate(matrix, matrix,
std::fmod(center[0] * 512, size[0]),
std::fmod(center[1] * 512, size[1]));
- matrix::rotate(matrix, matrix, -map.getState().getAngle());
+ matrix::rotate(matrix, matrix, -state.getAngle());
matrix::scale(matrix, matrix,
- scale * map.getState().getWidth() / 2,
- -scale * map.getState().getHeight() / 2);
+ scale * state.getWidth() / 2,
+ -scale * state.getHeight() / 2);
patternShader->u_patternmatrix = matrix;
backgroundBuffer.bind();
@@ -278,12 +430,12 @@ mat4 Painter::translatedMatrix(const mat4& matrix, const std::array<float, 2> &t
return matrix;
} else {
// TODO: Get rid of the 8 (scaling from 4096 to tile size)
- const double factor = ((double)(1 << id.z)) / map.getState().getScale() * (4096.0 / util::tileSize);
+ const double factor = ((double)(1 << id.z)) / state.getScale() * (4096.0 / util::tileSize);
mat4 vtxMatrix;
if (anchor == TranslateAnchorType::Viewport) {
- const double sin_a = std::sin(-map.getState().getAngle());
- const double cos_a = std::cos(-map.getState().getAngle());
+ const double sin_a = std::sin(-state.getAngle());
+ const double cos_a = std::cos(-state.getAngle());
matrix::translate(vtxMatrix, matrix,
factor * (translation[0] * cos_a - translation[1] * sin_a),
factor * (translation[0] * sin_a + translation[1] * cos_a),
diff --git a/src/renderer/painter_debug.cpp b/src/renderer/painter_debug.cpp
index f120533838..5bc36a233c 100644
--- a/src/renderer/painter_debug.cpp
+++ b/src/renderer/painter_debug.cpp
@@ -25,7 +25,7 @@ void Painter::renderDebugText(DebugBucket& bucket, const mat4 &matrix) {
// Draw white outline
plainShader->u_color = {{ 1.0f, 1.0f, 1.0f, 1.0f }};
- lineWidth(4.0f * map.getState().getPixelRatio());
+ lineWidth(4.0f * state.getPixelRatio());
bucket.drawLines(*plainShader);
#ifndef GL_ES_VERSION_2_0
@@ -36,7 +36,7 @@ void Painter::renderDebugText(DebugBucket& bucket, const mat4 &matrix) {
// Draw black text.
plainShader->u_color = {{ 0.0f, 0.0f, 0.0f, 1.0f }};
- lineWidth(2.0f * map.getState().getPixelRatio());
+ lineWidth(2.0f * state.getPixelRatio());
bucket.drawLines(*plainShader);
glEnable(GL_DEPTH_TEST);
@@ -56,7 +56,7 @@ void Painter::renderDebugFrame(const mat4 &matrix) {
// draw tile outline
tileBorderArray.bind(*plainShader, tileBorderBuffer, BUFFER_OFFSET(0));
plainShader->u_color = {{ 1.0f, 0.0f, 0.0f, 1.0f }};
- lineWidth(4.0f * map.getState().getPixelRatio());
+ lineWidth(4.0f * state.getPixelRatio());
glDrawArrays(GL_LINE_STRIP, 0, (GLsizei)tileBorderBuffer.index());
glEnable(GL_DEPTH_TEST);
@@ -87,14 +87,14 @@ void Painter::renderDebugText(const std::vector<std::string> &strings) {
VertexArrayObject debugFontArray;
debugFontArray.bind(*plainShader, debugFontBuffer, BUFFER_OFFSET(0));
plainShader->u_color = {{ 1.0f, 1.0f, 1.0f, 1.0f }};
- lineWidth(4.0f * map.getState().getPixelRatio());
+ lineWidth(4.0f * state.getPixelRatio());
glDrawArrays(GL_LINES, 0, (GLsizei)debugFontBuffer.index());
#ifndef GL_ES_VERSION_2_0
glPointSize(2);
glDrawArrays(GL_POINTS, 0, (GLsizei)debugFontBuffer.index());
#endif
plainShader->u_color = {{ 0.0f, 0.0f, 0.0f, 1.0f }};
- lineWidth(2.0f * map.getState().getPixelRatio());
+ lineWidth(2.0f * state.getPixelRatio());
glDrawArrays(GL_LINES, 0, (GLsizei)debugFontBuffer.index());
}
diff --git a/src/renderer/painter_fill.cpp b/src/renderer/painter_fill.cpp
index 6c17ab037a..f2759ffd61 100644
--- a/src/renderer/painter_fill.cpp
+++ b/src/renderer/painter_fill.cpp
@@ -49,8 +49,8 @@ void Painter::renderFill(FillBucket& bucket, util::ptr<StyleLayer> layer_desc, c
// Draw the entire line
outlineShader->u_world = {{
- static_cast<float>(map.getState().getFramebufferWidth()),
- static_cast<float>(map.getState().getFramebufferHeight())
+ static_cast<float>(state.getFramebufferWidth()),
+ static_cast<float>(state.getFramebufferHeight())
}};
depthRange(strata, 1.0f);
bucket.drawVertices(*outlineShader);
@@ -58,12 +58,10 @@ void Painter::renderFill(FillBucket& bucket, util::ptr<StyleLayer> layer_desc, c
if (pattern) {
// Image fill.
- Sprite &sprite = *map.getSprite();
- if (pass == RenderPass::Translucent && sprite) {
- SpriteAtlas &spriteAtlas = *map.getSpriteAtlas();
- const SpriteAtlasPosition pos = spriteAtlas.getPosition(properties.image, sprite, true);
- const float mix = std::fmod(float(map.getState().getZoom()), 1.0f);
- const float factor = 8.0 / std::pow(2, map.getState().getIntegerZoom() - id.z);
+ if (pass == RenderPass::Translucent) {
+ const SpriteAtlasPosition pos = spriteAtlas.getPosition(properties.image, true);
+ const float mix = std::fmod(float(state.getZoom()), 1.0f);
+ const float factor = 8.0 / std::pow(2, state.getIntegerZoom() - id.z);
mat3 patternMatrix;
matrix::identity(patternMatrix);
@@ -114,8 +112,8 @@ void Painter::renderFill(FillBucket& bucket, util::ptr<StyleLayer> layer_desc, c
// Draw the entire line
outlineShader->u_world = {{
- static_cast<float>(map.getState().getFramebufferWidth()),
- static_cast<float>(map.getState().getFramebufferHeight())
+ static_cast<float>(state.getFramebufferWidth()),
+ static_cast<float>(state.getFramebufferHeight())
}};
depthRange(strata + strata_epsilon, 1.0f);
diff --git a/src/renderer/painter_line.cpp b/src/renderer/painter_line.cpp
index cd973b46d6..9893f032dd 100644
--- a/src/renderer/painter_line.cpp
+++ b/src/renderer/painter_line.cpp
@@ -15,7 +15,7 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
const LineProperties &properties = layer_desc->getProperties<LineProperties>();
- float antialiasing = 1 / map.getState().getPixelRatio();
+ float antialiasing = 1 / state.getPixelRatio();
float width = properties.width;
float offset = properties.offset / 2;
float blur = properties.blur + antialiasing;
@@ -34,7 +34,7 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
float dash_length = properties.dash_array[0];
float dash_gap = properties.dash_array[1];
- float ratio = map.getState().getPixelRatio();
+ float ratio = state.getPixelRatio();
mat4 vtxMatrix = translatedMatrix(matrix, properties.translate, id, properties.translateAnchor);
depthRange(strata, 1.0f);
@@ -45,15 +45,15 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
linejoinShader->u_matrix = vtxMatrix;
linejoinShader->u_color = color;
linejoinShader->u_world = {{
- map.getState().getFramebufferWidth() * 0.5f,
- map.getState().getFramebufferHeight() * 0.5f
+ state.getFramebufferWidth() * 0.5f,
+ state.getFramebufferHeight() * 0.5f
}};
linejoinShader->u_linewidth = {{
- ((outset - 0.25f) * map.getState().getPixelRatio()),
- ((inset - 0.25f) * map.getState().getPixelRatio())
+ ((outset - 0.25f) * state.getPixelRatio()),
+ ((inset - 0.25f) * state.getPixelRatio())
}};
- float pointSize = std::ceil(map.getState().getPixelRatio() * outset * 2.0);
+ float pointSize = std::ceil(state.getPixelRatio() * outset * 2.0);
#if defined(GL_ES_VERSION_2_0)
linejoinShader->u_size = pointSize;
#else
@@ -62,12 +62,11 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
bucket.drawPoints(*linejoinShader);
}
- const util::ptr<Sprite> &sprite = map.getSprite();
- if (properties.image.size() && sprite) {
- SpriteAtlasPosition imagePos = map.getSpriteAtlas()->getPosition(properties.image, *sprite);
+ if (properties.image.size()) {
+ SpriteAtlasPosition imagePos = spriteAtlas.getPosition(properties.image);
- float factor = 8.0 / std::pow(2, map.getState().getIntegerZoom() - id.z);
- float fade = std::fmod(map.getState().getZoom(), 1.0);
+ float factor = 8.0 / std::pow(2, state.getIntegerZoom() - id.z);
+ float fade = std::fmod(state.getZoom(), 1.0);
useProgram(linepatternShader->program);
@@ -82,7 +81,7 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
linepatternShader->u_pattern_br = imagePos.br;
linepatternShader->u_fade = fade;
- map.getSpriteAtlas()->bind(true);
+ spriteAtlas.bind(true);
glDepthRange(strata + strata_epsilon, 1.0f); // may or may not matter
bucket.drawLinePatterns(*linepatternShader);
diff --git a/src/renderer/painter_raster.cpp b/src/renderer/painter_raster.cpp
index c362042e55..df655cdae8 100644
--- a/src/renderer/painter_raster.cpp
+++ b/src/renderer/painter_raster.cpp
@@ -31,14 +31,11 @@ void Painter::renderRaster(RasterBucket& bucket, util::ptr<StyleLayer> layer_des
return vtxMatrix;
}();
- // call updateTiles to get parsed data for sublayers
- map.updateTiles();
-
for (const util::ptr<StyleLayer> &layer : layer_desc->layers->layers) {
setOpaque();
- map.renderLayer(layer, RenderPass::Opaque, &id, &preMatrix);
+ renderLayer(layer, &id, &preMatrix);
setTranslucent();
- map.renderLayer(layer, RenderPass::Translucent, &id, &preMatrix);
+ renderLayer(layer, &id, &preMatrix);
}
if (bucket.properties.blur > 0) {
diff --git a/src/renderer/painter_symbol.cpp b/src/renderer/painter_symbol.cpp
index 415dead70e..79625f1681 100644
--- a/src/renderer/painter_symbol.cpp
+++ b/src/renderer/painter_symbol.cpp
@@ -25,10 +25,8 @@ void Painter::renderSDF(SymbolBucket &bucket,
mat4 exMatrix;
matrix::copy(exMatrix, projMatrix);
- const float angleOffset =
- bucketProperties.rotation_alignment == RotationAlignmentType::Map
- ? map.getState().getAngle()
- : 0;
+ bool aligned_with_map = (bucketProperties.rotation_alignment == RotationAlignmentType::Map);
+ const float angleOffset = aligned_with_map ? state.getAngle() : 0;
if (angleOffset) {
matrix::rotate_z(exMatrix, exMatrix, angleOffset);
@@ -45,24 +43,24 @@ void Painter::renderSDF(SymbolBucket &bucket,
sdfShader.u_texsize = texsize;
// Convert the -pi..pi to an int8 range.
- float angle = std::round(map.getState().getAngle() / M_PI * 128);
+ float angle = std::round(state.getAngle() / M_PI * 128);
// adjust min/max zooms for variable font sies
float zoomAdjust = std::log(fontSize / bucketProperties.max_size) / std::log(2);
+ sdfShader.u_flip = (aligned_with_map && bucketProperties.keep_upright) ? 1 : 0;
sdfShader.u_angle = (int32_t)(angle + 256) % 256;
- sdfShader.u_flip = (bucket.properties.placement == PlacementType::Line ? 1 : 0);
- sdfShader.u_zoom = (map.getState().getNormalizedZoom() - zoomAdjust) * 10; // current zoom level
+ sdfShader.u_zoom = (state.getNormalizedZoom() - zoomAdjust) * 10; // current zoom level
FadeProperties f = frameHistory.getFadeProperties(300_milliseconds);
sdfShader.u_fadedist = f.fadedist * 10;
sdfShader.u_minfadezoom = std::floor(f.minfadezoom * 10);
sdfShader.u_maxfadezoom = std::floor(f.maxfadezoom * 10);
- sdfShader.u_fadezoom = (map.getState().getNormalizedZoom() + f.bump) * 10;
+ sdfShader.u_fadezoom = (state.getNormalizedZoom() + f.bump) * 10;
// The default gamma value has to be adjust for the current pixelratio so that we're not
// drawing blurry font on retina screens.
- const float gamma = 0.105 * sdfFontSize / fontSize / map.getState().getPixelRatio();
+ const float gamma = 0.105 * sdfFontSize / fontSize / state.getPixelRatio();
const float sdfPx = 8.0f;
const float blurOffset = 1.19f;
@@ -122,35 +120,19 @@ void Painter::renderSymbol(SymbolBucket &bucket, util::ptr<StyleLayer> layer_des
glDisable(GL_STENCIL_TEST);
- if (bucket.hasTextData()) {
- GlyphAtlas &glyphAtlas = *map.getGlyphAtlas();
- glyphAtlas.bind();
-
- renderSDF(bucket,
- id,
- matrix,
- bucket.properties.text,
- properties.text,
- 24.0f,
- {{ float(glyphAtlas.width) / 4, float(glyphAtlas.height) / 4 }},
- *sdfGlyphShader,
- &SymbolBucket::drawGlyphs);
- }
-
if (bucket.hasIconData()) {
bool sdf = bucket.sdfIcons;
const float angleOffset =
bucket.properties.icon.rotation_alignment == RotationAlignmentType::Map
- ? map.getState().getAngle()
+ ? state.getAngle()
: 0;
// If layerStyle.size > bucket.info.fontSize then labels may collide
const float fontSize = properties.icon.size != 0 ? properties.icon.size : bucket.properties.icon.max_size;
const float fontScale = fontSize / 1.0f;
- SpriteAtlas &spriteAtlas = *map.getSpriteAtlas();
- spriteAtlas.bind(map.getState().isChanging() || bucket.properties.placement == PlacementType::Line || angleOffset != 0 || fontScale != 1 || sdf);
+ spriteAtlas.bind(state.isChanging() || bucket.properties.placement == PlacementType::Line || angleOffset != 0 || fontScale != 1 || sdf);
std::array<float, 2> texsize = {{
float(spriteAtlas.getWidth()),
@@ -185,19 +167,22 @@ void Painter::renderSymbol(SymbolBucket &bucket, util::ptr<StyleLayer> layer_des
iconShader->u_texsize = texsize;
// Convert the -pi..pi to an int8 range.
- const float angle = std::round(map.getState().getAngle() / M_PI * 128);
+ const float angle = std::round(state.getAngle() / M_PI * 128);
// adjust min/max zooms for variable font sies
float zoomAdjust = std::log(fontSize / bucket.properties.icon.max_size) / std::log(2);
iconShader->u_angle = (int32_t)(angle + 256) % 256;
- iconShader->u_flip = bucket.properties.placement == PlacementType::Line ? 1 : 0;
- iconShader->u_zoom = (map.getState().getNormalizedZoom() - zoomAdjust) * 10; // current zoom level
+
+ bool flip = (bucket.properties.icon.rotation_alignment == RotationAlignmentType::Map)
+ && bucket.properties.icon.keep_upright;
+ iconShader->u_flip = flip ? 1 : 0;
+ iconShader->u_zoom = (state.getNormalizedZoom() - zoomAdjust) * 10; // current zoom level
iconShader->u_fadedist = 0 * 10;
- iconShader->u_minfadezoom = map.getState().getNormalizedZoom() * 10;
- iconShader->u_maxfadezoom = map.getState().getNormalizedZoom() * 10;
- iconShader->u_fadezoom = map.getState().getNormalizedZoom() * 10;
+ iconShader->u_minfadezoom = state.getNormalizedZoom() * 10;
+ iconShader->u_maxfadezoom = state.getNormalizedZoom() * 10;
+ iconShader->u_fadezoom = state.getNormalizedZoom() * 10;
iconShader->u_opacity = properties.icon.opacity;
depthRange(strata, 1.0f);
@@ -205,5 +190,19 @@ void Painter::renderSymbol(SymbolBucket &bucket, util::ptr<StyleLayer> layer_des
}
}
+ if (bucket.hasTextData()) {
+ glyphAtlas.bind();
+
+ renderSDF(bucket,
+ id,
+ matrix,
+ bucket.properties.text,
+ properties.text,
+ 24.0f,
+ {{ float(glyphAtlas.width) / 4, float(glyphAtlas.height) / 4 }},
+ *sdfGlyphShader,
+ &SymbolBucket::drawGlyphs);
+ }
+
glEnable(GL_STENCIL_TEST);
}
diff --git a/src/renderer/symbol_bucket.cpp b/src/renderer/symbol_bucket.cpp
index 7d5036eea3..542c109dba 100644
--- a/src/renderer/symbol_bucket.cpp
+++ b/src/renderer/symbol_bucket.cpp
@@ -100,7 +100,7 @@ std::vector<SymbolFeature> SymbolBucket::processFeatures(const VectorTileLayer &
void SymbolBucket::addFeatures(const VectorTileLayer &layer, const FilterExpression &filter,
const Tile::ID &id, SpriteAtlas &spriteAtlas, Sprite &sprite,
- GlyphAtlas &glyphAtlas, GlyphStore &glyphStore) {
+ GlyphAtlas & glyphAtlas, GlyphStore &glyphStore) {
const std::vector<SymbolFeature> features = processFeatures(layer, filter, glyphStore, sprite);
@@ -148,7 +148,8 @@ void SymbolBucket::addFeatures(const VectorTileLayer &layer, const FilterExpress
// if feature has icon, get sprite atlas position
if (feature.sprite.length()) {
- image = spriteAtlas.waitForImage(feature.sprite, sprite);
+ sprite.waitUntilLoaded();
+ image = spriteAtlas.getImage(feature.sprite);
if (sprite.getSpritePosition(feature.sprite).sdf) {
sdfIcons = true;